from setup import simple_get
from xlsx_importer import open_xlsx_file_and_return_workbook, write_to_xlsx, close_xlsx_file
import json
import pprint
pp = pprint.PrettyPrinter(depth=6)

def get_trello_boards(personal_key, personal_token):
    """Get all trello boards of user

    Parameters:
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        boards (dict): trello boards of user, board id as a key and board name as a value.
                       F.E. {'ytNr5B5o9': 'New Board'}
        Or raising an error if http is failing

    """
    trello_url = 'https://api.trello.com/1/members/me/boards?key=' + personal_key + '&token=' + personal_token
    response = simple_get(trello_url)
    trello_boards_as_json = json.loads(response)
    boards = dict()
    for trello_card in trello_boards_as_json:
        boards[trello_card['shortLink']] = trello_card['name']
    return boards

    # Raise an exception if we failed to get any data from the url
    raise Exception('Error retrieving contents at {}'.format(trello_url))

def get_trello_board_data(board_id, personal_key, personal_token):
    """Get all data for one trello board of user

    Parameters:
        board_id (string): The id of a board as trello saving it.
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        trello_board_as_json (json): Return the id and the name of the trello board in a json
        Or raising an error if http is failing

    """
    trello_url = 'https://api.trello.com/1/boards/' + board_id + '?fields=name,url&key=' + personal_key + '&token=' + personal_token
    response = simple_get(trello_url)
    trello_board_as_json = json.loads(response)
    return trello_board_as_json

    # Raise an exception if we failed to get any data from the url
    raise Exception('Error retrieving contents at {}'.format(trello_url))

def get_trello_board_cards_data(board_id, members_names, my_team, list_names, personal_key, personal_token):
    """Get all relevant data from trello board cards

    Parameters:
        board_id (string): The id of a board as trello saving it.
        members_names (dict): All the members names of the board,
                              member id as a key and member name as a value. F.e. {'TxCogm4e0rI': 'Tomer'}
        my_team (array): The names of the relevant trello members to look if they assigned to card.
        list_names (dict): All the list (columns) of the board,
                           column id as a key and column name as a value. F.e. {'To19302Do': 'To Do'}
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        sorted_array_of_parsed_cards (array): Return array of meaningful data of cards:
                                              members, name, url, column.
                                              sorted by column value
        Or raising an error if http is failing
    """
    array_of_parsed_cards = list()
    trello_url = 'https://api.trello.com/1/boards/' + board_id + '/cards?key=' + personal_key + '&token=' + personal_token
    response = simple_get(trello_url)
    # make it valid JSON
    trello_cards_as_json = json.loads(response)
    for trello_card in trello_cards_as_json:
        parsed_card = {}
        parsed_card['members'] = list()
        is_team_card = False
        for members_id in trello_card['idMembers']:
            if members_names[members_id] in my_team:
                is_team_card = True
                parsed_card['members'].append(members_names[members_id])
        if (not is_team_card):
            continue
        parsed_card['column'] = list_names[trello_card['idList']]
        parsed_card['name'] = trello_card['name']
        parsed_card['url'] = trello_card['url']
        array_of_parsed_cards.append(parsed_card)
    sorted_array_of_parsed_cards = sorted(array_of_parsed_cards, key=lambda k: k['column'])
    return sorted_array_of_parsed_cards

    # Raise an exception if we failed to get any data from the url
    raise Exception('Error retrieving contents at {}'.format(trello_url))

def get_trello_board_lists_data(board_id, personal_key, personal_token):
    """Get all lists of one trello board

    Parameters:
        board_id (string): The id of a board as trello saving it.
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        list_names (dict): Return dictionary of columns.
                           Column id as a key and column name as a value. F.e. {'To19302Do': 'To Do'}
        Or raising an error if http is failing
    """
    list_names = {}
    trello_url = 'https://api.trello.com/1/boards/' + board_id + '/lists?key=' + personal_key + '&token=' + personal_token
    response = simple_get(trello_url)
     # make it valid JSON
    trello_lists_as_json = json.loads(response)
    for trello_list in trello_lists_as_json:
        list_names[trello_list['id']] = trello_list['name']
    return list_names

    # Raise an exception if we failed to get any data from the url
    raise Exception('Error retrieving contents at {}'.format(trello_url))

def get_trello_board_members_data(board_id, personal_key, personal_token):
    """Get all members of one trello board

    Parameters:
        board_id (string): The id of a board as trello saving it.
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        members_names (dict): Return dictionary of members.
                           Member id as a key and member name as a value. F.e. {'TxCogm4e0rI': 'Tomer'}
        Or raising an error if http is failing
    """
    members_names = {}
    trello_url = 'https://api.trello.com/1/boards/' + board_id + '/members?key=' + personal_key + '&token=' + personal_token
    response = simple_get(trello_url)
     # make it valid JSON
    trello_members_as_json = json.loads(response)
    for trello_member in trello_members_as_json:
        members_names[trello_member['id']] = trello_member['fullName']
    return members_names

    # Raise an exception if we failed to get any data from the url
    raise Exception('Error retrieving contents at {}'.format(trello_url))

def get_trello_data(boards, team, remove_column_flag, personal_key, personal_token):
    """Get all relevant data of trello and export it into xlsx file

    Parameters:
        boards (array): All id's of relevant trello boards.
        team (array): The names of the relevant trello members to look if they assigned to card.
        personal_key (string): Personal developer API key of trello user.
        personal_token (string): Generated Token of trello user.

    Returns:
        all_trello_data (dict): Return dictionary of trello board data.
                                Trello board name as a key and Trello board data as a value.
                                F.e. {'New Board': [
                                                    {
                                                       members: ['Tomer1', 'Meitale2']
                                                       column: 'Done'
                                                       url: 'https://trello.com/b/Great2Work/565-make-life'
                                                       name: 'make life'
                                                    }]}
        Or raising an error if http is failing
    """
    members_names = {}
    list_names = {}
    workbook = open_xlsx_file_and_return_workbook()
    worksheet = workbook.add_worksheet()

    all_trello_data = dict()
    row = 1
    for board_id in boards:
        trello_board_name = get_trello_board_data(board_id, personal_key, personal_token)['name']
        members_names = get_trello_board_members_data(board_id, personal_key, personal_token)
        list_names = get_trello_board_lists_data(board_id, personal_key, personal_token)
        one_board_trello_data = get_trello_board_cards_data(board_id, members_names, team, list_names, personal_key, personal_token)
        if not one_board_trello_data:
            return
        all_trello_data[trello_board_name] = one_board_trello_data
        fieldnames = one_board_trello_data[0].keys
        if remove_column_flag:
            fieldnames.remove(remove_column_flag)
        options = {
            'merge_format': workbook.add_format({
                'bold': 1,
                'border': 1,
                'align': 'center',
                'valign': 'vcenter',
                'fg_color': 'gray',
                'font_color': 'white'}),
            'red': workbook.add_format({'bg_color': 'red'}),
            'green': workbook.add_format({'bg_color': 'green'}),
            'yellow': workbook.add_format({'bg_color': 'yellow'})
            }
        row = write_to_xlsx(worksheet, trello_board_name, fieldnames, one_board_trello_data, row, options)
    close_xlsx_file(workbook)
    return all_trello_data


import os
import time
import pandas as pd
import numpy as np

import tensorflow as tf
import tensorflow_hub as hub

def load_dataset(file_path, num_samples):
    df = pd.read_csv(file_path, usecols=[6, 9], nrows=num_samples)
    df.columns = ['rating', 'title']

    text = df['title'].tolist()
    text = [str(t).encode('ascii', 'replace') for t in text]
    text = np.array(text, dtype=object)[:]

    labels = df['rating'].tolist()
    labels = [1 if i>=4 else 0 if i==3 else -1 for i in labels]
    labels = np.array(pd.get_dummies(labels), dtype=int)[:]

    return labels, text
##https://tfhub.dev/google/tf2-preview/nnlm-en-dim50/1
##https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1

def get_model():
    strategy = tf.distribute.MirroredStrategy()
    with strategy.scope():
        hub_layer = hub.KerasLayer("https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1", output_shape=[128],
                               input_shape=[], dtype=tf.string, name='input', trainable=False)

        # model = tf.keras.Sequential()
        # model.add(hub_layer)
        # model.add(tf.keras.layers.Dense(64, activation='relu'))
        # model.add(tf.keras.layers.Dense(3, activation='softmax', name='output'))

        input_layer = tf.keras.layers.Input(shape=[], dtype=tf.string, name='input_layer')
        embedding = hub_layer(input_layer)
        x = tf.keras.layers.Dense(64, activation='relu')(embedding)
        x = tf.keras.layers.Dense(32, activation='relu')(x)
        output_layer = tf.keras.layers.Dense(3, activation='softmax', name='output')(x)
        model = tf.keras.Model(input_layer, output_layer, name='nnlm_model')

        model.compile(loss='categorical_crossentropy',
                      optimizer='Adam', metrics=['accuracy'])
    return model

def train(args):
    WORKING_DIR = os.getcwd() #use to specify model checkpoint path
    print("Loading training/validation data ...")
    y_train, x_train = load_dataset(args['train_data_path'], num_samples=100000)
    y_val, x_val = load_dataset(args['test_data_path'], num_samples=10000)

    print("Training the model ...")
    model = get_model()
    print(model.summary())
    model.fit(x_train, y_train, batch_size=32, epochs=args['epochs'], verbose=1,
              validation_data=(x_val, y_val),
              callbacks=[tf.keras.callbacks.ModelCheckpoint(os.path.join(WORKING_DIR,
                                                                         'model_checkpoint'),
                                                            monitor='val_loss', verbose=1,
                                                            save_best_only=True,
                                                            save_weights_only=False,
                                                            mode='auto')])

    path = os.path.join(args['output_dir'], str(int(time.time())))
    tf.saved_model.save(model, path)
    print("Exported trained model to {}".format(path))


import numpy as np
import sys,os

sims_per_job = 25

for i in xrange(8,10,1):

    a=\
       """#!/bin/bash
#SBATCH -J %d
#SBATCH --exclusive
#SBATCH -t 1-00:00
#SBATCH --nodes=32
#SBATCH --ntasks-per-node=16
######SBATCH --partition=general
#SBATCH --partition=preempt
#SBATCH --export=ALL
#######SBATCH --qos=double

module load intel
module load mvapich2_ib
module load gsl/2.1
module load gmp/6.0.0a
module load fftw/2.1.5
module load hdf5/1.8.14

IC_code=/simons/scratch/fvillaescusa/pdf_information/ICs_codes/n-genic_growth/N-GenIC
G3=/simons/scratch/fvillaescusa/Gadget-III_Quijote/g3_new_w/P-Gadget3

root="/simons/scratch/fvillaescusa/pdf_information/Snapshots/"
for cosmo in "w_p/" "w_m/"
do
   for i in {%d..%d}
   do
      folder=$root$cosmo$i
      cd $folder

      if [ ! -f "snapdir_004/snap_004.0.hdf5" ]
      then
         cd $folder"/ICs/"
         srun -n 16 --mpi=pmi2 $IC_code N-GenIC.param >> logIC
         cd ..
         srun -n 512 --mpi=pmi2 $G3 ../G3.param >> logfile
         rm -rf restartfiles
         mkdir extra_files/
         mv balance.txt cpu.txt energy.txt darkenergy.txt drift*.txt growth_*.dat ewald_*.dat free_largest_*.txt free_smallest_*.txt info.txt logfile logIC memory_largest_*.txt memory_smallest_*.txt parameters-usedvalues PIDs.txt processes_largest_*.txt processes_smallest_*.txt ps_file*.txt ps_largest_*.txt ps_smallest_*.txt Timebin.txt timings.txt extra_files/
      fi
   done
done
"""%(i, i*sims_per_job, (i+1)*sims_per_job)

    f = open('dumb_script.sh','w');  f.write(a);  f.close()
    os.system('sbatch dumb_script.sh');  os.system('rm dumb_script.sh')


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

