from math import log, pi

from fluids.constants import g
from fluids.friction import friction_factor

__all__ = ['Lehrer', 'Stein_Schmidt']

def Lehrer(m, Dtank, Djacket, H, Dinlet, rho, Cp, k, mu, muw=None,
           isobaric_expansion=None, dT=None, inlettype='tangential',
           inletlocation='auto'):
    r'''Calculates average heat transfer coefficient for a jacket around a
    vessel according to [1]_ as described in [2]_.

    .. math::
        Nu_{S,L} = \left[\frac{0.03Re_S^{0.75}Pr}{1 + \frac{1.74(Pr-1)}
        {Re_S^{0.125}}}\right]\left(\frac{\mu}{\mu_w}\right)^{0.14}

    .. math::
        d_g = \left(\frac{8}{3}\right)^{0.5}\delta

    .. math::
        v_h = (v_Sv_{inlet})^{0.5} + v_A

    .. math::
        v_{inlet} = \frac{Q}{\frac{\pi}{4}d_{inlet}^2}

    .. math::
        v_s = \frac{Q}{\frac{\pi}{4}(D_{jacket}^2 - D_{tank}^2)}

    For Radial inlets:

    .. math::
        v_A = 0.5(2g H \beta\delta \Delta T)^{0.5}

    For Tangential inlets:

    .. math::
        v_A = 0

    Parameters
    ----------
    m : float
        Mass flow rate of fluid, [kg/s]
    Dtank : float
        Outer diameter of tank or vessel surrounded by jacket, [m]
    Djacket : float
        Inner diameter of jacket surrounding a vessel or tank, [m]
    H : float
        Height of the vessel or tank, [m]
    Dinlet : float
        Inner diameter of inlet into the jacket, [m]
    rho : float
        Density of the fluid at Tm [kg/m^3]
    Cp : float
        Heat capacity of fluid at Tm [J/kg/K]
    k : float
        Thermal conductivity of fluid at Tm [W/m/K]
    mu : float
        Viscosity of fluid at Tm [Pa*s]
    muw : float, optional
        Viscosity of fluid at Tw [Pa*s]
    isobaric_expansion : float, optional
        Constant pressure expansivity of a fluid, [m^3/mol/K]
    dT : float, optional
        Temperature difference of fluid in jacket, [K]
    inlettype : str, optional
        Either 'tangential' or 'radial'
    inletlocation : str, optional
        Either 'top' or 'bottom' or 'auto'

    Returns
    -------
    h : float
        Average heat transfer coefficient inside the jacket [W/m^2/K]

    Notes
    -----
    If the fluid is heated and enters from the bottom, natural convection
    assists the heat transfer and the Grashof term is added; if it were to enter
    from the top, it would be subtracted. The situation is reversed if entry
    is from the top.

    Examples
    --------
    Example as in [2]_, matches completely.

    >>> Lehrer(m=2.5, Dtank=0.6, Djacket=0.65, H=0.6, Dinlet=0.025, dT=20.,
    ... rho=995.7, Cp=4178.1, k=0.615, mu=798E-6, muw=355E-6)
    2922.128124761829

    Examples similar to in [2]_ but covering the other case:

    >>> Lehrer(m=2.5, Dtank=0.6, Djacket=0.65, H=0.6, Dinlet=0.025, dT=20.,
    ... rho=995.7, Cp=4178.1, k=0.615, mu=798E-6, muw=355E-6,
    ... inlettype='radial', isobaric_expansion=0.000303)
    3269.4389632666557

    References
    ----------
    .. [1] Lehrer, Isaac H. "Jacket-Side Nusselt Number." Industrial &
       Engineering Chemistry Process Design and Development 9, no. 4
       (October 1, 1970): 553-58. doi:10.1021/i260036a010.
    .. [2] Gesellschaft, V. D. I., ed. VDI Heat Atlas. 2nd edition.
       Berlin; New York:: Springer, 2010.
    '''
    delta = (Djacket-Dtank)/2.
    Q = m/rho
    Pr = Cp*mu/k
    vs = Q/H/delta
    vo = Q/(pi/4*Dinlet**2)
    if dT is not None and isobaric_expansion is not None and inlettype == 'radial' and inletlocation is not None:
        if dT > 0: # Heating jacket fluid
            if inletlocation == 'auto' or inletlocation == 'bottom':
                va = 0.5*(2*g*H*isobaric_expansion*abs(dT))**0.5
            else:
                va = -0.5*(2*g*H*isobaric_expansion*abs(dT))**0.5
        else: # cooling fluid
            if inletlocation == 'auto' or inletlocation == 'top':
                va = 0.5*(2*g*H*isobaric_expansion*abs(dT))**0.5
            else:
                va = -0.5*(2*g*H*isobaric_expansion*abs(dT))**0.5
    else:
        va = 0
    vh = (vs*vo)**0.5 + va
    dg = (8/3.)**0.5*delta
    Res = vh*dg*rho/mu
    if muw is not None:
        NuSL = (0.03*Res**0.75*Pr)/(1 + 1.74*(Pr-1)/Res**0.125)*(mu/muw)**0.14
    else:
        NuSL = (0.03*Res**0.75*Pr)/(1 + 1.74*(Pr-1)/Res**0.125)
    return NuSL*k/dg

def Stein_Schmidt(m, Dtank, Djacket, H, Dinlet,
                  rho, Cp, k, mu, muw=None, rhow=None,
                  inlettype='tangential', inletlocation='auto', roughness=0.0):
    r'''Calculates average heat transfer coefficient for a jacket around a
    vessel according to [1]_ as described in [2]_.

    .. math::
        l_{ch} = \left[\left(\frac{\pi}{2}\right)^2 D_{tank}^2+H^2\right]^{0.5}

    .. math::
        d_{ch} = 2\delta

    .. math::
        Re_j = \frac{v_{ch}d_{ch}\rho}{\mu}

    .. math::
        Gr_J = \frac{g\rho(\rho-\rho_w)d_{ch}^3}{\mu^2}

    .. math::
        Re_{J,eq} = \left[Re_J^2\pm \left(\frac{|Gr_J|\frac{H}{d_{ch}}}{50}
        \right)\right]^{0.5}

    .. math::
        Nu_J = (Nu_A^3 + Nu_B^3 + Nu_C^3 + Nu_D^3)^{1/3}\left(\frac{\mu}
        {\mu_w}\right)^{0.14}

    .. math::
        Nu_J = \frac{h d_{ch}}{k}

    .. math::
        Nu_A = 3.66

    .. math::
        Nu_B = 1.62 Pr^{1/3}Re_{J,eq}^{1/3}\left(\frac{d_{ch}}{l_{ch}}
        \right)^{1/3}

    .. math::
        Nu_C = 0.664Pr^{1/3}(Re_{J,eq}\frac{d_{ch}}{l_{ch}})^{0.5}

    .. math::
        \text{if } Re_{J,eq} < 2300: Nu_D = 0

    .. math::
        Nu_D = 0.0115Pr^{1/3}Re_{J,eq}^{0.9}\left(1 - \left(\frac{2300}
        {Re_{J,eq}}\right)^{2.5}\right)\left(1 + \left(\frac{d_{ch}}{l_{ch}}
        \right)^{2/3}\right)

    For Radial inlets:

    .. math::
        v_{ch} = v_{Mit}\left(\frac{\ln\frac{b_{Mit}}{b_{Ein}}}{1 -
        \frac{b_{Ein}}{b_{Mit}}}\right)

    .. math::
        b_{Ein} = \frac{\pi}{8}\frac{D_{inlet}^2}{\delta}

    .. math::
        b_{Mit} = \frac{\pi}{2}D_{tank}\sqrt{1 + \frac{\pi^2}{4}\frac
        {D_{tank}^2}{H^2}}

    .. math::
        v_{Mit} = \frac{Q}{2\delta b_{Mit}}

    For Tangential inlets:

    .. math::
        v_{ch} = (v_x^2 + v_z^2)^{0.5}

    .. math::
        v_x = v_{inlet}\left(\frac{\ln[1 + \frac{f_d D_{tank}H}{D_{inlet}^2}
        \frac{v_x(0)}{v_{inlet}}]}{\frac{f_d D_{tank}H}{D_{inlet}^2}}\right)

    .. math::
        v_x(0) = K_3 + (K_3^2 + K_4)^{0.5}

    .. math::
        K_3 = \frac{v_{inlet}}{4} -\frac{D_{inlet}^2v_{inlet}}{4f_d D_{tank}H}

    .. math::
        K_4 = \frac{D_{inlet}^2v_{inlet}^2}{2f_d D_{tank} H}

    .. math::
        v_z = \frac{Q}{\pi D_{tank}\delta}

    .. math::
        v_{inlet} = \frac{Q}{\frac{\pi}{4}D_{inlet}^2}

    Parameters
    ----------
    m : float
        Mass flow rate of fluid, [kg/m^3]
    Dtank : float
        Outer diameter of tank or vessel surrounded by jacket, [m]
    Djacket : float
        Inner diameter of jacket surrounding a vessel or tank, [m]
    H : float
        Height of the vessel or tank, [m]
    Dinlet : float
        Inner diameter of inlet into the jacket, [m]
    rho : float
        Density of the fluid at Tm [kg/m^3]
    Cp : float
        Heat capacity of fluid at Tm [J/kg/K]
    k : float
        Thermal conductivity of fluid at Tm [W/m/K]
    mu : float
        Viscosity of fluid at Tm [Pa*s]
    muw : float, optional
        Viscosity of fluid at Tw [Pa*s]
    rhow : float, optional
        Density of the fluid at Tw [kg/m^3]
    inlettype : str, optional
        Either 'tangential' or 'radial'
    inletlocation : str, optional
        Either 'top' or 'bottom' or 'auto'
    roughness : float, optional
        Roughness of the tank walls [m]

    Returns
    -------
    h : float
        Average  transfer coefficient inside the jacket [W/m^2/K]

    Notes
    -----
    [1]_ is in German and has not been reviewed. Multiple other formulations
    are considered in [1]_.

    If the fluid is heated and enters from the bottom, natural convection
    assists the heat transfer and the Grashof term is added; if it were to enter
    from the top, it would be subtracted. The situation is reversed if entry
    is from the top.

    Examples
    --------
    Example as in [2]_, matches in all but friction factor:

    >>> Stein_Schmidt(m=2.5, Dtank=0.6, Djacket=0.65, H=0.6, Dinlet=0.025,
    ... rho=995.7, Cp=4178.1, k=0.615, mu=798E-6, muw=355E-6, rhow=971.8)
    5695.2041698088615

    References
    ----------
    .. [1] Stein, Prof Dr-Ing Werner Alexander, and Dipl-Ing (FH) Wolfgang
       Schmidt. "Wärmeübergang auf der Wärmeträgerseite eines Rührbehälters mit
       einem einfachen Mantel." Forschung im Ingenieurwesen 59, no. 5
       (May 1993): 73-90. doi:10.1007/BF02561203.
    .. [2] Gesellschaft, V. D. I., ed. VDI Heat Atlas. 2nd edition.
       Berlin; New York:: Springer, 2010.
    '''
    delta = (Djacket-Dtank)/2.
    Q = m/rho
    Pr = Cp*mu/k
    lch = (pi**2/4*Dtank**2 + H**2)**0.5
    dch = 2*delta
    if inlettype == 'radial':
        bEin = pi/8*Dinlet**2/delta
        bMit = pi/2*Dtank*(1 + pi**2/4*Dtank**2/H**2)**0.5
        vMit = Q/(2*delta*bMit)
        vch = vMit*log(bMit/bEin)/(1 - bEin/bMit)
        ReJ = vch*dch*rho/mu
    elif inlettype == 'tangential':
        f = friction_factor(1E5, roughness/dch)
        for run in range(5):
            vinlet = Q/(pi/4*Dinlet**2)
            vz = Q/(pi*Dtank*delta)
            K4 = Dinlet**2*vinlet**2/(2*f*Dtank*H)
            K3 = vinlet/4. - Dinlet**2*vinlet/(4*f*Dtank*H)
            vx0 = K3 + (K3**2 + K4)**0.5
            vx = vinlet*log(1 + f*Dtank*H/Dinlet**2*vx0/vinlet)/(f*Dtank*H/Dinlet**2)
            vch = (vx**2 + vz**2)**0.5
            ReJ = vch*dch*rho/mu
            f = friction_factor(ReJ, roughness/dch)
    if inletlocation and rhow:
        GrJ = g*rho*(rho-rhow)*dch**3/mu**2
        if rhow < rho: # Heating jacket fluid
            if inletlocation == 'auto' or inletlocation == 'bottom':
                ReJeq = (ReJ**2 + GrJ*H/dch/50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ*H/dch/50.)**0.5
        else: # Cooling jacket fluid
            if inletlocation == 'auto' or inletlocation == 'top':
                ReJeq = (ReJ**2 + GrJ*H/dch/50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ*H/dch/50.)**0.5
    else:
        ReJeq = (ReJ**2)**0.5
    NuA = 3.66
    NuB = 1.62*Pr**(1/3.)*ReJeq**(1/3.)*(dch/lch)**(1/3.)
    NuC = 0.664*Pr**(1/3.)*(ReJeq*dch/lch)**0.5
    if ReJeq < 2300:
        NuD = 0
    else:
        NuD = 0.0115*Pr**(1/3.)*ReJeq**0.9*(1 - (2300./ReJeq)**2.5)*(1 + (dch/lch)**(2/3.))
    if muw:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1/3.)*(mu/muw)**0.14
    else:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1/3.)
    return NuJ*k/dch


