import numpy as np
import matplotlib.pyplot as pl
import networkx as nx

from BiasedRandomWalks import BiasedRandomWalk

# Create a test Graph with weighted edges where weights are distances
G = nx.Graph()
N = 4
G.add_nodes_from(range(N))
G.add_edge(0,1,weight=1)
G.add_edge(0,2,weight=1)
G.add_edge(1,2,weight=1)
G.add_edge(1,3,weight=0.1)
G.add_edge(2,3,weight=0.2)

# define sink nodes
sink_nodes = [3,]

# define bias
gamma = 1

# initial distribution on transient
p0 = np.array([1,0,0])

# initial distribution on all
p0_all = np.array([1,0,0,0])

# initial base class (choose 'exponential' or 'scale free')
RW = BiasedRandomWalk(G, gamma, sink_nodes, bias_kind = 'exponential')

print("adjacency_matrix =", RW.adjacency_matrix)
print("weight_matrix =", RW.weight_matrix)
print("transition_matrix =", RW.full_transition_matrix)
print("distance_matrix =", RW.distance_matrix)


"""Corrected the lowercase Column

Revision ID: dda7a1ca7a04
Revises: f2b849ffb71f
Create Date: 2022-08-13 20:14:00.669172

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'dda7a1ca7a04'
down_revision = 'f2b849ffb71f'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('Artist', sa.Column('past_shows_count', sa.Integer(), nullable=True))
    op.add_column('Venue', sa.Column('past_shows_count', sa.Integer(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('Venue', 'past_shows_count')
    op.drop_column('Artist', 'past_shows_count')
    # ### end Alembic commands ###


"""
You are given an array prices where prices[i] is the price of a given stock on the ith day.

You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.

Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.

Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.

