import os

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import requests
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler
import matplotlib as mpl

mpl.rcParams['font.family'] = 'Candara'
mpl.rcParams['font.weight'] = 'bold'
mpl.rcParams['font.size'] = 12

from adjustText.adjustText import adjust_text

# Here we develop an OOPs oriented format in which we have various methods to operate on the csv file

class DataInput:
    def __init__(self, filepath_data):
        self.data = pd.read_csv(filepath_data, index_col='Rk')
        try:
            self.data['Player'] = self.data['Player'].apply(lambda x: ' '.join(x.split('\\')[1].split('-')))
            self.data['Comp'] = self.data['Comp'].apply(lambda x: ' '.join(x.split()[1:]))
            self.data['Nation'] = self.data['Nation'].apply(lambda x: x.split()[-1])
        except:
            print('Error in loading file:' + filepath_data)

        self.filtereddf = self.data.copy()

    # The below method shows the head of the data after a filtering option. We can control the number of
    # data rows by changing the no option

    def showdata(self, no=5):
        print(self.filtereddf.head(no))

    # The below method will filter the data based on min number of 90s played, team, league and nation
    # We can list the positions we want to remove by adding them as parameters after the min_90s parameter
    # To find the names of different leagues, teams, nations and positions, we have defined various methods later on

    def filterdata(self, min_90s=5, *pos_to_remove, team: object = False,
                   league: object = False, nation: object = False):
        notpos = []
        for pos in pos_to_remove:
            notpos.append(pos)
        self.filtereddf = self.filtereddf[self.filtereddf['Pos'].apply(lambda x: x not in notpos)]
        self.filtereddf = self.filtereddf[self.filtereddf['90s'] >= min_90s]
        if team:
            self.filtereddf = self.filtereddf[self.filtereddf['Squad'] == team]
        if league:
            self.filtereddf = self.filtereddf[self.filtereddf['Comp'] == league]
        if nation:
            self.filtereddf = self.filtereddf[self.filtereddf['Nation'] == nation]

    # This method lists the various positions which can be found in the original or filtered dataset
    # To find positions in filtered dataset make the filtered_dataset param = True
    def show_different_positions(self, filtered_dataset=False):
        if filtered_dataset:
            print(self.filtereddf['Pos'].unique())
        print(self.data['Pos'].unique())

    # This method shows us the different nations which can be found in the original or filtered dataset
    def show_different_nations(self, filtered_dataset=False):
        if filtered_dataset:
            print(self.filtereddf['Pos'].unique())
        print(self.data['Pos'].unique())

    # This method shows all the the columns or only the stats columns in the original dataset
    def show_relevant_columns(self, all_cols=False):
        if all_cols:
            print(list(self.data.columns))

        columns = list(self.data.columns)
        col_to_remove = ['Player', 'Nation', 'Pos', 'Squad', 'Comp', 'Age', 'Born', '90s']
        for col in col_to_remove:
            if col in columns:
                columns.remove(col)
        print(columns)

    # This properly lists all the names of the leagues in the original dataset
    @property
    def show_leaguenames(self):
        print(self.data['Comp'].unique())

    # This methods shows all the teams present in a particular league
    def show_teams_in_league(self, leaguename):
        print(self.data[self.data['Comp'] == leaguename]['Squad'].unique())

    # This methods shows all the players present in a particular team
    def show_players_in_team(self, teamname):
        print(self.data[self.data['Squad'] == teamname][['Player','90s','Pos']].reset_index(drop=True))

    # This method saves the filtered df as a csv file on your system
    # The first parameters saves the file in that name(don't add the .csv)
    # The second parameter saves the file in the directory you choose(if not sure, leave as be, it will
    # save the csv in the same directory as this Python script)
    def save_new_csv(self, filename='new_csv', filepath=os.getcwd()):
        try:
            self.filtereddf.to_csv(filepath + '\\' + filename + '.csv', encoding='utf-8-sig')
        except:
            print('An error occurred in saving the file')
        else:
            print('File has been saved as {0} at {1}'.format(filename, filepath))

    # This is a plotting method
    # on_x refers to the x-axis parameter while #on_y refers to the y-axis parameter
    # per90 makes the graph a per90 graph(make sure no parameters are per90 among the two though)
    # no_of_players limits the graph the top n players in the two metrics
    # season changes the input of season to add to title
    # plot_on_page plots the graph(default in Jupyter Notebook)
    # custom_headers lets you make custom labels for x, y axes and title
    # size is the figure size(input as a tuple, first refers to x width, second to y width)
    # point_col, text_col and bg_color refer to the colour of the points, the text and background respectively
    # annotate tells whether you want to label all points or not
    # player_focus labels a particular player you want to focus on in the filtered dataframe, for this annotate has to be off
    # save saves the plot in a directory of your choice
    # add_xref, add_yred and add_refline adds reference lines according to slope needed
    # repel creates a ggrepel type feature which repels each label
    # Above code taken from https://github.com/Phlya/adjustText
    def plot(self, on_x, on_y, per90=False, no_of_players=False, season='20-21', plot_on_page=True,
             custom_headers=False, figure_size=(12, 8), point_col='red', text_col='black',
             bgcolor='white', annotate = True, player_focus = None, save=False, add_xref=False,
             add_yref=False, add_refline=False, repel=True):

        df = self.filtereddf.copy().reset_index(drop=True)
        x_axis, y_axis = on_x, on_y

        p90statement: str = ''

        if per90:
            p90statement += ' per 90'
            if (on_x[-1] != '%') and (on_x[-2:] != '90'):
                df[on_x] = df[on_x] / df['90s']
                x_axis += p90statement
            if (on_y[-1] != '%') and (on_y[-2:] != '90'):
                df[on_y] = df[on_y] / df['90s']
                y_axis += p90statement

        if annotate or not player_focus:
            if no_of_players:
                scaled = MinMaxScaler().fit_transform(df[[on_x, on_y]])
                df_scaled = []
                for i in range(scaled.shape[0]):
                    df_scaled.append(np.prod(scaled[i]))
                df['Custom'] = pd.Series(df_scaled)
                # df['Custom'] = df[on_x] * df[on_y]
                df = df.sort_values('Custom', ascending=False)[:no_of_players].reset_index(drop=True)
                df.drop('Custom', axis=1, inplace=True)

        league = ''
        nation = ''
        team = ''
        if (int(df['Comp'].nunique()) > 1) and (int(df['Squad'].nunique()) > 1):
            title = '{0} vs {1} top {2} players across Europe\'s top 5 leagues for {3}{4}'.format(on_x, on_y,
                                                                                str(no_of_players),
                                                                                str(season),
                                                                                p90statement)
            if int(df['Nation'].nunique()) == 1:
                nation += df['Nation'].iloc[0] + ' nationality'
                title = '{0} vs {1} top {2} players across Europe\'s top 5 leagues of {3} for {4}{5}'.format(on_x, on_y,
                                                                                str(no_of_players), nation,
                                                                                str(season),p90statement)
        else:
            if int(df['Comp'].nunique()) == 1:
                league += df['Comp'].iloc[0]
            if int(df['Squad'].nunique()) == 1:
                team += df['Squad'].iloc[0]
                league = ''
            if int(df['Nation'].nunique()) == 1:
                nation += df['Nation'].iloc[0] + ' nationality'

            # title_dict = {'League': league, 'Team': team, 'Nation': nation}
            title_lst = [league, team, nation]
            title_lst = [name for name in title_lst if len(name) > 0]

            if len(title_lst) == 1:
                title_st = title_lst[0]
            else:
                title_st = ' and of '.join(title_lst)

            title = '{0} vs {1} top {2} players in {3} for {4}{5}'.format(on_x, on_y, str(no_of_players), title_st,
                                                                            season, p90statement)

        if custom_headers:
            title = input('Title header: ')
            x_axis = input('X axis title: ')
            y_axis = input('Y axis title: ')

        fig, ax = plt.subplots(figsize=figure_size)
        ax.patch.set_facecolor(bgcolor)
        fig.set_facecolor(bgcolor)

        x_dist = (df[on_x].max() - df[on_x].min()) / 50
        y_dist = (df[on_y].max() - df[on_y].min()) / 50
        size = 12

        # SCATTERPLOT
        alpha = 0.75 if len(df.index)<30 else 0.375
        p = sns.scatterplot(x=on_x, y=on_y, data=df, color=point_col, edgecolor='black', alpha=alpha)
        p.grid(True, axis='both', c='gray', ls='--', alpha=0.5)

        # TEXT ANNOTATIONS
        if annotate:
            if not repel:
                for line in range(df.shape[0]):
                    plt.text(df[on_x][line] - x_dist, df[on_y][line] + y_dist,
                             df['Player'][line],
                             fontdict=dict(color=text_col, size=size))
            else:
                texts = []
                for x, y, s in zip(df[on_x], df[on_y], df['Player']):
                    texts.append(plt.text(x, y, s,
                                          fontdict=dict(color=text_col, size=size)))
                adjust_text(texts, force_points=0.2, force_text=0.2,
                            expand_points=(1, 1), expand_text=(1, 1),
                            arrowprops=dict(arrowstyle="-", color='white', lw=0.5,alpha=0))

        else:
            if player_focus:
                df_player = df[df['Player']==player_focus]
                try:
                    ax.scatter(df_player[on_x], df_player[on_y], s=50, c='black', ec='black', zorder=2, alpha=0.8)
                    ax.text(df_player[on_x] - x_dist, df_player[on_y] + y_dist, df_player['Player'].values[0], size=14)
                except: pass

        # FOOTER
        fig.text(0.01,0.015, 'Made using FootballFbrefPlotting by Shreyas Khatri/@khatri_shreyas. '+
        'Code repo present at https://github.com/shreyas7kha/FootballFbrefPlotting.',
        size=10, weight='bold')

        # SET TITLES AND AXES LABELS
        p.set_xlabel(x_axis, weight='heavy', family='Century Gothic', size=15, color=text_col)
        p.set_ylabel(y_axis, weight='heavy', family='Century Gothic', size=15, color=text_col)
        p.set_title(title.upper(), weight='heavy', family='Century Gothic', size=20, color=text_col)

        if add_xref:
            p.axvline(add_xref, ls='--')

        if add_yref:
            p.axhline(add_yref, ls='--')

        if add_refline:
            slope, intercept = add_refline

            def abline(slope, intercept):
                """Plot a line from slope and intercept"""
                axes = plt.gca()
                x_vals = np.array(axes.get_xlim())
                y_vals = intercept + slope * x_vals
                plt.plot(x_vals, y_vals, '--')

            abline(slope, intercept)

        if save:
            file_path = input('Choose filepath you want to save in or click enter if in same directory: ')
            filename = input('Save file as(don\'t add the .png): ')

            if len(file_path.split()) == 0:
                file_path = os.getcwd()

            if input('Do you want to save the image in an uncreated sub directory:').lower()[0] == 'y':
                sub_dir = input('Name of the sub directory: ')
                os.mkdir(file_path + '\\' + sub_dir)
                file_path = file_path + '\\' + sub_dir

            try:
                plt.savefig(file_path + '\\' + filename + '.png', facecolor=bgcolor ,dpi=300)
            except:
                print('An error occurred in saving the plot')
            else:
                print(f'File was saved succesfully at {file_path} with name {filename}')
        if plot_on_page:
            plt.show()