# -*- coding: utf-8 -*-
"""
Created on Wed Apr  8 19:57:00 2020

@author: xs27
"""

# import ECE552_Project
# import previous stamps
import numpy as np
import scipy.linalg as linalg
import matplotlib.pyplot as plt

#####################
# stamp for DC source
#####################

def VS_stamp(G,s,n1,n2,b12,v):
    # b12: branch number
    # n1,n2: node number
    G[b12,n1] += 1
    G[b12,n2] -= 1
    G[n1,b12] += 1
    G[n2,b12] -= 1
    s[b12] += v
    return G, s

#######################
# stamp for MOSFET
#######################

def NMOS_stamp(G,x,s,k,Vg,Vs,Vd,Vth):
    # construct the stamp of a NMOS
    # Input:
    #     Vg:  node number for gate
    #     Vd:  node number for drain
    #     Vs:  node number for source
    #     k:   coefficient
    #     Vth: threshold voltage
    #     G:   NA matrix
    #     x:   current solution
    #     s:   RHS of the NA equation
    # Output:
    #     G,s: updated G & s
    # check region of operation
    # and construct NA stamp
    # notation from (6.3.23)
    Vov = x[Vg]-x[Vs]-Vth
    Vds = x[Vd]-x[Vs]
    Vgs = x[Vg]-x[Vs]
    if Vgs <= Vth: # cut-off
        a11 = 0
        a12 = 0 #1e-5# large resistor
        b1 = 0
    elif Vds < Vov: # linear
        a11 = k*Vds
        a12 = k*(Vov-Vds)
        b1 = k*(Vov*Vds-0.5*Vds*Vds)-a11*Vgs-a12*Vds
    else: # saturation
        a11 = 0.5*k*(2*Vov*(1+lamda*(Vds-Vov)-lamda*Vov*Vov))
        a12 = 0.5*k*lamda*Vov*Vov
        b1 = 0.5*k*Vov*Vov*(1+lamda*(Vds-Vov))-a11*Vgs-a12*Vds
    # update on the matrix
    a12 += 1e-9 # large resistor
    G[Vd,Vg] += a11
    G[Vs,Vg] -= a11
    G[Vd,Vd] += a12
    G[Vs,Vd] -= a12
    G[Vd,Vs] -= a11+a12
    G[Vs,Vs] += a11+a12
    s[Vd] -= b1
    s[Vs] += b1
    return G,s

def PMOS_stamp(G,x,s,k,Vg,Vs,Vd,Vth):
    # construct the stamp of a PMOS
    # Input:
    #     Vg:  node number for gate
    #     Vd:  node number for drain
    #     Vs:  node number for source
    #     k:   coefficient
    #     Vth: threshold voltage
    #     G:   NA matrix
    #     x:   current solution
    #     s:   RHS of the NA equation
    # Output:
    #     G,s: updated G & s
    # check region of operation
    # and construct NA stamp
    # notation from (6.3.23)
    Vov = x[Vs]-x[Vg]-Vth
    Vsd = x[Vs]-x[Vd]
    Vsg = x[Vs]-x[Vg]
    if Vsg <= Vth: # cut-off
        a11 = 0
        a12 = 0#1e-5 # large resistor
        b1 = 0
    elif Vsd < Vov: # linear
        a11 = k*Vsd
        a12 = k*(Vov-Vsd)
        b1 = k*(Vov*Vsd-0.5*Vsd**2)-a11*Vsg-a12*Vsd
    else: # saturation
        a11 = 0.5*k*(2*Vov*(1+lamda*(Vsd-Vov)-lamda*Vov**2))
        a12 = 0.5*k*lamda*Vov**2
        b1 = 0.5*k*Vov**2*(1+lamda*(Vsd-Vov))-a11*Vsg-a12*Vsd
    # update on the matrix
    a12 += 1e-9 # large resistor
    G[Vd,Vg] += a11
    G[Vs,Vg] -= a11
    G[Vd,Vd] += a12
    G[Vs,Vd] -= a12
    G[Vd,Vs] -= a11+a12
    G[Vs,Vs] += a11+a12
    s[Vd] += b1
    s[Vs] -= b1
    return G,s

# find number of nodes and extra banches in MNA
def node_and_branch_number(total_list):
    # return the largest number of node in the netlist
    # starting from 0 (index for python)
    # and determine extra lines for the netlist(inductor current etc)
    node_max = 0
    extra_branch = 0
    for line in total_list:
        component = line.split()
        # find the largest node
        if int(component[1]) > node_max:
            node_max = int(component[1])
        if int(component[2]) > node_max:
            node_max = int(component[2])
        # find the number of extra branches for MNA
        if 'V' == component[0][0]:
            extra_branch += 1
    return node_max, extra_branch

# read the netlist, and stamp the matrix G(real) and C(imaginary)
def read_netlist(netlist,total_list,node_max,G,source):
    for line in total_list:
        component = line.split()
        if 'V' == component[0][0]:
            G,source = VS_stamp(G,source,int(component[1])-1,int(component[2])-1,\
                                node_max,float(component[3]))
            node_max += 1
    return G,source

def update_G(G,source,x):
# go through the netlist and update the G & source matrices
    G[0:5,0:5] = 0
    source[0:5] = 0
    for line in total_list:
        component = line.split()
        if 'NMOS' == component[0][0:4]:
            G, source = NMOS_stamp(G,x,source,kn,int(component[1])-1,int(component[2])-1,int(component[3])-1,Vth)
        elif 'PMOS' == component[0][0:4]:
            G, source = PMOS_stamp(G,x,source,kp,int(component[1])-1,int(component[2])-1,int(component[3])-1,Vth)
    A[0:node_max-1,0:node_max-1] = G[0:node_max-1,0:node_max-1]
    A[0:node_max-1,node_max-1:node_max+extra_branch-1] = G[0:node_max-1,node_max:node_max+extra_branch]
    A[node_max-1:node_max+extra_branch-1,0:node_max-1] = G[node_max:node_max+extra_branch,0:node_max-1]
    A[node_max-1:node_max+extra_branch-1,node_max-1:node_max+extra_branch-1] = G[node_max:node_max+extra_branch,node_max:node_max+extra_branch]
    s[0:node_max-1] = source[0:node_max-1]
    s[node_max-1:node_max + extra_branch-1] = source[node_max:node_max + extra_branch]
    return A,s
# G[:,node_max-1:node_max+extra_branch-1] = G[:,node_max:node_max+extra_branch]
# G[node_max-1:node_max+extra_branch-1,:] = G[node_max:node_max+extra_branch,:]

################
#   Constants  #
################

kn = 1e-4
kp = 5e-5
lamda = 0.02
Vth = 1
x = np.ndarray(8,dtype = float)
x[:] = 0
x_old = np.ndarray(8,dtype = float)
x_old[:] = 0

###########################
###########################
#  Start of the program   #
###########################
###########################

netlist = open('netlist_MOS.txt','r')
total_list = netlist.readlines()
# node = np.ndarray((len(total_list),2),dtype = int)

# find the number of nodes and determine the number of extra current branches
node_max, extra_branch = node_and_branch_number(total_list)

# construct the NA matrix: G (real) and source (real)
G = np.ndarray((node_max+extra_branch,node_max+extra_branch), dtype = float)
G[:,:] = 0
A = np.ndarray((node_max+extra_branch-1,node_max+extra_branch-1), dtype = float)
source = np.ndarray(node_max+extra_branch,dtype = float)
source[:] = 0
s = np.ndarray(node_max+extra_branch-1,dtype = float)

G, source = read_netlist(netlist,total_list,node_max,G,source)

# prepare for iteration updates
def iteration_solve(G,source,x,x_old,epsilon):
    cnt = 0
    while (max(abs(x_old-x))>epsilon) and (cnt<50):
        x_old = x
        A, s = update_G(G,source,x)
        lu, piv = linalg.lu_factor(A)
        x = linalg.lu_solve((lu,piv),s)
        cnt += 1
    return x,cnt

# Q1
# x, cnt = iteration_solve(G, source, x, x_old, 1e-9)

N = 501
solution = np.ndarray((N,8,3),dtype = float)

VA = np.linspace(0,5,N)
Vout = np.ndarray(N+1,dtype = float)

VB = np.array([2, 3.5, 5])

for jj in range(3):
    source[7] = VB[jj]
    for ii in range(N):
        x[4] = VA[ii]
        source[6] = VA[ii]
        x_old[:] = 0
        x,cnt = iteration_solve(G,source,x,x_old,1e-9)
        solution[ii,:,jj] = x

########################
# Plotting results
########################
Vout1 = solution[1:N+1,2,0]
Vout2 = solution[1:N+1,2,1]
Vout3 = solution[1:N+1,2,2]
# Vout = Vout.reshape(501)
plt.plot(VA[1:N+1], Vout1, label='VB = 2V', color = 'r')
plt.plot(VA[1:N+1], Vout2, label='VB = 3.5V', color = 'g')
plt.plot(VA[1:N+1], Vout3, label='VB = 5V', color = 'b')
plt.scatter(3,Vout1[int(3*(N+1)/5)])
plt.text(3.1,Vout1[int(3*(N+1)/5)],'%.4f V'%Vout1[int(3*(N+1)/5)],ha="left")
plt.xlabel('Input Voltage')
plt.ylabel('Output Voltage')
plt.legend()
plt.show()

############################
############################
#    End of ECE552 pj2     #
############################
############################


# O(n) time | O(n) space - where n is the length of the input array
def arrayOfProducts(array):
    # create determined length arrays with value 1 as placeholder
    products = [1 for _ in range(len(array))]
    leftProducts = [1 for _ in range(len(array))]
    rightProducts = [1 for _ in range(len(array))]

    # get the product of all values to the left of element
    leftRunningProduct = 1
    for i in range(len(array)):
        leftProducts[i] = leftRunningProduct
        leftRunningProduct *= array[i]

    # get the product of all values to the right of element
    rightRunningProduct = 1
    for i in reversed(range(len(array))):
        rightProducts[i] = rightRunningProduct
        rightRunningProduct *= array[i]

    # populate products array with result by multiplying the values at the
    # given index
    for i in range(len(array)):
        products[i] = leftProducts[i] * rightProducts[i]

    return products

print(arrayOfProducts([1, 2, 3, 4]))


import re
from typing import Dict, Set, Tuple, Optional