from google.util.GoogleOauthUtil import GoogleOauthUtil
import pycurl, urllib.parse, json
from io import BytesIO

class GoogleAnalyticsUtil(GoogleOauthUtil):
    def getV3(self, params):
        query = urllib.parse.urlencode(params)
        buffer = BytesIO()
        c = pycurl.Curl()
        c.setopt(c.URL, 'https://www.googleapis.com/analytics/v3/data/ga?' + query)
        c.setopt(c.HTTPHEADER, ['Authorization: Bearer ' + self.oAuth.accessToken])
        c.setopt(c.WRITEDATA, buffer)
        c.perform()
        c.close()
        body = buffer.getvalue()
        return json.loads(body.decode('utf-8'))

    def getV4(self, params):
        post = json.dumps(params)
        buffer = BytesIO()
        c = pycurl.Curl()
        c.setopt(c.URL, 'https://analyticsreporting.googleapis.com/v4/reports:batchGet')
        c.setopt(c.HTTPHEADER, ['Content-Type: application/json', 'Authorization: Bearer ' + self.oAuth.accessToken])
        c.setopt(c.POSTFIELDS, post)
        c.setopt(c.WRITEDATA, buffer)
        c.perform()
        c.close()
        body = buffer.getvalue()
        return json.loads(body.decode('utf-8'))


import streamlit as st

# Custom Functions
import questions
import results
import homepage
import segmentation

def main():
    st.title('Groceries Survey Analysis')
    page = st.sidebar.selectbox("Please select a page:", ["Homepage", "Results"])
    responses_df, questions_df = load_data()

    if page == "Homepage":
        homepage.load_homepage()
    #elif page == "Questions":
     #   load_question_page(question_df)
    elif page == "Results":
        load_results_page(responses_df, questions_df)

@st.cache_data # Caches the data and only run it if it has not been seen before
def load_data():
    #DATA_PATH = os.path.join(pathlib.Path(__file__).parent.resolve(), "data")
    DATA_URL = "https://raw.githubusercontent.com/Ready-Set-Care/groceries-survey/main/Data/"

    GEN_POP_PATH = DATA_URL + "raw_gen_pop.csv"
    CAREGIVERS_PATH = DATA_URL + 'raw_caregivers.csv'

    gen_pop_df = results.prepare_data(GEN_POP_PATH)
    caregiver_responses_df = results.prepare_data(CAREGIVERS_PATH, caregivers=True)
    questions_df = questions.create_question_df()

    responses_df = results.combine_data(gen_pop_df, caregiver_responses_df)

    return responses_df, questions_df

def load_results_page(df, questions):

    col1, col2 = st.columns(2)
    with col1:
        selection = st.selectbox(
            "Segmentation:",
            ('Not Segmented', 'Caregiver Status', 'Gender', 'Annual Household Income', "Community Classification"))
    with col2:
        display_data = st.radio(
            "Select the data:",
            ("All", 'General Population', 'Caregivers')
        )

        if display_data == 'General Population':
            data = df.loc[df['Caregiver Status'] == 0]
        elif display_data == 'Caregivers':
            data = df.loc[df['Caregiver Status'] == 1]
        else:
            data = df

    count = data.shape[0]
    st.markdown(f"**Total Number of participants:** {count}")

    st.markdown(f'## Survey Results for {selection}')

    if selection == "Caregiver Status":
        segments = segmentation.get_segmentation("Caregiver Status", data)
        results.get_response_data(data, questions, segments)
    elif selection == 'Gender':
        segments = segmentation.get_segmentation("Gender", data)
        results.get_response_data(data, questions, segments, 'Variable: External: Q1: Gender')
    elif selection == "Community Classification":
        segments = segmentation.get_segmentation("Community Classification", data)
        results.get_response_data(data, questions, segments, "Variable: External: Q3: _ Urban/Rural (self-report)")
    elif selection == 'Annual Household Income':
        segments = segmentation.get_segmentation("Annual Household Income", data)
        results.get_response_data(data, questions, segments, "External Variable: Annual Household Income (US)")
    else:
        results.get_response_data(data, questions)

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
import src.funcoes as f

meus_cnae = f.readFile('input\cnae.txt')
print( 'QUANTIDADE DE CNAES LIDOS ',len(meus_cnae))
for cnae in meus_cnae:
    f.dados_cnae(cnae.rstrip('\n').split("-"))

    #ENvia PARA FUNÇÃO REALIZAR SCRAP


from flask import Flask, request, render_template, redirect, flash, session, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin, LoginManager, login_required, login_user, logout_user
from flask_marshmallow import Marshmallow

app = Flask(__name__)
app.secret_key = "secretkey"

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///Users.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
ma = Marshmallow(app)

class Users(db.Model):
    __tablename__="Users"
    username = db.Column(db.String(50),primary_key=True)
    userpsw = db.Column(db.String(50))
    user_fname = db.Column(db.String(50))
    user_lname = db.Column(db.String(50))

    def __init__(self,username, userpsw, user_fname, user_lname):
        self.username = username
        self.userpsw = userpsw
        self.user_fname = user_fname
        self.user_lname = user_lname

@app.route('/', methods=["GET","POST"])
def login():
    global username, userpsw
    if request.method == "GET":
        return render_template("login.html")

    if request.method == "POST":
        username= request.form['username']
        userpsw = request.form['userpsw']

        findUser = Users.query.filter_by(username=username, userpsw=userpsw).first()
        if findUser:
            session['name'] = username
            flash("Successfully Logged In")
            return redirect(url_for('index'))
        else:
            flash("Invalid Credentials")
            return redirect('/')

    return render_template("login.html")

@app.route('/register', methods=["GET","POST"])
def register():
    global reguname, regpsw, fname, lname
    if request.method == "GET":
        return render_template("registration.html")

    if request.method == "POST":
        username = request.form['reguname']
        regpsw = request.form['regpsw']
        fname = request.form['fname']
        lname = request.form['lname']

        checkUser = Users.query.filter_by(username=username).first()
        if checkUser:
            return redirect('/register')
        else:
            new_user = Users(reguname, regpsw, fname, lname)
            db.session.add(new_user)
            db.session.commit()
            return redirect('/register')

    return render_template("registration.html")

@app.route('/index')
def index():
    return render_template("index.html")

if __name__=="__main__":
    app.run(host="0.0.0.0", port=8080, debug=True)


import base64
import functools
import os

from django.conf import settings
from django.contrib.auth import login, logout
from django.core import signing
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import HttpResponseRedirect
from django.utils.encoding import force_bytes
from django.utils.http import is_safe_url
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _

from rest_framework import generics
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from waffle.decorators import waffle_switch

import olympia.core.logger
from olympia import amo
from olympia.access.models import GroupUser
from olympia.amo import messages
from olympia.amo.decorators import write
from olympia.api.authentication import (
    JWTKeyAuthentication, WebTokenAuthentication)
from olympia.api.permissions import GroupPermission
from olympia.users.models import UserProfile

from . import verify
from .serializers import AccountSuperCreateSerializer, UserProfileSerializer
from .utils import fxa_login_url, generate_fxa_state

log = olympia.core.logger.getLogger('accounts')

ERROR_AUTHENTICATED = 'authenticated'
ERROR_NO_CODE = 'no-code'
ERROR_NO_PROFILE = 'no-profile'
ERROR_NO_USER = 'no-user'
ERROR_STATE_MISMATCH = 'state-mismatch'
ERROR_STATUSES = {
    ERROR_AUTHENTICATED: 400,
    ERROR_NO_CODE: 422,
    ERROR_NO_PROFILE: 401,
    ERROR_STATE_MISMATCH: 400,
}
LOGIN_ERROR_MESSAGES = {
    ERROR_AUTHENTICATED: _(u'You are already logged in.'),
    ERROR_NO_CODE:
        _(u'Your login attempt could not be parsed. Please try again.'),
    ERROR_NO_PROFILE:
        _(u'Your Firefox Account could not be found. Please try again.'),
    ERROR_STATE_MISMATCH: _(u'You could not be logged in. Please try again.'),
}

API_TOKEN_COOKIE = 'api_auth_token'

def safe_redirect(url, action):
    if not is_safe_url(url):
        url = reverse('home')
    log.info(u'Redirecting after {} to: {}'.format(action, url))
    return HttpResponseRedirect(url)

def find_user(identity):
    """Try to find a user for a Firefox Accounts profile. If the account
    hasn't been migrated we'll need to do the lookup by email but we should
    use the ID after that so check both. If we get multiple users we're in
    some weird state where the accounts need to be merged but that behaviour
    hasn't been defined so let it raise.
    """
    try:
        return UserProfile.objects.get(
            Q(fxa_id=identity['uid']) | Q(email=identity['email']))
    except UserProfile.DoesNotExist:
        return None
    except UserProfile.MultipleObjectsReturned:
        # This shouldn't happen, so let it raise.
        log.error(
            'Found multiple users for {email} and {uid}'.format(**identity))
        raise

def register_user(request, identity):
    user = UserProfile.objects.create_user(
        email=identity['email'], username=None, fxa_id=identity['uid'])
    log.info('Created user {} from FxA'.format(user))
    login(request, user)
    return user

def update_user(user, identity):
    """Update a user's info from FxA if needed, as well as generating the id
    that is used as part of the session/api token generation."""
    if (user.fxa_id != identity['uid'] or
            user.email != identity['email']):
        log.info(
            'Updating user info from FxA for {pk}. Old {old_email} {old_uid} '
            'New {new_email} {new_uid}'.format(
                pk=user.pk, old_email=user.email, old_uid=user.fxa_id,
                new_email=identity['email'], new_uid=identity['uid']))
        user.update(fxa_id=identity['uid'], email=identity['email'])
    if user.auth_id is None:
        # If the user didn't have an auth id (old user account created before
        # we added the field), generate one for them.
        user.update(auth_id=UserProfile._meta.get_field('auth_id').default())

def login_user(request, user, identity):
    update_user(user, identity)
    log.info('Logging in user {} from FxA'.format(user))
    user.log_login_attempt(True)
    login(request, user)

def fxa_error_message(message):
    login_help_url = (
        'https://support.mozilla.org/kb/access-your-add-ons-firefox-accounts')
    return format_html(
        u'{error} {help_text}',
        url=login_help_url, help_text=_(u'Need help?'),
        error=message)