# Many a times we want to create a plot from two different csv files, the below class helps us do so
# TwoDataInput takes 2 csvs as input and merges them, all the methods remain similar to the previous class

# A preliminary function which combines both dfs and cleans the dataframe
def combine_and_cleancolumns(d1, d2):
    data = pd.merge(d1, d2, on=['Player','Squad'])
    columns = data.columns
    new_cols = []

    for col in columns:
        if (col[-2:] != '_x') and (col[-2:]!='_y'):
            new_cols.append(col)
        else:
            if col[:-2] not in new_cols:
                new_cols.append(col[:-2])
            else:
                data.drop(col, inplace=True, axis=1)
    data.columns = new_cols
    try:
        data['Player'] = data['Player'].apply(lambda x: ' '.join(x.split('\\')[1].split('-')))
        data['Comp'] = data['Comp'].apply(lambda x: ' '.join(x.split()[1:]))
        data['Nation'] = data['Nation'].apply(lambda x: x.split()[-1])
    except:
        print('Error in loading file at ' + d1 + ' and ' + d2)
    finally:
        return data

class TwoDataInput(DataInput):
    def __init__(self, filepath_data1, filepath_data2):
        super().__init__(filepath_data1)
        super().__init__(filepath_data2)
        self.d1 = pd.read_csv(filepath_data1, index_col='Rk')
        self.d2 = pd.read_csv(filepath_data2, index_col='Rk')
        self.data = combine_and_cleancolumns(self.d1, self.d2)
        self.filtereddf = self.data.copy()

# A function which can read data from a Fbref webpage
def readfromhtml(filepath):
    df = pd.read_html(filepath)[0]

    column_lst = list(df.columns)
    unique_col_names = []
    for col in column_lst:
        if col[1] not in unique_col_names:
            unique_col_names.append(col[1])
        else:
            unique_col_names.append(col[0]+' '+col[1])

    df.columns = unique_col_names
    df.drop(df[df['Player'] == 'Player'].index, inplace=True)
    df = df.fillna('0')
    df.set_index('Rk', drop=True, inplace=True)
    try:
        df['Comp'] = df['Comp'].apply(lambda x: ' '.join(x.split()[1:]))
        df['Nation'] = df['Nation'].astype(str)
        df['Nation'] = df['Nation'].apply(lambda x: x.split()[-1])
    except:
        print('Error in uploading file:' + filepath)
    finally:
        df = df.apply(pd.to_numeric, errors='ignore')
        return df

# Similar to the data input, this particular class takes information directly from
# Fbref's website based on url
class DataInputFromWebpage(DataInput):
    def __init__(self, filepath_data):
        self.data = readfromhtml(filepath_data)
        self.filtereddf = self.data.copy()

# This is the two class extension extended to both files from Fbref's website
class TwoDataInputFromWebpage(DataInput):
    def __init__(self, filepath_data1, filepath_data2):
        self.d1 = readfromhtml(filepath_data1)
        self.d2 = readfromhtml(filepath_data2)
        self.data = pd.merge(self.d1, self.d2)
        self.filtereddf = self.data.copy()

from bs4 import BeautifulSoup as soup

# If you want all data for the big 5 leagues, you just need to run this function with
# the filepath where you want to save all the files
def save_all_csvs(base_url='https://fbref.com/en/comps/Big5/Big-5-European-Leagues-Stats',
                  filepath=os.getcwd()):
    req = requests.get(base_url)
    parse_soup = soup(req.content, 'lxml')
    scripts = parse_soup.find_all('ul')
    url_list = scripts[4]
    urls = []
    for url in url_list.find_all('a', href=True):
        urls.append(url['href'])
    urls = [base_url[:17] + url for url in urls]
    for url in urls:
        df = readfromhtml(url)
        filename = url.split('/')[6]
        try:
            df.to_csv(filepath + '\\' + filename + '.csv', encoding='utf-8-sig')
        except:
            print('An error occurred in saving the file')
        else:
            print('File has been saved as {0} at {1}'.format(filename, filepath))


import cv2
import imageio
import numpy as np

images = []
while True:
    img = np.random.random((250,350))*255
    img = np.array(img , dtype=np.uint8)
    images.append(img)
    cv2.imshow('',img)
    if cv2.waitKey(25) & 0xFF == ord('q'):
        break

imageio.mimsave('Output/tv.gif',images)


#  对请求返回值做处理，加"ThisIdYellowBegin" ，"ThisIdYellowEnd"
#  注意对最后一层的修改如果是不可变类型（string，int）返回上一级是不会修改的，除非有修改的返回值
#  对list，dict的修改返回上一层也是修改的结果