def parse_extras(requirements_path: str) -> Dict[str, Set[str]]:
    """Parse over the requirements.txt file to find extras requested.

    Args:
        requirements_path: The filepath for the requirements.txt file to parse.

    Returns:
         A dictionary mapping the requirement name to a set of extras requested.
    """

    extras_requested = {}
    with open(requirements_path, "r") as requirements:
        # Merge all backslash line continuations so we parse each requirement as a single line.
        for line in requirements.read().replace("\\\n", "").split("\n"):
            requirement, extras = _parse_requirement_for_extra(line)
            if requirement and extras:
                extras_requested[requirement] = extras

    return extras_requested

def _parse_requirement_for_extra(
    requirement: str,
) -> Tuple[Optional[str], Optional[Set[str]]]:
    """Given a requirement string, returns the requirement name and set of extras, if extras specified.
    Else, returns (None, None)
    """

    # https://www.python.org/dev/peps/pep-0508/#grammar
    extras_pattern = re.compile(
        r"^\s*([0-9A-Za-z][0-9A-Za-z_.\-]*)\s*\[\s*([0-9A-Za-z][0-9A-Za-z_.\-]*(?:\s*,\s*[0-9A-Za-z][0-9A-Za-z_.\-]*)*)\s*\]"
    )

    matches = extras_pattern.match(requirement)
    if matches:
        return (
            matches.group(1),
            {extra.strip() for extra in matches.group(2).split(",")},
        )

    return None, None


#!/bin/python3

import os

'''
Problem - https://www.hackerrank.com/
challenges/maximum-perimeter-triangle/
problem?h_r=next-challenge&h_v=zen&
h_r=next-challenge&h_v=zen
'''

def is_triangle(points):
    return points[0] + points[1] > points[2]

def maximumPerimeterTriangle(sticks):
    sticks = sorted(sticks)
    all_triangles = []
    for i in range(0, len(sticks) - 2):
        points = sticks[i: i + 3]
        if not is_triangle(points):
            continue
        all_triangles.append(points)

    maximum_side = -1
    minimum_side = -1
    max_triangle = None
    if not all_triangles:
        return [-1]
    else:
        for triangle in all_triangles:
            longest_side = max(triangle)
            shortest_side = min(triangle)
            if longest_side > maximum_side:
                maximum_side = longest_side
                minimum_side = shortest_side
                max_triangle = triangle
            elif longest_side == maximum_side:
                if shortest_side > minimum_side:
                    maximum_side = longest_side
                    minimum_side = shortest_side
                    max_triangle = triangle
    return max_triangle

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    n = int(input())

    sticks = list(map(int, input().rstrip().split()))

    result = maximumPerimeterTriangle(sticks)

    fptr.write(' '.join(map(str, result)))
    fptr.write('\n')

    fptr.close()


import os.path
from itertools import groupby

import pros.common.ui as ui
import pros.conductor as c
from pros.cli.common import *
from pros.conductor.templates import ExternalTemplate
from pros.ga.analytics import analytics

@pros_root
def conductor_cli():
    pass

@conductor_cli.group(cls=PROSGroup, aliases=['cond', 'c', 'conduct'], short_help='Perform project management for PROS')
@default_options
def conductor():
    """
    Conductor is PROS's project management facility. It is responsible for obtaining
    templates for which to create projects from.

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    pass

@conductor.command(aliases=['download'], short_help='Fetch/Download a remote template',
                   context_settings={'ignore_unknown_options': True})
@template_query(required=True)
@default_options
def fetch(query: c.BaseTemplate):
    """
    Fetch/download a template from a depot.

    Only a template spec is required. A template spec is the name and version
    of the template formatted as name@version (libblrs@1.0.0). Semantic version
    ranges are accepted (e.g., libblrs@^1.0.0). The version parameter is also
    optional (e.g., libblrs)

    Additional parameters are available according to the depot.

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("fetch-template")
    template_file = None
    if os.path.exists(query.identifier):
        template_file = query.identifier
    elif os.path.exists(query.name) and query.version is None:
        template_file = query.name
    elif query.metadata.get('origin', None) == 'local':
        if 'location' not in query.metadata:
            logger(__name__).error('--location option is required for the local depot. Specify --location <file>')
            logger(__name__).debug(f'Query options provided: {query.metadata}')
            return -1
        template_file = query.metadata['location']

    if template_file and (os.path.splitext(template_file)[1] in ['.zip'] or
                          os.path.exists(os.path.join(template_file, 'template.pros'))):
        template = ExternalTemplate(template_file)
        query.metadata['location'] = template_file
        depot = c.LocalDepot()
        logger(__name__).debug(f'Template file found: {template_file}')
    else:
        if template_file:
            logger(__name__).debug(f'Template file exists but is not a valid template: {template_file}')
        template = c.Conductor().resolve_template(query, allow_offline=False)
        logger(__name__).debug(f'Template from resolved query: {template}')
        if template is None:
            logger(__name__).error(f'There are no templates matching {query}!')
            return -1
        depot = c.Conductor().get_depot(template.metadata['origin'])
        logger(__name__).debug(f'Found depot: {depot}')
    # query.metadata contain all of the extra args that also go to the depot. There's no way for us to determine
    # whether the arguments are for the template or for the depot, so they share them
    logger(__name__).debug(f'Additional depot and template args: {query.metadata}')
    c.Conductor().fetch_template(depot, template, **query.metadata)

@conductor.command(context_settings={'ignore_unknown_options': True})
@click.option('--upgrade/--no-upgrade', 'upgrade_ok', default=True, help='Allow upgrading templates in a project')

@click.option('--install/--no-install', 'install_ok', default=True, help='Allow installing templates in a project')
@click.option('--download/--no-download', 'download_ok', default=True,
              help='Allow downloading templates or only allow local templates')
@click.option('--upgrade-user-files/--no-upgrade-user-files', 'force_user', default=False,
              help='Replace all user files in a template')
@click.option('--force', 'force_system', default=False, is_flag=True,
              help="Force all system files to be inserted into the project")
@click.option('--force-apply', 'force_apply', default=False, is_flag=True,
              help="Force apply the template, disregarding if the template is already installed.")
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
              help='Remove empty directories when removing files')
@click.option('--beta', is_flag=True, default=False, show_default=True,
              help='Allow applying beta templates')
@project_option()
@template_query(required=True)
@default_options
def apply(project: c.Project, query: c.BaseTemplate, **kwargs):
    """
    Upgrade or install a template to a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("apply-template")
    return c.Conductor().apply_template(project, identifier=query, **kwargs)

@conductor.command(aliases=['i', 'in'], context_settings={'ignore_unknown_options': True})
@click.option('--upgrade/--no-upgrade', 'upgrade_ok', default=False)
@click.option('--download/--no-download', 'download_ok', default=True)
@click.option('--force-user', 'force_user', default=False, is_flag=True,
              help='Replace all user files in a template')
@click.option('--force-system', '-f', 'force_system', default=False, is_flag=True,
              help="Force all system files to be inserted into the project")
@click.option('--force-apply', 'force_apply', default=False, is_flag=True,
              help="Force apply the template, disregarding if the template is already installed.")
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
              help='Remove empty directories when removing files')
@click.option('--beta', is_flag=True, default=False, show_default=True,
              help='Allow applying beta templates')
@project_option()
@template_query(required=True)
@default_options
@click.pass_context
def install(ctx: click.Context, **kwargs):
    """
    Install a library into a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("install-template")
    return ctx.invoke(apply, install_ok=True, **kwargs)

@conductor.command(context_settings={'ignore_unknown_options': True}, aliases=['u'])
@click.option('--install/--no-install', 'install_ok', default=False)
@click.option('--download/--no-download', 'download_ok', default=True)
@click.option('--force-user', 'force_user', default=False, is_flag=True,
              help='Replace all user files in a template')
@click.option('--force-system', '-f', 'force_system', default=False, is_flag=True,
              help="Force all system files to be inserted into the project")
@click.option('--force-apply', 'force_apply', default=False, is_flag=True,
              help="Force apply the template, disregarding if the template is already installed.")
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
              help='Remove empty directories when removing files')
@click.option('--beta', is_flag=True, default=False, show_default=True,
              help='Allow upgrading to beta templates')
@project_option()
@template_query(required=False)
@default_options
@click.pass_context
def upgrade(ctx: click.Context, project: c.Project, query: c.BaseTemplate, **kwargs):
    """
    Upgrade a PROS project or one of its libraries

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("upgrade-project")
    if not query.name:
        for template in project.templates.keys():
            click.secho(f'Upgrading {template}', color='yellow')
            q = c.BaseTemplate.create_query(name=template, target=project.target,
                                            supported_kernels=project.templates['kernel'].version)
            ctx.invoke(apply, upgrade_ok=True, project=project, query=q, **kwargs)
    else:
        ctx.invoke(apply, project=project, query=query, upgrade_ok=True, **kwargs)

@conductor.command('uninstall')
@click.option('--remove-user', is_flag=True, default=False, help='Also remove user files')
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
              help='Remove empty directories when removing files')
@click.option('--no-make-clean', is_flag=True, default=True, help='Do not run make clean after removing')
@project_option()
@template_query()
@default_options
def uninstall_template(project: c.Project, query: c.BaseTemplate, remove_user: bool,
                       remove_empty_directories: bool = False, no_make_clean: bool = False):
    """
    Uninstall a template from a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("uninstall-template")
    c.Conductor().remove_template(project, query, remove_user=remove_user,
                                  remove_empty_directories=remove_empty_directories)
    if no_make_clean:
        with ui.Notification():
            project.compile(["clean"])

@conductor.command('new-project', aliases=['new', 'create-project'])
@click.argument('path', type=click.Path())
@click.argument('target', default=c.Conductor().default_target, type=click.Choice(['v5', 'cortex']))
@click.argument('version', default='latest')
@click.option('--force-user', 'force_user', default=False, is_flag=True,
              help='Replace all user files in a template')
@click.option('--force-system', '-f', 'force_system', default=False, is_flag=True,
              help="Force all system files to be inserted into the project")
@click.option('--force-refresh', is_flag=True, default=False, show_default=True,
              help='Force update all remote depots, ignoring automatic update checks')
@click.option('--no-default-libs', 'no_default_libs', default=False, is_flag=True,
              help='Do not install any default libraries after creating the project.')
@click.option('--compile-after', is_flag=True, default=True, show_default=True,
              help='Compile the project after creation')
@click.option('--build-cache', is_flag=True, default=None, show_default=False,
              help='Build compile commands cache after creation. Overrides --compile-after if both are specified.')
@click.option('--beta', is_flag=True, default=False, show_default=True,
              help='Create a project with a beta template')