"""
from typing import List

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        print (prices)
        ans = 0
        buy_index = 0
        sell_index = 0
        for i in range(1, len(prices)):
            if prices[i] < prices[buy_index]:
                buy_index = i
            profit = prices[i] - prices[buy_index]
            if profit > ans:
                sell_index = i
                ans = profit
        print (buy_index, sell_index)
        return ans


import pymysql
import warnings
import keras
from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
from keras.models import load_model
import jieba
import pickle
import json
import numpy as np
import re
from env_paras import *

def load_models():
    tokenizer_maincat = pickle.load(open(MODEL_MAIN_TOKEN, 'rb'))
    cnn_maincat = load_model(MODEL_MAIN, compile=False)
    tokenizer_cat = pickle.load(open(MODEL_SUB_TOKEN, 'rb'))
    cnn_cat = load_model(MODEL_SUB, compile=False)
    jieba.load_userdict(MODEL_DICC)

    cnn_maincat.predict(pad_sequences([[0]], maxlen=37))
    cnn_cat.predict(pad_sequences([[0]], maxlen=55))

    return (tokenizer_maincat, cnn_maincat, tokenizer_cat, cnn_cat)

tokenizer_maincat, cnn_maincat, tokenizer_cat, cnn_cat = load_models()

def remove_puncs(x, puncs):
    for s in puncs:
        x = x.replace(s, ' ')
    return x

def remove_units(x, units):
    for u in units:
        if u in x:
            x.remove(u)
    return x

def preclean(df, col_name):
    if col_name not in list(df.columns):
        puncs = PUNCS
        df[col_name] = df['goods_name'].apply(lambda x: re.sub(r'\d+', ' ', str(x)))
        df[col_name] = df[col_name].apply(lambda x: remove_puncs(x, puncs))

    return df

def predict_maincat(df, maxlen, col_name, tokenizer, cnn):
    units = UNITS.split('|')
    df[col_name] = df[col_name].astype('str')
    df['segmentation'] = df[col_name].apply(
        lambda x: list(' '.join([' '.join(jieba.cut(seg)) for seg in x.split()]).split()))
    df['segmentation'] = df['segmentation'].apply(lambda x: remove_units(x, units))

    x = df['segmentation']
    x = tokenizer.texts_to_sequences(x)
    x = pad_sequences(x, maxlen=maxlen)
    predict = cnn.predict_classes(x)
    df['CNN_cat1'] = predict
    labelmap = {CLASS_NAME_LIST[0]: 0, CLASS_NAME_LIST[1]: 1, CLASS_NAME_LIST[2]: 2, CLASS_NAME_LIST[3]: 3, CLASS_NAME_LIST[4]: 4}
    df['CNN_cat1'] = df['CNN_cat1'].map(dict(zip(labelmap.values(), labelmap.keys())))

    return df

def predict_category(df, maxlen, col_name, prob_threshold, tokenizer_cat, cnn_cat):
    # 读取模型
    with open(MODEL_LABEL_JSON, 'r', encoding='utf8')as f:
        label_cat_dicc = json.load(f)
        label_cat_dicc = dict(zip(map(int, label_cat_dicc.keys()), label_cat_dicc.values()))

    with open(MODEL_NAME_JSON, 'r', encoding='utf8')as f:
        cat_name_dicc = json.load(f)

    pred_category = []

    for idx, row in df.iterrows():
        if row['CNN_cat1'] == CLASS_NAME_LIST[1] or row['CNN_cat1'] == CLASS_NAME_LIST[2]:
            seqs = pad_sequences(tokenizer_cat.texts_to_sequences([row['segmentation']]), maxlen)
            pred = cnn_cat.predict_proba(seqs)[0]
            max_idx = np.argmax(pred)
            if np.max(pred) >= prob_threshold:
                pred_category.append(cat_name_dicc[label_cat_dicc[max_idx]])
            else:
                pred_category.append(row['CNN_cat1'])
        else:
            pred_category.append(row['CNN_cat1'])
    df['CNN_cat2'] = pred_category

    return df.drop([col_name, 'CNN_cat1', 'segmentation'], axis=1)


from applications.biblioteca.models import Author
from django.shortcuts import render

# Create your views here.
from django.views.generic import (
    TemplateView,
    ListView,
    CreateView,
)

from .models import Author, Book

class AuthorsList(ListView):
    template_name = "biblioteca/authors-list.html"
    model = Author
    context_object_name = 'authors'

#View to list books by author
class AuthorBooksList(ListView):
    template_name = "biblioteca/books-list.html"
    context_object_name = 'books'

    def get_queryset(self):
        # Identify the author
        id = self.kwargs['id'] #From url get the arg 'id'
        # Filter books by author
        books = Book.objects.filter(
            author=id
        )
        # Return results
        return books

class AddAuthor(CreateView):
    """View to add new author"""
    template_name = 'biblioteca/add-author.html'
    model = Author
    fields = ['name', 'nationality']
    success_url =  '/' #This reload the page when author is added.


from matplotlib import lines
import scipy
import cmath
import math
from math import pi, sin, cos, sqrt, exp
import matplotlib

import numpy as np
import progressbar

import matplotlib.pyplot as plt
matplotlib.use('Agg')
from matplotlib.path import Path
from matplotlib.patches import PathPatch
'''
# int
'''
a = 2.46               #A
b = 4*pi/(sqrt(3)*a)    #1/A, dot(a,b)=sqrt(3)a*b/2 = 2pi
S = sqrt(3)/2 * a**2    #A^2
a1 = np.array([a*sqrt(3)/2,  -a/2])
a2 = np.array([a*sqrt(3)/2,  a/2])
l_list=np.array([a1,a2])

def rotate(in_list,theta):
    # rotate k theta in raduis
    T_rotate=np.array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]])
    out_list=[]
    for i in range(2):
        k = in_list[i]
        kr = np.matmul(T_rotate,k)
        out_list.append( kr )
    out_list = np.array(out_list)
    return out_list

def rotate_2D(in_list,theta):
    # rotate k theta in raduis
    T_rotate=np.array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]])
    kr = np.matmul(T_rotate, in_list)
    out_list = np.array(kr)
    return out_list

def rotate_3D(in_list,theta):
    # rotate k theta in raduis
    T_rotate=np.array([[cos(theta),-sin(theta), 0],[sin(theta),cos(theta), 0], [0, 0, 1]])
    kr = np.matmul(T_rotate, in_list)
    out_list = np.array(kr)
    return out_list

def strian(in_list,theta,ex,ey):
    # give strain ex in diraction theta
    # and strain ey in diraction theta+pi/2
    T_rotate=np.array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]])
    T_rotate_back=np.array([[cos(-theta),-sin(-theta)],[sin(-theta),cos(-theta)]])
    T_strian = np.array([[1/(1+ex),0],[0,1/(1+ey)]])
    T_sum = np.matmul(T_rotate,np.matmul(T_strian,T_rotate_back))
    out_list=[]
    for i in range(2):
        k = in_list[i]
        kr = np.matmul(T_sum,k)
        out_list.append( kr )
    out_list = np.array(out_list)
    return out_list

def gen_revise_vectors(input_vectors):
    """
    Generate reciprocal lattice vectors from real-space lattice vectors.
    or Generate real-space lattice vectors from reciprocal lattice vectors.

    NOTE: Here we evaluate reciprocal lattice vectors via
        dot_product(a_i, b_j) = 2 * pi * delta_{ij}
    The formulae based on cross-products are not robust in some cases.

    :param input_vectors: (3, 3) float64 array
        Cartesian coordinates of input lattice vectors
    :return: output_vectors: (3, 3) float64 array
        Cartesian coordinates of output lattice vectors.
    """
    output_vectors = np.zeros((2, 2))
    product = 2 * pi * np.eye(2)
    for i in range(2):
        output_vectors[i] = np.linalg.solve(input_vectors, product[i])
    return output_vectors

def cart2frac(k_base, k_in):
    """
    Convert k_in to combination of k_base.

    :param k_base: (2, 2) float64 array
        Cartesian coordinates of base k vectors
    :param k_in: (num_coord, 2) float64 array
        Cartesian coordinates to convert
    :return: fractional_coordinates: (num_coord, 3) float64 array
        fractional coordinates in basis of lattice vectors
    """
    fractional_coordinates = np.zeros(k_in.shape)
    conversion_matrix = np.linalg.inv(k_base.T)
    for i, row in enumerate(k_in):
        fractional_coordinates[i] = np.matmul(conversion_matrix, row.T)
    return fractional_coordinates

def plot_reciprocal(k_top,k_bottom,k_moire,k_list):
    fig, ax = plt.subplots()
    ax.set_aspect('equal')

    #   Gamma vector
    ax.arrow(0, 0, k_top[0,0]-k_list[0,0], k_top[0,1]-k_list[0,1], head_width=0.01, head_length=0.01,fc='r', ec='r',label="dK_top")
    ax.arrow(0, 0, k_top[1,0]-k_list[1,0], k_top[1,1]-k_list[1,1], head_width=0.01, head_length=0.01,fc='r', ec='r')
    ax.arrow(0, 0, k_bottom[0,0]-k_list[0,0], k_bottom[0,1]-k_list[0,1], head_width=0.01, head_length=0.01,fc='b', ec='b',label="dK_bottom")
    ax.arrow(0, 0, k_bottom[1,0]-k_list[1,0], k_bottom[1,1]-k_list[1,1], head_width=0.01, head_length=0.01,fc='b', ec='b')
    ax.arrow(0, 0, k_moire[0,0], k_moire[0,1], head_width=0.01, head_length=0.01,fc='k', ec='k',label="K_Moire")
    ax.arrow(0, 0, k_moire[1,0], k_moire[1,1], head_width=0.01, head_length=0.01,fc='k', ec='k')

    plt.text(0.5, 0.35,'k_top=\n'+str(cart2frac(k_moire, k_top))+"\n*k_moire", horizontalalignment='center',
     verticalalignment='center', transform=ax.transAxes)
    plt.text(0.5, 0.15, 'k_bottom=\n'+str(cart2frac(k_moire, k_bottom))+"\n*k_moire", horizontalalignment='center',
     verticalalignment='center', transform=ax.transAxes)
    plt.legend()
    dk1=np.linalg.norm(k_moire[0,:])
    dk2=np.linalg.norm(k_moire[1,:])
    kmax=sqrt(3)*max(dk1,dk2)
    plt.xlim((-kmax, kmax))
    plt.ylim((-kmax, kmax))
    plt.xlabel("kx (1/A)")
    plt.ylabel("ky (1/A)")
    plt.savefig(fname='reciprocal_space.png',dpi=600)
    plt.close

def plot_lattice(l_top,l_bottom,l_moire):
    fig, ax = plt.subplots()
    ax.set_aspect('equal')

    #   Gamma vector
    ax.arrow(0, 0, l_top[0,0], l_top[0,1], head_width=0.01, head_length=0.01,fc='r', ec='r',label="l_top")
    ax.arrow(0, 0, l_top[1,0], l_top[1,1], head_width=0.01, head_length=0.01,fc='r', ec='r')
    ax.arrow(0, 0, l_bottom[0,0], l_bottom[0,1], head_width=0.01, head_length=0.01,fc='b', ec='b',label="l_bottom")
    ax.arrow(0, 0, l_bottom[1,0], l_bottom[1,1], head_width=0.01, head_length=0.01,fc='b', ec='b')
    ax.arrow(0, 0, l_moire[0,0], l_moire[0,1], head_width=0.01, head_length=0.01,fc='k', ec='k',label="l_Moire")
    ax.arrow(0, 0, l_moire[1,0], l_moire[1,1], head_width=0.01, head_length=0.01,fc='k', ec='k')

    plt.text(0.5, 0.35,'L_moire=\n'+str(cart2frac(l_top, l_moire))+"\n*L_top", horizontalalignment='center',
     verticalalignment='center', transform=ax.transAxes)
    plt.text(0.5, 0.15, 'L_moire=\n'+str(cart2frac(l_bottom, l_moire))+"\n*L_bottom", horizontalalignment='center',
     verticalalignment='center', transform=ax.transAxes)
    plt.legend()
    L1=np.linalg.norm(l_moire[0,:])
    L2=np.linalg.norm(l_moire[1,:])
    theta= np.arccos(np.inner(l_moire[0,:],l_moire[1,:]) /(L1*L2))
    lmax=max(L1,L2)
    plt.xlim((-lmax, lmax))
    plt.ylim((-lmax, lmax))
    plt.xlabel("x (A)")
    plt.ylabel("y (A)")
    plt.title("L1: %3.3f A  L2:% 3.3f A\ntheta:%3.3f °" %(L1,L2, 180*theta/pi))
    plt.savefig(fname='real_space.png',dpi=600)
    plt.close

def normalization_lattice(l_top,l_bottom,l_moire):

    #print('old_L_moire=\n'+str(cart2frac(l_top, l_moire))+"\n*L_top")
    #print('old_L_moire=\n'+str(cart2frac(l_bottom, l_moire))+"\n*L_bottom")

    Matrixtop=cart2frac(l_top, l_moire)
    Matrixbottom=cart2frac(l_bottom, l_moire)
    topmin =min(np.min((np.abs(Matrixtop))),1)
    bottomin=min(np.min((np.abs(Matrixbottom))),1)
    l_moire_new = l_moire/topmin
    for i in range(0,2):
        for j in range(0,2):
            Matrixtop[i,j] = int(Matrixtop[i,j]/topmin)
            Matrixbottom[i,j] = int(Matrixbottom[i,j]/bottomin)
    l_top_new = np.matmul(np.linalg.inv(Matrixtop),l_moire_new)
    l_bottom_new = np.matmul(np.linalg.inv(Matrixbottom),l_moire_new)

    #print('L_moire=\n'+str(cart2frac(l_top_new, l_moire_new))+"\n*L_top")
    #print('L_moire=\n'+str(cart2frac(l_bottom_new, l_moire_new))+"\n*L_bottom")
    return l_top_new,l_bottom_new,l_moire_new

class tBG():
    def __init__(self):
        """
        initialize all required parameters
        """
        # def hopping constants
        self.a0 =  1.42            #: [A] C-C bond length
        self.a  =  2.46            #: [A] C-C cell length
        self.d0 =  3.35             #: [A] interlayer distance normal:3.35

    def Lattice(self,l_top,l_bottom,l_moire,topx,topy,botx,boty,zstrain,twist):
        """
        bilayerGraphene-hBN lattice.
        orbital_coords: orbital_coords[2i] is sub-lattice A,
                        orbital_coords[2i+1] is sub-lattice B,
                        and spin down part is a copy of spin up.
        """
        L = np.linalg.norm(l_moire[0,:])            #: [A] Moire period length
        print ('Moire period/nm=',L)

        def judge_and_swap(l_moire):
            L1 = np.array([l_moire[0,0], l_moire[0,1], 0])
            L2 = np.array([l_moire[1,0], l_moire[1,1], 0])
            cross_a1_a2 = np.cross(L1,L2)
            if cross_a1_a2[2] > 0: #z value of cross product of a1, a2
                #print("a2 on the anti-clockwise direction of a2, no swapping needed")
                return l_moire
            if cross_a1_a2[2] < 0:
                #print("a2 on the clockwise direction of a1, now swap a1 and a2")
                l_moire[0,0], l_moire[1,0] = l_moire[1,0], l_moire[0,0]
                l_moire[0,1], l_moire[1,1] = l_moire[1,1], l_moire[0,1]
                return l_moire

        l_moire = judge_and_swap(l_moire)
        #print("Swapped l_moire matrix is\n",l_moire)

        a1= np.array([l_moire[0,0], l_moire[0,1], 0])              #: [A] Supercell vector
        a2= np.array([l_moire[1,0], l_moire[1,1], 0])              #: [A] Supercell vector
        a3= np.array([0, 0, 6*self.d0])      #: [A] Supercell vector

        theta_old_1 = np.arctan2(a1[1], a1[0])#angle with respect to x-axis of original a1 vector
        theta_old_2 = np.arctan2(a2[1], a2[0]) #angle with respect to x-axis of original a2 vector

        #print("the old theta of a1 and a2 w.r.t. x-axis is", theta_old_1, theta_old_2)

        theta_rotate = -theta_old_1
        #print("The rotate theta is", theta_rotate)

        l_moire = rotate(l_moire, theta_rotate)

        a1= np.array([l_moire[0,0], l_moire[0,1], 0])              #: [A] Supercell vector
        a2= np.array([l_moire[1,0], l_moire[1,1], 0])
        self.vectors = [a1, a2, a3]
        #print('lattice_vectors is ',self.vectors)

        r1 = l_bottom[0,:]   #: [nm] layer1 vector
        r2 = l_bottom[1,:]   #: [nm] layer1 vector
        r1p = l_top[0,:]     #: [nm] layer3 vector
        r2p = l_top[1,:]     #: [nm] layer3 vector

       #print(r1,r2,r1p,r2p)

        r1 = rotate_2D(r1, theta_rotate)
        r2 = rotate_2D(r2, theta_rotate)
        r1p = rotate_2D(r1p, theta_rotate)
        r2p = rotate_2D(r2p, theta_rotate)
        #print(r1,r2,r1p,r2p)

        l_bottom[0,:] = r1
        l_bottom[1,:] = r2
        l_top[0,:] = r1p
        l_top[1,:] = r2p

        delta =np.append((r1 +r2 )/3,0)     #: [nm] layer1 AB vector
        deltap=np.append((r1p+r2p)/3,0)     #: [nm] layer2 AB vector
        height=np.array([0, 0, self.d0])    #: [nm] height vector
        #print(r1,r2,delta)

        orbital_coords = []
        L1= l_moire[0,:]
        L2= l_moire[1,:]
        SL= np.cross(L1,L2)
        #print(SL,L1,L2)

        def judge(orb, L1, L2):
            """
            private method:
            move the bottom-layer/layer1,2 i,j atom location
              or the    top-layer/layer3,4 j,i atom location
            """
            if (0<=np.cross(L1,orb)<SL) and (0<=np.cross(orb,L2)<SL):
                return True
            else:
                #print(np.cross(L1,orb)/SL,np.cross(orb,L2)/SL)
                return False
        bar = progressbar.ProgressBar(max_value=1600)
        print("Making TBG sample.")
        for  i in range(-800,800):
            for j in range(-800,800):
                rr1=i*r1 +j*r2
                if judge(rr1, L1, L2):
                    ra1 = np.append(rr1,-self.d0/2)
                    rb1=ra1+delta
                    orbital_coords.append(ra1) # A1
                    orbital_coords.append(rb1) # B1

                rr3=i*r1p+j*r2p
                if judge(rr3, L1, L2):
                    ra3 = np.append(rr3,self.d0/2)
                    rb3=ra3+deltap
                    orbital_coords.append(ra3) # A3
                    orbital_coords.append(rb3) # B3
            bar.update(i+800)
        #print("Done1!")

        #-Near Origin=ABBC-
        #--A3--B3--
        #--A1--B1--
        self.n_atom = len(orbital_coords)
        #print(self.n_atom)
        #print(len(orbital_coords))
        #fw = open("strain_TBG_"+str(int(round(L/10,0)))+"nm.data",'w+')
        fw = open(f"./TBG_top_x_{topx}_topy_{topy}_botx_{botx}_boty_{boty}_zstrain_{zstrain}_twist_{twist}/Strain.data",'w+')
        fw.write(("#L/Angstroms = %.4f" %(float(L))))
        fw.write(("\n%d atoms" %(int(len(orbital_coords)))))
        fw.write(("\n4 atom types"))
        fw.write(("\n"))

        fw.write(("\n%10.8f %10.8f   xlo xhi" %(float(0.),float(L1[0]))))
        fw.write(("\n%10.8f %10.8f   ylo yhi" %(float(0.),float(L2[1]))))
        fw.write(("\n%10.8f %10.8f   zlo zhi" %(float(-a3[2]),float(a3[2]))))
        fw.write(("\n"))

        fw.write(("\n %10.7f %10.7f %10.7f  xy xz yz" %(float(L2[0]),float(0.),float(0.))))
        fw.write(("\n"))

        fw.write(("\nAtoms"))
        fw.write(("\n"))
        #print("Done2!")
        for i in range(self.n_atom):
            coord = orbital_coords[i]
            if coord[2] >0:
                type =2
            else:
                type =0
            fw.write(('\n%6d %4d      %12.6f %12.6f %12.6f'
                    %(int(i+1),
                    int(type+i%2+1),
                    float(coord[0]),
                    float(coord[1]),
                    float(coord[2]))
                    ))
        #print("Done3!")
    def Sample(self,l_top,l_bottom,l_moire, topx,topy,botx,boty,zstrain,twist):
        """
        Calculate and plot tBG sample
        """
        self.Lattice(l_top,l_bottom,l_moire, topx,topy,botx,boty,zstrain,twist)

def make_sample(l_top,l_bottom,l_moire,topx,topy,botx,boty,zstrain,twist):
    tBG_sample = tBG()
    tBG_sample.d0 = zstrain
    tBG_sample.Sample(l_top,l_bottom,l_moire, topx,topy,botx,boty,zstrain,twist)
    return  tBG_sample

def make_strain_twisted_sample(ktop_x, ktop_y, kbot_x, kbot_y, twist_angle,z_strain):

    t = twist_angle*pi/180
    print("twist angle: %3.3f °"%(t*180/pi))

    k_list   = gen_revise_vectors(l_list)
    #k_top    = rotate(strian(k_list,0,x*t,y*t),t)
    #k_bottom = strian(k_list,0,z*t,0)
    k_top    = rotate(strian(k_list, 0, ktop_x, ktop_y),t)
    #k_top = strian(k_list,0, ktop_x, k_top_y)
    k_bottom = strian(k_list,0, kbot_x, kbot_y)
    k_moire  = k_top-k_bottom
    plot_reciprocal(k_top,k_bottom,k_moire,k_list)

    l_top = gen_revise_vectors(k_top)
    l_bottom = gen_revise_vectors(k_bottom)
    l_moire = gen_revise_vectors(k_moire)
    print("l_top is:",l_top)
    print("l_bot is:",l_bottom)
    l_top_new,l_bottom_new,l_moire_new=normalization_lattice(l_top,l_bottom,l_moire)
    print("l_top_new is:",l_top_new)
    print("l_bot_new is:",l_bottom_new)
    plot_lattice(l_top_new,l_bottom_new,l_moire_new)

    make_sample(l_top_new,l_bottom_new,l_moire_new, ktop_x,ktop_y,kbot_x,kbot_y,z_strain,twist_angle)


"""
Куйвалайнен Д.А.
kuyvalaynen@gmail.com
ЗЕБЗ-01-16
"""

class Roman:
    ARABIC_MIN = 1
    ARABIC_MAX = 3999
    ROMAN_MIN = "I"
    ROMAN_MAX = "MMMCMXCIX"

    LETTERS = ["M", "CM", "D", "CD", "C", "XC", "L",
               "XL", "X", "IX", "V", "IV", "I"]
    NUMBERS = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]

    def __init__(self, value):
        if not isinstance(value, (int, str)):
            raise TypeError("Не могу создать римское число из {0}".
                            format(type(value)))

        if isinstance(value, int):
            self.__check_arabic(value)
            self._arabic = value
        elif isinstance(value, str):
            self._arabic = self.to_arabic(value)

    def __add__(self, other):
        if isinstance(other, Roman):
            return Roman(self.arabic + other.arabic)
        elif isinstance(other, int):
            self._arabic += other
            return self
        else:
            raise TypeError("Не корректный тип!")

    def __sub__(self, other):
        if isinstance(other, Roman):
            return Roman(self.arabic - other.arabic)
        elif isinstance(other, int):
            self._arabic -= other
            return self
        else:
            raise TypeError("Не корректный тип!")

    def __mul__(self, other):
        if isinstance(other, Roman):
            return Roman(self.arabic * other.arabic)
        elif isinstance(other, int):
            self._arabic *= other
            return self
        else:
            raise TypeError("Не корректный тип!")

    def __floordiv__(self, other):
        if isinstance(other, Roman):
            return Roman(self.arabic // other.arabic)
        elif isinstance(other, int):
            self._arabic //= other
            return self
        else:
            raise TypeError("Не корректный тип!")

    def __truediv__(self, other):
        return self.__floordiv__(other)

    def __str__(self):
        return Roman.to_roman(self._arabic)

    @staticmethod
    def __check_arabic(value):
        if value < Roman.ARABIC_MIN or value > Roman.ARABIC_MAX:
            raise ValueError("Число не принадлежит [{}; {}]".format(
                Roman.ARABIC_MIN, Roman.ARABIC_MAX))

    @staticmethod
    def __check_roman(value):
        for letter in value:
            if not(letter in Roman.LETTERS):
                raise ValueError("\'value\' содержит недопустимые символы!")

    @property
    def arabic(self):
        return self._arabic

    @staticmethod
    def to_arabic(roman):
        def letter_to_number(letter):
            i = Roman.LETTERS.index(letter)
            return Roman.NUMBERS[i]

        Roman.__check_roman(roman)

        i = 0
        value = 0

        while i < len(roman):

            number = letter_to_number(roman[i])

            i += 1

            if i == len(roman):
                value += number
            else:
                next_number = letter_to_number(roman[i])
                if next_number > number:
                    value += next_number - number
                    i += 1
                else:
                    value += number

        Roman.__check_arabic(value)
        return value

    @staticmethod
    def to_roman(arabic):
        Roman.__check_arabic(arabic)

        roman = ""
        n = arabic

        for i, number in enumerate(Roman.NUMBERS):
            while n >= number:
                roman += Roman.LETTERS[i]
                n -= Roman.NUMBERS[i]

        return roman


def imprimirPolinomios(lista,it):
    lon = len(lista)
    if lon == 1:
        if(lista[-1]) > 0:
            return " + " + str(abs(lista[-1]))
        elif(lista[-1] < 0):
            return " - " + str(abs(lista[-1]))
        elif (it == 0):
            return " + 0"
        else:
            return ""
    else:
        it = it + 1
        if(lista[-1] > 0):
            return " + " + str(abs(lista[-1])) + "x^" + str(lon-1) + imprimirPolinomios(lista[:-1],it)
        elif(lista[-1] < 0):
            return " - " + str(abs(lista[-1])) + "x^" + str(lon-1) + imprimirPolinomios(lista[:-1],it)
        else:
            return imprimirPolinomios(lista[:-1],it)

def casoDePrueba():
    try:
        grado = int(input())
        if(grado >= 0 and grado <= 100):
            numeros = input().split()
            lista = list(map(int, numeros))
            if(len(lista) == (grado+1)):
                if(len(lista) > 1 and lista[-1] != 0) or (len(lista) == 1):
                    print(imprimirPolinomios(lista,0))
                    return True
    except:
        return False

if __name__ == "__main__":
    while casoDePrueba():
        pass


from socket import *
import json
import threading
import time

# map x in range in_min - in_max to the new range out_min - out_max
def valueMap(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

def progress_bar(x, x_min, x_max, width=30, pchar='#'):
    print("[ ", end='')
    converted = int(valueMap(x, x_min, x_max, 0, width))
    for i in range(converted):
        print(pchar, end='')
    for i in range(width-converted):
        print(" ", end='')
    print(f" ]  {x} / {x_max}")

class UdpDummySender():
    def __init__(self):
        self.cs = socket(AF_INET, SOCK_DGRAM)
        self.cs.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.cs.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
        self.load_gps_data()

    def send_object(self, obj):
        """
        test out all paket types

        """
        as_str = json.dumps(obj).encode(encoding='ascii')
        self.cs.sendto(as_str, ('255.255.255.255', 5005))
        print("sending:", as_str)

    def load_gps_data(self):
        with open('gps_data.json', 'r') as file:
            data = file.read()
            self.gps_data = json.loads(data)

    def send_gps_data(self, freq = 60):
        for payload in self.gps_data:
            self.send_object(payload)
            time.sleep(1 / freq)

if __name__ == '__main__':
    sender = UdpDummySender()
    while 1:
        sender.send_gps_data(freq = 60)


import sys

# from sys import stdin
# from collections import defaultdict
#
# read = stdin.readline
# N = int(read())
# dict_list = defaultdict(list)
#
# while True:
#     a, b = map(int, read().split())
#     if a == -1:
#         break
#     dict_list[a].append(b)
#     dict_list[b].append(a)
#
# new_dict = dict()
# _max = -1
# for k, v in dict_list.items():
#     m = len(dict_list[k])
#     new_dict[k] = m
#     if m > _max:
#         _max = m
# result = []
# for k, v in new_dict.items():
#     if v == _max:
#         result.append(k)
# score = N - 1
# final_score = score - _max + 1
#
# print(final_score, len(result))
# print(*result)

# if __name__ == "__main__":
#     n = int(sys.stdin.readline())
#     graph = [[float('inf') for _ in range(n + 1)] for _ in range(n + 1)]
#
#     for i in range(1, n + 1):
#         graph[i][i] = 0
#
#     while True:
#         a, b = map(int, sys.stdin.readline().split())
#         if a == -1 and b == -1:
#             break
#         else:
#             graph[a][b] = 1
#             graph[b][a] = 1
#
#     for k in range(1, n + 1):
#         for i in range(1, n + 1):
#             for j in range(1, n + 1):
#                 graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
#
#     # 회장 후보 점수 찾기
#     min_score = float('inf')
#     for i in range(1, n + 1):
#         min_score = min(min_score, max(graph[i][1:]))
#
# print('min', min_score)
# for g in graph:
#     print(g)

"""
5
1 2
2 3
3 4
4 5
2 4
5 3
-1 -1
"""

import copy

inf = float('inf')
arr = [
    [0, 5, inf, 8],
    [7, 0, 9, inf],
    [2, inf, 0, 4],
    [inf, inf, 3, 0]
]
N = 4

def floydWarshall():
    # temp = [[0] * (N) for _ in range(N)]

    # for i in range(N):
    #     for j in range(N):
    #         temp[i][j] = arr[i][j]
    temp = copy.deepcopy(arr)
    print('1')
    for i in temp:
        print(i)

    print(' ')

    for l in range(N):
        for m in range(N):
            for n in range(N):
                if temp[m][n] > temp[m][l] + temp[l][n]:
                    temp[m][n] = temp[m][l] + temp[l][n]
    for i in (temp):
        print(i)

floydWarshall()


caseNum = int(input())
lists=[]

for i in range(caseNum):
    lists.append(list(map(int, input().split())))

def ter(lists):
    d = (lists[0]-lists[3])**2+(lists[1]-lists[4])**2
    minus =(lists[2]-lists[5])**2
    plus = (lists[2]+lists[5])**2
    if d == 0 and minus == 0 :
        return -1
    elif d == plus or d == minus :
        return 1
    elif d < plus and d > minus :
        return 2
    elif d > plus or minus> d or d==0:
        return 0

for i in lists :
    print(ter(i))


from __future__ import absolute_import, unicode_literals

import requests
from time import sleep
import csv
import os
from os import link
from bs4 import BeautifulSoup

from celery import shared_task
from .models import News
from celery.schedules import crontab

@shared_task()
def news_task():
    News.objects.all().delete()
    print('Collecting news article..')
    for i in range(1,2):
      url=f"https://www.livemint.com/companies/page-{i}"
      page_response = requests.get(url, timeout=240)
      page_content = BeautifulSoup(page_response.content, "lxml")
      main_content=page_content.findAll('li',class_="clearfix")
      hline=page_content.findAll('h2', class_="headline")
      datediv=page_content.findAll('div',class_="headlineSec")
      for i in datediv:
       j=i.find('h2',class_="headline").text.strip()
       k=i.find('span',class_="fl date").text.strip()
       l=i.find('h2',class_="headline")
       x=l.find('a',href=True)
       x=x['href']
       page_secondary=requests.get(x,timeout=240)
       page_content_sec=BeautifulSoup(page_secondary.content,"lxml")
       try:
          desc=page_content_sec.find("ul",class_="highlights").text.strip()
       except:
          desc="No description available"
       count=k.find("Updated:")
       print(count)
       if(count==-1):
        count=17-8
       k=k[count+8:]
       j=j.encode('unicode-escape').decode('utf-8')

       print({'title':j,'description': desc,
                 'pubdate': k,'link':x})

       News.objects.create(
                title=j,
                description=desc,
                pubdate=k,
                link=x,
                news_bool=False
            )

news_task()


import utils

data = [{
  'country': 'colombia',
  'population': 500
}, {
  'country': 'argentina',
  'population': 700
}]

def run():
  keys, values = utils.get_population()
  print(keys, values)

  print(utils.a)

  country = input("type country=> ")

  result = utils.population_by_country(data, country)
  print(result)

#Entry point
if __name__ == '__main__':
  run()


#! /usr/bin/python

import MySQLdb
import crawl_utils
import random
import sys
import os.path
from datetime import datetime
import time
import query
import combos
from loaddb import START_TIME, LOG_DB_MAPPINGS, make_xlog_db_query, query_first

import logging
from logging import debug, info, warn, error

NOMINEE_FILE = 'nemelex-combos.txt'
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'

NEMELEX_USE_LIST = True

def parse_time(when):
  return datetime(*(time.strptime(when, DATE_FORMAT)[0:6]))

def find_previous_nominees(targetfile = NOMINEE_FILE):
  if os.path.exists(targetfile):
    f = open(targetfile)
    nominees = [x.strip().split() for x in f.readlines()
                if x.strip() and not x.strip().startswith('#')]
    f.close()
    return [{'combo': x[0],
             'time': parse_time(x[1] + ' ' + x[2])}
            for x in nominees]
  return []

def _fixup_nominee_validity(c):
  newcombos = []
  for i in range(0, len(c)):
    cur = c[i]
    next = None
    if i < len(c) - 1:
      next = c[i + 1]['time']
    newcombos.append([cur['combo'], cur['time'], next])
  return newcombos

NEMELEX_COMBOS = _fixup_nominee_validity(find_previous_nominees())
NEMELEX_SET = set([x[0] for x in NEMELEX_COMBOS])

def apply_combo(combo, tofile = NOMINEE_FILE):
  time = datetime.utcnow()
  f = open(tofile, 'a')
  f.write("%s %s\n" % (combo, time.strftime(DATE_FORMAT)))
  f.close()
  global NEMELEX_COMBOS
  global NEMELEX_SET
  NEMELEX_COMBOS = _fixup_nominee_validity(find_previous_nominees())
  NEMELEX_SET = set([x[0] for x in NEMELEX_COMBOS])

def filter_combos(combos, filters):
  race_set = set([x[:2] for x in filters])
  class_set = set([x[2:] for x in filters])
  return [x for x in combos if x[:2] not in race_set and x[2:] not in class_set]

def weight_combos(combos, previous):
  weights = []
  for x in combos:
    w = 1
    for y in previous:
      if x[:2] == y[:2] or x[2:] == y[2:]:
        w *= 10
    weights.append(w)
  return weights

def current_nemelex_choice():
  return NEMELEX_COMBOS and NEMELEX_COMBOS[-1]

def list_nemelex_choices(c):
  # Check the file again so that we don't miss one.
  combos = _fixup_nominee_validity(find_previous_nominees())
  nem_list = []
  for x in combos:
    nem_list.append([x[0], x[1], min(count_nemelex_wins(c,x[0]), 9),
        min(count_clan_nemelex_wins(c,x[0]), 9)])
  return nem_list

def is_nemelex_choice(combo, when):
  """Returns true if the given combo for a game that ended at the given
  datetime is a chosen combo for the Nemelex' Choice banner."""
  if combo in NEMELEX_SET:
    for c in NEMELEX_COMBOS:
      if c[0] == combo:
        return True
  return False