import json
#  有返回值的修改
def test2(temp):
    if isinstance(temp, dict):
        for key in temp.keys():
            temp[key] = test2(temp[key])
    elif isinstance(temp, (list, tuple)):
        for i in range(0, len(temp)):
            temp[i] = test2(temp[i])
    elif isinstance(temp, str):
        if temp[0] in ['{', '[']:
            temp = json.loads(temp)
            temp = test2(temp)
        else:
            temp = "ThisIdYellowBegin" + temp + "ThisIdYellowEnd"
    elif isinstance(temp, int):
        temp  = "ThisIdYellowBegin" + str(temp) + "ThisIdYellowEnd"
    else:
        pass
    return temp  # 注意递归的每次都有return返回上层

# 原因解释：最底层的修改，没有返回上一层；是不是因为底层是不可变数据类型,可变类型是适用的
def test3(temp):
    if isinstance(temp, dict):
        for key in temp.keys():
            res = test3(temp[key])
    elif isinstance(temp, (list,tuple)):
        for i in range(0, len(temp)):
            res = test3(temp[i])
    elif isinstance(temp, str):
        if temp[0] in ['{' ,'[']: # 加判断
            res =json.loads(temp)
            test3(temp)
        else:
            temp="ThisIdYellowBegin" + temp + "ThisIdYellowEnd"
    elif isinstance(temp, int):
        temp="ThisIdYellowBegin" + str(temp) + "ThisIdYellowEnd"
    else:
        pass

    return False

if __name__=='__main__':
    # temp = {'cur_filter': 123}
    temp = {'cur_filter': '123'}
    # temp = {'cur_filter': '{"department_5":"4339","department_6":"43399"}'}
    # temp = {'cur_filter': {"department_5":"4339","department_6":"43399"}}
    # temp = {'cur_filter': [{"department_5":"4339","department_6":"43399"}]}
    # temp = {'cur_filter': '[{"department_1":"1726","department":"2785","department_3":"3626","department_4":"4338","department_5":"4339","department_erp":"abc"}]'}
    # temp={'cur_filter': {"department_6":"43399","department_5":"4339"}}
    # ans = test(temp)
    # print(ans)
    test3(temp)
    print(temp)


import pandas
import numpy
import csv
import sys
import event

theory_fname = sys.argv[1]
opt_event_fname = sys.argv[2]
plot_fname = sys.argv[3]
current_fname = sys.argv[4]

df = pandas.read_csv(theory_fname, header=None)
theory_data = df.to_numpy()
theory_spec = event.Event(0, theory_data[0,:])
print("theo mean", theory_spec.mean, "theo var", theory_spec.variance)

df = pandas.read_csv(opt_event_fname, header=None)
opt_data = df.to_numpy()
opt_spec = event.Event(0, opt_data[0,:])

# order is important
[opt_align, dist] = event.alignment2(theory_spec.data, opt_spec.data)

#for i in range(50):
#    print(i, opt_align[i], theory_spec.data[i])

from matplotlib import pyplot as plt
plt.plot(theory_spec.data, label="Theoretical")
plt.plot(opt_align, label="Experimental")
plt.legend()
plt.savefig(plot_fname);

norm_opt_align = opt_spec.de_norm_intensity(opt_align)

seq_len = 42
data_len = len(norm_opt_align)
print("data len", data_len)
bin_size = (data_len - 1) / (seq_len + 1)
wing = 1
print("bin size", bin_size, "wing size", wing)

min_pos = numpy.argmin(norm_opt_align)
min_val = norm_opt_align[min_pos]
print("min", min_val)

current = []

for i in range(seq_len):
    pos = round(bin_size * (i+1))
    sample = norm_opt_align[pos-wing: pos+wing+1]
    mean = numpy.mean(sample)
    #print(i, pos, opt_align[pos])
    current.append(mean - min_val)

with open(current_fname, mode='w') as current_file:
    current_writer = csv.writer(current_file, delimiter=',')
    current_writer.writerow(current)


from utils import verify_request
from webob import MultiDict

import webapp2
import cgi
import unittest
import hashlib
import binascii
import urllib
import hmac
import ndb_tests

from google.appengine.ext.ndb import model

class TestVerifier(ndb_tests.NDBTest):

    def setUp(self):
        super(TestVerifier, self).setUp()

        class AppAccess(model.Model):
            secret = model.StringProperty(required=True)

        self.eins_zwo = AppAccess(secret="meine weihnacht").put()
        self.other_key = AppAccess(secret="secret souce").put()

    def test_no_key(self):
        self.assertRaises(webapp2.HTTPException,
                verify_request, "GET", "http://example.com", {})

    def test_no_signature(self):
        self.assertRaises(webapp2.HTTPException,
                verify_request, "GET", "http://example.com", {"_key": ""})

    def test_unknown_key(self):
        self.assertRaises(webapp2.HTTPException,
                verify_request, "GET", "http://example.com",
                {"_key": self.other_key.urlsafe()[:4] + "blaa",
                        "_signature": "faulty"})

    def test_faulty_signature(self):
        self.assertRaises(webapp2.HTTPException, verify_request,
            "GET", "http://example.com",
            {"_key": self.eins_zwo.urlsafe(), "_signature": "faulty"})

    def test_simple(self):
        key = self.eins_zwo.urlsafe()
        secret = "meine weihnacht"
        params = {"yay": "other", "second": "yes", "_key": key}
        query = '&'.join(("GET", "http://www.example.com",
                    urllib.urlencode(params)))
        params["_signature"] = binascii.b2a_base64(
            hmac.new(secret, query, hashlib.sha256).digest())

        self.assertEquals(self.eins_zwo.get(), verify_request("GET",
                    "http://www.example.com", params))

    def test_lists(self):
        key = self.eins_zwo.urlsafe()
        secret = "meine weihnacht"
        params = {"yay": ["other", "peter", "michael"],
                "second": "yes", "_key": key}
        query = '&'.join(("GET", "http://www.example.com",
                    urllib.urlencode(params)))
        params["_signature"] = binascii.b2a_base64(
            hmac.new(secret, query, hashlib.sha256).digest())

        self.assertEquals(self.eins_zwo.get(), verify_request("GET",
                    "http://www.example.com", params))

    def test_unsorted_params(self):
        key = self.eins_zwo.urlsafe()
        secret = "meine weihnacht"
        done_params = "c=b&a=b&_key=" + key
        query = '&'.join(("GET", "http://www.example.com",
                    done_params))
        params = MultiDict(cgi.parse_qsl(
                done_params, keep_blank_values=True,
                strict_parsing=False))
        params["_signature"] = binascii.b2a_base64(
            hmac.new(secret, query, hashlib.sha256).digest())

        self.assertEquals(self.eins_zwo.get(), verify_request("GET",
                    "http://www.example.com", params))

    def test_post(self):
        key = self.other_key.urlsafe()
        secret = "secret souce"
        params = {"yay": "other", "second": "yes", "_key": key}
        query = '&'.join(("POST", "http://www.example.com",
                    urllib.urlencode(params)))
        params["_signature"] = binascii.b2a_base64(
            hmac.new(secret, query, hashlib.sha256).digest())

        self.assertEquals(self.other_key.get(), verify_request("POST",
                    "http://www.example.com", params))

    def test_changed_params(self):
        key = self.eins_zwo.urlsafe()
        secret = "meine weihnacht"
        params = {"yay": "other", "second": "yes", "_key": key}
        query = '&'.join(("GET", "http://www.example.com",
                    urllib.urlencode(params)))
        params["_signature"] = binascii.b2a_base64(
            hmac.new(secret, query, hashlib.sha256).digest())

        # let's play with the params
        params["yay"] = "oupsi"

        self.assertRaises(webapp2.HTTPException,
                verify_request, "GET", "http://www.example.com", params)

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


'''Get Google Chrome bookmark entries.
'''

import csv
import getpass
import json
import sys
from typing import Callable

config = {
    # macOS:
    'chrome_bookmark_path': (
        '/Users/{username}/Library/Application Support/'
        'Google/Chrome/Default/Bookmarks'
    ).format(username=getpass.getuser())
}

def main():
    data = get_chrome_bookmark_data()

    # printer = Printer(RawPrintStrategy())
    # printer = Printer(SimplePrintStrategy())
    printer = Printer(CsvPrintStrategy())

    printer.walk(data)

def get_chrome_bookmark_data() -> dict:
    '''Get the json of user's Chrome bookmark.'''
    with open(config['chrome_bookmark_path']) as f:
        return json.load(f)