@click.pass_context
@default_options
def new_project(ctx: click.Context, path: str, target: str, version: str,
                force_user: bool = False, force_system: bool = False,
                no_default_libs: bool = False, compile_after: bool = True, build_cache: bool = None, **kwargs):
    """
    Create a new PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("new-project")
    if version.lower() == 'latest' or not version:
        version = '>0'
    if not force_system and c.Project.find_project(path) is not None:
        logger(__name__).error('A project already exists in this location at ' + c.Project.find_project(path) +
                               '! Delete it first. Are you creating a project in an existing one?', extra={'sentry': False})
        ctx.exit(-1)
    try:
        _conductor = c.Conductor()
        if target is None:
            target = _conductor.default_target
        project = _conductor.new_project(path, target=target, version=version,
                                         force_user=force_user, force_system=force_system,
                                         no_default_libs=no_default_libs, **kwargs)
        ui.echo('New PROS Project was created:', output_machine=False)
        ctx.invoke(info_project, project=project)

        if compile_after or build_cache:
            with ui.Notification():
                ui.echo('Building project...')
                ctx.exit(project.compile([], scan_build=build_cache))

    except Exception as e:
        pros.common.logger(__name__).exception(e)
        ctx.exit(-1)

@conductor.command('query-templates',
                   aliases=['search-templates', 'ls-templates', 'lstemplates', 'querytemplates', 'searchtemplates'],
                   context_settings={'ignore_unknown_options': True})
@click.option('--allow-offline/--no-offline', 'allow_offline', default=True, show_default=True,
              help='(Dis)allow offline templates in the listing')
@click.option('--allow-online/--no-online', 'allow_online', default=True, show_default=True,
              help='(Dis)allow online templates in the listing')
@click.option('--force-refresh', is_flag=True, default=False, show_default=True,
              help='Force update all remote depots, ignoring automatic update checks')
@click.option('--limit', type=int, default=15,
              help='The maximum number of displayed results for each library')
@click.option('--beta', is_flag=True, default=False, show_default=True,
              help='View beta templates in the listing')
@template_query(required=False)
@click.pass_context
@default_options
def query_templates(ctx, query: c.BaseTemplate, allow_offline: bool, allow_online: bool, force_refresh: bool,
                    limit: int, beta: bool):
    """
    Query local and remote templates based on a spec

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("query-templates")
    if limit < 0:
        limit = 15
    templates = c.Conductor().resolve_templates(query, allow_offline=allow_offline, allow_online=allow_online,
                                                force_refresh=force_refresh, beta=beta)
    if beta:
        templates += c.Conductor().resolve_templates(query, allow_offline=allow_offline, allow_online=allow_online,
                                                force_refresh=force_refresh, beta=False)

    render_templates = {}
    for template in templates:
        key = (template.identifier, template.origin)
        if key in render_templates:
            if isinstance(template, c.LocalTemplate):
                render_templates[key]['local'] = True
        else:
            render_templates[key] = {
                'name': template.name,
                'version': template.version,
                'location': template.origin,
                'target': template.target,
                'local': isinstance(template, c.LocalTemplate)
            }
    import semantic_version as semver
    render_templates = sorted(render_templates.values(), key=lambda k: (k['name'], semver.Version(k['version']), k['local']), reverse=True)

    # Impose the output limit for each library's templates
    output_templates = []
    for _, g in groupby(render_templates, key=lambda t: t['name'] + t['target']):
        output_templates += list(g)[:limit]
    ui.finalize('template-query', output_templates)

@conductor.command('info-project')
@click.option('--ls-upgrades/--no-ls-upgrades', 'ls_upgrades', default=False)
@project_option()
@default_options
def info_project(project: c.Project, ls_upgrades):
    """
    Display information about a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    analytics.send("info-project")
    from pros.conductor.project import ProjectReport
    report = ProjectReport(project)
    _conductor = c.Conductor()
    if ls_upgrades:
        for template in report.project['templates']:
            import semantic_version as semver
            templates = _conductor.resolve_templates(c.BaseTemplate.create_query(name=template["name"],
                                                                                version=f'>{template["version"]}',
                                                                                target=project.target))
            template["upgrades"] = sorted({t.version for t in templates}, key=lambda v: semver.Version(v), reverse=True)

    ui.finalize('project-report', report)

@conductor.command('add-depot')
@click.argument('name')
@click.argument('url')
@default_options
def add_depot(name: str, url: str):
    """
    Add a depot

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    _conductor = c.Conductor()
    _conductor.add_depot(name, url)

    ui.echo(f"Added depot {name} from {url}")

@conductor.command('remove-depot')
@click.argument('name')
@default_options
def remove_depot(name: str):
    """
    Remove a depot

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    _conductor = c.Conductor()
    _conductor.remove_depot(name)

    ui.echo(f"Removed depot {name}")

@conductor.command('query-depots')
@click.option('--url', is_flag=True)
@default_options
def query_depots(url: bool):
    """
    Gets all the stored depots

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    _conductor = c.Conductor()
    ui.echo(f"Available Depots{' (Add --url for the url)' if not url else ''}:\n")
    ui.echo('\n'.join(_conductor.query_depots(url))+"\n")


#!/usr/bin/python

import os

from .binary_file import BinaryFile, SearchError

class SerialFile(BinaryFile):
    def __init__(self, path, record, block_f, empty_key=-1):
        BinaryFile.__init__(self, path, record, block_f, empty_key)
        self.init_file()

    def init_file(self):
        if os.path.isfile(self.path) and os.stat(self.path).st_size != 0:
            return

        with open(self.path, "wb+") as f:
            block = self.block_f*[self.record.get_empty_rec()]  # inicijalizacija datoteke podrazumeva unos bloka koji sadrzi prazne slogove
            self.write_block(f, block)

    def insert_record(self, rec):
        if self.find_by_id(rec["id"]):  # provera da li vec postoji slog sa zadatim id-jem - svakom unosu prethodi pretraga!
            raise SearchError()

        with open(self.path, "rb+") as f:
            f.seek(-self.block_size, 2)  # citamo poslednji blok
            block = self.read_block(f)

            for i in range(self.block_f):
                if block[i]["id"] == self.empty_key:  # trazimo prvi prazan slog
                    block[i] = rec
                    break

            i += 1

            if i == self.block_f:  # provera da li smo popunili trenutni blok ili ne
                f.seek(-self.block_size, 1)
                self.write_block(f, block)
                block = self.block_f*[self.record.get_empty_rec()]
                self.write_block(f, block)
            else:
                block[i] = self.record.get_empty_rec()
                f.seek(-self.block_size, 1)
                self.write_block(f, block)

    def find_by_id(self, id):
        i = 0
        with open(self.path, "rb") as f:
            while True:
                block = self.read_block(f)

                for j in range(self.block_f):
                    if block[j]["id"] == id:
                        return (i, j)
                    elif block[j]["id"] == self.empty_key:  # ukoliko smo naisli na prazan slog - stigli smo do kraja datoteke
                        return None
                i += 1

    def reformat_file(self):
        open(self.path, "w").close()
        self.init_file()


import requests
from bs4 import BeautifulSoup
import csv
import io
import os

for file in os.listdir("/Users/novin/Desktop/Extractor"):
    if file.endswith(".html"):
        quotes = []  # a list to store quotes
        f = open(file, "r", encoding="utf-8")
        soup = BeautifulSoup(f.read(), 'html.parser')
        rows = soup.findAll('div', {"class": 'display_question question multiple_choice_question'})
        name = soup.select('div.displaying h1')[0].text
        for row in rows:
            questions = row.findAll('div', {"class": 'question_text user_content enhanced'})
            # print(len(questions))
            question = {}
            for q in questions:
                question = q.text
            options = row.select('div.answer.answer_for_')
            opts = []
            for opt in options:
                option = {'text': opt.findAll('div', {"class": 'answer_text'})[0].text,
                          'is_ans': 'correct_answer' in opt.get('class')}
                opts.append(option)
            quotes.append({'question': question, 'options': opts})

        opt_header = ['
الف)
',
                      '
ب)
',
                      '
ج)
',
                      '