def eligible_combos(c):
  # first one is always picked from the special list
  if len(NEMELEX_COMBOS) == 0:
    return [combos.NEM_ELIGIBLE_COMBOS]
  # sometimes look at the special list for the later ones, too
  if NEMELEX_USE_LIST:
    won_games = query.get_winning_games(c)
    won_combos = set([x['charabbrev'] for x in won_games])
    eligible =  [x for x in combos.NEM_ELIGIBLE_COMBOS
                 if (x not in won_combos)]
    pcombo_names = [x[0] for x in NEMELEX_COMBOS]
    weighting = weight_combos(eligible, pcombo_names)
    return [eligible,weighting]
  # otherwise pick from the valid combos with the lowest high score in the tourney:
  else:
    eligible = combos.VALID_COMBOS
    pcombo_names = [x[0] for x in NEMELEX_COMBOS]
    # Try not to use a repeat race or class if possible.
    filtered_eligible = filter_combos(eligible, pcombo_names)
    if filtered_eligible:
      eligible = filtered_eligible
    eligible_with_scores = [[combo_name, query.highscore(c, combo_name)] for combo_name in eligible]
    eligible_with_scores.sort(key = lambda e: e[1])
    l = 19
    if l > len(eligible_with_scores)-1:
      l = len(eligible_with_scores)-1
    candidates = [e[0] for e in eligible_with_scores if e[1] <= eligible_with_scores[l][1]]
    return [candidates]