def walk_bookmark(entry: dict, callback: Callable) -> None:
    '''Walk through bookmark entry tree.

    Execute a callback function for bookmark entries.
    '''
    if isinstance(entry, list):
        for child in entry:
            walk_bookmark(child, callback)

    if isinstance(entry, dict):
        if 'type' in entry:
            if entry['type'] == 'folder':
                walk_bookmark(entry['children'], callback)
            elif entry['type'] == 'url':
                callback(entry)

class Printer:
    '''Base Printer class for a bookmark entry.

    Includes the following functions.
    - Prints a boomark entry.
    - Stores the count of times the method is invoked.
    '''

    def __init__(self, print_strategy):
        self.print_strategy = print_strategy
        self.count = 0

    def walk(self, data):
        walk_bookmark(data['roots']['bookmark_bar'], self.print)
        walk_bookmark(data['roots']['other'], self.print)
        print('Total: {}'.format(self.count))

    def print(self, entry) -> None:
        self.print_strategy.print(entry)
        self.count += 1

class RawPrintStrategy:
    def print(self, entry) -> None:
        print(entry)

class SimplePrintStrategy:
    def print(self, entry) -> None:
        print('{}: {}'.format(entry['name'], entry['url']))

class CsvPrintStrategy:
    def __init__(self):
        self.writer = csv.writer(sys.stdout)

    def print(self, entry) -> None:
        self.writer.writerow(
            [entry['id'], entry['name'], entry['date_added'], entry['url']]
        )

if __name__ == '__main__':
    main()


from os.path import join, exists
from os import mkdir, makedirs
from config import debug, local
from IPython import display
import numpy as np
import itertools
from matplotlib import pyplot as plt
from matplotlib_inline import backend_inline
from sklearn import metrics

def use_svg_display():
    """Use the svg format to display a plot."""

    backend_inline.set_matplotlib_formats('svg')

def set_axes(axes, x_label, y_label, x_lim, y_lim, x_scale, y_scale, legend):
    """Set the axes for matplotlib.

    Defined in :numref:`sec_calculus`"""
    if x_label is not None:
        axes.set_xlabel(x_label)
    if y_label is not None:
        axes.set_ylabel(y_label)
    if x_scale is not None:
        axes.set_xscale(x_scale)
    if y_scale is not None:
        axes.set_yscale(y_scale)
    axes.set_xlim(x_lim)
    axes.set_ylim(y_lim)
    if legend:
        axes.legend(legend)
    axes.grid()

class Animator:
    """For plotting data_access in animation."""

    def __init__(self, x_label=None, y_label=None, legend=None, x_lim=None,
                 y_lim=None, x_scale='linear', y_scale='linear',
                 fmts=('-', 'm--', 'g-.', 'r:'), num_rows=1, num_cols=1,
                 fig_size=(5., 3.5)):
        """init parameter for plot."""

        # Incrementally plot multiple lines
        if legend is None:
            legend = []
        use_svg_display()
        self.fig, self.axes = plt.subplots(num_rows, num_cols, figsize=fig_size)
        if num_rows * num_cols == 1:
            self.axes = [self.axes, ]
        # Use a lambda function to capture arguments
        self.config_axes = lambda: set_axes(
            self.axes[0], x_label, y_label, x_lim, y_lim, x_scale, y_scale, legend)
        self.X, self.Y, self.fmts = None, None, fmts

    def add(self, x, y):
        # Add multiple data_access points into the figure
        if not hasattr(y, "__len__"):
            y = [y]
        n = len(y)
        if not hasattr(x, "__len__"):
            x = [x] * n
        if not self.X:
            self.X = [[] for _ in range(n)]
        if not self.Y:
            self.Y = [[] for _ in range(n)]
        for i, (a, b) in enumerate(zip(x, y)):
            if a is not None and b is not None:
                self.X[i].append(a)
                self.Y[i].append(b)
        if debug is True and local is True:
            self.axes[0].cla()
            for x, y, fmt in zip(self.X, self.Y, self.fmts):
                self.axes[0].plot(x, y, fmt)
            self.config_axes()
            display.display(self.fig)
            display.clear_output(wait=True)
            plt.pause(0.01)

    def show(self):
        # Show picture
        self.axes[0].cla()
        for x, y, fmt in zip(self.X, self.Y, self.fmts):
            self.axes[0].plot(x, y, fmt)
        self.config_axes()

    @staticmethod
    def plot_confusion_matrix(cm, classes,
                              normalize=False,
                              title='Confusion matrix',
                              cmap=plt.cm.Blues):
        """This function prints and plots the confusion matrix. Normalization
        can be applied by setting `normalize=True`.
        """
        if normalize:
            cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
            print("Normalized confusion matrix")
        else:
            print('Confusion matrix, without normalization')

        print(cm)

        plt.imshow(cm, interpolation='nearest', cmap=cmap)
        plt.title(title)
        plt.colorbar()
        tick_marks = np.arange(len(classes))
        plt.xticks(tick_marks, classes, rotation=45)
        plt.yticks(tick_marks, classes)

        fmt = '.2f' if normalize else 'd'
        thresh = cm.max() / 2.
        for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
            plt.text(j, i, format(cm[i, j], fmt),
                     horizontalalignment="center",
                     color="white" if cm[i, j] > thresh else "black")

        plt.tight_layout()
        plt.ylabel('True label')
        plt.xlabel('Predicted label')
        plt.gcf().subplots_adjust(bottom=0.25)

    @staticmethod
    def get_confusion_matrix(cnf_matrix,
                             saving_dir: str = None,
                             model_name: str = ''):
        plt.figure()
        Animator.plot_confusion_matrix(cnf_matrix,
                                       classes=[0, 1],
                                       title='Confusion matrix, without normalization')
        plt.show()
        if saving_dir is not None:
            if not exists(saving_dir):
                makedirs(saving_dir)
            file_name = join(saving_dir, f'{model_name}_' + 'confusion')
            plt.savefig(file_name)

        plt.figure()
        Animator.plot_confusion_matrix(cnf_matrix, normalize=True, classes=[0, 1],
                                   title='Normalized confusion matrix')
        plt.show()
        if saving_dir is not None:
            if not exists(saving_dir):
                makedirs(saving_dir)
            file_name = join(saving_dir, f'{model_name}_' +  'confusion_normalized')
            plt.savefig(file_name)

    @staticmethod
    def get_metrics(effect,
                    saving_dir: str = None,
                    model_name: str = ''):
        plt.figure()
        if type(effect).__name__ == 'dict':
            ax = list(effect.keys())
            ay = list(effect.values())
            plt.ylim([0.0, 1.05])
            plt.tick_params(axis='x', labelsize=12)
            plt.bar(ax, ay)
            for a, b, i in zip(ax, ay, range(len(ax))):  # zip 函数
                plt.text(a, b + 0.01, "%.2f" % ay[i], ha='center', fontsize=12)
            plt.show()
            if saving_dir is not None:
                if not exists(saving_dir):
                    makedirs(saving_dir)
                plt.savefig(join(saving_dir, f'{model_name}_' + "metrics"))

    @staticmethod
    def get_auc(y_prob, y_true,
                saving_dir: str = None,
                model_name: str = ''):
        auc_fig = plt.figure()
        fpr, tpr, thresholds = metrics.roc_curve(y_true, y_prob, pos_label=1)
        roc_auc = metrics.auc(fpr, tpr)
        plt.figure(auc_fig.number)
        plt.plot(fpr, tpr, label=model_name + ' (area = %0.2f)' % roc_auc)
        plt.plot([0, 1], [0, 1], 'k--')
        plt.xlim([0.0, 1.0])
        plt.ylim([0.0, 1.05])
        plt.xlabel('False Positive Rate', fontsize=12)
        plt.ylabel('True Positive Rate', fontsize=12)
        plt.title('Receiver operating characteristic (ROC)', fontsize=12)
        plt.legend(loc="lower right")
        auc_fig.show()
        if saving_dir is not None:
            if not exists(saving_dir):
                makedirs(saving_dir)
            auc_fig.savefig(join(saving_dir, f'{model_name}_' + 'auc_curves'))

    @staticmethod
    def get_auprc(y_prob, y_true,
                 saving_dir: str = None,
                 model_name: str = ''):
        prc_fig = plt.figure()
        prc_fig.set_size_inches((10, 6))
        precision, recall, thresholds = metrics.precision_recall_curve(y_true, y_prob, pos_label=1)
        roc_auc = metrics.average_precision_score(y_true, y_prob)
        plt.figure(prc_fig.number)
        plt.plot(recall, precision, label=model_name + ' (area under precision recall curve = %0.2f)' % roc_auc)

        plt.xlim([0.0, 1.0])
        plt.ylim([0.0, 1.05])
        plt.xlabel('Recall', fontsize=12)
        plt.ylabel('precision', fontsize=12)
        plt.title('Precision Recall Curve (PRC)', fontsize=12)
        plt.legend(loc="lower right")
        prc_fig.show()
        if saving_dir is not None:
            if not exists(saving_dir):
                makedirs(saving_dir)
            prc_fig.savefig(join(saving_dir, f'{model_name}_' + 'auprc_curves'))