د)
']

        filename = 'All_Questions.html'
        with io.open(filename, "a", encoding="utf-8") as f:
            f.write("  "
                    ""
                    "\n
")
            f.write("

" + name + "
\n

")
            for quote in quotes:
                f.write("
\n
")
                # print([quote['name'], quote['uni'], quote['date']])
                f.write("{0}\n".format(quote['question']))
                i = 0
                for opt in quote['options']:
                    if opt['is_ans']:
                        f.write("
")
                    f.write('
'+opt_header[i] + opt['text'] + "\n
")
                    i += 1
                    if opt['is_ans']:
                        f.write("
")
                f.write("
\n")
            f.write("
  ")


import secrets
import json
from pathlib import Path

def random_key(L):
    '''
    生成随机密钥，返回整数
    '''
    bytes_key = secrets.token_bytes(nbytes=L)
    int_key = int.from_bytes(bytes_key, byteorder='big') # 大端存储
    # int_key = int.from_bytes(bytes_key, byteorder='little') # 小端存储
    return int_key
# print(random_key(10))
def Encryption(string):
    '''
    将字符串参数编码为字节串并转换为整数，与一个随机密钥进行异或运算生成
    '''
    string_bytes = str.encode(string)
    int_string = int.from_bytes(string_bytes, byteorder='big')
    random_k = random_key(len(string_bytes))
    secret = int_string ^ random_k
    return {'key':random_k, 'secret':secret}

# random_k,secret = Encryption('abc')

def Decryption(random_k,secret):
    '''
    将密文和密钥异或，计算密文长度，返回字符串
    '''
    int_message = secret ^ random_k
    byte_message = int_message.to_bytes((int_message.bit_length() + 7) // 8,byteorder='big')
    str_message = bytes.decode(byte_message)
    return str(str_message)

string1 = "路漫漫其修远兮，吾将上下而求索。"
string2 = "Never put off until tomorrow what may be done today."

# # 选择要加解密的字符串
stringx = string1
print(Encryption(stringx))
Encryption_pair = Encryption(stringx)
print(Decryption(Encryption_pair['key'],Encryption_pair['secret']))

stringx = string2
print(Encryption(stringx))
Encryption_pair = Encryption(stringx)
print(Decryption(Encryption_pair['key'],Encryption_pair['secret']))

# path = 'key.txt'
def Encryption_file(path='key.txt'):
    '''
    加密文件，得到key和密文
    '''
    path = Path(path) # path of random_key
    message_path = 'message.txt'
    secret_path_new = 'secret_new.txt'

    with open(path,'wt',encoding='utf-8') as fkey, open(message_path,'rt',encoding='utf-8') as fmessage, open(secret_path_new,'wt',encoding='utf-8') as fsecret:
        Encryptiontxt = Encryption(fmessage.read())
        secret1, key1 = Encryptiontxt['secret'], Encryptiontxt['key']
        # print(Encryptiontxt)
        json.dump(key1,fkey)
        json.dump(secret1,fsecret)

def Decryption_file():
    '''
    解密文件，得到明文
    '''
    key_path = 'key.txt'
    message_path_new = 'message_new.txt'
    secret_path = 'secret_new.txt'

    with open(key_path,'rt',encoding='utf-8') as fkey, open(message_path_new,'wt',encoding='utf-8') as fmessage, open(secret_path,'rt',encoding='utf-8') as fsecret:
        Decryptiontxt = Decryption(json.load(fkey),json.load(fsecret))
        fmessage.write(Decryptiontxt)

# Encryption_file()
# Decryption_file()


#!/usr/bin/python

def permutation(items, n):
    if (n > len(items)) or (n <= 0) or (len(items) == 0):
        return
    if n == 1:
        for i in range(len(items)):
            yield [items[i]]
    else:
        for i in items:
            st = list(items)
            st.remove(i)
            for j in permutation(st, n-1):
                yield [i] + j

def combination(items, n):
    if (n > len(items)) or (n <= 0) or (len(items) == 0):
        return
    if n == 1:
        for i in items:
            yield [i]
    else:
        for i in range(len(items)):
            for j in combination(items[i+1:], n-1):
                yield [items[i]] + j


# -*- coding: utf-8 -*-
import scrapy
from pyquery import PyQuery
from page_read.json_read import *

class JobSpider(scrapy.Spider):
    name = 'Job'
    allowed_domains = ['51job.com']
    urlInfo = read_json_file("config/startUrl.json")
    start_urls = []
    start_urls.append(urlInfo["start"])
    for i in range(2, urlInfo["pageNumber"]):
        start_urls.append(urlInfo["default"].format(i))

    print(start_urls)

    def parse(self, response):
        jpy = PyQuery(response.text)
        items = jpy('.el').items()
        for item in items:
            position = item('.t1 > span > a').text()
            positionUrl = item('.t1 > span > a').attr('href')
            company = item('span.t2 > a').text()
            companyUrl = item('span.t2 > a').attr('href')
            address = item('.t3').text()
            salary = item('.t4').text()
            updateTime = item('.t5').text()

            if position:
                info = {
                    "position": position,
                    "company": company,
                    "positionUrl": response.urljoin(positionUrl),
                    "companyUrl": response.urljoin(companyUrl),
                    "address": address,
                    "salary": salary,
                    "updateTime": updateTime
                }
                yield scrapy.Request(info["positionUrl"], meta={"info": info}, callback=self.parse_second)

    def parse_second(self, response):
        info = response.meta["info"]
        jpy = PyQuery(response.text)
        info["information"] = "|".join(jpy('.msg.ltype').text().split("   |  "))
        info["requirement"] = jpy('.sp4').text()
        info["others"] = jpy('.t2').text()
        info["workAddress"] = jpy(
            'body > div.tCompanyPage > div.tCompany_center.clearfix > div.tCompany_main > div:nth-child(3) > div > p').text().replace(
            "上班地址：", "")
        info["companyInfo"] = jpy(
            'body > div.tCompanyPage > div.tCompany_center.clearfix > div.tCompany_main > div:nth-child(4) > div').text()
        info["positionInfo"] = jpy(
            'body > div.tCompanyPage > div.tCompany_center.clearfix > div.tCompany_main > div:nth-child(2) > div').text()
        return info


import random
from typing import List

import numpy as np
import torch
import torch.nn.functional as F
from torch import nn

from environments import MVCEnvironment
from graph_utils import draw_graph, get_adjacency_matrix

class Struc2Vec(nn.Module):

    def __init__(self, p: int = 64):
        super(Struc2Vec, self).__init__()
        self.theta1 = torch.Tensor(np.random.randn(*(1, p)) * 0.01)
        self.theta1.requires_grad = True
        self.theta2 = torch.Tensor(np.random.randn(*(p, p)) * 0.01)
        self.theta2.requires_grad = True
        self.theta3 = torch.Tensor(np.random.randn(*(p, p)) * 0.01)
        self.theta3.requires_grad = True
        self.theta4 = torch.Tensor(np.random.randn(*(1, 1, p)) * 0.01)
        self.theta4.requires_grad = True

    def forward(self, x: torch.Tensor, mu: torch.Tensor, w: torch.Tensor, adj_mat: torch.Tensor):
        t1 = self.theta1.mul(x)  # (N, p)

        t2 = adj_mat.mm(mu)
        t2 = t2.mm(self.theta2)  # (N, p)

        t3 = self.theta4.mul(w.unsqueeze(2))
        t3 = F.relu(t3)
        t3 = t3.sum(dim=1)
        t3 = t3.mm(self.theta3)  # (N, p)
        return F.relu(torch.add(t1, t2.add(t3)))

    @staticmethod
    def s2x(s: List[int], n_nodes: int):
        """One hot encode the state [1, 4, 5] to the Tensor x"""
        eye = np.eye(n_nodes)
        x = eye[s, :].sum(axis=0).reshape((-1, 1))
        return torch.Tensor(x)

class ReplayMemory(object):

    def __init__(self, capacity):
        self.capacity = capacity
        self.memory = []
        self.position = 0

    def push(self, transition):
        if len(self.memory) < self.capacity:
            self.memory.append(None)
        self.memory[self.position] = transition
        self.position = (self.position + 1) % self.capacity

    def sample(self, batch_size):
        if batch_size >= len(self.memory):
            return random.sample(self.memory, len(self.memory))
        return random.sample(self.memory, batch_size)

    def __len__(self):
        return len(self.memory)

class DQN(nn.Module):

    def __init__(self, emb_dim=64):
        super().__init__()
        self.theta5 = torch.Tensor(np.random.randn(*(2 * emb_dim, 1))*0.01)
        self.theta5.requires_grad = True
        self.theta6 = torch.Tensor(np.random.randn(*(emb_dim, emb_dim)) * 0.01)
        self.theta6.requires_grad = True
        self.theta7 = torch.Tensor(np.random.randn(*(emb_dim, emb_dim)) * 0.01)
        self.theta7.requires_grad = True

    def forward(self, mu: torch.Tensor):
        t1 = mu.sum(dim=(0,)).repeat((mu.shape[0], 1))
        t1 = t1.mm(self.theta6)  # (N, emb_dim)

        t2 = mu.mm(self.theta7)  # (N, emb_dim)

        t3 = torch.cat((t1, t2), dim=1)
        t3 = F.relu(t3)
        t3 = t3.mm(self.theta5)  # (N, 1)
        return t3

class Test:

    def __init__(self, n_graphs: int = 100, n_nodes_max: int = 200):
        np.random.seed(1234)

        self.graphs = []

        for i in range(n_graphs):
            n_nodes = random.randint(10, n_nodes_max)
            graph = draw_graph(n_nodes=n_nodes)
            self.graphs.append(graph)

    def evaluate_policy(self, agent):
        cumulated_reward = 0

        for graph in self.graphs:
            env = MVCEnvironment(name='test', graph=graph)
            adj_mat = get_adjacency_matrix(graph=graph)
            weights = adj_mat

            while not env.is_terminated():
                best_action = agent.pick_action(s=env.s, v_bar=env.v_bar, w=weights, adj_mat=adj_mat, train=False)
                _ = env.make_transition(best_action)

            cumulated_reward += env.get_cumulated_reward()

        return cumulated_reward


"""
Tendo como dado de entrada a altura (h) de uma pessoa, construa um algoritmo que calcule seu peso ideal, utilizando as seguintes fórmulas:
Para homens: (72.7*h) - 58
Para mulheres: (62.1*h) - 44.7
"""

h = float(input("Digite a sua altura (metros): "))

peso_homem = (72.7 * h ) - 58
peso_mulher = (62.1 * h ) - 44.7

print(f"O seu pêso ideal sendo homem será {peso_homem:.2f} kilogramas.")

print(f"O seu pêso ideal sendo mulher será {peso_mulher:.2f} kilogramas.")


n = int(input())
data = [[0]*n for _ in range(n)]
plan = input().split()
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
move_types = ['L', 'R', 'U', 'D']
x = 1
y = 1

for i in plan:
    for j in range(len(move_types)):
        if i == move_types[j]:
            nx = x + dx[j]
            ny = y + dy[j]

        if nx < 1 or ny < 1 or nx > n or ny > n:
            continue
        x = nx
        y = ny

pritn(x, y)


import os
from pathlib import Path
from typing import Any, Dict, Union
import numpy as np

def isdicom(path: Union[str, Path]) -> bool:
    """ Judge whether a given file is a valid dicom.

    Args:
        path: given file path.

    Returns:
        True if given path is a valid dicom, otherwise False.
    """
    if not os.path.isfile(path):
        return False

    # read preamble and magic code
    with open(path, "rb") as f:
        header = f.read(132)

    if not header:
        return False

    # magic code of a dicom file should be "DICM"
    return False if header[128:132] != b"DICM" else True

def get_reorient_image(vtd: Dict[str, Any]) -> np.ndarray:
    return np.flip(
        vtd["image_zyx"],
        np.where(vtd["direction_zyx"] < 0)[0]
    )


from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import logging

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']

class GmailAPI():
    def __init__(self):
        """Shows basic usage of the Gmail API.
        Lists the user's Gmail labels.
        """
        creds = None
        # The file token.pickle stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists('token.pickle'):
            with open('token.pickle', 'rb') as token:
                creds = pickle.load(token)
        # If there are no (valid) credentials available, let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                logging.info("Refreshing OAuth Token, Check browser...")
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'credentials.json', SCOPES)
                creds = flow.run_local_server(port=0)
            # Save the credentials for the next run
            with open('token.pickle', 'wb') as token:
                pickle.dump(creds, token)

        self.service = build('gmail', 'v1', credentials=creds)

    def get_email_list(self, options, pageToken=None):
        logging.info("Getting emails, Options: %s", options)

        response = self.service.users().messages().list(**options).execute()
        emails = response['messages']

        if response.get('nextPageToken'):
            options['pageToken'] = response['nextPageToken']
            next_page_response = self.get_email_list(options)
            emails.extend(next_page_response)

        return emails

    def get_emails(self, email_ids):
        logging.info("Downloading emails: %s", len(email_ids))
        response_array = []
        exception_array = []
        global total_downloaded
        total_downloaded = 0

        def callback_callable(request_idx, response, exception):
            global total_downloaded
            if exception:
                exception_array.append(request_idx) if request_idx not in exception_array else None
            else:
                total_downloaded += 1
                print("\rEmail Downloaded:", total_downloaded + 1, end="")
                response_array.append(response)

        batch = self.service.new_batch_http_request(callback=callback_callable)

        [batch.add(self.service.users().messages().get(
            userId='me', id=e_id), request_id=e_id) for e_id in email_ids]

        batch.execute()

        if exception_array:
            logging.warning("Exception Handling for: %s", exception_array)
            response_array.extend(self.get_emails(exception_array))

        return response_array


def bubblesort(arr=[]):
    if arr is None or len(arr) == 0:
        return arr

    arr_length = len(arr)

    for i in range(arr_length):
        something_sorted = False

        for j in range(0, arr_length - 1 - i):
            if arr[j] < arr[j + 1]:
                continue

            something_sorted = True
            arr[j], arr[j + 1] = arr[j + 1], arr[j]

        if not something_sorted:
            break

    return arr


#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
plt.style.use( 'publication.sty' )

from UtilitiesModule import GetFileArray, GetData

#### ========== User Input ==========

rootDirectory_NR \
  = '/home/kkadoogan/Work/Codes/thornado/SandBox/AMReX/Applications/\
StandingAccretionShock_NonRelativistic/'
rootDirectory_GR \
  = '/home/kkadoogan/Work/Codes/thornado/SandBox/AMReX/Applications/\
StandingAccretionShock_Relativistic/'

#IDs = np.array( [ '1D_M2.8_Mdot0.3_Rs060_nX380', \
#                  '1D_M2.8_Mdot0.3_Rs075_nX380', \
#                  '1D_M2.8_Mdot0.3_Rs090_nX380', \
#                  '1D_M2.8_Mdot0.3_Rs120_nX380', \
#                  '1D_M2.8_Mdot0.3_Rs150_nX380', \
#                  '1D_M2.8_Mdot0.3_Rs180_nX380' ], str )

IDs = np.array( [ '1D_M3.0_Mdot0.3_Rs020_nX400' ], str )

R_PNS = 10.0
#Rsh = np.array( [ 60.0, 75.0, 90.0, 120.0, 150.0, 180.0 ], np.float64 )
Rsh = np.array( [ 20.0 ], np.float64 )

nRows = 2
nCols = 1

yLabels = np.array( [ r'$p/\left(\rho\,c^{2}\right)$', \
                      r'$v/c$' ], str )

saveFigAs = 'fig.CompareNRvsGR_IC_Fluid.png'

verbose = False

#### ====== End of User Input =======

### Plotting

fig = plt.figure( figsize = (12,9) )
fig.suptitle( 'M3.0, Mdot0.3, Rpns010', fontsize = 15, y = 0.92 )

ax0 = fig.add_subplot( nRows, nCols, 1 )
ax1 = fig.add_subplot( nRows, nCols, 2 )

ax0.set_ylabel( yLabels[0] )
ax1.set_ylabel( yLabels[1] )

plotFileDirectory_NR = rootDirectory_NR
plotFileDirectory_GR = rootDirectory_GR

c = [ 'red',  \
      'orange',  \
      'yellow',  \
      'green',  \
      'blue',  \
      'magenta' ]

y0Min = +np.inf
y0Max = -np.inf
y1Min = +np.inf
y1Max = -np.inf
for i in range( IDs.shape[0] ):

    plotFileBaseName_NR = 'NR' + IDs[i] + '.plt'
    plotFileBaseName_GR = 'GR' + IDs[i] + '.plt'

    plotFileArray_NR \
      = GetFileArray( plotFileDirectory_NR, plotFileBaseName_NR )
    plotFileArray_GR \
      = GetFileArray( plotFileDirectory_GR, plotFileBaseName_GR )

    plotFile_NR = plotFileDirectory_NR + plotFileArray_NR[-1]
    plotFile_GR = plotFileDirectory_GR + plotFileArray_GR[-1]

    time, rho_NR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_NR, 'PF_D', verbose = verbose )
    time, rho_GR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_GR, 'PF_D', verbose = verbose )
    time, p_NR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_NR, 'AF_P', verbose = verbose )
    time, p_GR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_GR, 'AF_P', verbose = verbose )
    time, v_NR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_NR, 'PF_V1', verbose = verbose )
    time, v_GR, dataUnits, X1, X2, X3, dX1, dX2, dX3, nX \
      = GetData( plotFile_GR, 'PF_V1', verbose = verbose )

    rho_NR *= (2.99792458e10)**2
    rho_GR *= (2.99792458e10)**2

    v_NR /= 2.99792458e5
    v_GR /= 2.99792458e5

    lab = IDs[i][16:21]

    eta = np.copy( ( X1 - R_PNS ) / ( Rsh[i] - R_PNS ) )
    #eta = np.copy( X1 )

    ind = np.where( eta <= 1.0 )[0]
    eta = np.copy( eta[ind] )

    y0_NR = np.copy( p_NR[ind,0,0] / rho_NR[ind,0,0] )
    y0_GR = np.copy( p_GR[ind,0,0] / rho_GR[ind,0,0] )
    y1_NR = np.copy( v_NR[ind,0,0] )
    y1_GR = np.copy( v_GR[ind,0,0] )

    ax0.plot( eta, y0_NR, color = c[i], ls = '-', \
              label = r'\texttt{{NR_'+'{:}}}'.format( lab ) )
    ax0.plot( eta, y0_GR, color = c[i], ls = '--', \
              label = r'\texttt{{GR_'+'{:}}}'.format( lab ) )

    ax1.plot( eta, y1_NR, color = c[i], ls = '-' )
    ax1.plot( eta, y1_GR, color = c[i], ls = '--' )

#ax0.set_xlim( R_PNS, 5.0e1 )
#ax1.set_xlim( R_PNS, 5.0e1 )

#ax0.set_xlabel( r'Radial Coordinate $\left[\mathrm{km}\right]$' )
#ax1.set_xlabel( r'Radial Coordinate $\left[\mathrm{km}\right]$' )
ax0.set_xlabel \
  ( r'$\left(r-R_{\textsc{pns}}\right)/\left(R_{s}-R_{\textsc{pns}}\right)$' )
ax1.set_xlabel \
  ( r'$\left(r-R_{\textsc{pns}}\right)\left(R_{s}-R_{\textsc{pns}}\right)$' )

ax0.tick_params( axis = 'x', colors = 'k', labelsize = 15 )
ax0.tick_params( axis = 'y', colors = 'k', labelsize = 15 )
ax1.tick_params( axis = 'x', colors = 'k', labelsize = 15 )
ax1.tick_params( axis = 'y', colors = 'k', labelsize = 15 )

ax0.legend( loc = 1, prop = { 'size' : 13 } )

plt.subplots_adjust( hspace = 0.3 )
plt.savefig( saveFigAs, dpi = 300 )
#plt.show()
plt.close()

import os
os.system( 'rm -rf __pycache__ ' )


import pandas as pd
import numpy as np
from sklearn.compose import make_column_transformer
from sklearn.pipeline import make_pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.model_selection import RandomizedSearchCV

# Acknowledgement:
# The format of the function documentations are derived from the sample project provided.
# Proper citation to the sample projct is included in `notebooks/fraud_detection.ipynb`.
# https://github.com/ttimbers/demo-tests-ds-analysis-python/blob/main/src/count_classes.py
# Proper citation to the sample projct is included in `UGFraud`
# https://github.com/safe-graph/UGFraud/blob/master/UGFraud/Detector/SVD.py

def run_model_with_random_search(
    X_train, y_train, numerical_features, credit_feature, categorical_features,
    drop_features, model_class, param_dist, n_iter=5, cv=2, scoring="f1", need_class_weights=True):
    """
    Run a machine learning model with hyperparameter tuning using RandomizedSearchCV.

    Parameters:
    - X_train: Training input data.
    - y_train: True labels for training data.
    - numerical_features: List of numerical feature names.
    - credit_feature: Credit feature name.
    - categorical_features: List of categorical feature names.
    - drop_features: List of features to drop.
    - model_class: Machine learning model class (e.g., LogisticRegression, RandomForestClassifier).
    - param_dist: Parameter distribution for RandomizedSearchCV.
    - n_iter: Number of iterations for RandomizedSearchCV.
    - cv: Number of cross-validation folds.
    - scoring: Scoring metric for RandomizedSearchCV.

    Returns:
    - RandomizedSearchCV object

    Example:
    ```
    param_dist_logreg = {"logisticregression__C": 10.0 ** np.arange(-2, 3),
                        "logisticregression__solver": ["newton-cholesky", "lbfgs"]}
    logreg_search = run_model_with_random_search(
    X_train, y_train, numerical_features, credit_feature, categorical_features, drop_features,
    LogisticRegression, param_dist_logreg)
    logreg_search.fit(X_train, y_train)
    ```
    """
    # Input validation
    if not isinstance(X_train, pd.DataFrame):
        raise ValueError("X_train must be a DataFrame.")
    if not isinstance(y_train, pd.Series):
        raise ValueError("y_train must be a Series.")
    if X_train.shape[0] != y_train.shape[0]:
        raise ValueError("Number of rows in X_train and y_train must match.")

    # Check for duplicate feature names
    all_features = set(numerical_features + credit_feature + categorical_features + drop_features)
    if len(all_features) != len(numerical_features) + len(credit_feature) + len(categorical_features) + len(drop_features):
        raise ValueError("Duplicate feature names found.")

    # Ensure all features are non-empty strings
    if not all(isinstance(feature, str) and feature for feature in all_features):
        raise ValueError("All feature names must be non-empty strings.")

    # Check for overlapping features between numerical and categorical features
    if any(feature in numerical_features for feature in categorical_features):
        raise ValueError("Numerical and categorical features must not overlap.")

    # Check if numerical and credit features have any common elements
    if any(feature in numerical_features for feature in credit_feature):
        raise ValueError("Numerical and credit features must not have common elements.")

    ct = make_column_transformer(
        (
        make_pipeline(SimpleImputer(strategy="median"), StandardScaler()),
        numerical_features,
        ),
        (
        make_pipeline(SimpleImputer(strategy="mean"), StandardScaler()),
        credit_feature,
        ),
        (OneHotEncoder(drop="if_binary", handle_unknown="ignore"), categorical_features),
        ("drop", drop_features)
    )
    if need_class_weights:
        pipe = make_pipeline(ct, model_class(class_weight="balanced"))
    else:
        pipe = make_pipeline(ct, model_class())
    random_search = RandomizedSearchCV(
        pipe, param_dist, n_jobs=-1, n_iter=n_iter, cv=cv, scoring=scoring, return_train_score=True
    )

    return random_search


import Image
import ImageDraw
import math

def drawing(img):
    x,y = img.size
    cx = x/2
    cy = y/2
    if x < y:
        rad = x/2
    else:
        rad = y/2
    draw = ImageDraw.Draw(img)
    for i in range(0,x):
        for j in range(0,y):
            dist = math.sqrt((i - cx)*(i - cx) + (j - cy)*(j - cy))
            val = 0xff*(1.0 - (dist/rad));
            draw.point((i, j), (0xff,0xff,0xff,int(val)))
    return img

def make_image(screen, bgcolor, filename):
    img = Image.new('RGBA', screen, bgcolor)
    img = drawing(img)
    img.save(filename)

if __name__ == '__main__':
    screen = (64,64)

    bgcolor=(0x00,0x00,0x00,0x00)

    filename = "sphere.png"

    make_image(screen, bgcolor, filename)

#EOF


#!/usr/bin/env python3

from collections import OrderedDict

def singleton(func):
    return func()

@singleton
def primes(n=10**6):
    seive = [True for _ in range(n+1)]
    seive[0] = seive[1] = False
    for idx in range(2, int(n**0.5)+1):
        if not idx:
            continue
        for change in range(2*idx, n+1, idx):
            seive[change] = False
    return OrderedDict([(idx,0) for idx, valid in enumerate(seive) if valid])

def goldbach_even(n):
    for p in primes:
        if n-p in primes:
            return p, n-p

def main():
    while True:
        n = int(input())
        if n == 0:
            break
        a, b = goldbach_even(n)
        print('{} = {} + {}'.format(n, a, b))

if __name__ == '__main__':
    main()


import random
import re
import time
import pymongo
import requests
from urllib.parse import quote
from multiprocessing import Pool
from config import *

'''
爬取淘宝1688商品信息，运行前请先打开代理
'''

client = pymongo.MongoClient(MONGO_URI)
db = client[MONGO_DB]
item_id = set()

def get_proxy():
    '''
    获取代理
    '''
    return requests.get("http://127.0.0.1:5010/get/").text

def get_one_page(page):
    '''
    得到单页商品信息
    '''
    try:
        print('正在爬取第%d页' % page)
        # for syncreq in range(1, MAX_SYNCREQ + 1):
        proxy = get_proxy()
        url = 'https://data.p4psearch.1688.com/data/ajax/get_premium_offer_list.json'
        data = {
            'beginpage': str(page),  # 页数
            'syncreq': '1',  # 同步请求参数  str(syncreq)
            'keywords': KEYWORD  # 搜索关键词
        }
        headers = {
            'User_Agent': random.choice(USER_AGENT),
            'Referer': 'https://p4psearch.1688.com/p4p114/p4psearch/offer.htm?keywords=' + quote(
                KEYWORD) + '&sortType=&descendOrder=&province=&city=&priceStart=&priceEnd=&dis=&provinceValue=%E6%89%80%E5%9C%A8%E5%9C%B0%E5%8C%BA',
            'Cookie': COOKIE,
        }
        proxies = {"http": "http://{}".format(proxy)}
        response = requests.get(url=url, headers=headers, params=data, proxies=proxies, timeout=5)
        time.sleep(1)
        if response.status_code == 200:
            data = response.json()
            get_info(data=data)
    except Exception:
        print('出现异常，重新爬取第%d页' % page)
        return get_one_page(page)

def get_info(data):
    '''
    得到并保存商品信息
    '''
    try:
        print('正在获取商品信息..')
        items = data['data']['content']['offerResult']
        # item为每一个商品
        for item in items:
            param1 = item['attr']['company']
            company = param1['name']
            type = param1['bizTypeName']
            city = param1['city']
            province = param1['province']
            param2 = item['attr']['tradePrice']['offerPrice']
            originalValue = param2['originalValue']['integer'] + param2['originalValue']['decimals'] / 10
            quantityPrices = param2['value']['integer'] + param2['value']['decimals'] / 10
            param3 = item['attr']['tradeQuantity']
            sales = param3['number']
            saleType = param3['sortType']
            detailUrl = item['eurl']
            imgUrl = item['imgUrl']
            originaltitle = item['title']
            title = re.sub('<.*>', '', originaltitle)
            result = {
                '标题': title,
                '原价': originalValue,
                '最低批发价': quantityPrices,
                '销售量': sales,
                '销售形式': saleType,
                '详细链接': detailUrl,
                '图片链接': imgUrl,
                '公司': company,
                '公司类型': type,
                '城市': city,
                '省份': province,
            }
            save_to_mongo(result=result)
    except TypeError:
        pass

def save_to_mongo(result):
    '''
    信息保存至mongoDB
    '''
    # 去除标题相同的商品
    if result['标题'] in item_id:
        print('发现重复item，丢弃--->%s<---' % result['标题'])
    else:
        item_id.add(result['标题'])
        if db[MONGO_TABLE].insert(result):
            print('成功保存至mongoDB', result['标题'])

def main(page):
    get_one_page(page)
    print('有效商品数为%d'%len(item_id))  # 打印有效商品数量

if __name__ == '__main__':
    page = [x for x in range(1, MAX_PAGE + 1)]
    # 多进程
    pool = Pool()
    pool.map(main, page)

# todo 待解决问题：
'''
关于遍历syncreq获取单页更多信息，每页的第一个请求正常，
后续获得商品重复，怀疑与请求头里面的一些参数有关，若无
法分析参数规律，该爬虫只可扩大MAX_PAGE获得更多采集量。
或者换用selenium的方式来爬取。
2019.1.10
'''


from top.util.config import Config
from top.trainer import get_model_dirs, load_best_model_weight
from top.env.reversi_player import ReversiPlayer, Player, Winner
from top.env.reversi_env import ReversiEnv
from top.model.residual_network import ReversiModel
import os
import numpy as np

# evaluate which model is better
def start(config: Config):
    evaluator = Evaluator(config)
    evaluator.start()

class Evaluator:
    def __init__(self, config: Config):
        self.config = config
        self.test_model = None
        self.best_model = None
        self.test_model_path = None

    def start(self):
        if self._load_model():
            self._start_evaluate()

    def _load_model(self):
        self.best_model = ReversiModel(self.config)
        self.test_model = ReversiModel(self.config)
        dirs = get_model_dirs(self.config.resource)
        if load_best_model_weight(self.best_model):
            print('restore best model: ', self.best_model.config.resource.model_best_weight_path)
        else:
            print('fail to restore best model: ', self.best_model.config.resource.model_best_weight_path)
            return False
        if len(dirs) == 0:
            print('fail to restore best model.')
            return False
        latest_dir = dirs[-1]
        self.test_model_path = latest_dir
        config_path = os.path.join(latest_dir, self.config.resource.next_generation_model_config_filename)
        weight_path = os.path.join(latest_dir, self.config.resource.next_generation_model_weight_filename)
        self.test_model.load(config_path, weight_path)
        print('restore model from {}'.format(weight_path))
        return True

    def _start_evaluate(self):
        best_player = ReversiPlayer(self.best_model, self.config, play_config=self.config.eval.play_config)
        test_player = ReversiPlayer(self.test_model, self.config, play_config=self.config.eval.play_config)
        winning_rate = 0
        env = ReversiEnv()
        for game_idx in range(self.config.eval.game_num):
            best_is_black = np.random.random() < 0.5
            if best_is_black:
                black_player, white_player = best_player, test_player
            else:
                black_player, white_player = test_player, best_player
            env.reset()
            observation = env.observation
            while not env.done:
                if env.curr_player == Player.Black:
                    action = black_player.action(observation.black, observation.white)
                else:
                    action = white_player.action(observation.white, observation.black)
                observation = env.step(action)
            black, white = env.board.number_of_stones
            if env.winner == Winner.Black:
                if best_is_black:
                    print(('Winner: Best Model(Black)', (black, white)))
                    winning_rate += 1
                else:
                    print(('Winner: Test Model(Black)', (black, white)))
            else:
                if best_is_black:
                    print(('Winner: Test Model(White)', (black, white)))
                else:
                    print(('Winner: Best Model(White)', (black, white)))
                    winning_rate += 1
        print('Best Model winning rate: {}'.format(1.0 * winning_rate / self.config.eval.game_num))
        print('Test Model winning rate: {}'.format(1 - 1.0 * winning_rate / self.config.eval.game_num))
        print('Test Model is {}'.format(self.test_model_path))


#@+leo-ver=5-thin
#@+node:ville.20090518182905.5419: * @file nav_qt.py
#@+<< docstring >>
#@+node:ville.20090518182905.5420: ** << docstring >>
'''Adds "Back" and "Forward" buttons (Qt only).

Creates "back" and "forward" buttons on button bar. These navigate
the node history.

This plugin does not need specific setup. If the plugin is loaded, the buttons
will be available. The buttons use the icon specified in the active Qt style

'''
#@-<< docstring >>

__version__ = '0.2'
#@+<< version history >>
#@+node:ville.20090518182905.5421: ** << version history >>
#@@killcolor
#@+at
#
# 0.1 Functionally complete version
# 0.2 EKR: check p before calling c.selectPosition(p)
#@-<< version history >>

#@+<< imports >>
#@+node:ville.20090518182905.5422: ** << imports >>
import leo.core.leoGlobals as g

g.assertUi('qt')

import PyQt4.QtGui as QtGui
import PyQt4.QtCore as QtCore
#@-<< imports >>

controllers = {}
    # keys are c.hash(), values are NavControllers

#@+others
#@+node:ville.20090518182905.5423: ** init
def init ():

    ok = g.app.gui.guiName() == "qt"

    if ok:
        g.registerHandler('after-create-leo-frame',onCreate)

        g.plugin_signon(__name__)

    return ok
#@+node:ville.20090518182905.5424: ** onCreate
def onCreate (tag, keys):

    global controllers

    c = keys.get('c')
    if not c: return

    h = c.hash()

    nc = controllers.get(h)
    if not nc:
        controllers [h] = NavController(c)
#@+node:ville.20090518182905.5425: ** class NavController
class NavController:

    #@+others
    #@+node:ville.20090518182905.5426: *3* __init__
    def __init__ (self,c):

        self.c = c
        c._prev_next = self

        self.makeButtons()

    #@+node:ville.20090518182905.5427: *3* makeButtons
    def makeButtons(self):

        c = self.c
        w = c.frame.iconBar.w
        if not w: return # EKR: can be None when unit testing.

        icon_l = w.style().standardIcon(QtGui.QStyle.SP_ArrowLeft)
        icon_r = w.style().standardIcon(QtGui.QStyle.SP_ArrowRight)

        act_l = QtGui.QAction(icon_l,'prev',w)
        act_r = QtGui.QAction(icon_r,'next',w)

        # 2011/04/02: Use the new commands.
        act_l.connect(act_l,QtCore.SIGNAL("triggered()"),c.goToPrevHistory)
        act_r.connect(act_r,QtCore.SIGNAL("triggered()"),c.goToNextHistory)

        # 2011/04/02: Don't execute the command twice.
        self.c.frame.iconBar.add(qaction = act_l) #, command = self.clickPrev)
        self.c.frame.iconBar.add(qaction = act_r) #, command = self.clickNext)
    #@-others
#@-others
#@-leo


import argparse
from ReadStream import StreamReader

""" USAGE:

    python download_data.py -o <output_data_directory> -run <last_4_digits_of_run>
    -n <number_of_files_to_read> -format <upper or lower>

    The output data directory should be ../data/ unless you want to save data somewhere else (not recommended).
    The ../data/ folder will be created while running this script the first time, and it has already been added to .gitignore!

    Example: to download the old data RUN001231

    python download_data.py -run 1231 -format upper

    Example: to download a small portion of RUN001231 into the ../data/ folder simply type

    python download_data.py -run 1231 -n 20 -format upper

    IF data is NEW data then set -format lower

    Example: to download the new data Run000054

    python download_data.py -run 0054 -format lower

    IF data is the NEWEST data then set -format lower and -capital lower

    Example: to download the new data run000057

    python download_data.py -run 0054 -format lower -capital lower

    If you change the output directory please make sure to add the new folder to .gitignore

"""

def argParser():
    """manages command line arguments"""

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-o", "--output", type=str, default="../data/", help="output directory"
    )
    parser.add_argument(
        "-format", "--format", type=str, default="upper", help="CVeneto container format"
    )
    parser.add_argument(
        "-capital", "--capital", type=str, default="upper", help="first letter capital or not"
    )
    parser.add_argument(
        "-run", "--run", type=str, default="0054", help="run number"
    )
    parser.add_argument(
        "-n", "--nfiles", type=int, default=-1, help="number of files"
    )

    return parser.parse_args()

def main(args):
    """
        MAIN FUNCTION gets data from CloudVeneto and save them into a .txt file

        args: the command line arguments
    """

    # store the command line arguments
    RUNNUMBER = args.run
    OUT_PATH  = args.output
    N_FILES   = args.nfiles
    FORMAT    = args.format
    CAPITAL   = args.capital

    # create an instance of StreamReader to manage data I/O from CloudVeneto
    reader = StreamReader(RUNNUMBER, OUT_PATH, N_FILES, FORMAT, CAPITAL)

    # get data from CloudVeneto
    reader.readStream()
    # save data into a .txt file
    reader.saveData()

    print("\n\nExiting...\n\n")

if __name__ == "__main__":
    args = argParser()
    main(args)


# EXERCISE 1

phonebook_dict = {
  'Alice': '703-493-1834',
  'Bob': '857-384-1234',
  'Elizabeth': '484-584-2923'
}

def phone_by_name(name):
    print(phonebook_dict.get(name))

def add_entry(name, phone_number):
    phonebook_dict[name] = phone_number
    print(phonebook_dict)

def delete_entry(name):
    phonebook_dict.pop(name)
    print(phonebook_dict)

def update_entry(name, phone_number):
    phonebook_dict.update({name:phone_number})
    print(phonebook_dict)

def print_phonebook():
    print(phonebook_dict)

# Print Elizabeth's phone number.
phone_by_name("Elizabeth")
# Add a entry to the dictionary: Kareem's number is 938-489-1234.
add_entry(name=input("What is the contact\'s name?"), phone_number=input("What is the contact\'s phone number?"))
# Delete Alice's phone entry.
delete_entry(name=input("What is the name of the contact you want to delete?"))
# Change Bob's phone number to '968-345-2345'.
update_entry(name=input("Who's phone number do you want to update?"), phone_number=input("What is the contact\'s phone number?"))
# Print all the phone entries.
print_phonebook()

# EXERCISE 2
ramit = {
  'name': 'Ramit',
  'email': 'ramit@gmail.com',
  'interests': ['movies', 'tennis'],
  'friends': [
     {
       'name': 'Jasmine',
       'email': 'jasmine@yahoo.com',
       'interests': ['photography', 'tennis']
     },
     {
        'name': 'Jan',
        'email': 'jan@hotmail.com',
        'interests': ['movies', 'tv']
     }
    ]
}

# Write a python expression that gets the email address of Ramit.
print(ramit['email'])
# Write a python expression that gets the first of Ramit's interests.
print(ramit['interests'][0])
# Write a python expression that gets the email address of Jasmine.
print(ramit['friends'][0]['email'])
# Write a python expression that gets the second of Jan's two interests.
print(ramit['friends'][1]['interests'][1])

# EXERCISE 3 - Letter Summary
# Write a letter_histogram function that takes a word as its input, and returns a dictionary containing the tally of how many times each letter in the alphabet was used in the word. For example:

def letter_histogram(word) :
    d = dict()
    for letter in word:
        if letter not in d:
            d[letter.lower()] = 1
        else:
            d[letter.lower()] += 1
    return d

def print_hist(h):
    for letter in h:
        print(letter, h[letter])

print_hist(letter_histogram(input("Please enter a word: ")))
print("*"*30)

# Exercise 4 - Word Summary
# Write a word_histogram function that takes a paragraph of text as its input, and returns a dictionary containing the tally of how many times each word in the alphabet was used in the text. For example:

def word_histogram(paragraph) :
    word_d = dict()
    for word in paragraph.split(" "):
        if word not in word_d:
            word_d[word.lower()] = 1
        else:
            word_d[word.lower()] += 1
    return word_d

def print_hist(k):
    for word in k:
        print(word, k[word])

print_hist(word_histogram('To be or not to be'))

# Bonus Challenge
# Given a histogram tally (one returned from either letter_histogram or word_summary), print the top 3 words or letters.


from django.db import models

class Trainer(models.Model):
    base_user = models.OneToOneField(
        to='users.User',
        on_delete=models.CASCADE,
        related_name='trainer',
        verbose_name='id пользователя'
    )

    class Meta:
        verbose_name = 'Тренер'
        verbose_name_plural = 'Тренер'
        ordering = ('base_user',)

    def __str__(self):
        return self.base_user


from fastapi import APIRouter, Body, Depends, Path

from api.database.config import DBConnectionHandler

from . import domain, models

router = APIRouter()

@router.post("/", response_model=models.Condominium)
async def insert_condominium(
    payload: models.Condominium = Body(...), context: DBConnectionHandler = Depends()
):
    return await domain.InsertCondominiumUseCase(context, payload).execute()

@router.post("/{condominium_id}", response_model=models.BaseUser, status_code=202)
async def create_user(
    condominium_id: int = Path(...),
    payload: models.CreateUser = Body(...),
    context: DBConnectionHandler = Depends(),
):
    return await domain.CreateUserUseCase(condominium_id, context, payload).execute()


class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        ls = [['a',a],['b', b],['c', c]]
        res = ''

        flag = True
        while flag:
            flag = False
            ls.sort(key = lambda x: x[1],reverse = True)

            for element in ls:
                if (len(res) < 2 or not res[-2] == res[-1] == element[0]):
                    if element[1] > 0:
                            flag = True
                            res += element[0]
                            element[1] -= 1
                            break

        return res


import pandas as pd
import os
from datetime import datetime
from module import get_start_endtime, get_exechost

def main():
        '''
        From darshan log, jobid, starttime, endtime are gathered with get_start_endtime() from module.py.
        '''
        print('please input darshan log file name')
        filename = input() # Manual input the name we want to analyze
        jobid, start, end = get_start_endtime(filename)

        '''
        Get nodelist used by the corresponding jobid from the scheduled log of the date obtained above.
        get_start_endtime() from  module.py
        '''
        jobid, hostlist = get_exechost(start[:8], jobid) #return jobid, nodelist

        '''
        # Open csv of the date and make newdf between start time-10 and end time+10.
        # groupby('{}').mean().format(feature)
        # The average of counts per feature in the time period is obtained.
        # save one row in (csv/DB)
        # index = jobid, nodename / column = each feature
        '''
        for i in range(len(hostlist)): #for all host list for one jobid
                bound = datetime.timedelta(seconds=10)
                path1 = str(os.getcwd())+'/res/{}/{}data.csv'.format(hostlist[i],start[2:8])
                df1 = pd.read_csv(path1,'/','')
                df1['timestamp'] = pd.to_datetime(df1['timestamp'], infer_datetime_format=True)

                if start[8]==end[8]:
                        mask = (df1['timestamp'] > start - bound) & (df1['timestamp'] < end + bound)
                        selected_df = df1.loc[mask]
                else:
                        path2 = str(os.getcwd())+'/res/{}/{}data.csv'.format(hostlist[i],end[2:8])
                        df2 = pd.read_csv(path2)
                        df2['timestamp'] = pd.to_datetime(df1['timestamp'], infer_datetime_format=True)
                        mask1 = (df1['timestamp'] > start - bound)
                        mask2 = (df2['timestamp'] < end + bound)
                        selected_df = pd.concat(df1.loc[mask1],df2.loc[mask2])

                # get mean, std of each feature per one node that is used. save each row in csv
                print( hostlist[i],':\n', selected_df.describe() )

if __name__== '__main__':
    main()


# 导入随机包
import copy
import math
import random

class RandomPlayer:
    """
    随机玩家, 随机返回一个合法落子位置
    """

    def __init__(self, color):
        """
        玩家初始化
        :param color: 下棋方，'X' - 黑棋，'O' - 白棋
        """
        self.color = color

    def random_choice(self, board):
        """
        从合法落子位置中随机选一个落子位置
        :param board: 棋盘
        :return: 随机合法落子位置, e.g. 'A1'
        """
        # 用 list() 方法获取所有合法落子位置坐标列表
        action_list = list(board.get_legal_actions(self.color))

        # 如果 action_list 为空，则返回 None,否则从中选取一个随机元素，即合法的落子坐标
        if len(action_list) == 0:
            return None
        else:
            return random.choice(action_list)

    def get_move(self, board):
        """
        根据当前棋盘状态获取最佳落子位置
        :param board: 棋盘
        :return: action 最佳落子位置, e.g. 'A1'
        """
        if self.color == 'X':
            player_name = '黑棋'
        else:
            player_name = '白棋'
        print("请等一会，对方 {}-{} 正在思考中...".format(player_name, self.color))
        action = self.random_choice(board)
        return action

class HumanPlayer:
    """
    人类玩家
    """

    def __init__(self, color):
        """
        玩家初始化
        :param color: 下棋方，'X' - 黑棋，'O' - 白棋
        """
        self.color = color

    def get_move(self, board):
        """
        根据当前棋盘输入人类合法落子位置
        :param board: 棋盘
        :return: 人类下棋落子位置
        """
        # 如果 self.color 是黑棋 "X",则 player 是 "黑棋"，否则是 "白棋"
        if self.color == "X":
            player = "黑棋"
        else:
            player = "白棋"

        # 人类玩家输入落子位置，如果输入 'Q', 则返回 'Q'并结束比赛。
        # 如果人类玩家输入棋盘位置，e.g. 'A1'，
        # 首先判断输入是否正确，然后再判断是否符合黑白棋规则的落子位置
        while True:
            action = input(
                "请'{}-{}'方输入一个合法的坐标(e.g. 'D3'，若不想进行，请务必输入'Q'结束游戏。): ".format(player,
                                                                             self.color))

            # 如果人类玩家输入 Q 则表示想结束比赛
            if action == "Q" or action == 'q':
                return "Q"
            else:
                row, col = action[1].upper(), action[0].upper()

                # 检查人类输入是否正确
                if row in '12345678' and col in 'ABCDEFGH':
                    # 检查人类输入是否为符合规则的可落子位置
                    if action in board.get_legal_actions(self.color):
                        return action
                else:
                    print("你的输入不合法，请重新输入!")

import copy
class Node:
    def __init__(self,state,color,parent = None,action = None):
        self.visit = 0
        self.blackwin = 0
        self.whitewin = 0
        self.reward = 0.0
        self.state = state
        self.children = []
        self.parent = parent
        self.action = action
        self.color = color

    def add_child(self,new_state,action,color):
        child_node = Node(new_state,parent=self,action = action,color=color)
        self.children.append(child_node)

    def if_fully_expanded(self):
        cnt_max = len(list(self.state.get_legal_actions(self.color)))
        print("cnt_max = ",cnt_max)
        cnt_now = len(self.children)
        print("cnt_now = ", cnt_now)
        if(cnt_max <= cnt_now):
            return True
        else:
            return False

class AIPlayer:
    """
    AI 玩家
    """

    def __init__(self, color):
        """
        玩家初始化
        :param color: 下棋方，'X' - 黑棋，'O' - 白棋
        """

        self.color = color
    def if_terminal(self,state):
        # to see a state is terminal or not
        action_black = list(state.get_legal_actions('X'))
        action_white = list(state.get_legal_actions('O'))
        if(len(action_white) == 0 and len(action_black) == 0):
            return True
        else:
            return False

    def back_propagate(self,node,blackw,whitew):
        while(node is not None):
            node.visit+=1
            node.blackwin+=blackw
            node.whitewin+=whitew
            node = node.parent
        return 0

    def reverse_color(self,color):
        if(color == 'X'):
            return 'O'
        else:
            return 'X'

    def stimulate_policy(self,node):
        board = copy.deepcopy(node.state)
        color = copy.deepcopy(node.color)
        cnt = 0
        while not self.if_terminal(board):
            actions = list(node.state.get_legal_actions(color))
            if(len(actions)==0):
                #no way to go
                color = self.reverse_color(color)
            else:
                #have ways to go
                action = random.choice(actions)
                board._move(action,color)
                color = self.reverse_color(color)
            cnt+=1
            if cnt>20:
                break
        return board.count('X'),board.count('O')

    def ucb(self,node,uct_scalar=0.0):
        max = -float('inf')
        max_set=[]
        for c in node.children:
            exploit = 0
            if c.color == 'O':
                exploit = c.blackwin/(c.blackwin+c.whitewin)
            else:
                exploit = c.whitewin/(c.blackwin+c.whitewin)
            explore = math.sqrt(2.0*math.log(node.visit)/float(c.visit))
            uct_score = exploit+uct_scalar*explore
            if(uct_score==max):
                max_set.append(c)
            elif(uct_score>max):
                max_set=[c]
                max = uct_score
        if(len(max_set)==0):
            print("max_set is empty")
            print(len(node.children))
            node.state.display()
            return node.parent
        else:
            return random.choice(max_set)

    def expand(self,node):
        actions_available = list(node.state.get_legal_actions(node.color))
        actions_already = [c.action for c in node.children]
        if(len(actions_available)==0):
            return node.parent
        action = random.choice(actions_available)
        while action in actions_already:
            action=random.choice(actions_available)
        print(action)
        new_state = copy.deepcopy(node.state)
        new_state._move(action,node.color)
        new_state.display()
        new_color = self.reverse_color(node.color)
        node.add_child(new_state,action = action,color= new_color)
        return node.children[-1]

    def select_policy(self,node):
        while(not self.if_terminal(node.state)):
            if(len(list(node.state.get_legal_actions(node.color)))==0):
                return node;
            elif(not node.if_fully_expanded()):
                print("need to expand")
                new_node = self.expand(node)
                print("end of expand")
                return new_node
            else:
                print("fully expaned")
                node.state.display()
                print(len(node.children))
                print(list(node.state.get_legal_actions(node.color)))
                node = self.ucb(node)
        return node

    def MCTS_search(self,root,maxt = 100):
        #print("root state :")
        #root.state.display()
        for t in range(maxt):
            print("$$$$$$$$$$$$$$t = ",t)
            leave = self.select_policy(root)
            #print("leave state:")
            #leave.state.display()
            blackwin,whitewin = self.stimulate_policy(leave)
            self.back_propagate(leave,blackw=blackwin,whitew=whitewin)
        #print("root state :")
        #root.state.display()
        return self.ucb(root).action

    def get_move(self, board):
        """
        根据当前棋盘状态获取最佳落子位置
        :param board: 棋盘
        :return: action 最佳落子位置, e.g. 'A1'
        """
        if self.color == 'X':
            player_name = '黑棋'
        else:
            player_name = '白棋'
        print("请等一会，对方 {}-{} 正在思考中...".format(player_name, self.color))

        # -----------------请实现你的算法代码--------------------------------------
        action = None
        root_board = copy.deepcopy(board)
        root = Node(state=root_board,color=self.color)
        action = self.MCTS_search(root)

        # ------------------------------------------------------------------------

        return action

# 导入黑白棋文件
from game import Game

# 人类玩家黑棋初始化
black_player =  AIPlayer("X")

# AI 玩家 白棋初始化
white_player = RandomPlayer("O")

# 游戏初始化，第一个玩家是黑棋，第二个玩家是白棋
game = Game(black_player, white_player)

# 开始下棋
game.run()


from django.contrib import admin
from django.urls import path, include
from .views import index, kategoriolustur, dersolustur, kategoriler, kategori_ayrinti,ders_ayrinti

app_name = 'dersler'

urlpatterns = [
    path('', index, name='index'),
    path('yeni-kategori/', kategoriolustur, name='kategoriolustur'),
    path('yeni-ders/', dersolustur, name='dersolustur'),
    path('kategoriler/', kategoriler, name='kategoriler'),
    path('kategori/<int:kategori_id>', kategori_ayrinti, name='kategori_ayrinti'),
    path('ders/<int:ders_id>', ders_ayrinti, name='ders_ayrinti'),

]


#! /usr/bin/env python
#coding = utf-8

'''
@version:??
@author:rock zhou
@file: ippre.py
@time: 2016/3/26 9:55
'''

def ippre(filepath,filenamein):
    filein=open(filepath+filenamein,'r')
    flag=0
    iplist=[]
    for line in filein.readlines():
        if(flag==0):
            iplist.append(line)
            flag=1
        else:
            flag=0
    filein.close()
    return iplist
def dealiplist(iplist):
    toiplist=[]
    for ele in iplist:
        onelist=[]
        onelist=ele.split('\t')
        ip=onelist[1]
        port=onelist[2]
        templist=ip+':'+port+'\n'
        toiplist.append(templist)
    return toiplist

def writeiplist(filepath,filenameout,iplist):
    fileout=open(filepath+filenameout,'a+')
    for elem in iplist:
        fileout.write(elem)
    fileout.close()

if __name__ == '__main__':
    filepath="F:\\temp\\"
    filenamein="inip.txt"
    filenameout="ouip.txt"
    iplist=ippre(filepath,filenamein)
    toiplist=dealiplist(iplist)
    writeiplist(filepath,filenameout,toiplist)