def render_error(request, error, next_path=None, format=None):
    if format == 'json':
        status = ERROR_STATUSES.get(error, 422)
        response = Response({'error': error}, status=status)
    else:
        if not is_safe_url(next_path):
            next_path = None
        messages.error(
            request, fxa_error_message(LOGIN_ERROR_MESSAGES[error]),
            extra_tags='fxa')
        if next_path is None:
            response = HttpResponseRedirect(reverse('users.login'))
        else:
            response = HttpResponseRedirect(next_path)
    return response

def parse_next_path(state_parts):
    next_path = None
    if len(state_parts) == 2:
        # The = signs will be stripped off so we need to add them back
        # but it only cares if there are too few so add 4 of them.
        encoded_path = state_parts[1] + '===='
        try:
            next_path = base64.urlsafe_b64decode(
                force_bytes(encoded_path)).decode('utf-8')
        except TypeError:
            log.info('Error decoding next_path {}'.format(
                encoded_path))
            pass
    if not is_safe_url(next_path):
        next_path = None
    return next_path

def with_user(format, config=None):

    def outer(fn):
        @functools.wraps(fn)
        @write
        def inner(self, request):
            if config is None:
                if hasattr(self, 'get_fxa_config'):
                    fxa_config = self.get_fxa_config(request)
                else:
                    fxa_config = (
                        settings.FXA_CONFIG[settings.DEFAULT_FXA_CONFIG_NAME])
            else:
                fxa_config = config

            if request.method == 'GET':
                data = request.query_params
            else:
                data = request.data

            state_parts = data.get('state', '').split(':', 1)
            state = state_parts[0]
            next_path = parse_next_path(state_parts)
            if not data.get('code'):
                log.info('No code provided.')
                return render_error(
                    request, ERROR_NO_CODE, next_path=next_path, format=format)
            elif (not request.session.get('fxa_state') or
                    request.session['fxa_state'] != state):
                log.info(
                    'State mismatch. URL: {url} Session: {session}'.format(
                        url=data.get('state'),
                        session=request.session.get('fxa_state'),
                    ))
                return render_error(
                    request, ERROR_STATE_MISMATCH, next_path=next_path,
                    format=format)
            elif request.user.is_authenticated():
                response = render_error(
                    request, ERROR_AUTHENTICATED, next_path=next_path,
                    format=format)
                # If the api token cookie is missing but we're still
                # authenticated using the session, add it back.
                if API_TOKEN_COOKIE not in request.COOKIES:
                    log.info('User %s was already authenticated but did not '
                             'have an API token cookie, adding one.',
                             request.user.pk)
                    response = add_api_token_to_response(
                        response, request.user)
                return response
            try:
                identity = verify.fxa_identify(data['code'], config=fxa_config)
            except verify.IdentificationError:
                log.info('Profile not found. Code: {}'.format(data['code']))
                return render_error(
                    request, ERROR_NO_PROFILE, next_path=next_path,
                    format=format)
            else:
                return fn(
                    self, request, user=find_user(identity), identity=identity,
                    next_path=next_path)
        return inner
    return outer

def generate_api_token(user):
    """Generate a new API token for a given user."""
    data = {
        'auth_hash': user.get_session_auth_hash(),
        'user_id': user.pk,
    }
    return signing.dumps(data, salt=WebTokenAuthentication.salt)

def add_api_token_to_response(response, user):
    """Generate API token and add it to the response (both as a `token` key in
    the response if it was json and by setting a cookie named API_TOKEN_COOKIE.
    """
    token = generate_api_token(user)
    if hasattr(response, 'data'):
        response.data['token'] = token
    # Also include the API token in a session cookie, so that it is
    # available for universal frontend apps.
    response.set_cookie(
        API_TOKEN_COOKIE,
        token,
        max_age=settings.SESSION_COOKIE_AGE,
        secure=settings.SESSION_COOKIE_SECURE,
        httponly=settings.SESSION_COOKIE_HTTPONLY)

    return response

def remove_api_token_cookie(response):
    """Delete the api token cookie."""
    response.delete_cookie(API_TOKEN_COOKIE)

class FxAConfigMixin(object):

    def get_config_name(self, request):
        return request.GET.get('config', self.DEFAULT_FXA_CONFIG_NAME)

    def get_allowed_configs(self):
        return getattr(
            self, 'ALLOWED_FXA_CONFIGS', [self.DEFAULT_FXA_CONFIG_NAME])

    def get_fxa_config(self, request):
        config_name = self.get_config_name(request)
        if config_name in self.get_allowed_configs():
            return settings.FXA_CONFIG[config_name]
        log.info('Using default FxA config instead of {}'.format(config_name))
        return settings.FXA_CONFIG[self.DEFAULT_FXA_CONFIG_NAME]

class LoginStartBaseView(FxAConfigMixin, APIView):

    def get(self, request):
        request.session.setdefault('fxa_state', generate_fxa_state())
        return HttpResponseRedirect(
            fxa_login_url(
                config=self.get_fxa_config(request),
                state=request.session['fxa_state'],
                next_path=request.GET.get('to'),
                action=request.GET.get('action', 'signin')))

class LoginStartView(LoginStartBaseView):
    DEFAULT_FXA_CONFIG_NAME = settings.DEFAULT_FXA_CONFIG_NAME
    ALLOWED_FXA_CONFIGS = settings.ALLOWED_FXA_CONFIGS

class LoginBaseView(FxAConfigMixin, APIView):

    @with_user(format='json')
    def post(self, request, user, identity, next_path):
        if user is None:
            return Response({'error': ERROR_NO_USER}, status=422)
        else:
            update_user(user, identity)
            response = Response({'email': identity['email']})
            add_api_token_to_response(response, user)
            log.info('Logging in user {} from FxA'.format(user))
            return response

    def options(self, request):
        return Response()

class LoginView(LoginBaseView):
    DEFAULT_FXA_CONFIG_NAME = settings.DEFAULT_FXA_CONFIG_NAME
    ALLOWED_FXA_CONFIGS = settings.ALLOWED_FXA_CONFIGS

class RegisterView(APIView):
    authentication_classes = (SessionAuthentication,)

    @with_user(format='json')
    def post(self, request, user, identity, next_path):
        if user is not None:
            return Response({'error': 'That account already exists.'},
                            status=422)
        else:
            user = register_user(request, identity)
            response = Response({'email': user.email})
            add_api_token_to_response(response, user)
            return response

class AuthenticateView(FxAConfigMixin, APIView):
    DEFAULT_FXA_CONFIG_NAME = settings.DEFAULT_FXA_CONFIG_NAME
    ALLOWED_FXA_CONFIGS = settings.ALLOWED_FXA_CONFIGS

    authentication_classes = (SessionAuthentication,)

    @with_user(format='html')
    def get(self, request, user, identity, next_path):
        if user is None:
            user = register_user(request, identity)
            fxa_config = self.get_fxa_config(request)
            if fxa_config.get('skip_register_redirect'):
                response = safe_redirect(next_path, 'register')
            else:
                response = safe_redirect(reverse('users.edit'), 'register')
        else:
            login_user(request, user, identity)
            response = safe_redirect(next_path, 'login')
        add_api_token_to_response(response, user)
        return response

def logout_user(request, response):
    logout(request)
    remove_api_token_cookie(response)

class SessionView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request, *args, **kwargs):
        response = Response({'ok': True})
        logout_user(request, response)
        return response

class ProfileView(generics.RetrieveAPIView):
    authentication_classes = [JWTKeyAuthentication]
    permission_classes = [IsAuthenticated]
    serializer_class = UserProfileSerializer

    def retrieve(self, request, *args, **kw):
        return Response(self.get_serializer(request.user).data)

class AccountSuperCreate(APIView):
    authentication_classes = [JWTKeyAuthentication]
    permission_classes = [
        IsAuthenticated,
        GroupPermission(amo.permissions.ACCOUNTS_SUPER_CREATE)]

    @waffle_switch('super-create-accounts')
    def post(self, request):
        serializer = AccountSuperCreateSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'errors': serializer.errors},
                            status=422)

        data = serializer.data

        group = serializer.validated_data.get('group', None)
        user_token = os.urandom(4).encode('hex')
        username = data.get('username', 'super-created-{}'.format(user_token))
        fxa_id = data.get('fxa_id', None)
        email = data.get('email', '{}@addons.mozilla.org'.format(username))

        user = UserProfile.objects.create(
            username=username,
            email=email,
            fxa_id=fxa_id,
            display_name='Super Created {}'.format(user_token),
            is_verified=True,
            notes='auto-generated from API')
        user.save()

        if group:
            GroupUser.objects.create(user=user, group=group)

        login(request, user)
        request.session.save()

        log.info(u'API user {api_user} created and logged in a user from '
                 u'the super-create API: user_id: {user.pk}; '
                 u'user_name: {user.username}; fxa_id: {user.fxa_id}; '
                 u'group: {group}'
                 .format(user=user, api_user=request.user, group=group))

        cookie = {
            'name': settings.SESSION_COOKIE_NAME,
            'value': request.session.session_key,
        }
        cookie['encoded'] = '{name}={value}'.format(**cookie)

        return Response({
            'user_id': user.pk,
            'username': user.username,
            'email': user.email,
            'display_name': user.display_name,
            'groups': list((g.pk, g.name, g.rules) for g in user.groups.all()),
            'fxa_id': user.fxa_id,
            'session_cookie': cookie,
        }, status=201)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 14 12:21:18 2018