import argparse
import os
import shutil

import mindspore
from mindspore import CheckpointConfig
from tensorboardX import SummaryWriter

from mindediting import create_trainer_by_name
from mindediting.dataset.create_loaders import create_data_loader
from mindediting.deploy.utils.config import Config, merge, parse_cli_to_yaml, parse_yaml
from mindediting.loss import create_loss
from mindediting.models import create_model_by_name
from mindediting.optim import create_optimizer
from mindediting.scheduler import create_scheduler_by_name
from mindediting.utils.callbacks import EvalAsInValPyCallBack, ProfileCallback, TrainingMonitor
from mindediting.utils.device_adapter import get_device_id, get_device_num
from mindediting.utils.init_utils import init_env

def train(cfg, profile):
    init_env(cfg)
    # create dataset
    rank_id = get_device_id()
    group_size = get_device_num()

    # create train data loader
    loader_train = create_data_loader(
        cfg.model.name,
        cfg.dataset,
        cfg.train_pipeline,
        "train",
        cfg.dataset.batch_size,
    )

    # create model
    cfg.mode = "train"
    net, eval_network = create_model_by_name(model_name=cfg.model.name, cfg=cfg)
    cfg.net, cfg.steps_per_epoch = net, loader_train.get_dataset_size()

    # create loss
    loss = create_loss(loss_name=cfg.loss.name, **cfg.loss.cfg_dict)

    # create learning rate schedule
    optimizer_params, learning_rate = create_scheduler_by_name(model_name=cfg.model.name, cfg=cfg)

    # create optimizer
    loss_scale = 1.0 if cfg.loss.amp_level == "O0" else cfg.loss.loss_scale
    optimizer = create_optimizer(
        params=optimizer_params,
        lr=learning_rate,
        opt=cfg.optimizer.name,
        loss_scale=loss_scale,
        **{"beta1": cfg.optimizer.beta1, "beta2": cfg.optimizer.beta2}
    )

    # define callbacks
    save_checkpoint_steps = cfg.train_params.save_epoch_frq * loader_train.get_dataset_size()
    config_ck = CheckpointConfig(
        save_checkpoint_steps=save_checkpoint_steps, keep_checkpoint_max=cfg.train_params.keep_checkpoint_max
    )
    summary_writer = None
    if rank_id == 0:
        summary_writer = SummaryWriter(os.path.join(cfg.train_params.ckpt_save_dir, "summary"))
    callbacks = [mindspore.TimeMonitor()]
    if cfg.train_params.need_val:
        callbacks.append(EvalAsInValPyCallBack(cfg, net, eval_network, summary_writer=summary_writer))
    if profile:
        callbacks.append(ProfileCallback(**cfg.train_params.profile.cfg_dict))
    if rank_id == 0:
        callbacks.append(
            TrainingMonitor(
                cfg.train_params.epoch_size,
                cfg.steps_per_epoch,
                print_frequency=cfg.train_params.print_frequency,
                summary_writer=summary_writer,
            )
        )
        callbacks.append(
            mindspore.ModelCheckpoint(
                prefix=cfg.model.name + "_" + cfg.dataset.dataset_name,
                directory=cfg.train_params.ckpt_save_dir,
                config=config_ck,
            )
        )

    # define trainer
    trainer = create_trainer_by_name(cfg.model.name, net, loss, optimizer, cfg)
    initial_epoch = cfg.train_params.get("initial_epoch", 0)
    print(" training...")
    trainer.train(
        cfg.train_params.epoch_size,
        loader_train,
        dataset_sink_mode=cfg.dataset.dataset_sink_mode,
        callbacks=callbacks,
        initial_epoch=initial_epoch,
    )

    if summary_writer:
        summary_writer.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="default name", add_help=False)
    parser.add_argument("--config_path", type=str, help="Config file path", required=True)
    parser.add_argument("--profile", action="store_true", help="Enables profile callback.")
    known_args, _ = parser.parse_known_args()
    default, helper, choices = parse_yaml(known_args.config_path)
    args = parse_cli_to_yaml(
        parser=parser, cfg=default, helper=helper, choices=choices, cfg_path=known_args.config_path
    )
    final_config = merge(args, default)
    final_config = Config(final_config)
    if get_device_id() == 0:
        os.makedirs(final_config.train_params.ckpt_save_dir, exist_ok=True)
        try:
            shutil.copy(known_args.config_path, final_config.train_params.ckpt_save_dir)
        except shutil.SameFileError:
            pass
    train(final_config, known_args.profile)


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

# OpenGL example code - Geometry Shader and Blending
# Uses a geometry shader to expand points to billboard quads.
# The billboards are then blended while drawing to create a galaxy
# made of particles.

import math
from random import random as rand
import ctypes

import numpy as np
from OpenGL.GL import *
from OpenGL.GL import shaders

from glfw import *
import glm