def pick_combo(data):
  if data[0]:
    eligible = data[0]
    if len(data) > 1:
      weighting = data[1]
      n = len(eligible)
      combo = None
      while not combo:
        i = random.randrange(len(eligible))
        if random.randrange(weighting[i]) == 0:
          combo = eligible[i]
    else:
      combo = eligible[random.randrange(len(eligible))]
    apply_combo(combo)

def need_new_combo(c):
  if not NEMELEX_COMBOS:
    nowtime = datetime.utcnow().strftime('%Y%m%d%H%M')
    return (nowtime >= START_TIME)
  return (count_nemelex_wins(c, current_nemelex_choice()[0]) > 0)

def award_nemelex_win(c, xdict, filename):
    iq = make_xlog_db_query(LOG_DB_MAPPINGS, xdict, filename, None,
                            'player_nemelex_wins')
    try:
      iq.execute(c)
    except Exception as e:
      error("Error inserting %s into %s (query: %s [%s]): %s"
            % (xdict, 'player_nemelex_wins', iq.query, iq.values, e))
      raise

def player_has_nemelex_win(c, player, char):
    return (query_first(c, '''SELECT COUNT(*) FROM player_nemelex_wins
                              WHERE player = %s AND charabbrev = %s''',
                              player, char) > 0)

def count_clan_nemelex_wins(c, char):
    return query_first(c, '''SELECT COUNT(*) FROM clan_nemelex_wins
                             WHERE clan_finish = 1 AND charabbrev = %s''',
                             char)

def count_nemelex_wins(c, char):
    return query_first(c, '''SELECT COUNT(*) FROM player_nemelex_wins
                             WHERE charabbrev = %s''', char)


class Solution:
    def similarity(self, A, B):
        union = set()

        for x in A:
            union.add(x)

        numOfSame = 0
        for x in B:
            if x in union:
                numOfSame += 1
            else:
                union.add(x)

        return numOfSame / len(union)

def main():
    A = [3, 4, 1, 2, 7]
    B = [6, 1, 3, 5, 10]

    sol = Solution()
    print(sol.similarity(A, B))

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""
Created on Fri Jul 21 10:29:18 2017