@author: timothy
"""
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
from scipy import stats
from sklearn import linear_model
from sklearn.decomposition import PCA
from sklearn.metrics import mean_squared_error
from sklearn.pipeline import Pipeline
import statsmodels.formula.api as sm
from tabulate import tabulate

def linear_func(x, m, b):
    return m*x + b

def sigmoid_func(x, k, x0, A):

    return A / (1 + np.exp(-k*(x-x0)))

class RegressionModel():
    def __init__(self, feature_object):
        self.features = feature_object.encoded_features
        self.dependent_variable = feature_object.dependent_variable
        self.independent_variables = feature_object.continuous_independent_variables
        self.X_train = feature_object.training_features()[self.independent_variables]
        self.y_train = feature_object.training_features()[self.dependent_variable]
        self.X_test = feature_object.standardized_features()[self.independent_variables]
        self.y_test = feature_object.standardized_features()[self.dependent_variable]
        self.question_choices = feature_object.question_choices()
        self.encoders = feature_object.encoders()
        self.simulating_features = feature_object.simulating_features()
        self.question_stats = feature_object.independent_variable_stats()
        self.trained_model = self.trained_pipeline()
        self.y_pred = self.prediction()

    def trained_pipeline(self):
        ols = sm.GLS(self.y_train, self.X_train)
        model = ols.fit(maxiter=1000)
        return model

    def prediction(self):

        print(self.trained_model.predict(self.X_train))
        return self.trained_model.predict(self.X_test)

    def visualize_fit(self):

        fig, ax = plt.subplots()
        predicted = self.y_pred
        ax.scatter(self.y_test, predicted, edgecolors=(0, 0, 0))
        ax.plot([self.y_test.min(), self.y_test.max()],
                 [self.y_test.min(), self.y_test.max()], 'k--', lw=4)
        ax.set_xlabel('Measured')
        ax.set_ylabel('Predicted')

        return ax

    def visualize_goodness(self):
        fit_df = pd.DataFrame({'truth':self.y_test,
                               'prediction': self.y_pred})
        num_ticks = len(self.question_choices[self.dependent_variable])
        fig, ax = plt.subplots()
        for i, choice in enumerate(self.question_choices[self.dependent_variable]):
            encoded_choice = self.encoders[self.dependent_variable].transform([choice])[0]
            temp = fit_df[fit_df['truth'] == encoded_choice]['prediction'].copy()
            if temp.empty:
                pass
            else:
                n, bins, patches =\
                    plt.hist(temp, np.linspace(0,num_ticks -1 ,5*num_ticks),
                             density=False, alpha=0.5, label = choice)
        plt.xticks(np.linspace(0,num_ticks -1, num_ticks),
                   self.question_choices[self.dependent_variable],
                   rotation = 45)
        plt.legend(loc = 0)
        return ax
    def simulate_outcomes(self, independent_variable):

        outcome_range =\
            np.sort(self.y_test.unique())
        idx = self.independent_variables.index(independent_variable)

        simulation_df = self.simulating_features
        standard_features = [
            feat+'_std' for feat in self.independent_variables
        ]
        simulation_df['prediction'] = (
            self.trained_model
            .predict(simulation_df[standard_features])
        )

        indep_vals = (
            simulation_df
            .groupby(
                [independent_variable+'_val',
                 independent_variable]
            )['prediction']
            .mean().reset_index()
        ).sort_values(by=independent_variable)
        response_range = (
            indep_vals[independent_variable].tolist()
        )

        predictions = (
            indep_vals['prediction'].tolist()
        )
        question_choices = (
            indep_vals[independent_variable+'_val'].tolist()
        )
        fig, ax = plt.subplots()
        ax.scatter(response_range, predictions)
        popt, pcov = curve_fit(linear_func, response_range, predictions)
        slope = popt[0]
        intercept = popt[1]
        if intercept > 0:
             title = independent_variable + ": y =" + str(round(slope,3)) +\
                     "x +" + str(round(intercept,2))
        elif intercept > 0:
             title = independent_variable + ": y =" + str(round(slope,3)) +\
                     "x -" + str(-1*round(intercept,2))
        else:
             title = independent_variable + ": y =" + str(round(slope,3)) + "x"
        #print(ticks[indep_var])

        #ax.scatter(response_range, linear_func(response_range, slope, intercept))
        ax.plot(
            response_range,
            [linear_func(resp, slope, intercept) for resp in response_range]
        )
        #ax.set_xlabel('Varied '+indep_var)
        ax.set_ylabel('Prediction')
        ax.set_yticks(np.sort(outcome_range))
        ax.set_yticklabels([str(outcome)+' ' + choice for outcome, choice in
                            zip(outcome_range, self.question_choices[self.dependent_variable])])
        ax.set_xticks(np.sort(response_range))
        ax.set_xticklabels(self.question_choices[independent_variable], rotation=90)
        ax.set_title(title)
        return ax

    def print_results(self):

        print(self.trained_model.summary())

class MixedClassificationModel():
    def __init__(self, feature_object):
        self.features = feature_object.encoded_features
        self.dependent_variable = feature_object.dependent_variable
        self.independent_variables = feature_object.independent_variables
        self.continuous_independent_variables  = feature_object.continuous_independent_variables
        self.dummies = feature_object.dummies
        self.standardized_features = feature_object.standardized_features()
        self.training_features = feature_object.training_features()
        self.balanced = self.balance_training()
        self.X_train = self.balanced[self.independent_variables]
        self.y_train = self.balanced['outcome']
        self.X_test = self.standardized_features[self.independent_variables]
        self.y_test = self.standardized_features['outcome']
        self.question_choices = feature_object.question_choices()
        self.encoders = feature_object.encoders()
        self.simulating_features = feature_object.simulating_features()
        self.question_stats = feature_object.independent_variable_stats()
        self.trained_model = self.trained_pipeline()
        self.y_pred = self.prediction()

    def balance_training(self):

        pos_samples = len(self.training_features\
         [self.training_features['outcome'] == 1])

        neg_samples = len(self.training_features\
         [self.training_features['outcome'] == 0])

        sample_size = min(pos_samples, neg_samples)
        balanced =\
            pd.concat([self.training_features
                        [self.training_features['outcome'] == 0]
                        .sample(n=sample_size),
                       self.training_features
                        [self.training_features['outcome'] == 1]
                        .sample(n=sample_size)
                      ])
        return balanced

    def trained_pipeline(self):
        np.random.seed(44)
        log_reg = sm.Logit(self.y_train, self.X_train)
        param_array = np.zeros(len(self.independent_variables)+1)
        iterations = 5
        for i in range(0,iterations):
            model = log_reg.fit(
                maxiter=5000,
                avextol=.0001,
                epsilon=.1,
                full_output=1,
                disp=0
            )
            params = list(model.params)
            param_array = [
                a + b for a,b in zip(param_array,params)
            ]
        start = [p/iterations for p in param_array]
        model = log_reg.fit(
            start_params=start,
            maxiter=5000,
            avextol=.0001,
            epsilon=.1,
            full_output=1,
            disp=1
        )
        return model

    def prediction(self):
        return self.trained_model.predict(self.X_test)

    def visualize_fit(self):

        fig, ax = plt.subplots()
        ax.scatter(self.y_test, self.y_pred, edgecolors=(0, 0, 0), alpha = .2)

        ax.set_xlabel('Measured')
        ax.set_ylabel('Predicted')

        return ax

    def visualize_goodness(self):
        fit_df = pd.DataFrame({'truth':self.y_test,
                               'prediction': [prob_a for prob_a in
                                              self.y_pred]})
        num_ticks = 2
        outcome_labels = ['negative', 'positive']
        outcome_choices = [0, 1]
        fig, ax = plt.subplots()
        for i, choice in enumerate(outcome_labels):
            encoded_choice = outcome_choices[i]
            temp = fit_df[fit_df['truth'] == encoded_choice]['prediction'].copy()
            if temp.empty:
                pass
            else:
                n, bins, patches =\
                    plt.hist(temp, np.linspace(0,num_ticks -1 ,5*num_ticks),
                             density=False, alpha=0.5, label = choice)
        plt.xticks(np.linspace(0,num_ticks -1, num_ticks),
                   outcome_labels,
                   rotation = 45)
        plt.legend(loc = 0)
        return ax

    def simulate_continuous_outcomes(self, independent_variable):
        outcome_labels = ['negative', 'positive']
        outcome_choices = [0, 1]
        simulation_df = (
            self.simulating_features
            .sort_values(by=independent_variable)
            .reset_index()
        )
        standard_features = [
            feat+'_std' for feat in self.independent_variables
        ]
        simulation_df['prediction'] = (
            self.trained_model
            .predict(simulation_df[standard_features])
        )

        indep_vals = (
            simulation_df
            .groupby(
                [independent_variable+'_val',
                 independent_variable]
            )['prediction']
            .mean().reset_index()
        ).sort_values(by=independent_variable)
        response_range = (
            indep_vals[independent_variable].tolist()
        )
        predictions = (
            indep_vals['prediction'].tolist()
        )
        question_choices = (
            indep_vals[independent_variable+'_val'].tolist()
        )
        return {
            "response_range":response_range,
            "predictions": predictions,
            "question_choices": question_choices
        }

    def plot_simulations(self, independent_variable):
        outcome_labels = ['negative', 'positive']
        outcome_choices = [0, 1]
        sim_dict = self.simulate_continuous_outcomes(independent_variable)
        response_range = sim_dict['response_range']
        predictions = sim_dict['predictions']
        question_choices = sim_dict['question_choices']
        fig, ax = plt.subplots()
        ax.scatter(response_range, predictions)
        x0_start = np.mean(response_range)
        A_start = 1
        try:
            k_start = .5
            popt, pcov =\
                 curve_fit(sigmoid_func, response_range,
                           predictions, p0 = [k_start, x0_start, A_start],
                           maxfev=1000)
            k = popt[0]
            x0 = popt[1]
            A = popt[2]
        except RuntimeError:
            try:
                k_start = -.5
                popt, pcov =\
                     curve_fit(sigmoid_func, response_range,
                               predictions, p0 = [k_start, x0_start, A_start],
                               maxfev=2000)
                k = popt[0]
                x0 = popt[1]
                A = popt[2]
            except RuntimeError:
                try:
                    k_start = 0
                    A_start = .5
                    popt, pcov =\
                    curve_fit(sigmoid_func, response_range,
                              predictions, p0 = [k_start, x0_start, A_start],
                              maxfev=2000)
                    k = popt[0]
                    x0 = popt[1]
                    A = popt[2]
                except RuntimeError:
                    k = 0
                    x0 = 0
                    A = 1

        title = (independent_variable + "p(Positive|x) ="+str(round(A,2))+
            "/(1+exp(-"+str(round(k,2))+ "(x +"+ str(round(x0,2))+")))"
        )
        ax.plot(
            response_range,
            [sigmoid_func(resp, k, x0, A) for resp in response_range]
        )
        #ax.set_xlabel('Varied '+indep_var)
        ax.set_ylabel('Prediction')
        ax.set_yticks(np.sort(outcome_choices))
        ax.set_yticklabels([str(outcome)+' ' + choice for outcome, choice in
                            zip(outcome_choices, outcome_labels)])
        ax.set_xticks(np.sort(response_range))
        ax.set_xticklabels(question_choices, rotation=90)
        ax.set_title(title)
        return ax

    def simulate_binary_outcomes(self, independent_variable):
        outcome_labels = ['negative', 'positive']
        outcome_choices = [0, 1]

        simulation_df = (
            self.simulating_features
            .sort_values(by=independent_variable)
            .reset_index()
        )
        standard_features = [
            feat+'_std' for feat in self.independent_variables
        ]
        simulation_df['prediction'] = (
            self.trained_model
            .predict(simulation_df[standard_features])
        )

        indep_vals = (
            simulation_df
            .groupby(
                [independent_variable+'_val',
                 independent_variable]
            )['prediction']
            .mean().reset_index()
        ).sort_values(by=independent_variable)
        #print(indep_vals)
        response_range = (
            indep_vals[independent_variable].tolist()
        )
        predictions = (
            indep_vals['prediction'].tolist()
        )

        fig, ax = plt.subplots()
        ax.scatter(response_range, predictions)
        #ax.set_xlabel('Varied '+indep_var)
        ax.set_ylabel('Prediction')
        ax.set_yticks(np.sort(outcome_choices))
        ax.set_yticklabels([str(outcome)+' ' + choice for outcome, choice in
                            zip(outcome_choices, outcome_labels)])
        ax.set_xticks(np.sort(response_range))
        ax.set_xticklabels(['no','yes'], rotation=90)
        ax.set_title(independent_variable)
        return ax

    def print_results(self):

        print(self.trained_model.summary())

    def result_df(self):
        return self.trained_model.pvalues

    def odds_ratio(self):
        odds_increase = [
            int(round(100*(np.exp(param) - 1),0))
            for param in self.trained_model.params
        ]
        odds_ratio_table = pd.DataFrame(
            {'independent_variable':self.independent_variables,
             'odds_%_increase': odds_increase
            }
        )
        odds_ratio_table['mu'] = odds_ratio_table.apply(
            lambda row:
            round(self.question_stats[row['independent_variable']]['mu'], 2),
            axis=1
        )
        odds_ratio_table['std'] = odds_ratio_table.apply(
            lambda row:
            round(self.question_stats[row['independent_variable']]['std'],2),
            axis=1
        )
        #odds_ratio_table.to_string(index=False))
        return odds_ratio_table
        #print(np.exp(self.trained_model.params))


import logging, os, random

log = logging.getLogger(__name__)

APP_ROOT = os.path.abspath(os.path.join(__file__, "..", "..", ".."))
VERSION_FILE = os.path.join(APP_ROOT, "VERSION_TOKEN")

if os.path.exists(VERSION_FILE):
    VERSION_TOKEN = open(VERSION_FILE).read().strip()
else:
    VERSION_TOKEN = random.random()
log.info("USING NEW STATIC RESOURCE TOKEN: %s", VERSION_TOKEN)

from dogpile.cache import make_region

class Globals(object):
    mailConfig = {"mail.on":True,"mail.transport":"smtp", "mail.smtp.tls":True}
    def __init__ (self, **settings):
        self.is_debug = settings.get('pyramid.debug_templates', 'false') == 'true'
        self.VERSION_TOKEN = "v={}".format(VERSION_TOKEN)
        self.cache = make_region().configure_from_config(settings, "cache.")


import pygame
import cv2
import numpy as np

video=cv2.VideoCapture(0)

faceDetect=cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

pygame.init()

window=pygame.display.set_mode((1400,1500))

pygame.display.set_caption("Face Detection App")

img=pygame.image.load("cat.jpeg").convert()

start=True
while start:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            start=False
            pygame.quit()

    ret,frame=video.read()
    gray=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces=faceDetect.detectMultiScale(frame,1.3,5)
    for(x,y,w,h) in faces:
        x1,y1=x+w,y+h
        cv2.rectangle(frame,(x,y),(x+w,y+h),(50,50,255),1)
        cv2.line(frame,(x,y),(x+30,y),(0,0,255),6)
        cv2.line(frame,(x,y),(x,y+30),(0,0,255),6)

        cv2.line(frame,(x1,y),(x1-30,y),(0,0,255),6)
        cv2.line(frame,(x1,y),(x1,y+30),(0,0,255),6)

        cv2.line(frame,(x,y1),(x+30,y1),(0,0,255),6)
        cv2.line(frame,(x,y1),(x,y1-30),(0,0,255),6)

        cv2.line(frame,(x1,y1),(x1-30,y1),(0,0,255),6)
        cv2.line(frame,(x1,y1),(x1,y1-30),(0,0,255),6)

    imgRGB=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    imgRGB=np.rot90(imgRGB)
    imgRGB=pygame.surfarray.make_surface(imgRGB).convert()

    font=pygame.font.Font(None,50)
    text=font.render("Face Detection :  {} Face Detected".format(len(faces)),True,(255,255,255))

    window.blit(img,(0,0))
    window.blit(imgRGB,(70,70))

    pygame.draw.rect(window,(144,238,144),(100,30,1200,50),border_top_left_radius=10, border_top_right_radius=10)
    pygame.draw.rect(window,(144,238,144),(100,800,1200,50),border_bottom_left_radius=10,border_bottom_right_radius=10)
    window.blit(text,(320,50))
    pygame.display.update()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from scipy import stats
s1=pd.Series([1,2,4,5,6,7,8,7])
mu, sigma = stats.norm.fit(s1)  #mean, standard deviation
ax=sns.distplot(s1, kde=False, fit=stats.norm)
plt.title="Check against normal distribution"
plt.legend("normal ($\mu=${0:.2g}, $\sigma=${1:.2f})".format(mu, sigma))
ax.legend("normal ($\mu=${0:.2g}, $\sigma=${1:.2f})".format(mu, sigma))
plt.ylabel("frequency")
plt.xlabel("observation")

s1=np.fromiter( [np.sin(x/10) for x in range(0, 300)], np.float)
s2=np.fromiter( [np.sin(x/5 + 50) for x in range(0, 300)], np.float)

g=sns.regplot(x=s1, y=s2,  color="m")
g.figure.show()

import pandas as pd
s1 = pd.Series([np.random.randint(0,100) for x in range(100)])
boxplot=s1.plot.box()
x=1


from flask import Flask
import pandas as pd
import numpy as np
from flask import request
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity

app = Flask(__name__)

def create_soup(x):
    return x['task_title'] + ' ' + x['difficulty_level'] + ' '+x['task_handler'] + ' ' + x['t1']

def test_deploy(predictionTask):
    task = pd.read_csv('./software_task_updated.csv',
                       encoding="ISO-8859-1", engine='python')
    employees = pd.read_csv(
        './employee.csv',  encoding="ISO-8859-1", engine='python')
    task['soup'] = task.apply(create_soup, axis=1)
    task[['soup']]
    count = CountVectorizer(stop_words='english')
    count_matrix = count.fit_transform(task['soup'])
    cosine_sim2 = cosine_similarity(count_matrix, count_matrix)
    task = task.reset_index()
    indices = pd.Series(task.index, index=task['task_title'])

    def get_recommendations(task_title, cosine_sim=cosine_sim2):
        # Get the index of the movie that matches the title
        #     print(task_title)
        try :
            idx = indices[task_title]

            # Get the pairwsie similarity scores of all movies with that movie
            sim_scores = list(enumerate(cosine_sim[idx]))

            #     # Sort the movies based on the similarity scores
            sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
            #     sim_scores = sorted(sim_scores, reverse=True)

            #     # Get the scores of the 10 most similar movies
            sim_scores = sim_scores[1:11]
            #     # Get the movie indices
            task_indices = [i[0] for i in sim_scores]

            #     # Return the top 10 most similar movies
            return task['task_handler'].iloc[task_indices]

        except:
            return False

    pred_task = predictionTask
    predicted_Category = get_recommendations(pred_task, cosine_sim2)
    if type(predicted_Category) == bool:
        return {'status': 'false', 'message': 'null'}
    # yaha check lagana
    predicted_Category = predicted_Category.values[0]
    # return predicted_Category
    # if predicted Category not found

    def map_function(x):

        if x == 'Advanced':
            return 3
        elif x == 'Intermediate':
            return 2
        elif x == 'Beginner':
            return 1

    employees['expertise_level'] = employees['expertise_level'].apply(
        map_function)

    def getEmployee(taskCategory):
        indexes = []
        for idx, employee in enumerate(employees['employee_type']):
            if taskCategory in employee:
                if employees['available'][idx] == 'Yes':
                    indexes.append(idx)
        return indexes

    filteredDF = employees.filter(
        items=getEmployee(predicted_Category), axis=0)
    sortedDF = filteredDF.sort_values(
        by=['years_of_experience', 'expertise_level'], inplace=False, ascending=False)

    d = dict(enumerate(sortedDF.values[0].flatten(), 1))
    return {'status': 'true', 'message': d}

@app.route("/", methods=['GET'])
def hello_world():
    predictionTask = request.args.get('predictionTask')
    # return result
    return test_deploy(predictionTask)


# 3. Scrieti un decorator care primeste ca argument
# numele unui fisier si pentru orice functie apelata,
# el va scrie in acel fisier numele functiei,
# lista de argumente ca si string
# si rezultatul apelului.
# Fisierul este de tip csv.
# Functiile decorate pot primi oricate argumente
import csv
import functools

def write_log_in_file(filename):
    def log_message(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            func_name = f'{func.__name__}'
            func_args = f'{args, kwargs}'
            func_run = f'{func(*args, **kwargs)}'
            with open(filename, 'a', newline='') as f:
                writer = csv.writer(f)
                writer.writerow([func_name, func_args, func_run])

        return wrapper

    return log_message

@write_log_in_file('test.csv')
def a_function_that_returns_a_string():
    return 'a string'

@write_log_in_file('test.csv')
def sum_of_two_numbers(x, y):
    addition = x + y
    return addition

@write_log_in_file('test.csv')
def all_n_numbers(n):
    empty = []
    for i in range(1, n):
        empty.append(i)
    return empty

a_function_that_returns_a_string()
sum_of_two_numbers(x=7, y=9)
all_n_numbers(18)


import random
from typing import List, Tuple, Any

from jass.agents.agent import Agent
from jass.logic.card import Card, Suit
from jass.logic.deck import Deck
from jass.logic.exceptions import GameOver
from jass.logic.player import Player
from jass.logic.trick import Trick

GOAL = 1000

class Team:
    def __init__(self, player1: Player, player2: Player):
        self.player1 = player1
        self.player2 = player2
        self.score = 0

    @property
    def players(self) -> List[Player]:
        return [self.player1, self.player2]

    def __contains__(self, player: Player):
        return self.player1 == player or self.player2 == player

class Game:
    def __init__(self, agents: List[Agent], names: List[str] = None, log_fn=None, goal=GOAL):
        assert len(agents) == 4, 'It is a 4 players game, need 4 agents'
        if names is None:
            names = [f'{a.__class__.__name__}{random.randint(1e6, 1e7 - 1)}' for a in agents]
        assert len(set(names)) == 4, 'It is a 4 players game, need 4 unique names'

        self.__players = [Player(name, agent) for name, agent in zip(names, agents)]
        team1 = Team(
            player1=self.__players[0],
            player2=self.__players[2],
        )
        team2 = Team(
            player1=self.__players[1],
            player2=self.__players[3],
        )
        self.__goal = goal
        self.__teams = (team1, team2)
        self.__log_fn = log_fn
        self.n = 0

    @property
    def players(self) -> Tuple[Player, Player, Player, Player]:
        p1, p2, p3, p4 = self.__players
        return p1, p2, p3, p4

    @property
    def teams(self) -> Tuple[Team, Team]:
        return self.__teams

    def start(self) -> None:

        self.__log('Let\'s start a Jass Game :)')

        trump_chooser: Player = None
        deck = Deck()  # this reuses the same cards object -> slight memory/performance gain

        try:
            while True:

                #########################
                # GIVE CARDS TO PLAYERS #
                #########################

                for player, hand in zip(self.__players, deck.shuffle().give_hands()):
                    player.give(hand)

                ################
                # CHOOSE TRUMP #
                ################

                if trump_chooser is None:
                    for p in self.__players:
                        if p.has_7_diamonds():
                            trump_chooser = p
                            self.__log(f'{p} has the {Card(7, Suit.diamonds)}!')
                            break

                trump = self.choose_trump(
                    trump_chooser=trump_chooser
                )

                #####################
                # PLAY THE 9 TRICKS #
                #####################

                self.play_9_tricks(
                    trump=trump,
                    trump_chooser=trump_chooser,
                )

                ###########
                # RESTART #
                ###########

                trump_chooser = self.__next_player(trump_chooser)
                self.__log_score()

                self.n += 1
                if self.n % 20 == 0:
                    self.n = 0
                    print(f'Score difference: {self.teams[0].score - self.teams[1].score}')

        except GameOver as e:
            self.__log(e)
            self.__log_score()

    def choose_trump(self, trump_chooser: Player) -> Suit:
        trump = trump_chooser.choose_trump(can_chibre=True)
        if trump is None:  # chibre!
            self.__log(f'{trump_chooser} chibre!')
            partner = self.__partner_of(trump_chooser)
            trump = partner.choose_trump(can_chibre=False)
            self.__log(f'{partner} choose trump suit = {trump}')
        else:
            self.__log(f'{trump_chooser} choose trump suit = {trump}')
        return trump

    def play_9_tricks(self, trump: Suit, trump_chooser: Player) -> None:
        next_trick_starter: Player = trump_chooser
        prev_tricks: List[Trick] = []

        trick_7 = None
        for trick_idx in range(9):

            trick, points = self.play_trick(
                trump=trump,
                trump_chooser=trump_chooser,
                starter=next_trick_starter,
                is_last_trick=trick_idx == 8,
                prev_tricks=prev_tricks,
            )
            prev_tricks.append(trick)
            winner = trick.winner

            ##############
            # ADD POINTS #
            ##############

            winning_team = self.__team_of(winner)
            winning_team.score += points
            if trick_idx == 7:
                trick_7 = trick
            else:
                if trick_idx == 8:
                    if trick_7.winner in winning_team:
                        points += trick_7.points
                    else:
                        points -= trick_7.points
                for p in self.__players:
                    if p in winning_team:
                        p.reward(points=points, is_last_trick=trick_idx == 8)
                    else:
                        p.reward(points=-points, is_last_trick=trick_idx == 8)

            next_trick_starter = winner

            if self.__has_won(winning_team):
                raise GameOver(f'{winning_team.player1}-{winning_team.player2} team won')

    def play_trick(self, trump: Suit, trump_chooser: Player, starter: Player, is_last_trick: bool,
                   prev_tricks: List[Trick]):

        trick = Trick(trump)

        ####################
        # PLAY EACH A CARD #
        ####################

        for player in self.__players_order_from(starter):
            if is_last_trick:
                card_played = player.hand_cards[0]
            else:
                card_played = player.play(
                    trump=trump,
                    trump_chooser=trump_chooser,
                    players=self.__players_order_from(player),
                    trick_cards=trick.played_cards,
                    round_tricks=[trick.played_cards for trick in prev_tricks],
                )
            self.__log(f'{player} played {card_played}')
            trick.add_card(card_played, player)

        ####################
        # DETERMINE WINNER #
        ####################

        winner = trick.winner
        points = trick.points
        if is_last_trick:
            points += 5
            if all([self.__team_of(t.winner) == self.__team_of(winner) for t in prev_tricks]):
                points += 100
                self.__log(f'Match!')

        self.__log(f'{winner} wins the trick ({points} points)')

        return trick, points

    def __has_won(self, team: Team) -> bool:
        return team.score >= self.__goal

    def __players_order_from(self, player: Player) -> List[Player]:
        player_idx = self.__players.index(player)
        return self.__players[player_idx:] + self.__players[:player_idx]

    def __next_player(self, player) -> Player:
        return self.__players_order_from(player)[1]

    def __partner_of(self, player: Player) -> Player:
        return self.__players_order_from(player)[2]

    def __team_of(self, player: Player) -> Team:
        return [t for t in self.teams if player in t][0]

    def __log(self, s: Any) -> None:
        if self.__log_fn is not None:
            self.__log_fn(s)

    def __log_score(self):
        for team in self.__teams:
            self.__log(f'{team.player1}-{team.player2} team score: {team.score}')


arr1 = []
arr2 = []
arr3 = []
def enqueue(order, value):
    if order % 3 == 0:
        arr1.append(value)
    elif order % 3 == 1:
        arr2.append(value)
    elif order % 3 == 2:
        arr3.append(value)

def dequeue(order):
    if order % 3 == 0:
        return "[" + "arr1"+"," + arr1.pop(0) + "]"
    elif order % 3 == 1:
        return "[" + "arr2"+"," + arr2.pop(0) + "]"
    elif order % 3 == 2:
        return "[" + "arr3"+"," + arr3.pop(0) + "]"

def solution(inputs) :
    for i in range(len(inputs)):
        enqueue(i%3, inputs[i])

    result = []
    for i in range(len(inputs)):
        result.append(dequeue(i%3))

    return print(result)

solution(["a", "b", "c"])


"""
Implementation of Temporal Fusion Transformers: https://arxiv.org/abs/1912.09363
"""

import math
import torch
import ipdb
import json
from torch import nn
import numpy as np
import torch.nn.functional as F
from layers.add_and_norm import AddAndNorm
from layers.gated_residual_network import GatedResidualNetwork
from layers.gated_linear_unit import GLU
from layers.linear_layer import LinearLayer
from layers.lstm_combine_and_mask import LSTMCombineAndMask
from layers.static_combine_and_mask import StaticCombineAndMask
from layers.time_distributed import TimeDistributed
from layers.interpretable_multi_head_attention import InterpretableMultiHeadAttention

from torch.utils.data import DataLoader,Dataset, Subset

USE_GELU = 1

class Transformer(nn.Module):
    def __init__(self, raw_params):
        super(Transformer, self).__init__()

        params = dict(raw_params)  # copy locally
        print(params)

        # Data parameters
        self.time_steps = int(params['total_time_steps'])
        self.input_size = int(params['input_size'])
        self.output_size = int(params['output_size'])
        self.category_counts = json.loads(str(params['category_counts']))
        self.n_multiprocessing_workers = int(params['multiprocessing_workers'])

        # Relevant indices for TFT
        self._input_obs_loc = json.loads(str(params['input_obs_loc']))
        self._static_input_loc = json.loads(str(params['static_input_loc']))
        self._known_regular_input_idx = json.loads(
            str(params['known_regular_inputs']))
        self._known_categorical_input_idx = json.loads(
            str(params['known_categorical_inputs']))

        self.column_definition = params['column_definition']

        # Network params
        self.quantiles = list(params['quantiles'])
        self.device = str(params['device'])
        self.hidden_layer_size = int(params['hidden_layer_size'])
        self.dropout_rate = float(params['dropout_rate'])
        self.max_gradient_norm = float(params['max_gradient_norm'])
        self.learning_rate = float(params['learning_rate'])
        self.minibatch_size = int(params['minibatch_size'])
        self.num_epochs = int(params['num_epochs'])
        self.early_stopping_patience = int(params['early_stopping_patience'])

        self.num_encoder_steps = int(params['num_encoder_steps'])
        self.num_stacks = int(params['stack_size'])
        self.num_heads = int(params['num_heads'])
        self.inputs_encoder = params['inputs_encoder']
        self.inputs_decoder = params['inputs_decoder']

        self.batch_first = True
        self.num_static = len(self._static_input_loc)
        #self.num_inputs = len(self._known_regular_input_idx) + len(self._known_categorical_input_idx) + self.output_size
        #self.num_inputs = len(self._known_regular_input_idx) + self.output_size
        #self.num_inputs_decoder = len(self._known_regular_input_idx)
        #self.num_inputs = len(self._known_regular_input_idx) + len(self._known_categorical_input_idx) + self.output_size
        #self.num_inputs_decoder = len(self._known_regular_input_idx) + len(self._known_categorical_input_idx)
        self.num_inputs = len(self.inputs_encoder) - self.num_static
        self.num_inputs_decoder = len(self.inputs_decoder) - self.num_static

        print("_known_regular_input_idx:{}, _known_categorical_input_idx:{}, num_static: {}, num_inputs:{}".format(
            self._known_regular_input_idx, self._known_categorical_input_idx, self.num_static, self.num_inputs))
        # Serialisation options
        # self._temp_folder = os.path.join(params['model_folder'], 'tmp')
        # self.reset_temp_folder()

        # Extra components to store Tensorflow nodes for attention computations
        self._input_placeholder = None
        self._attention_components = None
        self._prediction_parts = None

        # print('*** params ***')
        # for k in params:
        #   print('# {} = {}'.format(k, params[k]))

        #######
        time_steps = self.time_steps
        num_categorical_variables = len(self.category_counts)
        num_regular_variables = self.input_size - num_categorical_variables

        embedding_sizes = [
          self.hidden_layer_size for i, size in enumerate(self.category_counts)
        ]

        print("num_categorical_variables")
        print(num_categorical_variables)
        self.embeddings = nn.ModuleList()
        for i in range(num_categorical_variables):
            embedding = nn.Embedding(self.category_counts[i], embedding_sizes[i])
            self.embeddings.append(embedding)

        self.static_input_layer = nn.Linear(self.hidden_layer_size, self.hidden_layer_size)
        self.time_varying_embedding_layer = LinearLayer(input_size=1, size=self.hidden_layer_size,
                                                        use_time_distributed=True, batch_first=self.batch_first)

        ## transformer的参数
        # 输入历史特征天级别特征大小, 注意static是否加入
        self.model_enc_dim = int(params['model_enc_dim'])
        # 输入未来特征天级别特征大小, 注意static是否加入
        self.model_dec_dim = int(params['model_dec_dim'])
        # encoder和decoder的天级别变化特征大小
        self.model_dim = int(params['model_dim'])

        self.num_layers = int(params.get('num_layers', 2))
        self.num_heads = int(params.get('num_heads', 4))
        self.use_conv = int(params.get("use_conv", 1))  # 是否使用卷积来进行qkv变换
        self.ffn_dim = int(params.get("ffn_dim", 64))  # attention之后的feedforward的隐藏层节点个数
        self.dropout = float(params.get("dropout", 0.1)) #

        self.attn_log = int(params.get("attn_log", 1))   # atten在softmax之前是否要log
        self.layer_norm = int(params.get("layer_norm", 1))  #

        self.encoder = Encoder(self.num_layers, self.model_enc_dim, self.model_dim,
                               self.num_heads, self.ffn_dim, self.dropout, use_conv=self.use_conv)
        self.decoder = Decoder(self.num_layers, self.model_dec_dim, self.model_dim,
                               self.num_heads, self.ffn_dim, self.dropout, use_conv=False)

        self.linear = nn.Linear(self.model_dim, 1, bias=False)

    def get_decoder_mask(self, self_attn_inputs):
        """Returns causal mask to apply for self-attention layer.

        Args:
          self_attn_inputs: Inputs to self attention layer to determine mask shape
        """
        len_s = self_attn_inputs.shape[1] # 192
        bs = self_attn_inputs.shape[:1][0] # [64]
        # create batch_size identity matrices
        mask = torch.cumsum(torch.eye(len_s).reshape((1, len_s, len_s)).repeat(bs, 1, 1), 1)
        return mask

    def get_tft_embeddings(self, all_inputs):
        time_steps = self.time_steps

        num_categorical_variables = len(self.category_counts)
        num_regular_variables = self.input_size - num_categorical_variables
        # 5 - 1 = 4

        embedding_sizes = [
          self.hidden_layer_size for i, size in enumerate(self.category_counts)
        ]
        #embedding_sizes = [160]

        ## 这个地方就要求，recular_inputs全部放在category之前, TODO
        regular_inputs, categorical_inputs \
            = all_inputs[:, :, :num_regular_variables], \
              all_inputs[:, :, num_regular_variables:]

        regular_inputs = regular_inputs.float()

        embedded_inputs = [
            self.embeddings[i](categorical_inputs[:,:, i].long())
            for i in range(num_categorical_variables)
        ]

        #print("num_regular_variables:{}, regular_inputs:{}, categorical_inputs:{}".format(
        #    num_regular_variables, regular_inputs.shape, categorical_inputs.shape))

        # Static inputs
        if self._static_input_loc:
            static_inputs = [self.static_input_layer(
                regular_inputs[:, 0, i:i + 1]) for i in range(num_regular_variables)
                              if i in self._static_input_loc] \
                + [embedded_inputs[i][:, 0, :]
                    for i in range(num_categorical_variables)
                    if i + num_regular_variables in self._static_input_loc]
            static_inputs = torch.stack(static_inputs, dim=1)
        else:
            static_inputs = None

        # Targets
        ## 这个地方问题是为什么要加一个time_varying_embedding_layer ??
        obs_inputs = torch.stack([
            self.time_varying_embedding_layer(regular_inputs[Ellipsis, i:i + 1].float())
            for i in self._input_obs_loc
        ], dim=-1)

        # Observed (a prioir unknown) inputs
        wired_embeddings = []
        for i in range(num_categorical_variables):
            if i not in self._known_categorical_input_idx and i not in self._input_obs_loc:
                e = self.embeddings[i](categorical_inputs[:, :, i])
                wired_embeddings.append(e)

        unknown_inputs = []
        for i in range(regular_inputs.shape[-1]):
            if i not in self._known_regular_input_idx and i not in self._input_obs_loc:
                e = self.time_varying_embedding_layer(regular_inputs[Ellipsis, i:i + 1])
                unknown_inputs.append(e)

        if unknown_inputs + wired_embeddings:
            unknown_inputs = torch.stack(unknown_inputs + wired_embeddings, dim=-1)
        else:
            unknown_inputs = None

        # A priori known inputs
        known_regular_inputs = [
            self.time_varying_embedding_layer(regular_inputs[Ellipsis, i:i + 1].float())
            for i in self._known_regular_input_idx
            if i not in self._static_input_loc
        ]
        known_categorical_inputs = [
            embedded_inputs[i]
            for i in self._known_categorical_input_idx
            if i + num_regular_variables not in self._static_input_loc
        ]

        known_combined_layer = torch.stack(known_regular_inputs + known_categorical_inputs, dim=-1)

        return unknown_inputs, known_combined_layer, obs_inputs, static_inputs

    def forward(self, x):
        # Size definitions.
        time_steps = self.time_steps
        combined_input_size = self.input_size
        encoder_steps = self.num_encoder_steps
        all_inputs = x.to(self.device)

        unknown_inputs, known_combined_layer, obs_inputs, static_inputs \
            = self.get_tft_embeddings(all_inputs)
        # 这个地方返回分别对应：未来不知道，未来知道, labels, 静态特征
        print("all_inputs:{}, unknown_inputs:{}, known_combined_layer:{}, obs_inputs:{}, static_inputs:{}".format(
           all_inputs.shape,
           None if unknown_inputs is None else unknown_inputs.shape, known_combined_layer.shape, obs_inputs.shape, static_inputs.shape
        ))

        # Isolate known and observed historical inputs.
        #print("unknown_inputs:", unknown_inputs)

        if unknown_inputs is not None:
            historical_inputs = torch.cat([
                #static_inputs[:, :encoder_steps, :],
                unknown_inputs[:, :encoder_steps, :],
                known_combined_layer[:, :encoder_steps, :],
                obs_inputs[:, :encoder_steps, :]
            ], dim=-1)
        else:
            historical_inputs = torch.cat([
                  #static_inputs[:, :encoder_steps, :],
                  known_combined_layer[:, :encoder_steps, :],
                  obs_inputs[:, :encoder_steps, :]
              ], dim=-1)

        # static怎么加入的问题，TODO
        # Isolate only known future inputs.
        future_inputs = known_combined_layer[:, encoder_steps:, :]

        #print("historical_inputs:{}, future_inputs:{}".format(historical_inputs.shape, future_inputs.shape))
        enc_output, enc_self_attn = self.encoder(historical_inputs)

        context_attn_mask = None
        output, dec_self_attn, ctx_attn = self.decoder(
            future_inputs, enc_output, context_attn_mask)

        output = self.linear(output)
        return output, enc_self_attn, dec_self_attn, ctx_attn

class ScaledDotProductAttention(nn.Module):
    """Scaled dot-product attention mechanism."""

    def __init__(self, attention_dropout=0.0):
        super(ScaledDotProductAttention, self).__init__()
        self.dropout = nn.Dropout(attention_dropout)
        # self.softmax = nn.Softmax(dim=2)
        self.softmax = nn.LogSoftmax(dim=2)

    def forward(self, q, k, v, scale=None, attn_mask=None, attn_log=1):
        """前向传播.

        Args:
        	q: Queries张量，形状为[B, L_q, D_q]
        	k: Keys张量，形状为[B, L_k, D_k]
        	v: Values张量，形状为[B, L_v, D_v]，一般来说就是k
        	scale: 缩放因子，一个浮点标量
        	attn_mask: Masking张量，形状为[B, L_q, L_k]

        Returns:
        	上下文张量和attetention张量
        """
        attention = torch.bmm(q, k.transpose(1, 2))
        if scale:
            attention = attention * scale
        if attn_mask:
            # 给需要mask的地方设置一个负无穷
            attention = attention.masked_fill_(attn_mask, -np.inf)
        # 计算softmax, enc_attention几乎所有值都为0，为了防止这样子，这个地方特意
        if attn_log:
            attention = attention.masked_fill_(attention < 0.1, 0.1)
            attention = torch.log(attention)
            # attention = torch.sign(attention) * torch.sqrt(torch.abs(attention))
            # pass

        attention = self.softmax(attention)
        if torch.sum(torch.isnan(attention.cpu())) > 0.1:
            print(q)
            print(k)
            raise Exception("attention is null")
        # 添加dropout
        attention = self.dropout(attention)
        # 和V做点积
        context = torch.bmm(attention, v)
        return context, attention

class ConvCasual1D(nn.Module):
    """用cnn的方式来计算kqv(因果卷积)
    """

    def __init__(self, input_size, output_size=1, kernel_size=3):
        super(ConvCasual1D, self).__init__()

        self.input_size = input_size
        self.output_size = output_size
        self.kernel_size = kernel_size

        # padding = 0
        # 二维conv：https://blog.csdn.net/m0_37586991/article/details/87855342
        # self.conv2 = nn.Conv2d()
        # 卷积
        self.conv1 = nn.Conv1d(in_channels=input_size, out_channels=output_size, kernel_size=self.kernel_size,
                               padding=(self.kernel_size - 1), padding_mode="circular")
        # self.conv1 = nn.Conv1d(in_channels=input_size, out_channels=output_size, kernel_size=self.kernel_size, padding=2*(self.kernel_size-1), padding_mode="same")
        # shape: bs, output_size, new_len

        # self.active_func = nn.SELU()
        self.active_func = nn.GELU()
        # self.active_func = nn.ReLU()

        # output_size

    def forward(self, input):
        ## input.shape: bs, nday, d_model
        ## torch.nn.Conv1d
        input = input.permute(0, 2, 1)  # bs, d_model, nday
        # print(input.shape)
        output = self.conv1(input)
        # 因果卷积, bs, output_size, new_len
        output = output[:, :, :-(self.kernel_size - 1)]
        output = output.permute(0, 2, 1)

        # NEW add gelu
        return self.active_func(output)

class MultiHeadAttention(nn.Module):

    def __init__(self, model_dim=512, num_heads=8, dropout=0.0, use_conv=True):
        super(MultiHeadAttention, self).__init__()

        self.dim_per_head = model_dim // num_heads
        self.num_heads = num_heads
        if not use_conv:
            self.linear_k = nn.Linear(model_dim, self.dim_per_head * num_heads)
            self.linear_v = nn.Linear(model_dim, self.dim_per_head * num_heads)
            self.linear_q = nn.Linear(model_dim, self.dim_per_head * num_heads)
        else:
            output_size = self.dim_per_head * num_heads
            self.linear_k = ConvCasual1D(input_size=model_dim, output_size=output_size, kernel_size=3)
            self.linear_v = ConvCasual1D(input_size=model_dim, output_size=output_size, kernel_size=3)
            self.linear_q = ConvCasual1D(input_size=model_dim, output_size=output_size, kernel_size=3)

        self.dot_product_attention = ScaledDotProductAttention(dropout)
        self.linear_final = nn.Linear(model_dim, model_dim)
        self.dropout = nn.Dropout(dropout)
        # multi-head attention之后需要做layer norm
        self.layer_norm = nn.LayerNorm(model_dim)

    def forward(self, key, value, query, attn_mask=None, attn_log=1, layer_norm=1):
        # 残差连接
        residual = query

        dim_per_head = self.dim_per_head
        num_heads = self.num_heads
        batch_size = key.size(0)

        # linear projection
        key = self.linear_k(key)
        value = self.linear_v(value)
        query = self.linear_q(query)

        # split by heads
        key = key.contiguous().view(batch_size * num_heads, -1, dim_per_head)
        value = value.contiguous().view(batch_size * num_heads, -1, dim_per_head)
        query = query.contiguous().view(batch_size * num_heads, -1, dim_per_head)

        if attn_mask:
            attn_mask = attn_mask.repeat(num_heads, 1, 1)
        # scaled dot product attention
        scale = (key.size(-1) // num_heads) ** -0.5
        context, attention = self.dot_product_attention(
            query, key, value, scale, attn_mask, attn_log=attn_log)

        # concat heads
        context = context.view(batch_size, -1, dim_per_head * num_heads)

        # final linear projection
        output = self.linear_final(context)

        # dropout
        output = self.dropout(output)

        # add residual and norm layer
        if layer_norm:
            output = self.layer_norm(residual + output)
        else:
            output = residual + output

        return output, attention

class LayerNorm(nn.Module):
    """实现LayerNorm。其实PyTorch已经实现啦，见nn.LayerNorm。
    这个layernorm是否有必要？
    """

    def __init__(self, features, epsilon=1e-6):
        """ feature, 模型的维度
        """
        super(LayerNorm, self).__init__()
        # alpha
        self.gamma = nn.Parameter(torch.ones(features))
        # beta
        self.beta = nn.Parameter(torch.zeros(features))
        self.epsilon = epsilon

    def forward(self, x):
        """
        """
        # 根据公式进行归一化
        # 在X的最后一个维度求均值，最后一个维度就是模型的维度
        mean = x.mean(-1, keepdim=True)
        # 在X的最后一个维度求方差，最后一个维度就是模型的维度
        std = x.std(-1, keepdim=True)
        return self.gamma * (x - mean) / (std + self.epsilon) + self.beta

# def padding_mask(seq_k, seq_q):
#     # seq_k和seq_q的形状都是[B,L]
#     len_q = seq_q.size(1)
#     # `PAD` is 0
#     pad_mask = seq_k.eq(0)
#     pad_mask = pad_mask.unsqueeze(1).expand(-1, len_q, -1)  # shape [B, L_q, L_k]
#     return pad_mask

# def sequence_mask(seq):
#     batch_size, seq_len = seq.size()
#     mask = torch.triu(torch.ones((seq_len, seq_len), dtype=torch.uint8),
#                     diagonal=1)
#     mask = mask.unsqueeze(0).expand(batch_size, -1, -1)  # [B, L, L]
#     return mask

class PositionalEncoding(nn.Module):

    def __init__(self, d_model, max_seq_len):
        """初始化。

            d_model: 一个标量。模型的维度，论文默认是512
            max_seq_len: 一个标量。文本序列的最大长度
        """
        super(PositionalEncoding, self).__init__()

        # 根据论文给的公式，构造出PE矩阵
        position_encoding = np.array([
            [pos / np.pow(10000, 2.0 * (j // 2) / d_model) for j in range(d_model)]
            for pos in range(max_seq_len)])
        # 偶数列使用sin，奇数列使用cos
        position_encoding[:, 0::2] = np.sin(position_encoding[:, 0::2])
        position_encoding[:, 1::2] = np.cos(position_encoding[:, 1::2])

        # 在PE矩阵的第一行，加上一行全是0的向量，代表这`PAD`的positional encoding
        # 在word embedding中也经常会加上`UNK`，代表位置单词的word embedding，两者十分类似
        # 那么为什么需要这个额外的PAD的编码呢？很简单，因为文本序列的长度不一，我们需要对齐，
        # 短的序列我们使用0在结尾补全，我们也需要这些补全位置的编码，也就是`PAD`对应的位置编码
        pad_row = torch.zeros([1, d_model])
        position_encoding = torch.cat((pad_row, position_encoding))

        # 嵌入操作，+1是因为增加了`PAD`这个补全位置的编码，
        # Word embedding中如果词典增加`UNK`，我们也需要+1。看吧，两者十分相似
        self.position_encoding = nn.Embedding(max_seq_len + 1, d_model)
        self.position_encoding.weight = nn.Parameter(position_encoding,
                                                     requires_grad=False)

    def forward(self, input_len):
        """神经网络的前向传播。

        Args:
          input_len: 一个张量，形状为[BATCH_SIZE, 1]。每一个张量的值代表这一批文本序列中对应的长度。

        Returns:
          返回这一批序列的位置编码，进行了对齐。
        """

        # 找出这一批序列的最大长度
        max_len = torch.max(input_len)
        tensor = torch.cuda.LongTensor if input_len.is_cuda else torch.LongTensor
        # 对每一个序列的位置进行对齐，在原序列位置的后面补上0
        # 这里range从1开始也是因为要避开PAD(0)的位置
        input_pos = tensor(
            [list(range(1, len + 1)) + [0] * (max_len - len) for len in input_len])
        return self.position_encoding(input_pos)

class PositionalWiseFeedForward(nn.Module):

    def __init__(self, model_dim=512, ffn_dim=2048, dropout=0.0):
        super(PositionalWiseFeedForward, self).__init__()
        self.w1 = nn.Conv1d(model_dim, ffn_dim, 1)
        self.w2 = nn.Conv1d(ffn_dim, model_dim, 1)
        # self.gelu = nn.GELU()
        # self.active_func = nn.ReLU()
        # self.active_func = nn.SELU()
        self.active_func = nn.GELU()

        self.dropout = nn.Dropout(dropout)
        self.layer_norm = nn.LayerNorm(model_dim)

    def forward(self, x, layer_norm=1):
        output = x.transpose(1, 2)

        if USE_GELU:
            output = self.w2(self.active_func(self.w1(output)))
        else:
            output = self.w2(F.relu(self.w1(output)))

        output = self.dropout(output.transpose(1, 2))

        # add residual and norm layer
        if layer_norm:
            output = self.layer_norm(x + output)
        else:
            output = x + output
        return output

class EncoderLayer(nn.Module):
    """Encoder的一层。"""

    def __init__(self, model_dim=512, num_heads=8, ffn_dim=2018, dropout=0.0, use_conv=True):
        super(EncoderLayer, self).__init__()

        self.attention = MultiHeadAttention(model_dim, num_heads, dropout, use_conv=use_conv)
        self.feed_forward = PositionalWiseFeedForward(model_dim, ffn_dim, dropout)

    def forward(self, inputs, attn_mask=None, attn_log=1, layer_norm=1):
        # self attention
        context, attention = self.attention(inputs, inputs, inputs, attn_mask, attn_log=attn_log, layer_norm=layer_norm)

        # feed forward network
        output = self.feed_forward(context)

        return output, attention

class Encoder(nn.Module):
    """多层EncoderLayer组成Encoder。"""

    def __init__(self,
                 # vocab_size,
                 # max_seq_len,
                 num_layers=6,
                 model_enc_dim=512,
                 model_dim=512,
                 num_heads=8,
                 ffn_dim=2048,
                 dropout=0.0,
                 use_conv=True,
                 ):
        super(Encoder, self).__init__()

        self.encoder_normdim_layer = nn.Linear(model_enc_dim, model_dim, bias=True)

        self.encoder_layers = nn.ModuleList(
            [EncoderLayer(model_dim, num_heads, ffn_dim, dropout, use_conv=use_conv) for _ in
             range(num_layers)])

        # self.seq_embedding = nn.Embedding(vocab_size + 1, model_dim, padding_idx=0)
        #self.pos_embedding = PositionalEncoding(model_dim, max_seq_len)

    def forward(self, inputs, attn_log=1, layer_norm=1):
        # output = self.seq_embedding(inputs)
        # output += self.pos_embedding(inputs_len)

        # self_attention_mask = padding_mask(inputs, inputs)

        output = self.encoder_normdim_layer(inputs)

        attentions = []
        for encoder in self.encoder_layers:
            # output, attention = encoder(inputs, self_attention_mask)
            output, attention = encoder(output, attn_log=attn_log, layer_norm=layer_norm)
            attentions.append(attention)

        return output, attentions

class DecoderLayer(nn.Module):

    def __init__(self, model_dim, num_heads=8, ffn_dim=2048, dropout=0.0, use_conv=False):
        super(DecoderLayer, self).__init__()

        self.attention = MultiHeadAttention(model_dim, num_heads, dropout, use_conv=use_conv)
        self.feed_forward = PositionalWiseFeedForward(model_dim, ffn_dim, dropout)

    def forward(self,
                dec_inputs,
                enc_outputs,
                self_attn_mask=None,
                context_attn_mask=None,
                attn_log=1,
                layer_norm=1
                ):
        # self attention, all inputs are decoder inputs
        dec_output, self_attention = self.attention(
            dec_inputs, dec_inputs, dec_inputs, self_attn_mask, attn_log=attn_log, layer_norm=layer_norm)

        # context attention
        # query is decoder's outputs, key and value are encoder's inputs
        dec_output, context_attention = self.attention(
            enc_outputs, enc_outputs, dec_output, context_attn_mask, attn_log=attn_log, layer_norm=layer_norm)

        # decoder's output, or context
        dec_output = self.feed_forward(dec_output)

        return dec_output, self_attention, context_attention

class Decoder(nn.Module):

    def __init__(self,
                 # vocab_size,
                 # max_seq_len,
                 num_layers=6,
                 model_dec_dim=28,
                 model_dim=64,
                 num_heads=6,
                 ffn_dim=64,
                 dropout=0.0,
                 use_conv=False,
                 ):
        super(Decoder, self).__init__()

        self.num_layers = num_layers

        self.decoder_normdim_layer = nn.Linear(model_dec_dim, model_dim, bias=False)
        self.decoder_layers = nn.ModuleList(
            [DecoderLayer(model_dim, num_heads, ffn_dim, dropout, use_conv=use_conv) for _ in
             range(num_layers)])

        # self.seq_embedding = nn.Embedding(vocab_size + 1, model_dim, padding_idx=0)
        # self.pos_embedding = PositionalEncoding(model_dim, max_seq_len)

    def forward(self, inputs, enc_output, context_attn_mask=None, attn_log=1, layer_norm=1):
        # output = self.seq_embedding(inputs)
        # output += self.pos_embedding(inputs_len)

        # self_attention_padding_mask = padding_mask(inputs, inputs)
        # seq_mask = sequence_mask(inputs)
        # self_attn_mask = torch.gt((self_attention_padding_mask + seq_mask), 0)

        self_attn_mask = None
        context_attn_mask = None

        self_attentions = []
        context_attentions = []
        output = self.decoder_normdim_layer(inputs)
        for decoder in self.decoder_layers:
            output, self_attn, context_attn = decoder(
                output, enc_output, self_attn_mask, context_attn_mask, attn_log=attn_log, layer_norm=layer_norm)
            self_attentions.append(self_attn)
            context_attentions.append(context_attn)

        return output, self_attentions, context_attentions

from torch.nn import ModuleDict

class SparseFeatureDictNet(nn.Module):
    """Scaled dot-product attention mechanism."""

    def __init__(self, his_features_infos, pred_features_infos, use_onehot=True, use_onehot_freeze=True, sparse_di=16):
        """ 这个地方把所有的离散型的变量变换成长度一样的embedding，
        TODO: 可以在配置文件中设置各个离散变量的embedding的长度.

        如果use_onehot=True,那么使用onehot的值
        """
        super(SparseFeatureDictNet, self).__init__()
        self.his_features_infos = his_features_infos
        self.pred_features_infos = pred_features_infos
        self.sparse_di = sparse_di
        self.use_onehot = use_onehot
        self.use_onehot_freeze = use_onehot_freeze

        feature_class_map = self._parse_sparse_features()

        self.embedding_net_dict = ModuleDict()
        for col_name, n_class in feature_class_map.items():
            if use_onehot:
                self.embedding_net_dict[col_name] = nn.Embedding.from_pretrained(torch.eye(n_class),
                                                                                freeze=use_onehot_freeze)
            else:
                self.embedding_net_dict[col_name] = nn.Embedding(n_class, self.sparse_di)

    def _parse_sparse_features(self):
        feature_class_num_map = {}
        for f in self.his_features_infos + self.pred_features_infos:
            col_idx, col_name, is_sparse, n_class = f
            if n_class > 0:
                feature_class_num_map[col_name] = n_class
        return feature_class_num_map

    def forward(self, sparse_input, sparse_column):
        """ 输入一个sparse features，然后返回这个sparse_input的embeding
        sparse_input:: shape: (batch_size, nday)
        sparse_column:: str

        return: (batch_size, nday, embed_size)
        """
        assert sparse_column in self.embedding_net_dict, "输入的离散变量列名必须存在:[{}]".format(sparse_column)
        return self.embedding_net_dict[sparse_column](sparse_input)