class Window(object):

    def __init__(self, width=640, height=480, title='GLFW opengl window'):
        self.width = width
        self.height = height
        self.title = title
        self.window = None

        self.__vertexShader = './shaders/%s.vert' % self.title
        self.__geomShader = './shaders/%s.geom' % self.title
        self.__fragmentShader = './shaders/%s.frag' % self.title
        self.__shaderProgram = None
        self.__vao = None

        self.__viewLocation = None
        self.__projLocation = None

        self.__particles = 128 * 1024

    def shaderFromFile(self, shaderType, shaderFile):
        """read shader from file and compile it"""
        shaderSrc = ''
        with open(shaderFile) as sf:
            shaderSrc = sf.read()

        return shaders.compileShader(shaderSrc, shaderType)

    def initGL(self):
        """opengl initialization"""
        # load shaders
        vertexShader = self.shaderFromFile(GL_VERTEX_SHADER, self.__vertexShader)
        geomShader = self.shaderFromFile(GL_GEOMETRY_SHADER, self.__geomShader)
        fragmentShader = self.shaderFromFile(GL_FRAGMENT_SHADER, self.__fragmentShader)
        self.__shaderProgram = shaders.compileProgram(vertexShader, geomShader, fragmentShader)
        if not self.__shaderProgram:
            self.close()

        # obtain location of projection uniform
        self.__viewLocation = glGetUniformLocation(self.__shaderProgram, 'View')
        self.__projLocation = glGetUniformLocation(self.__shaderProgram, 'Projection')

        # generate and bind the vao
        self.__vao = glGenVertexArrays(1)
        glBindVertexArray(self.__vao)

        # generate and bind the buffer object
        vbo = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vbo)

        # create a galaxy like distribution of points
        vertexData = []
        for i in xrange(self.__particles):
            arm = 3 * rand()
            alpha = 1 / (.1 + math.pow(rand(), .7)) - 1/1.1
            r = 4.0 * alpha
            alpha += arm * 2.0 * 3.1416 / 3.0

            x = r * math.sin(alpha)
            y = 0
            z = r * math.cos(alpha)

            x += (4.0 - .2 * alpha) * (2 - rand() + rand() + rand() + rand())
            y += (2.0 - .1 * alpha) * (2 - rand() + rand() + rand() + rand())
            z += (4.0 - .2 * alpha) * (2 - rand() + rand() + rand() + rand())
            vertexData.append((x, y, z))
        vertexData = np.array(vertexData, dtype=np.float32)

        # fill with data
        glBufferData(GL_ARRAY_BUFFER, vertexData.nbytes, vertexData, GL_STATIC_DRAW)

        # set up generic attrib pointers
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * 4, None)

        glBindVertexArray(0)

        # we are blending so no depth testing
        glDisable(GL_DEPTH_TEST)

        # enable blending
        glEnable(GL_BLEND)
        # and set the blend function to result = 1 * source + 1 * destination
        glBlendFunc(GL_ONE, GL_ONE)

    def renderGL(self):
        """opengl render method"""
        # get the time in seconds
        t = glfwGetTime()

        # clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        # use the shader program
        glUseProgram(self.__shaderProgram)

        # calculate ViewProjection matrix
        projection = glm.perspective(90.0, 4.0 / 3.0, .1, 100.0)
        projection = np.array(projection, dtype=np.float32)

        # translate the world/view position
        view = glm.translate(glm.mat4(1.0), glm.vec3(0.0, 0.0, -50.0))

        # make the camera rotate around the origin
        view = glm.rotate(view, 30.0 * math.sin(t * 0.1), glm.vec3(1.0, 0.0, 0.0))
        view = glm.rotate(view, -22.5 * t, glm.vec3(0.0, 1.0, 0.0))
        view = np.array(view, dtype=np.float32)

        # set the uniform
        glUniformMatrix4fv(self.__viewLocation, 1, GL_FALSE, view)
        glUniformMatrix4fv(self.__projLocation, 1, GL_FALSE, projection)

        # bind the vao
        glBindVertexArray(self.__vao)

        # draw
        glDrawArrays(GL_POINTS, 0, self.__particles)

        glBindVertexArray(0)
        glUseProgram(0)

    def initWindow(self):
        """setup window options. etc, opengl version"""
        # select opengl version
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)

    def show(self):
        """create the window and show it"""
        self.initWindow()

        self.window = glfwCreateWindow(self.width, self.height, self.title, 0, 0)
        if self.window == 0:
            glfwTerminate()
            raise Exception('failed to open window')

        glfwMakeContextCurrent(self.window)

        # initialize opengl
        self.initGL()

        while not glfwWindowShouldClose(self.window):
            glfwPollEvents()

            self.renderGL()

            # check for errors
            error = glGetError()
            if error != GL_NO_ERROR:
                raise Exception(error)

            # finally swap buffers
            glfwSwapBuffers(self.window)

        self.close()

    def close(self):
        glfwDestroyWindow(self.window)
        glfwTerminate()

if __name__ == '__main__':
    import os.path

    if glfwInit() == GL_FALSE:
        raise Exception('failed to init GLFW')

    title = os.path.basename(__file__)
    win = Window(title=title[:-3])
    win.show()


import json
import random
import re
from collections import defaultdict
from typing import List

import morfeusz2

morf = morfeusz2.Morfeusz()

tags_to_delete = set(
    [
        "burk",
        "conj",
        "comp",
        "num",
        "ppron12",
        "ppron3",
        "pred",
        "prep",
        "siebie",
        "brev",
        "qub",
        "wulg",
        "interj",
    ]
)

def sieve_popularity_dict(popularity_file: str) -> None:
    """ "Sieve popularity dict to get rid of tags_to_delete."""
    with open(popularity_file, "r", encoding="utf-8") as popularity:
        dicti = json.load(popularity)
        words_to_del = set()
        for word in dicti:
            word_tags_set = set()
            for tup in morf.analyse(word):
                further_analysis = (tup[2])[2].split(":")
                for e in further_analysis:
                    word_tags_set.add(e)
            if len(word_tags_set) == 1:
                words_to_del.add(word)
            if len(word_tags_set.intersection(tags_to_delete)) != 0:
                words_to_del.add(word)
        for word in words_to_del:
            del dicti[word]
        with open("sieved_popularity.json", "w", encoding="utf-8") as save:
            json.dump(dicti, save, ensure_ascii=False)

def reverse_popularity_dict(popularity_file: str) -> None:
    """Find the less popular words by reversing the popularity dict"""
    with open(popularity_file, "r", encoding="utf-8") as popularity:
        dicti = json.load(popularity)
        desc_ord = dict(sorted(dicti.items(), key=lambda item: item[1], reverse=True))
        with open("reverse_pop.json", "w", encoding="utf-8") as save:
            json.dump(desc_ord, save, ensure_ascii=False)

def cut_to_n_keys(popularity_file: str, n: int) -> None:
    """Cut the popularity dict only to n chosen keys."""
    with open(popularity_file, "r", encoding="utf-8") as popularity:
        dicti = json.load(popularity)
        n_items = {k: dicti[k] for k in list(dicti.keys())[:n]}
        with open(str(n) + "_popularity_items.json", "w", encoding="utf-8") as save:
            json.dump(n_items, save, ensure_ascii=False)

def sieve_corpus_to_leave_populars(corpus: str, pop_dict: str) -> None:
    """Sieve corpora with popular dict to leave only the popular words."""
    with open(corpus, "r", encoding="utf-8") as corp:
        with open(pop_dict, "r", encoding="utf-8") as popul:
            with open("corpus_with_populars.txt", "w", encoding="utf-8") as f:
                pop_dic = json.load(popul)
                keys_set = set(pop_dic.keys())
                for line in corp:
                    line = line.rstrip()
                    guard = 1
                    for word in tokenize(line):
                        word = word.strip()
                        if word not in keys_set:
                            guard = 0
                            continue
                    if guard == 1:
                        f.write(line + "\n")

def tokenize(line: str) -> List[str]:
    """Tokenize line of text to have just words."""
    text = line.lower()
    pattern = r"\s*\w*\s*"
    return list(filter(None, re.findall(pattern, text)))

def create_indexes_dict() -> None:
    """Create a dict that remembers indexes of chosen words."""
    with open("corpus_with_populars.txt", "r", encoding="utf-8") as corp:
        with open("sieved_popularity.json", "r", encoding="utf-8") as pops:
            pops_dict = json.load(pops)
            keys_set = set(pops_dict.keys())
            indexes = defaultdict(list)
            for index, line in enumerate(corp):
                line = line.strip()
                for word in tokenize(line):
                    word = word.strip()
                    if word in keys_set:
                        indexes[word].append(index)

            for word in indexes:
                val = indexes[word]
                random.shuffle(val)
                indexes[word] = val[:1000]
    with open("index_dict.json", "w", encoding="utf-8") as save:
        json.dump(indexes, save, ensure_ascii=False)

def see_indexes() -> None:
    """Check indexes to see if they're correct."""
    with open("index_dict.json", "r", encoding="utf-8") as save:
        index_dict = json.load(save)
        i = 0
        for j, indexes in index_dict.items():
            print(j, indexes)
            print()
            i += 1
            if i > 5:
                break

def cut_indexes_lists() -> None:
    """Cut the lists of indexes to 1000 places."""
    with open("index_dict.json", "r", encoding="utf-8") as dicti:
        index_dict = json.load(dicti)
        for key in index_dict:
            if len(index_dict[key]) > 1000:
                val = index_dict[key]
                random.shuffle(val)
                index_dict[key] = val[:1000]
    with open("indexes_narrowed.json", "w", encoding="utf-8") as save:
        json.dump(index_dict, save, ensure_ascii=False)


import sys
sys.dont_write_bytecode = True

from flask import Blueprint, jsonify, request

# Entities
from models.entities.Subject_Period import Subject_Periods
# Models
from models.Subject_PeriodModel import subject_periodModel

main = Blueprint('subject_period_blueprint', __name__)

@main.route('/', methods=['GET'])
def get_subject_periods():
    try:
        grs = subject_periodModel.get_subject_periods()
        return jsonify(grs)
    except Exception as ex:
        return jsonify({'message': str(ex)}), 500

@main.route('/<id>', methods=['GET'])
def get_subject_period(id):
    try:
        gr = subject_periodModel.get_subject_period(id)
        if gr != None:
            return jsonify(gr)
        else:
            return jsonify({}), 404
    except Exception as ex:
        return jsonify({'message': str(ex)}), 500