@author: X.X
"""

from pycqed.measurement.waveform_control.viewer import *
from qcodes.data.data_set import load_data, new_data, DataSet
from qcodes.data.data_array import DataArray

import numpy as np
from io import StringIO
import matplotlib.pyplot as plt
from qcodes.data.hdf5_format import HDF5Format, HDF5FormatMetadata
from qcodes.data.io import DiskIO

NewIO = DiskIO(base_location = 'C:\\Users\\LocalAdmin\\Documents')

datalocation = 'data/2017-07-21/#003_T1_10-55-59'

datalocation2 = 'data/test/T1'
#formatter = HDF5Format()

#data = load_data(location=datalocation, formatter=None, io=NewIO)

original_data = np.genfromtxt('C:/Users/LocalAdmin/Documents/data/test/T1.dat', delimiter='\t', dtype=np.float)

data = original_data[:,(0,2)]

#%% Plot
import scipy
from qtt.algorithms.functions import exp_function

datax=data.T.reshape( (2,8,-1))
datax=np.transpose(datax, (0,2,1) )

plt.figure(10); plt.clf()
for ii in range(8):
    dd=datax[:,:,ii]

    plt.plot(dd[0],dd[1], '.-')

#%% Fitting

def fitT1(xdata, ydata, verbose=1, fig=None):
    """ Determine T1 time by fitting exponential

    Arguments:
        xdata, ydata (array): independent and dependent variable data

    Returns:
        p (array): fitted function parameters
        pp (dict): extra fitting data

    .. seealso:: exp_function
    """
    xdata = np.array(xdata)
    ydata = np.array(ydata)

    timescale = np.percentile(xdata, 99)- np.percentile(xdata, 1)
    # initial values
    p0 = [np.percentile(ydata, 1), np.percentile(ydata, 99)-np.percentile(ydata, 1), 1./timescale]

    if verbose:
        print('fitT1: initial parameters %s' % (p0, ))

    # fit
    pp = scipy.optimize.curve_fit(exp_function, xdata, ydata, p0=p0)
    p = pp[0]

    if fig is not None:
        y = exp_function(xdata, *list(p))
        plt.figure(fig)
        plt.clf()
        plt.plot(xdata, ydata, '.b', label='data')
        plt.plot(xdata, y, 'm-', label='fitted exponential')
        plt.legend(numpoints=1)
    return p, dict({'pp': pp, 'p0': p0})

xdata=dd[0]
ydata=dd[1]
p, r=fitT1(xdata, ydata, verbose=1, fig=100)
#==============================================================================
#
#==============================================================================
#%%
plt.figure(10); plt.clf()
for ii in range(8):
    dd=datax[:,:,ii]
    xdata=dd[0]
    ydata=dd[1]
    p, r=fitT1(xdata, ydata, verbose=0, fig=None)
    yfit = exp_function(xdata, *list(p))

    print('fitted: %s, T1 %.3f [ms]' % (p, 1e3*1./p[2]))

    plt.plot(dd[0],dd[1], '.')
    plt.plot(dd[0],yfit, '-')

#%%

data1 = DataArray(preset_data = data)

#file = open('C:/Users/LocalAdmin/Documents/data/test/T1.dat')

#datanew = new_data(io = NewIO, name = 'testest', arrays = data1)
#dataset = DataSet(arrays = data1, io = NewIO, location = 'data/test/xiao')

#datata = np.loadtxt(name = )
Npoints = 100

#
#plt.ion()
#plt.figure()
#
#
#plt.pcolor(np.linspace(1, Npoints, num=Npoints), data.arrays[data.action_id_map[()]], res_avg)


#!/usr/bin/env python
from tracemalloc import start
import rospy
from std_msgs.msg import String
from rtabmap_ros.msg import MapGraph
import math
import time
from controls import NavType, ControlType

from collections import deque

RAD_TO_DEGREES = 180 / math.pi
PATH_THRESHOLD = .5 # 50 centimeters
DIG_DISTANCE = 20 # meters
DUMP_TIME = 10 # seconds
DIG_TIME = 10 # seconds

class Coord:
    def __init__(self, x, y, z, angle, qX, qY, qZ):
        self.x = x
        self.y = y
        self.z = z
        self.rads = angle
        self.degrees = angle * RAD_TO_DEGREES
        self.qX = qX
        self.qY = qY
        self.qZ = qZ

    def strPos(self):
        return '{'+f'"x":{self.x:.4f},"y":{self.y:.4f}'+'}'

    def __str__(self):
        return '{'+ \
            f'"x":{self.x},"y":{self.y},"z":{self.z},'+ \
            f'"angle:"{self.degrees},"qX:"{self.qX},"qY"{self.qY},"qZ"{self.qZ}'+'}'

class Slam:

    def __init__(self):
        self.home = None
        self.digSite = None
        self.currentPos = None
        self.curPath = deque()
        self.recordedPath = deque()
        self.following = False
        self.turnFlag = True
        self.control = ControlType.NOTHING

    def saveHome(self):
        if self.currentPos is not None:
            self.home = self.currentPos
            angle = self.home.rads
            if self.home.qZ < 0:
                angle = 2*math.pi - angle

            angle += math.pi
            x = self.home.x + math.cos(angle)*20
            y = self.home.y + math.sin(angle)*20
            self.digSite = Coord(x, y,0,0,0,0,0)

            self.curPath.append(self.digSite)
            self.curPath.append(self.home)
            print(self.home)
            print(self.digSite)
            return True
        else:
            print('Ople couldnt find home')
            return False

    def callback(self, data):
        x = data.poses[-1].position.x
        y = data.poses[-1].position.y
        z = data.poses[-1].position.z

        qX = data.poses[-1].orientation.x
        qY = data.poses[-1].orientation.y
        qZ = data.poses[-1].orientation.z
        w = data.poses[-1].orientation.w

        # Note still need to normalize quaternion before calculations
        angTheta = math.acos(w)*2
        s = math.sqrt(1-w*w)
        if s > 0.001: # avoid division by 0
            qX = qX / s
            qY = qY / s
            qZ = qZ / s

        self.currentPos = Coord(x,y,z,angTheta,qX,qY,qZ)
        if self.following:
            if len(self.curPath) == 0:
                self.curPath.append(self.currentPos)

            lastPos = self.curPath[-1]

            if math.sqrt((x-lastPos.x)**2+(y-lastPos.y)**2) > PATH_THRESHOLD:
                self.curPath.append(self.currentPos)

        if (len(self.recordedPath) > 0):
            tarPos = self.recordedPath[-1]
            targetDeg = RAD_TO_DEGREES*math.atan2(
                tarPos.y-self.currentPos.y,
                tarPos.x-self.currentPos.x
                )
            curDeg = self.currentPos.degrees
            if self.currentPos.qZ < 0:
                curDeg = 360 - curDeg

            if targetDeg < 0:
                targetDeg = 360 + targetDeg

            eucDist = math.sqrt((self.currentPos.x-tarPos.x)**2+(self.currentPos.y-tarPos.y)**2)
            if eucDist < .1:
                self.turnFlag = True
                self.recordedPath.pop()
                control = ControlType.STOP

            elif self.turnFlag and (10 < abs(curDeg - targetDeg)):
                if (targetDeg-curDeg > 0):
                    # print('TURN LEFT', f'{targetDeg:.2f} {curDeg:.2f}')
                    control = ControlType.LEFT
                else:
                    # print('TURN RIGHT', f'{targetDeg:.2f} {curDeg:.2f}')
                    control = ControlType.RIGHT

            else:
                self.turnFlag = False
                # print('FORWARD TO:', eucDist)
                control = ControlType.FORWARD
            print(control)
            self.control = control

    def initPath(self):
        self.recordedPath = self.curPath.copy()
        self.curPath.clear()
        return NavType.FOLLOW_PATH

slam = Slam()

def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # name are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('ekf_slam')
    rospy.Subscriber("/rtabmap/mapGraph", MapGraph, slam.callback)

def followPath(digDumpFlag):
    control = slam.control
    navType = NavType.FOLLOW_PATH
    if control == ControlType.NOTHING:
        if digDumpFlag == ControlType.DIGGING:
            control = digDumpFlag
            navType = NavType.NOTHING
        else:
            navType = NavType.FIND_QR
            control = ControlType.STOP

    # elif objDetection.control != ControlType.NOTHING:
    #     control = objDetection.control
    return control, navType

def findQR(digDumpFlag):
    # TODO
    # Implement find QR code procedures
    time.sleep(5)
    # if QR code found and oriented correctly
    if digDumpFlag == ControlType.DIGGING: # Should only be true once
        if slam.saveHome():
            navType = slam.initPath()
            control = ControlType.STOP
    else:
        navType = NavType.NOTHING
        control = ControlType.DUMPING

    return control, navType

def dig():
    pass

def dump():
    pass

if __name__ == '__main__':
    listener()

    curControl = ControlType.NOTHING
    curNavType = NavType.FIND_QR
    digDumpFlag = ControlType.DIGGING
    startTime = None
    running = True
    while running:
        try:
            if curNavType == NavType.FIND_QR:
                control, curNavType = findQR(digDumpFlag)

            elif curNavType == NavType.FOLLOW_PATH:
                control, curNavType = followPath(digDumpFlag)

            elif curControl == ControlType.DIGGING:
                time.sleep(DIG_TIME)
                digDumpFlag = ControlType.DUMPING
                curNavType = slam.initPath()

            elif curControl == ControlType.DUMPING:
                time.sleep(DUMP_TIME)
                digDumpFlag = ControlType.DIGGING
                curNavType = slam.initPath()

            if control != curControl:
                curControl = control
                print(curControl)
        except Exception as e:
            print(e)
            running = False


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import arviz as az
import pandas as pd
import matplotlib.pyplot as plt
import stan as ps
import time

# data from Gossner et al (2022)
data = pd.read_csv("https://raw.githubusercontent.com/SimonErnesto/risk_dengue_2015-2019/main/dengue_travel_europe.csv")

infected = data["infected travellers"].values.astype("int")
total = data["total travellers"].values.astype("int")
N = len(data)
country_id = data['codes'] = np.arange(1,100, dtype = int)

mod = '''
data{
int<lower=0> N;
int<lower = 1> N_countries;
array[N] int y_i;
array[N] int y_t;
array[N] int<lower = 1, upper = N_countries> country_id;
}
parameters{
vector<lower = 0>[4] hp; // hyperpriors
vector<lower = 0>[N_countries] T;
vector<lower = 0>[N_countries] I;
}
model{
hp ~ normal(0,1);
T ~ lognormal(hp[1], hp[2]);
I ~ lognormal(hp[3], hp[4]);
y_t ~ poisson(T[country_id]);
y_i ~ poisson(I[country_id]);
}
'''

datDic = {'N': N,
	  'y_i': infected,
	  'y_t': total,
	  'N_countries': N,
	  'country_id': country_id}

sm = ps.build(mod, data = datDic)
start_time = time.time()
fit = sm.sample(num_chains = 4, num_samples = 1000, num_warmup = 1000)
print("--- %s seconds ---" % (time.time() - start_time))

print(az.summary(fit))
#az.plot_pair(fit, var_names = ['I', 'T'])
#fig = plt.gcf() # to get the current figure...
#fig.savefig("pair.png")


"""
科脉御商v9清洗逻辑
销售，成本，库存，商品， 分类
"""
from datetime import datetime
import pandas as pd
import boto3
import tempfile
import pytz
import time

_TZINFO = pytz.timezone("Asia/Shanghai")

S3_BUCKET = "ext-etl-data"
S3 = boto3.resource("s3")

CLEANED_PATH = "clean_data/source_id={source_id}/clean_date={date}/target_table={target_table}/dump={timestamp}&rowcount={rowcount}.csv.gz"

def clean_kemaiyushang(source_id, date, target_table, data_frames):
    if target_table == "goodsflow":
        return clean_goodsflow(source_id, date, target_table, data_frames)
    elif target_table == "cost":
        return clean_cost(source_id, date, target_table, data_frames)
    elif target_table == "store":
        return clean_store(source_id, date, target_table, data_frames)
    elif target_table == "goods":
        return clean_goods(source_id, date, target_table, data_frames)
    elif target_table == "category":
        return clean_category(source_id, date, target_table, data_frames)

def clean_goodsflow(source_id, date, target_table, data_frames):
    """
    清洗销售流水
    :param source_id:
    :param date:
    :param target_table:
    :param data_frames:
    :return:
    """
    columns = [
        'source_id', 'cmid', 'foreign_store_id', 'store_name', 'receipt_id', 'consumer_id', 'saletime',
        'last_updated', 'foreign_item_id', 'barcode', 'item_name', 'item_unit', 'saleprice', 'quantity', 'subtotal',
        'foreign_category_lv1', 'foreign_category_lv1_name', 'foreign_category_lv2', 'foreign_category_lv2_name',
        'foreign_category_lv3', 'foreign_category_lv3_name', 'foreign_category_lv4', 'foreign_category_lv4_name',
        'foreign_category_lv5', 'foreign_category_lv5_name', 'pos_id'
    ]
    cmid = source_id.split("Y")[0]

    master = data_frames["pos_t_salemaster"]
    store = data_frames["bi_t_branch_info"]
    sale = data_frames["pos_t_saleflow"]
    item = data_frames["bi_t_item_info"]
    temp = data_frames["bi_t_item_cls"]
    lv4 = temp[(temp.lever_num == 4) & (temp.item_flag == "0")]
    lv3 = temp[(temp.lever_num == 3) & (temp.item_flag == "0")]
    lv2 = temp[(temp.lever_num == 2) & (temp.item_flag == "0")]
    lv1 = temp[(temp.lever_num == 1) & (temp.item_flag == "0")]

    if len(master) == 0:
        frames = pd.DataFrame(columns=columns)
    else:
        frames = (
            master
            .merge(store, how="left", on="branch_id")
            .merge(sale, how="left", on="flow_no")
            .merge(item, how="left", on="item_id", suffixes=("_sale", "_item"))
        )

        frames["lv1_item"] = frames.item_clsno.apply(lambda x: x if pd.isnull(x) else x[:2])
        frames["lv2_item"] = frames.item_clsno.apply(lambda x: x if pd.isnull(x) else x[:4])
        frames["lv3_item"] = frames.item_clsno.apply(lambda x: x if pd.isnull(x) else x[:6])
        frames = (
            frames
            .merge(lv4, how="left", on="item_clsno")
            .merge(lv3, how="left", left_on="lv3_item", right_on="item_clsno", suffixes=("_lv4", "_lv3"))
            .merge(lv2, how="left", left_on="lv2_item", right_on="item_clsno")
            .merge(lv1, how="left", left_on="lv1_item", right_on="item_clsno", suffixes=("_lv2", "_lv1"))
        )
        frames = frames[frames["item_id"].notna()]

        frames["source_id"] = source_id
        frames["cmid"] = cmid
        frames["consumer_id"] = ""
        frames["last_updated"] = datetime.now(_TZINFO)
        frames["saleprice"] = frames.apply(lambda row: 0 if row["sell_way"] == "C" else row["sale_price"], axis=1)
        frames["quantity"] = frames.apply(
            lambda row:
            row["sale_qty"]
            if row["sell_way"] in ("A", "C")
            else -1 * row["sale_qty"], axis=1
        )

        def generate_subtotal(row):
            if row["sell_way"] == "A":
                return row["sale_money"]
            elif row["sell_way"] == "B":
                return -1 * row["sale_money"]
            elif row["sell_way"] == "C":
                return 0
        frames["subtotal"] = frames.apply(generate_subtotal, axis=1)

        frames["item_clsno_lv4"] = frames["item_clsno_lv4"].fillna("")
        frames["foreign_category_lv1"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 2 else row["item_clsno_lv1"], axis=1)
        )
        frames["foreign_category_lv1_name"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 2 else row["item_clsname_lv1"], axis=1)
        )
        frames["foreign_category_lv2"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 4 else row["item_clsno_lv2"], axis=1)
        )
        frames["foreign_category_lv2_name"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 4 else row["item_clsname_lv2"], axis=1)
        )
        frames["foreign_category_lv3"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 6 else row["item_clsno_lv3"], axis=1)
        )
        frames["foreign_category_lv3_name"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 6 else row["item_clsname_lv3"], axis=1)
        )
        frames["foreign_category_lv4"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 8 else row["item_clsno_lv4"], axis=1)
        )
        frames["foreign_category_lv4_name"] = (
            frames.apply(lambda row: "" if len(row["item_clsno_lv4"]) < 8 else row["item_clsname_lv4"], axis=1)
        )
        frames["foreign_category_lv5"] = ""
        frames["foreign_category_lv5_name"] = None
        frames["pos_id"] = ""
        frames = frames.rename(columns={
            "branch_id": "foreign_store_id",
            "branch_name": "store_name",
            "flow_no": "receipt_id",
            "oper_date": "saletime",
            "item_id": "foreign_item_id",
            "item_subno_sale": "barcode",
            "item_name": "item_name",
            "unit_no": "item_unit",
        })

        frames = frames[columns]

    return upload_to_s3(frames, source_id, date, target_table)

def clean_cost(source_id, date, target_table, data_frames):
    """
    清洗成本
    """
    columns = [
        "source_id", "foreign_store_id", "foreign_item_id", "date", "cost_type", "total_quantity", "total_sale",
        "total_cost", "foreign_category_lv1", "foreign_category_lv2", "foreign_category_lv3",
        "foreign_category_lv4", "foreign_category_lv5", "cmid"
    ]
    cmid = source_id.split("Y")[0]

    cost = data_frames["ic_t_jxc_daysum_amt"]
    item = data_frames["bi_t_item_info"]

    if len(cost) == 0:
        frames = pd.DataFrame(columns=columns)
    else:
        frames = (
            cost
            .merge(item, how="left", on="item_id")
        )
        frames = frames[frames["item_id"].notna()]
        frames = frames.groupby(["branch_id", "item_id", "oper_date", "item_clsno"], as_index=False)\
            .agg({"ls_qty": sum, "ls_amt_s": sum, "ls_amt": sum})

        frames["source_id"] = source_id
        frames["cost_type"] = ""
        frames["foreign_category_lv1"] = frames.item_clsno.apply(lambda x: x if len(x) == 2 else x[:2])
        frames["foreign_category_lv2"] = frames.item_clsno.apply(lambda x: "" if len(x) < 4 else x[:4])
        frames["foreign_category_lv3"] = frames.item_clsno.apply(lambda x: "" if len(x) < 6 else x[:6])
        frames["foreign_category_lv4"] = frames.item_clsno.apply(lambda x: "" if len(x) < 8 else x[:8])
        frames["foreign_category_lv5"] = ""
        frames["cmid"] = cmid
        frames = frames.rename(columns={
            "branch_id": "foreign_store_id",
            "item_id": "foreign_item_id",
            "oper_date": "date",
            "ls_qty": "total_quantity",
            "ls_amt_s": "total_sale",
            "ls_amt": "total_cost"
        })
        frames = frames[columns]

    return upload_to_s3(frames, source_id, date, target_table)

def clean_goods(source_id, date, target_table, data_frames):
    """
    清洗商品
    """

    cmid = source_id.split("Y")[0]

    item = data_frames["bi_t_item_info"]
    supcust = data_frames["bi_t_supcust_info"]

    frames = (
        item
        .merge(supcust, how="left", left_on="sup_id", right_on="supcust_id")
    )

    frames["cmid"] = cmid

    def generate_item_status(x):
        if x == "0":
            return "未审核"
        elif x == "1":
            return "建档"
        elif x == "2":
            return "新品"
        elif x == "3":
            return "正常"
        elif x == "4":
            return "新品"
        elif x == "5":
            return "预淘汰"
        elif x == "6":
            return "淘汰"
        elif x == "7":
            return "停用"
        elif x == "8":
            return "已删除"

    frames["item_status"] = frames.lifecycle_flag.apply(generate_item_status)
    frames["foreign_category_lv1"] = frames.item_clsno.apply(lambda x: "" if len(x) == 2 else x[:2])
    frames["foreign_category_lv2"] = frames.item_clsno.apply(lambda x: "" if len(x) == 2 else x[:4])
    frames["foreign_category_lv3"] = frames.item_clsno.apply(lambda x: "" if len(x) == 2 else x[:6])
    frames["foreign_category_lv4"] = frames.item_clsno.apply(lambda x: "" if len(x) == 2 else x[:8])
    frames["foreign_category_lv5"] = ""
    frames["storage_time"] = datetime.now(_TZINFO)
    frames["last_updated"] = datetime.now(_TZINFO)
    frames["isvalid"] = 1
    frames["warranty"] = ""
    frames["allot_method"] = ""
    frames["brand_name"] = ""

    frames = frames.rename(columns={
        "item_subno": "barcode",
        "item_id": "foreign_item_id",
        "item_name": "item_name",
        "in_price": "lastin_price",
        "sale_price": "sale_price",
        "unit_no": "item_unit",
        "item_no": "show_code",
        "sup_name": "supplier_name",
        "supcust_no": "supplier_code"
    })

    frames = frames[[
        "cmid", "barcode", "foreign_item_id", "item_name", "lastin_price", "sale_price", "item_unit", "item_status",
        "foreign_category_lv1", "foreign_category_lv2", "foreign_category_lv3", "foreign_category_lv4", "storage_time",
        "last_updated", "isvalid", "warranty", "show_code", "foreign_category_lv5", "allot_method", "supplier_name",
        "supplier_code", "brand_name"
    ]]

    return upload_to_s3(frames, source_id, date, target_table)

def clean_category(source_id, date, target_table, data_frames):
    """
    分类清洗
    """
    columns = [
        'cmid', 'level', 'foreign_category_lv1', 'foreign_category_lv1_name', 'foreign_category_lv2',
        'foreign_category_lv2_name', 'foreign_category_lv3', 'foreign_category_lv3_name',
        'last_updated', 'foreign_category_lv4', 'foreign_category_lv4_name', 'foreign_category_lv5',
        'foreign_category_lv5_name'
    ]
    cmid = source_id.split("Y")[0]

    temp = data_frames["bi_t_item_cls"]
    lv4 = temp[(temp.lever_num == 4) & (temp.item_flag == "0")]
    lv3 = temp[(temp.lever_num == 3) & (temp.item_flag == "0")]
    lv2 = temp[(temp.lever_num == 2) & (temp.item_flag == "0")]
    lv1 = temp[(temp.lever_num == 1) & (temp.item_flag == "0")]

    category1 = lv1.copy()
    category1["cmid"] = cmid
    category1["level"] = 1
    category1["foreign_category_lv2"] = ""
    category1["foreign_category_lv2_name"] = None
    category1["foreign_category_lv3"] = ""
    category1["foreign_category_lv3_name"] = None
    category1["foreign_category_lv4"] = ""
    category1["foreign_category_lv4_name"] = None
    category1["foreign_category_lv5"] = ""
    category1["foreign_category_lv5_name"] = None
    category1["last_updated"] = datetime.now(_TZINFO)
    category1 = category1.rename(columns={
        "item_clsno": "foreign_category_lv1",
        "item_clsname": "foreign_category_lv1_name"
    })
    category1 = category1[columns]

    category2 = (
        lv2.copy()
        .merge(lv1, how="left", left_on="up_clsno", right_on="item_clsno", suffixes=("_lv2", "_lv1"))
    )
    category2["cmid"] = cmid
    category2["level"] = 2
    category2["foreign_category_lv3"] = ""
    category2["foreign_category_lv3_name"] = None
    category2["foreign_category_lv4"] = ""
    category2["foreign_category_lv4_name"] = None
    category2["foreign_category_lv5"] = ""
    category2["foreign_category_lv5_name"] = None
    category2["last_updated"] = datetime.now(_TZINFO)
    category2 = category2.rename(columns={
        "item_clsno_lv1": "foreign_category_lv1",
        "item_clsname_lv1": "foreign_category_lv1_name",
        "item_clsno_lv2": "foreign_category_lv2",
        "item_clsname_lv2": "foreign_category_lv2_name"
    })
    category2 = category2[columns]

    category3 = (
        lv3.copy()
        .merge(lv2, how="left", left_on="up_clsno", right_on="item_clsno", suffixes=("_lv3", "_lv2"))
        .merge(lv1, how="left", left_on="up_clsno_lv2", right_on="item_clsno")
    )
    category3["cmid"] = cmid
    category3["level"] = 3
    category3["foreign_category_lv4"] = ""
    category3["foreign_category_lv4_name"] = None
    category3["foreign_category_lv5"] = ""
    category3["foreign_category_lv5_name"] = None
    category3["last_updated"] = datetime.now(_TZINFO)
    category3 = category3.rename(columns={
        "item_clsno": "foreign_category_lv1",
        "item_clsname": "foreign_category_lv1_name",
        "item_clsno_lv2": "foreign_category_lv2",
        "item_clsname_lv2": "foreign_category_lv2_name",
        "item_clsno_lv3": "foreign_category_lv3",
        "item_clsname_lv3": "foreign_category_lv3_name"
    })
    category3 = category3[columns]

    category4 = (
        lv4.copy()
        .merge(lv3, how="left", left_on="up_clsno", right_on="item_clsno", suffixes=("_lv4", "_lv3"))
        .merge(lv2, how="left", left_on="up_clsno_lv3", right_on="item_clsno")
        .merge(lv1, how="left", left_on="up_clsno", right_on="item_clsno", suffixes=("_lv2", "_lv1"))
    )
    category4["cmid"] = cmid
    category4["level"] = 4
    category4["foreign_category_lv5"] = ""
    category4["foreign_category_lv5_name"] = None
    category4["last_updated"] = datetime.now(_TZINFO)
    category4 = category4.rename(columns={
        "item_clsno_lv1": "foreign_category_lv1",
        "item_clsname_lv1": "foreign_category_lv1_name",
        "item_clsno_lv2": "foreign_category_lv2",
        "item_clsname_lv2": "foreign_category_lv2_name",
        "item_clsno_lv3": "foreign_category_lv3",
        "item_clsname_lv3": "foreign_category_lv3_name",
        "item_clsno_lv4": "foreign_category_lv4",
        "item_clsname_lv4": "foreign_category_lv4_name"
    })
    category4 = category4[columns]

    category = pd.concat([category1, category2, category3, category4])

    return upload_to_s3(category, source_id, date, target_table)

def clean_store(source_id, date, target_table, data_frames):
    """
    门店清洗
    """
    cmid = source_id.split("Y")[0]
    store_frames = data_frames["bi_t_branch_info"]

    store_frames["cmid"] = cmid
    store_frames["address_code"] = None
    store_frames["device_id"] = None
    store_frames["store_status"] = store_frames.display_flag.apply(lambda x: "闭店" if x == "0" else "正常")
    store_frames["create_date"] = datetime.now(_TZINFO)
    store_frames["lat"] = None
    store_frames["lng"] = None
    store_frames["area_code"] = ""
    store_frames["area_name"] = ""
    store_frames["business_area"] = None

    def generate_property(row):
        if row == "0":
            return "总部"
        elif row == "1":
            return "配套中心"
        elif row == "2":
            return "直营店"
        elif row == "8":
            return "仓库"
    store_frames["property_id"] = store_frames["property"]
    store_frames["property"] = store_frames.property.apply(generate_property)
    store_frames["source_id"] = source_id
    store_frames["last_updated"] = datetime.now(_TZINFO)

    frames = store_frames.rename(columns={
        "branch_id": "foreign_store_id",
        "branch_name": "store_name",
        "address": "store_address",
        "branch_no": "show_code",
        "branch_tel": "phone_number",
        "branch_man": "contacts"
    })
    frames = frames[
        ['cmid', 'foreign_store_id', 'store_name', 'store_address', 'address_code', 'device_id', 'store_status',
         'create_date', 'lat', 'lng', 'show_code', 'phone_number', 'contacts', 'area_code', 'area_name',
         'business_area', 'property_id', 'property', 'source_id', 'last_updated']]

    return upload_to_s3(frames, source_id, date, target_table)

def upload_to_s3(frame, source_id, date, target_table):
    filename = tempfile.NamedTemporaryFile(mode="w", encoding="utf-8")
    count = len(frame)
    frame.to_csv(filename.name, index=False, compression="gzip", float_format='%.4f')
    filename.seek(0)
    key = CLEANED_PATH.format(
        source_id=source_id,
        target_table=target_table,
        date=date,
        timestamp=now_timestamp(),
        rowcount=count,
    )
    S3.Bucket(S3_BUCKET).upload_file(filename.name, key)
    return key

def now_timestamp():
    _timestamp = datetime.fromtimestamp(time.time(), tz=_TZINFO)
    return _timestamp


# PROGRAM rotate_array:

'''
Given a random integer array of size n, write a function that rotates the given array by d elements (towards left).

Change in the input array itself. You don't need to return or print elements.

Input format:
Line 1 : Integer n (Array Size)
Line 2 : Array elements (separated by space)
Line 3 : Integer d

Output Format:
Updated array elements (separated by space)

Constraints :
1 <= N <= 1000
1 <= d <= N

Sample Input:
7
1 2 3 4 5 6 7
2

Sample Output:
3 4 5 6 7 1 2
'''

#######################
# Rotate Array Module #
#######################

def rotate_array(arr, d):
	new_tail = arr[:d]
	for i in range(d, len(arr)):
	# DO
		arr[i - d] = arr[i]
	# ENDFOR;
	for i in range(d):
	# DO
		arr[i - d] = new_tail[i]
	# ENDFOR;
# END rotate_array(arr, d).

n = int(input("Input the size of array (or list): \n"))
arr = [int(x) for x in input("Input the elements of array (or list, separated by space): \n").split()]
d = int(input("Input the number of elements (positive integer value) by which the array (or list) needs to be rotated towards the left: \n"))
rotate_array(arr, d)
print(*arr)
# END.


def getTreesHit(terrain, xSlope, ySlope=1):
    trees_hit = 0
    currentX = 0
    rowLength = len(terrain[0])
    for rowIndex in range(0, len(terrain), ySlope):
        if terrain[rowIndex][currentX] == '#':
            trees_hit += 1
        currentX = (currentX + xSlope) % rowLength
    return trees_hit

with open("input3.txt") as f:
    dumb = list(f)
    terrain = [x.strip() for x in dumb]
    slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
    results = [getTreesHit(terrain, x[0], x[1]) for x in slopes]
    print(results[1])
    print(results[0] * results[1] * results[2]
          * results[3] * results[4])


from random import shuffle
from typing import List

import ActivationFunctions
from ActivationFunctions import *
import pandas as pd

from ImageFilter import ImageFilter, Flatten
from Network import Network
from Utilities import LearningMode, HiddenLayersStructure
from Neurons.NeuronLayers import HiddenNeuronLayer

class MLPNeuralNetwork:

    def __init__(self, train_inputs: pd.DataFrame, train_outputs: pd.DataFrame,
                 hidden_structures: HiddenLayersStructure = HiddenLayersStructure(),
                 input_activation: ActivationFunctions = IdentityFunction(),
                 output_activation: ActivationFunctions = BipolarSigmoid(),
                 predict_activation: ActivationFunctions = BipolarFunction(),
                 input_filter: ImageFilter = None, learning_rate=-1,
                 initial_weights: List[pd.DataFrame] = None,
                 show_logs: bool = False):

        if type(train_outputs) is pd.Series:
            train_outputs = train_outputs.to_frame()
        if type(train_inputs) is pd.Series:
            train_inputs = train_inputs.to_frame()

        self.filter = input_filter
        self.train_inputs = self.alter_filters(train_inputs)
        self.train_outputs = train_outputs
        self.hidden_structures = hidden_structures

        self.network = self.generate_network(predict_activation, input_activation, output_activation,
                                             learning_rate, initial_weights, show_logs)

    def generate_network(self, predict_activation: ActivationFunctions = IdentityFunction(),
                         input_activation: ActivationFunctions = IdentityFunction(),
                         output_activation: ActivationFunctions = BipolarSigmoid(),
                         learning_rate=-1,
                         initial_weights: List[pd.DataFrame] = None,
                         show_logs: bool = False):
        network = Network(self.train_inputs.shape[1], self.train_outputs.shape[1]
                          , input_activation=input_activation
                          , output_activation=output_activation
                          , prediction_activation=predict_activation
                          , initial_weights=initial_weights
                          , show_logs=show_logs)
        for i in range(len(self.hidden_structures)):
            network.add_hidden_layer(HiddenNeuronLayer(network.output_layer.index, self.hidden_structures[i][0],
                                                       self.hidden_structures[i][1], show_logs=show_logs))
        network.generate_connection_layers(learning_rate)
        return network

    def train(self, epochs: int = 100, mode: LearningMode = LearningMode.Batch, show_logs: bool = False):

        if mode == LearningMode.Batch:
            self.__batch_train(epochs)
        elif mode == LearningMode.Incremental:
            self.__sequential_train(epochs)

    def evaluate(self, test_inputs: pd.DataFrame, test_outputs: pd.DataFrame):
        confusion_matrix: pd.DataFrame = None
        if type(test_outputs) is pd.Series:
            value_set = set(test_outputs)
            test_outputs = test_outputs.to_frame()
            confusion_matrix = pd.DataFrame(np.zeros((len(value_set), len(value_set))))
        else:
            confusion_matrix = pd.DataFrame(np.zeros((test_outputs.shape[1], test_outputs.shape[1])))

        if type(test_inputs) is pd.Series:
            test_inputs = test_inputs.to_frame()

        test_inputs = self.alter_filters(test_inputs)

        for i in range(test_inputs.shape[0]):
            output_vector = self.network.feed_test_values(test_inputs.iloc[i])
            if test_outputs.shape[1] == 1:
                n1 = test_outputs.iloc[i][0]-1
                n2 = output_vector[0]-1
                confusion_matrix[n1][n2] += 1
            else:
                for j in range(len(output_vector)):
                    for k in range(test_outputs.shape[1]):
                        if output_vector[j] > 0 and test_outputs.iloc[i, k] > 0:
                            confusion_matrix[k][j] += 1

        print('\nConfusion matrix:\n', confusion_matrix, '\n')

        return np.trace(confusion_matrix) / np.sum(confusion_matrix.values.flatten())

    def __batch_train(self, epochs: int = 100):
        ending_condition = False
        epoch = 0
        print('batch mode ')
        while not ending_condition:
            print('Epoch ', epoch+1)
            for i in range(self.train_inputs.shape[0]):
                self.network.feed_train_values(self.train_inputs.iloc[i], self.train_outputs.iloc[i])
            self.network.update_weights()
            epoch += 1
            ending_condition = epoch > epochs

    def __sequential_train(self, epochs: int = 100, show_logs: bool = False):
        ending_condition = False
        epoch = 0
        print('incremental mode ')
        while not ending_condition:
            print('Epoch ', epoch+1)
            indices = self.train_inputs.index.to_numpy()
            shuffle(indices)
            for i in indices:
                self.network.feed_train_values(self.train_inputs.iloc[i], self.train_outputs.iloc[i])
                self.network.update_weights()

            epoch += 1
            ending_condition = epoch > epochs

    def alter_filters(self, df: pd.DataFrame):
        if self.filter is not None:
            return self.filter.run(df)
        return df

    def has_flatten(self):
        for fil in self.filter.filter_functions:
            fff = isinstance(fil, Flatten)
            if fff:
                return True

        return False


import custom_sequence_classification as csc
from utils import prepare_data_for_modelling
from transformers import AutoTokenizer, TrainingArguments, Trainer, AutoModelForSequenceClassification, EarlyStoppingCallback, IntervalStrategy, set_seed
from datasets import load_dataset, ClassLabel
import torch
import logging
import time
import hydra
from omegaconf import DictConfig
import numpy as np
import pandas as pd
import os
import copy
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class ClassificationTrainer():
    def __init__(self, config):
        self.config = config
        self.seeds = self.config["seeds"]
        self.train_label = self.config["data"]["train_label"]
        self.test_label = self.config["data"]["test_label"]

        if self.config["data"]["emojis"]:
            self.emoji_tokens = open(self.config["data"]["emojis_names_path"], "r").read().replace("\n", " ").split(" ")
        else:
            self.emoji_tokens = None

        if self.config["data"]["author_feats"]:
            self.author_feats = open(self.config["data"]["author_feat_names_path"], "r").read().replace("\n", " ").split(" ")
        else:
            self.author_feats = None

        if not os.path.exists(self.config["logging"]["path"]):
            os.makedirs(self.config["logging"]["path"])

    def _prepare_data(self):
        data =  pd.read_csv(self.config["data"]["data_path"])
        if self.config["data"]["test_data_path"]:
            test_data = pd.read_csv(self.config["data"]["test_data_path"])

        for seed in self.seeds:
            # Split dataset (70/10/20)
            if self.config["data"]["test_data_path"]:
                _, data_test = train_test_split(test_data, test_size=0.2, random_state=seed, stratify=test_data[self.test_label])
                if self.test_label in data.columns:
                    strat_col = self.test_label
                else:
                    strat_col = self.train_label
                if self.config["data"]["val_size"]:
                    val_size = self.config["data"]["val_size"]
                else:
                    val_size = 0.1
                data_train, data_val = train_test_split(data, test_size=val_size, random_state=seed, stratify=data[strat_col])
                train_cols = list(data_train.columns)
                if self.test_label not in train_cols:
                    train_cols.append(self.test_label)
                data_test = data_test[train_cols]
            else:
                data_train, data_test = train_test_split(data, test_size=0.2, random_state=seed, stratify=data[self.test_label])
                data_train, data_val = train_test_split(data_train, train_size=(0.7/0.8), test_size=(0.1/0.8), random_state=seed, stratify=data_train[self.test_label])

            # Different column names handling in case of e.g. training with weak labels
            if self.test_label != self.train_label:
                data_test = data_test.drop(columns=[self.train_label])
                if self.test_label in data.columns:
                    data_train = data_train.drop(columns=[self.test_label])
                    data_val = data_val.drop(columns=[self.test_label])

                data_train = data_train.rename(columns={self.train_label: self.test_label})
                data_val = data_val.rename(columns={self.train_label: self.test_label})

            # Standardscaler
            if self.config["data"]["author_feats"]:
                scaler = StandardScaler()
                data_train[self.author_feats] = scaler.fit_transform(data_train[self.author_feats])
                data_test[self.author_feats] = scaler.transform(data_test[self.author_feats])
                data_val[self.author_feats] = scaler.transform(data_val[self.author_feats])

            # Save Samples
            save_directory = "{}/seed_{}/".format(self.config["data"]["data_splitted_dir"], seed)
            if not os.path.exists(save_directory):
                os.makedirs(save_directory)
            data_train.to_csv("{}data_train.csv".format(save_directory), index=False)
            data_val.to_csv("{}data_val.csv".format(save_directory), index=False)
            data_test.to_csv("{}data_test.csv".format(save_directory), index=False)

    def _read_prepared_data(self):
        data_dict = {}
        for seed in self.seeds:
            path_dir = "{}/seed_{}".format(self.config["data"]["data_splitted_dir"], seed)
            data_dict[seed] = load_dataset(path_dir, data_files={"train": "data_train.csv", "validation": "data_val.csv", "test": "data_test.csv"})
            label = ClassLabel(num_classes=self.config["num_classes"], names=[i for i in range(self.config["num_classes"])])
            data_dict[seed] = data_dict[seed].cast_column(self.test_label, label)
        self.data_dict = data_dict

    def train_and_test(self, model, dataset):
        train_args = TrainingArguments(
            output_dir="{}/trainer".format(self.config["logging"]["path"]),
            per_device_train_batch_size=self.config["train_args"]["batch_size_train"],
            per_device_eval_batch_size=self.config["train_args"]["batch_size_val"],
            evaluation_strategy=IntervalStrategy.STEPS,
            eval_steps=self.config["train_args"]["eval_steps"],
            save_steps=self.config["train_args"]["eval_steps"],
            save_total_limit=self.config["train_args"]["save_total_limit"],
            learning_rate=self.config["train_args"]["learning_rate"],
            num_train_epochs=self.config["train_args"]["num_train_epochs"],
            optim="adamw_hf",
            load_best_model_at_end=True,
            metric_for_best_model="eval_f1",
        )

        def compute_metrics(eval_pred):
            logits, labels = eval_pred
            probs = torch.nn.functional.softmax(torch.from_numpy(logits), dim=-1)
            predictions = np.argmax(logits, axis=-1)
            accuracy = metrics.accuracy_score(y_true=labels, y_pred=predictions)
            recall = metrics.recall_score(y_true=labels, y_pred=predictions)
            precision = metrics.precision_score(y_true=labels, y_pred=predictions)
            f1 = metrics.f1_score(y_true=labels, y_pred=predictions)
            auc = metrics.roc_auc_score(labels, [i[1] for i in probs])
            aps = metrics.average_precision_score(labels, [i[1] for i in probs])
            return {"accuracy": accuracy, "precision": precision, "recall": recall, "f1": f1, "auc": auc, "aps": aps}

        trainer = Trainer(
            model=model,
            args=train_args,
            train_dataset=dataset["train"],
            eval_dataset=dataset["validation"],
            compute_metrics=compute_metrics,
            callbacks=[EarlyStoppingCallback(early_stopping_patience=self.config["train_args"]["early_stopping_patience"])]
        )

        # Fine tuning
        logger.info("Beginning training...")
        start_time = time.time()
        trainer.train()
        logger.info("Training finished, took {} seconds".format(time.time() - start_time))

        # Save model
        #trainer.save_model("{}".format(self.config["logging"]["path"]))

        # Test and return performance metrics
        logger.info("Beginning testing...")
        return trainer.predict(dataset["test"])[2]

    def run_expirements(self):
        # Prepare data
        if not hasattr(self, "data_dict") and self.config["data"]["need_data_prep"]:
            logger.info("Preparing data {}...".format(self.config["data"]["train_data"]))
            self._prepare_data()
            logger.info("Reading data...")
            self._read_prepared_data()
        elif not hasattr(self, "data_dict") and not self.config["data"]["need_data_prep"]:
            logger.info("Reading data {}...".format(self.config["data"]["train_data"]))
            self._read_prepared_data()

        df_performance = pd.DataFrame(columns=["seed", "model", "train_data", "author_features"])
        for plm in self.config["plms"]:
            # Load tokenizer
            tokenizer = AutoTokenizer.from_pretrained(plm)
            if self.config["data"]["emojis"]:
                tokenizer.add_tokens(self.emoji_tokens)

            def tokenize_func(examples):
                return tokenizer(examples[self.config["data"]["text"]], padding="max_length", truncation=True, max_length=128)

            # Run expirements
            for seed in self.seeds:
                logger.info("Starting run for Data {}, PLM {}, seed {}...".format(self.config["data"]["train_data"], plm, seed))
                set_seed(seed)
                # Load model
                if self.config["data"]["author_feats"]:
                    if plm == "bert-large-cased":
                        model = csc.CustomBertForSequenceClassification.from_pretrained(plm, num_labels=2, num_extra_dims=len(self.author_feats))
                    else:
                        model = csc.CustomRobertaForSequenceClassification.from_pretrained(plm, num_labels=2, num_extra_dims=len(self.author_feats))
                    data = prepare_data_for_modelling(
                        data=self.data_dict[seed],
                        tokenizer=tokenizer,
                        text_field=self.config["data"]["text"],
                        # additional_tokens=emoji_tokens, already added
                        padding="max_length",
                        truncation=True,
                        max_length=128,
                        extra_feats=self.author_feats,
                    )
                else:
                    model = AutoModelForSequenceClassification.from_pretrained(plm, num_labels=self.config["num_classes"])
                    data = self.data_dict[seed].map(tokenize_func, batched=True)

                if self.config["data"]["emojis"]:
                    model.resize_token_embeddings(len(tokenizer))

                if self.config["train_args"]["num_freeze_layers"]:
                    modules = [model.base_model.embeddings, model.base_model.encoder.layer[:self.config["train_args"]["num_freeze_layers"]]]
                    for module in modules:
                        for param in module.parameters():
                            param.requires_grad = False

                results = self.train_and_test(copy.deepcopy(model), data)
                logger.info("Finished run for PLM {}, seed {}...".format(plm, seed))
                results.update({"seed": seed, "model": plm, "train_data": self.config["data"]["train_data"], "author_features": self.config["data"]["author_feats"]})
                df_performance = df_performance.append(results, ignore_index=True)
                df_performance.to_csv("{}/results_full_finetuning.csv".format(self.config["logging"]["path"], index=False))

@hydra.main(config_path="", config_name="config_hqp.yaml", version_base=None)
def main(cfg: DictConfig):
    ClassificationTrainer(cfg.conf_hqp).run_expirements()

if __name__ == '__main__':
    main()


#乱序字符串数是指一个字符串的重新排列,
#eg:python ypthon

def find_ruanxu_str(string1,string2):
    dic={}
    for i in string1:
        if dic.get(i):
            dic[i]+=1
        else:
            dic[i]=1
    for i in string2:
        if dic.get(i):
            dic[i]-=1
        else:
            return False