@main.route('/', methods=['POST'])
def add_subject_period():
    try:
        id = request.json['id']
        period = request.json['period']
        subject = request.json['subject']
        gr = Subject_Periods(id, period, subject)

        affected_rows = subject_periodModel.add_subject_period(gr)

        if affected_rows == 1:
            return jsonify(gr.id)
        else:
            return jsonify({'message': "Error al Insertar"}), 500

    except Exception as ex:
        return jsonify({'message': str(ex)}), 500

@main.route('/<id>', methods=['PUT'])
def update_subject_period(id):
    try:
        period = request.json['period']
        subject = request.json['subject']
        gr = Subject_Periods(id, period, subject)

        affected_rows = subject_periodModel.update_subject_period(gr)

        if affected_rows == 1:
            return jsonify(gr.id)
        else:
            return jsonify({'message': "Ningún subject_period actualizado."}), 404

    except Exception as ex:
        return jsonify({'message': str(ex)}), 500

@main.route('/<id>', methods=['DELETE'])
def delete_subject_period(id):
    try:
        gr = Subject_Periods(id)

        affected_rows = subject_periodModel.delete_subject_period(gr)

        if affected_rows == 1:
            return jsonify(gr.id)
        else:
            return jsonify({'message': "Ningún subject_period borrado."}), 404

    except Exception as ex:
        return jsonify({'message': str(ex)}), 500


# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding model 'ProjectSizeInfoModel'
        db.create_table('gnmplutostats_projectsizeinfomodel', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('project_id', self.gf('django.db.models.fields.CharField')(max_length=32, null=True, db_index=True)),
            ('storage_id', self.gf('django.db.models.fields.CharField')(max_length=32, db_index=True)),
            ('size_used_gb', self.gf('django.db.models.fields.IntegerField')()),
            ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
        ))
        db.send_create_signal('gnmplutostats', ['ProjectSizeInfoModel'])

        # Adding unique constraint on 'ProjectSizeInfoModel', fields ['project_id', 'storage_id']
        db.create_unique('gnmplutostats_projectsizeinfomodel', ['project_id', 'storage_id'])

    def backwards(self, orm):
        # Removing unique constraint on 'ProjectSizeInfoModel', fields ['project_id', 'storage_id']
        db.delete_unique('gnmplutostats_projectsizeinfomodel', ['project_id', 'storage_id'])

        # Deleting model 'ProjectSizeInfoModel'
        db.delete_table('gnmplutostats_projectsizeinfomodel')

    models = {
        'gnmplutostats.projectsizeinfomodel': {
            'Meta': {'unique_together': "(('project_id', 'storage_id'),)", 'object_name': 'ProjectSizeInfoModel'},
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
            'project_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'db_index': 'True'}),
            'size_used_gb': ('django.db.models.fields.IntegerField', [], {}),
            'storage_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'})
        }
    }

    complete_apps = ['gnmplutostats']


"""Script to update users analytics data to Elasticsearch."""

import argparse
import datetime
import functools
import json
import logging
import os
import random
import typing

import certifi as _  # Needed to handle SSL in elasticsearch connections, for production use.
import elasticsearch
from google.protobuf import json_format
import requests
import requests_aws4auth

from bob_emploi.frontend.api import geo_pb2
from bob_emploi.frontend.api import job_pb2
from bob_emploi.frontend.api import project_pb2
from bob_emploi.frontend.api import user_pb2
from bob_emploi.frontend.server import mongo
from bob_emploi.frontend.server import now
from bob_emploi.frontend.server import proto
from bob_emploi.frontend.server import scoring
from bob_emploi.frontend.server.asynchronous import report

_DB, _USER_DB, _ = mongo.get_connections_from_env()

def age_group(year_of_birth: int) -> str:
    """Estimate age group from year of birth."""

    if year_of_birth < 1920:
        return 'Unknown'
    precise_age = now.get() - datetime.datetime(year_of_birth, 7, 1)
    age = precise_age.days / 365
    if age < 18:
        return '-18'
    if age < 25:
        return '18-24'
    if age < 35:
        return '25-34'
    if age < 45:
        return '35-44'
    if age < 55:
        return '45-54'
    if age < 65:
        return '55-64'
    return '65+'

def nps_love_score(nps_score: int) -> typing.Optional[int]:
    """Convert NPS scode to lovers/detractors values.

    Returns -1 for detractors, meaning NPS score is between 1 and 5.
    Returns 0 for passive, meaning NPS score is 6 or 7.
    Returns 1 for lovers, meaning NPS score is 8, 9, 10.
    Returns None otherwise."""

    if nps_score <= 5:
        return -1
    if nps_score <= 7:
        return 0
    if nps_score <= 10:
        return 1
    logging.warning('Cannot convert nps_score %s', nps_score)
    return None

def bob_has_helped_love_score(answer: str) -> typing.Optional[int]:
    """Convert 'Bob has helped ?' answers to lovers/detractors values.

    Return -1 if answer is 'NO'
    Return 1 if answer is 'YES' or 'YES_A_LOT'
    Return None otherwise."""

    if answer in ('NO', 'NOT_AT_ALL'):
        return -1
    if answer in ('YES', 'YES_A_LOT'):
        return 1
    logging.warning('bobHasHelped field has unknown answer "%s"', answer)
    return None

def feedback_love_score(feedback_score: int) -> typing.Optional[int]:
    """Convert online feedback score to lovers/detractors values.

    Returns -1 if score is 1 or 2.
    Returns 0 if score 3.
    Returns 1 if score is 4 or 5.
    Returns None otherwise."""

    if feedback_score in (1, 2):
        return -1
    if feedback_score == 3:
        return 0
    if feedback_score in (4, 5):
        return 1
    logging.warning('Cannot convert feedback_score %s', feedback_score)
    return None

def _get_employment_status(user: user_pb2.User) -> typing.Optional[user_pb2.EmploymentStatus]:
    """Get the last employmentStatus for which we have an answer to bobHasHelped question, or get
    the last employmentStatus."""

    last_status = None
    for status in reversed(user.employment_status):
        if status.bob_has_helped:
            return status
        if not last_status:
            last_status = status
    return last_status

def _get_last_complete_project(user: user_pb2.User) -> typing.Optional[project_pb2.Project]:
    """Get last project which is not is_incomplete."""

    return next(
        (project for project in reversed(user.projects)
         if not project.is_incomplete),
        None)

_T = typing.TypeVar('_T')
_U = typing.TypeVar('_U')

def _remove_null_fields(mydict: typing.Dict[_T, typing.Optional[_U]]) -> typing.Dict[_T, _U]:
    out: typing.Dict[_T, _U] = {}
    for key, value in mydict.items():
        clean_value: typing.Optional[_U]
        if isinstance(value, dict):
            clean_value = typing.cast(_U, _remove_null_fields(value)) or None
        else:
            clean_value = value
        if clean_value is not None:
            out[key] = clean_value
    return out

# Cache (from MongoDB) of known cities.
@functools.lru_cache(maxsize=256, typed=False)
def _get_urban_context(city_id: str) -> typing.Optional[str]:
    target_city = _DB.cities.find_one({'_id': city_id})
    if target_city:
        target_city_proto = typing.cast(
            geo_pb2.FrenchCity, proto.create_from_mongo(target_city, geo_pb2.FrenchCity))
        return geo_pb2.UrbanContext.Name(target_city_proto.urban_context)
    return None

def _user_to_analytics_data(user: user_pb2.User) -> typing.Dict[str, typing.Any]:
    """Gather analytics data to insert into elasticsearch."""

    data: typing.Dict[str, typing.Any] = {
        'registeredAt': user.registered_at.ToJsonString(),
        'randomGroup': random.randint(0, 100) / 100,
        'profile': {
            'ageGroup': age_group(user.profile.year_of_birth),
            'canTutoie': user.profile.can_tutoie,
            'coachingEmailFrequency': user_pb2.EmailFrequency.Name(
                user.profile.coaching_email_frequency),
            'frustrations': [user_pb2.Frustration.Name(f) for f in user.profile.frustrations],
            'gender': user_pb2.Gender.Name(user.profile.gender),
            'hasHandicap': user.profile.has_handicap,
            'highestDegree': job_pb2.DegreeLevel.Name(user.profile.highest_degree),
            'origin': user_pb2.UserOrigin.Name(user.profile.origin),
        },
        'featuresEnabled': json_format.MessageToDict(user.features_enabled),
        'origin': {
            'medium': user.origin.medium,
            'source': user.origin.source,
        },
    }
    if user.net_promoter_score_survey_response.HasField('responded_at'):
        data['nps_response'] = {
            'loveScore': nps_love_score(user.net_promoter_score_survey_response.score),
            'score': user.net_promoter_score_survey_response.score,
            'time': user.net_promoter_score_survey_response.responded_at.ToJsonString(),
        }
    last_project = _get_last_complete_project(user)
    if last_project:
        scoring_project = scoring.ScoringProject(
            last_project, user.profile, user.features_enabled, _DB)
        data['project'] = {
            'targetJob': {
                'name': last_project.target_job.name,
                'job_group': {
                    'name': last_project.target_job.job_group.name,
                },
            },
            'areaType': geo_pb2.AreaType.Name(last_project.area_type),
            'city': {
                'regionName': last_project.city.region_name,
                'urbanScore': last_project.city.urban_score,
            },
            'job_search_length_months': round(scoring_project.get_search_length_at_creation()),
            'advices': [a.advice_id for a in last_project.advices if a.num_stars >= 2],
            'numAdvicesRead': sum(
                1 for a in last_project.advices if a.status == project_pb2.ADVICE_READ),
            'isComplete': not last_project.is_incomplete,
        }
        if last_project.kind:
            data['project']['kind'] = project_pb2.ProjectKind.Name(last_project.kind)
        if last_project.feedback.score:
            data['project']['feedbackScore'] = last_project.feedback.score
            data['project']['feedbackLoveScore'] = feedback_love_score(last_project.feedback.score)
        if last_project.min_salary and last_project.min_salary < 1000000000:
            data['project']['minSalary'] = last_project.min_salary
        urban_context = _get_urban_context(last_project.city.city_id)
        if urban_context:
            data['project']['city']['urbanContext'] = urban_context
    last_status = _get_employment_status(user)
    if last_status:
        data['employmentStatus'] = json_format.MessageToDict(last_status)
        data['employmentStatus']['daysSinceRegistration'] = \
            (last_status.created_at.ToDatetime() - user.registered_at.ToDatetime()).days
        if last_status.bob_has_helped:
            data['employmentStatus']['bobHasHelpedScore'] = bob_has_helped_love_score(
                last_status.bob_has_helped)
        if last_status.other_coaches_used:
            data['employmentStatus']['otherCoachesUsed'] = [
                user_pb2.OtherCoach.Name(c) for c in last_status.other_coaches_used
            ]
        if last_status.bob_relative_personalization:
            data['employmentStatus']['bobRelativePersonalization'] = \
                last_status.bob_relative_personalization

    if user.emails_sent:
        data['emailsSent'] = {
            # This will keep only the last email sent for each campaign.
            email.campaign_id: user_pb2.EmailSentStatus.Name(email.status)
            for email in sorted(user.emails_sent, key=lambda email: email.sent_at.ToDatetime())
        }

    if user.client_metrics.first_session_duration_seconds:
        data['clientMetrics'] = {
            'firstSessionDurationSeconds': user.client_metrics.first_session_duration_seconds,
        }
    if user.client_metrics.is_first_session_mobile:
        data['clientMetrics'] = data.get('clientMetrics', {})
        data['clientMetrics']['isFirstSessionMobile'] = \
            user_pb2.OptionalBool.Name(user.client_metrics.is_first_session_mobile)

    return _remove_null_fields(data)

def export_user_to_elasticsearch(
        es_client: elasticsearch.Elasticsearch, index: str, registered_from: str,
        dry_run: bool = True) -> None:
    """Synchronize users to elasticsearch for analytics purpose."""

    if not dry_run:
        if es_client.indices.exists(index=index):
            logging.info('Removing old bobusers index ...')
            es_client.indices.delete(index=index)
        logging.info('Creating bobusers index ...')
        es_client.indices.create(index=index)

    nb_users = 0
    nb_docs = 0
    cursor = _USER_DB.user.find({
        'registeredAt': {'$gt': registered_from},
        'featuresEnabled.excludeFromAnalytics': {'$ne': True},
    })
    for row in cursor:

        nb_users += 1
        user_id = str(row.pop('_id'))
        user = typing.cast(user_pb2.User, proto.create_from_mongo(row, user_pb2.User))
        data = _user_to_analytics_data(user)

        logging.debug(data)

        if not dry_run:
            es_client.create(index=index, doc_type='user', id=user_id, body=json.dumps(data))
            nb_docs += 1
            if nb_docs % 1000 == 0:
                logging.info('%i users processed', nb_docs)

    if not dry_run:
        es_client.indices.flush(index=index)

def main(
        es_client: elasticsearch.Elasticsearch,
        string_args: typing.Optional[typing.List[str]] = None) -> None:
    """Parse command line arguments and trigger sync_employment_status function."""

    parser = argparse.ArgumentParser(
        description='Synchronize mongodb employement status fields retrieving typeform data.')
    parser.add_argument(
        '-r', '--registered-from', default='2017-06-01',
        help='Process users registered from the given date')
    parser.add_argument(
        '--no-dry-run', dest='dry_run', action='store_false',
        help='No dry run really store in elasticsearch.')
    parser.add_argument('--index', default='bobusers', help='Elasticsearch index to write to')
    parser.add_argument('--verbose', '-v', action='store_true', help='More detailed output.')
    parser.add_argument(
        '--disable-sentry', action='store_true', help='Disable logging to Sentry.')
    args = parser.parse_args(string_args)

    logging.basicConfig(level='DEBUG' if args.verbose else 'INFO')
    if not args.dry_run and not args.disable_sentry:
        try:
            report.setup_sentry_logging(os.getenv('SENTRY_DSN'))
        except ValueError:
            logging.error(
                'Please set SENTRY_DSN to enable logging to Sentry, or use --disable-sentry option')
            return

    export_user_to_elasticsearch(es_client, args.index, args.registered_from, dry_run=args.dry_run)

def _get_auth_from_env(
        env: typing.Mapping[str, str]) -> typing.Optional[requests_aws4auth.AWS4Auth]:
    aws_in_docker = env.get('AWS_CONTAINER_CREDENTIALS_RELATIVE_URI')
    if aws_in_docker:
        # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html
        response = requests.get('http://169.254.170.2{}'.format(aws_in_docker))
        response.raise_for_status()
        credentials = response.json()
        access_key_id = credentials.get('AccessKeyId')
        secret_access_key = credentials.get('SecretAccessKey')
        session_token = credentials.get('Token')
    else:
        access_key_id = env.get('AWS_ACCESS_KEY_ID')
        secret_access_key = env.get('AWS_SECRET_ACCESS_KEY')
        session_token = None
    if not access_key_id:
        return None
    return requests_aws4auth.AWS4Auth(
        access_key_id, secret_access_key, 'eu-central-1', 'es', session_token=session_token)

def get_es_client_from_env() -> elasticsearch.Elasticsearch:
    """Get an Elasticsearch client configured from environment variables."""

    env = os.environ
    return elasticsearch.Elasticsearch(
        env.get('ELASTICSEARCH_URL', 'http://elastic:changeme@elastic-dev:9200').split(','),
        http_auth=_get_auth_from_env(env),
        connection_class=elasticsearch.RequestsHttpConnection)

if __name__ == '__main__':
    main(get_es_client_from_env())


import json
from textwrap import indent
from task1 import*
from task5 import*
tsk_a=open("task5.json","r+")
tsk_b=json.load(tsk_a)

dict={}
def analys_movie_ganer():
    for i in tsk_b:
        if "Genare" in i:
            a=i["Genare"]
            for j in a:
                if j in dict:
                    dict[j]+=1
                else:
                    dict[j]=1

        print(dict)

    with open("task11.json","w+")as file:
        json.load(dict,file,indent=4)

analys_movie_ganer()