#=======================================================================
#
#  Module in PVTfree, Copyright (C) Steve Furnival, HoBoil Limited
#  see PVTfree.py for further details
#
#  Write Data for Compositional Data Output
#
#=======================================================================

#!/usr/bin/python3

import datetime

import numpy     as NP

import calcWater as CW
import utilities as UT
import writeBlk  as WB
import writeOut  as WO

#========================================================================
#  Write GEM Output
#========================================================================

def writeGEM(ZMFvD,clsEOS,dicSAM,clsCMP,clsIO,clsUNI) :

#-- Initialisation --------------------------------------------------

    sCom = "**"
    nCom = clsEOS.nComp

    dVec = NP.zeros(nCom)

#-- Open the GEM File, if not already open -------------------------

    if not clsIO.qGEM :
        pathGEM = clsIO.patR + ".gem"
        fGEM    = open(pathGEM,'w')
        clsIO.setQGEM(True)
        clsIO.setFGEM(fGEM)
    else :
        fGEM = clsIO.fGEM

#== Headers ===========================================================

    print("Writing Compositional Description for GEM")

    fSim = clsIO.fGEM
    sInp = clsIO.fInp.name

    OutU = clsCMP.OutU

    if OutU[:3] == "MET" : sUni = "METRIC"
    else                 : sUni = "FIELD "

#-- Write Header Information to Simulator File ----------------------

    WO.outputHeader(fSim,sCom,clsIO)
    WO.outputEOS(fSim,sCom,clsIO,clsEOS)

#-- Header ----------------------------------------------------------

#               123456789012345678901234567890123456789012345678901234567890
    sHead = "**==========================================================\n"
    fSim.write(sHead)
    sLabl = "**  CMG-GEM EOS Model generated by PVTfree Program\n"
    fSim.write(sLabl)
    sLabl = "**  From dataset " + sInp + "\n"
    fSim.write(sLabl)
    sLabl = "**  User specified " + sUni + " Units\n"
    fSim.write(sLabl)
    fSim.write(sHead)
    fSim.write("\n")

#-- Equation of State -----------------------------------------------

    sLabl = "** Equation of State: Peng-Robinson (PR) or Soave-Redlich-Kwong (SRK)\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sEoS = clsEOS.EOS
    sOut = "*MODEL  *" + sEoS + "\n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Number of Components --------------------------------------------

    sLabl = "** Number of Components; All assumed to be USER components\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sOut = "*NC  " + str(nCom) + "  " + str(nCom) + "\n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Component Names -------------------------------------------------

    sLabl = "** Component Names\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sOut = "*COMPNAME  "
    for iC in range(nCom) :
        sNam = clsEOS.gNM(iC)
        sOut = sOut + "'" + sNam + "'  "
    sOut = sOut + "\n"
    fSim.write(sOut)
    fSim.write("\n")

    fSim.write("*EOSSET  1\n")
    fSim.write("\n")

#-- Mole Weights ----------------------------------------------------

    sCom = "**  Molecular Weights : [gm/gmol]\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MW",iC)
    writeVectorD(fSim,sCom,"*MW",7,"{:8.3f}",dVec)

#-- Specific Gravity ------------------------------------------------

    sCom = "**  Specific Gravity\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("SG",iC)
    writeVectorD(fSim,sCom,"*SG",7,"{:8.6f}",dVec)

#-- Boiling Point Temperature ---------------------------------------

    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("TB",iC)
    if OutU[:3] == "MET" :
        sUni = ": [degC]"
        for iC in range(nCom) : dVec[iC] = clsUNI.I2X(dVec[iC],"degc")
    else :
        sUni = ": [degF]"
        for iC in range(nCom) : dVec[iC] = clsUNI.I2X(dVec[iC],"degf")
    sCom = "**  Boiling Point Temperature " + sUni + "\n"
    writeVectorD(fSim,sCom,"*TB",7,"{:8.3f}",dVec)

#-- Critical Temperatures -------------------------------------------

    for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("TC",iC),"kelv")
    sCom = "**  Critical Temperatures : [Kelvin]" + "\n"
    writeVectorD(fSim,sCom,"*TCRIT",7,"{:8.3f}",dVec)

#-- Critical Pressures ----------------------------------------------

    for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("PC",iC),"atm")
    sCom = "**  Critical Pressures : [atm]\n"
    writeVectorD(fSim,sCom,"*PCRIT",7,"{:8.4f}",dVec)

#-- Critical Volumes ------------------------------------------------

    for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("VC",iC),"m3/kgmol")
    sCom = "**  Critical Volumes : [m3/kgmol]\n"
    writeVectorD(fSim,sCom,"*VCRIT",7,"{:8.3f}",dVec)

#-- Critical Z-Factors ----------------------------------------------

    sCom = "**  Critical Z-Factors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("ZC",iC)
    writeVectorD(fSim,sCom,"*ZCRIT",7,"{:8.6f}",dVec)

#-- Acentric Factors ------------------------------------------------

    sCom = "**  Acentric Factors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("AF",iC)
    writeVectorD(fSim,sCom,"*AC",7,"{:8.6f}",dVec)

#-- Parachors -------------------------------------------------------

    sCom = "**  Parachors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("PA",iC)
    writeVectorD(fSim,sCom,"*PCHOR",7,"{:8.3f}",dVec)

#-- Omega-A's -------------------------------------------------------

    sCom = "**  Omega-A Values " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MA",iC)*clsEOS.OA
    writeVectorD(fSim,sCom,"*OMEGA",6,"{:11.9f}",dVec)

#-- Omega-B's -------------------------------------------------------

    sCom = "**  Omega-B Values " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MB",iC)*clsEOS.OB
    writeVectorD(fSim,sCom,"*OMEGB",6,"{:11.9f}",dVec)

#-- Volume Shifts ---------------------------------------------------

    sCom = "**  Volume Shifts " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("SS",iC)
    writeVectorD(fSim,sCom,"*VSHIFT",7,"{:9.6f}",dVec)

#-- Binary Interaction Parameters -----------------------------------

    sCom = "** Binary Interaction Parameters\n"
    fSim.write(sCom)
    fSim.write("\n")
    sOut = "*BIN  "

    for iC in range(1,nCom) :
        for jC in range(iC) :
            dVal = clsEOS.gIJ(iC,jC) ; sVal = "{:9.6f}  ".format(dVal)
            sOut = sOut + sVal
        sOut = sOut + "\n"
        fSim.write(sOut)
        sOut = "      "

    fSim.write("\n")

#-- Reservoir Temperature -------------------------------------------

    tRes = clsCMP.Tres

    if OutU[:3] == "MET" :
        sUni = ": [degC]"
        tRes = clsUNI.I2X(tRes,"degC")
    else             :
        sUni = ": [degF]"
        tRes = clsUNI.I2X(tRes,"degF")
    sTr = "{:10.3f}\n".format(tRes)
    sLabl = "** Reservoir Temperature " + sUni + "\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sOut = "*TRES  " + sTr
    fSim.write(sOut)
    fSim.write("\n")

#== Brine Density at Standard (Stock Tank) Conditions =================

    if clsCMP.setBr :

        CW.calcPVTW(clsCMP,clsUNI,clsIO)  #-- Brine Properties

        dSTW = clsCMP.dSTW

#-- Aqueous Phase Properties ----------------------------------------

        sLabl = "** Aqueous Phase Properties\n"
        fSim.write(sLabl)
        fSim.write("\n")

        pRefW = clsCMP.pRefW    #-- Ref Pres
        bRefW = clsCMP.bRefW    #-- Bw = Vres/Vsur = RhoSur/RhoRes
        cRefW = clsCMP.cRefW    #-- Compressibility
        bSalt = clsCMP.bSalt

        dRes  = dSTW/bRefW      #-- Reservoir Density

        if OutU[:3] == "MET" :
            dSTW  = clsUNI.I2X(dSTW ,"kg/m3")
            dRes  = clsUNI.I2X(dRes ,"kg/m3")
            pRefW = clsUNI.I2X(pRefW,"kpa")
            cRefW = clsUNI.I2X(cRefW,"1/kpa")

        sDsur = "{:10.3f}\n".format(dSTW)
        sDres = "{:10.3f}\n".format(dRes)
        sPref = "{:10.3f}\n".format(pRefW)
        sCref = "{:10.3e}\n".format(cRefW)
        sSalt = "{:10.5f}\n".format(bSalt)

        fSim.write("*DENW   " + sDsur)
        fSim.write("*DENWS  " + sDres)
        fSim.write("*CW     " + sCref)
        fSim.write("*REFPW  " + sPref)
        fSim.write("\n")

        fSim.write("*AQUEOUS-VISCOSITY *KESTIN\n")
        fSim.write("*SALINITY          *WTFRAC  " + sSalt)
        fSim.write("\n")

#== Close the file ====================================================

    clsIO.qGEM = UT.closeFile(fSim)

#== No return value ===================================================

    return

#========================================================================
#  Write VIP-COMP or Nexus-COMP Output
#========================================================================

def writeVIP(ZMFvD,clsEOS,dicSAM,clsCMP,clsIO,clsUNI) :

#-- Initialisation --------------------------------------------------

    sCom = "C "
    nCom = clsEOS.nComp

    dVec = NP.zeros(nCom)

#-- Open the VIP File, if not already open -------------------------

    if not clsIO.qVIP :
        pathVIP = clsIO.patR + ".vip"
        fVIP    = open(pathVIP,'w')
        clsIO.setQVIP(True)
        clsIO.setFVIP(fVIP)
    else :
        fVIP = clsIO.fVIP

#== Headers ===========================================================

    print("Writing Compositional Description for VIP/Nexus")

    fSim = clsIO.fVIP
    sInp = clsIO.fInp.name

    OutU = clsCMP.OutU

    if OutU[:3] == "MET" : sUni = "METRIC"
    else                 : sUni = "FIELD "

#-- Write Header Information to Simulator File ----------------------

    WO.outputHeader(fSim,sCom,clsIO)
    WO.outputEOS(fSim,sCom,clsIO,clsEOS)

#-- Header ----------------------------------------------------------

#               123456789012345678901234567890123456789012345678901234567890
    sHead = "C ==========================================================\n"
    fSim.write(sHead)
    sLabl = "C   VIP/Nexus EOS Model generated by PVTfree Program\n"
    fSim.write(sLabl)
    sLabl = "C   From dataset " + sInp + "\n"
    fSim.write(sLabl)
    sLabl = "C   User specified " + sUni + " Units\n"
    fSim.write(sLabl)
    fSim.write(sHead)
    fSim.write("\n")

#-- Equation of State -----------------------------------------------

    sLabl = "C  Equation of State: Peng-Robinson (PR) or Soave-Redlich-Kwong (SRK)\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sEoS = clsEOS.EOS
    sOut = "EOS  " + sEoS + "  1  \n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Components ------------------------------------------------------

    sLabl = "C  Component Names\n"
    fSim.write(sLabl)
    fSim.write("\n")
    fSim.write("COMPONENTS\n")
    sOut = "  "
    for iC in range(nCom) :
        sNam = clsEOS.gNM(iC)
        sOut = sOut + sNam + "  "
    sOut = sOut + "\n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Main Properties Table -------------------------------------------

    sLabl = "C  Main Fluid Properties\n"
    fSim.write(sLabl)
    fSim.write("\n")

    if OutU[:3] == "MET" :
        sOut = "PROPERTIES  C  KPA\n"
    else :
        sOut = "PROPERTIES  F  PSIA\n"
    fSim.write(sOut)
#           12345678901
    sOut = "COMP        MW         TC          PC        ZC       ACENTRIC      OMEGAA      OMEGAB      VSHIFT      PCHOR\n"
    fSim.write(sOut)

    for iC in range(nCom) :
        sN = clsEOS.gNM(iC)      ; sNm = sN.ljust(9,' ')
        Mw = clsEOS.gPP("MW",iC) ; sMw = "{:10.3f}  ".format(Mw)
        Tc = clsEOS.gPP("TC",iC)
        Pc = clsEOS.gPP("PC",iC)
        if OutU[:3] == "MET" :
            Tc = clsUNI.I2X(Tc,"degc")
            Pc = clsUNI.I2X(Pc,"kpa" )
        else :
            Tc = clsUNI.I2X(Tc,"degf")
        sTc = "{:10.3f}  ".format(Tc)
        sPc = "{:10.3f}  ".format(Pc)
        Zc = clsEOS.gPP("ZC",iC) ; sZc = "{:10.5f}  ".format(Zc)
        AF = clsEOS.gPP("AF",iC) ; sAF = "{:10.5f}  ".format(AF)
        MA = clsEOS.gPP("MA",iC) ; sOA = "{:10.7f}  ".format(MA*clsEOS.OA)
        MB = clsEOS.gPP("MB",iC) ; sOB = "{:10.7f}  ".format(MB*clsEOS.OB)
        SS = clsEOS.gPP("SS",iC) ; sSS = "{:10.7f}  ".format(SS)
        PA = clsEOS.gPP("PA",iC) ; sPA = "{:10.3f}  ".format(PA)
        sOut = sNm + sMw + sTc + sPc + sZc + sAF + sOA + sOB + sSS + sPA + "\n"
        fSim.write(sOut)

    fSim.write("\n")

#-- BInary Interaction Parameters -----------------------------------

    sLabl = "C  Binary Interaction Parameters\n"
    fSim.write(sLabl)
    fSim.write("\n")

    for iC in range(1,nCom) :

        sCom = clsEOS.gNM(iC)

        sOut = "DJK  " + sCom + "\n"
        fSim.write(sOut)

        for jC in range(iC) :
            sCom = clsEOS.gNM(jC)    ; sNam = sCom.ljust(8,' ')
            dVal = clsEOS.gIJ(iC,jC) ; sVal = "  {:10.5f}\n".format(dVal)
            sOut = sNam + sVal
            fSim.write(sOut)

    fSim.write("\n")

#-- End of EOS Section ----------------------------------------------

    sOut = "C  End of EOS Section\n"
    fSim.write(sOut)
    fSim.write("\n")

    fSim.write(sHead)
    fSim.write("ENDEOS\n")
    fSim.write(sHead)
    fSim.write("\n")

#== Water Properties ==================================================

    if clsCMP.setBr :

        fSim.write("C\n")
        fSim.write("C  Water Properties\n")
        fSim.write("C\n")
        fSim.write("\n")

        CW.calcPVTW(clsCMP,clsUNI,clsIO)  #-- Brine Properties

        pRefW = clsCMP.pRefW    #-- Ref Pres
        dSTW  = clsCMP.dSTW     #-- Stock Tank Density
        bRefW = clsCMP.bRefW    #-- Ref Bw
        cRefW = clsCMP.cRefW    #-- Ref Comp
        uRefW = clsCMP.uRefW    #-- Ref Visc
        vRefW = clsCMP.vRefW    #-- Viscosibility

        if OutU[:3] == "MET" :
            pRefW = clsUNI.I2X(pRefW,"kpa")
            dSTW  = clsUNI.I2X(dSTW ,"kg/m3")
            cRefW = clsUNI.I2X(cRefW,"1/kpa")
            vRefW = clsUNI.I2X(vRefW,"1/kpa")

        vRefW = uRefW*vRefW     #-- d[Visc]/dp = Visc*Viscosibility

        sPref = "{:10.3f}  ".format(pRefW)
        sDsur = "{:10.3f}  ".format(dSTW)
        sBref = "{:10.5f}  ".format(bRefW)
        sCref = "{:10.3e}  ".format(cRefW)
        sUref = "{:10.5f}  ".format(uRefW)
        sVref = "{:10.3e}  ".format(vRefW)

#-- Write Water Properties ------------------------------------------

        fSim.write("PVTW  IPVTW  PBASEW       DWB          BWI        CW           VW        VWP\n")
        sOut = "      1      " + sPref + sDsur + sBref + sCref + sUref + sVref + "\n"
        fSim.write(sOut)
        fSim.write("\n")

#== Close the file ====================================================

    clsIO.qVIP = UT.closeFile(fSim)

#== No return values ==================================================

    return

#========================================================================
#  Write Tempest-MORE Output
#========================================================================

def writeMORE(ZMFvD,clsEOS,dicSAM,clsCMP,clsIO,clsUNI) :

#-- Initialisation --------------------------------------------------

    sCom = "--"
    nCom = clsEOS.nComp

    dVec = NP.zeros(nCom)

#-- Open the MORE File, if not already open ------------------------

    if not clsIO.qMOR :
        pathMOR = clsIO.patR + ".mor"
        fMOR    = open(pathMOR,'w')
        clsIO.setQMOR(True)
        clsIO.setFMOR(fMOR)
    else :
        fMOR = clsIO.fMOR

#== Headers ===========================================================

    print("Writing Compositional Description for Tempest-MORE")

    fSim = clsIO.fMOR
    sInp = clsIO.fInp.name

    OutU = clsCMP.OutU

    if OutU[:3] == "MET" : sUni = "METRIC"
    else                 : sUni = "FIELD "

#-- Write Header Information to Simulator File ----------------------

    WO.outputHeader(fSim,sCom,clsIO)
    WO.outputEOS(fSim,sCom,clsIO,clsEOS)

#-- Header ----------------------------------------------------------

#               123456789012345678901234567890123456789012345678901234567890
    sHead = "--==========================================================\n"
    fSim.write(sHead)
    sLabl = "--  Tempest-MORE EOS Model generated by PVTfree Program\n"
    fSim.write(sLabl)
    sLabl = "--  From dataset " + sInp + "\n"
    fSim.write(sLabl)
    sLabl = "--  User specified " + sUni + " Units\n"
    fSim.write(sLabl)
    fSim.write(sHead)
    fSim.write("\n")

#----------------------------------------------------------------------
#  MORE-Specific Data
#----------------------------------------------------------------------

    sLabl = "-- Component Names (CNAM) are specified in the INPU section\n"
    fSim.write(sLabl)
    fSim.write("\n")

    sOut = "CNAM  "
    for iC in range(nCom) :
        sOut = sOut + clsEOS.gNM(iC) + "  "
    sOut = sOut + "WATR\n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Composition -----------------------------------------------------

    sOut = "-- Compositions\n"
    fSim.write(sOut)
    fSim.write("\n")

    nSam = len(dicSAM)

    for iSam in range(nSam) :
        clsSAM = dicSAM[iSam]
        sNam   = clsSAM.sNam
        sCom = ""
        sKey = "SCMP  " + sNam + "\n"
        for iC in range(nCom) : dVec[iC] = clsSAM.gZI(iC)
        writeVectorD(fSim,sCom,sKey,6,"{:10.7f}",dVec)

#-- Fluid Section Header --------------------------------------------

    fSim.write(sHead)
    sLabl = "FLUI EOS\n"
    fSim.write(sLabl)
    fSim.write(sHead)
    fSim.write("\n")

    sLabl = "-- Equation of State\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sEoS = clsEOS.EOS
    sOut = "EQUA  " + sEoS + "\n"
    fSim.write(sOut)
    fSim.write("\n")

#-- Reservoir Temperature -------------------------------------------

    tRes = clsCMP.Tres

    if OutU[:3] == "MET" :
        sUni = ": [degC]"
        tRes = clsUNI.I2X(tRes,"degC")
    else             :
        sUni = ": [degF]"
        tRes = clsUNI.I2X(tRes,"degF")
    sTr = "{:10.3f}\n".format(tRes)
    sLabl = "-- Reservoir Temperature " + sUni + "\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sOut = "TEMP  " + sTr
    fSim.write(sOut)
    fSim.write("\n")

#-- Main Properties Table -------------------------------------------

    sLabl = "-- Main Fluid Properties\n"
    fSim.write(sLabl)
    fSim.write("\n")

    sOut = "PROP  CNam       Mw          Tc          Pc       AcF         Zc          SG         Para\n"
    fSim.write(sOut)

    if OutU[:3] == "MET" :
        sOut = "--                          Kelv        bara\n"
    else :
        sOut = "--                          degR        psia\n"
    fSim.write(sOut)

    for iC in range(nCom) :
        sN = clsEOS.gNM(iC)      ; sNm = sN.ljust(8,' ')
        Mw = clsEOS.gPP("MW",iC) ; sMw = "{:10.3f}  ".format(Mw)
        Tc = clsEOS.gPP("TC",iC)
        Pc = clsEOS.gPP("PC",iC)
        if OutU[:3] == "MET" :
            Tc = clsUNI.I2X(Tc,"kelv")
            Pc = clsUNI.I2X(Pc,"bara") ; sPc = "{:10.4f}".format(Pc)
        else :
            sPc = "{:10.3f}  ".format(Pc)
        sTc = "{:10.3f}  ".format(Tc)
        AF = clsEOS.gPP("AF",iC) ; sAF = "{:10.5f}  ".format(AF)
        Zc = clsEOS.gPP("ZC",iC) ; sZc = "{:10.5f}  ".format(Zc)
        SG = clsEOS.gPP("SG",iC) ; sSG = "{:10.5f}  ".format(SG)
        PA = clsEOS.gPP("PA",iC) ; sPA = "{:10.3f}  ".format(PA)
        sOut = "      " + sNm + sMw + sTc + sPc + sAF + sZc + sSG + sPA + "\n"
        fSim.write(sOut)

    fSim.write("/\n")
    fSim.write("\n")

#-- Omega-A & Omega-B Multiplers -----------------------------------

    sCom = "--  Omega-A Multipliers " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MA",iC)
    writeVectorD(fSim,sCom,"OMGA  MULT\n",6,"{:11.9f}",dVec)

    sCom = "--  Omega-B Multipliers " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MB",iC)
    writeVectorD(fSim,sCom,"OMGB  MULT\n",6,"{:11.9f}",dVec)

#-- Volume Shift Parameters -----------------------------------------

    sCom = "--  Volume Shifts " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("SS",iC)
    writeVectorD(fSim,sCom,"VOLU\n",6,"{:11.8f}",dVec)

#-- BIPs ------------------------------------------------------------

    fSim.write("-- Binary Iteraction Parameters (Lower Triangle)\n")
    fSim.write("\n")
    fSim.write("INTE\n")

    sCom = ""
    for iC in range(1,nCom) :
        bVec = NP.zeros(iC)
        for jC in range(iC) :
            bVec[jC] = clsEOS.gIJ(iC,jC)
        writeVectorD(fSim,sCom,"ROW",7,"{:9.6f}",bVec)

    fSim.write("/\n")
    fSim.write("\n")

#-- Brine Density at Standard (Stock Tank) Conditions ---------------

    mFrc = clsCMP.bSalt #-- Mass Fraction of Salt in the Brine

    dSTW,comW = CW.calcRoweChouDen(mFrc,UT.tStand,UT.pStand,clsUNI)  #-- Stock Tank Brine Density

    clsCMP.setDenSTW(dSTW)

    clsCMP.setDenSTO(-1.0)  #-- In EoS Mode, E300 calculates STO Density
    clsCMP.setDenSTG(-1.0)  #-- Ditto

#== Brine Properties at Reference Pressure & Tres (for PVTW keyword) ==

    if clsCMP.setBr :

        CW.calcPVTW(clsCMP,clsUNI,clsIO)

#== Write DENSITY and PVTW keywords ===================================

        WB.outputECLDensity(OutU,fSim,clsCMP,clsUNI)
        WB.outputECLPVTW(OutU,fSim,clsCMP,clsUNI)

#== Close the file ====================================================

    clsIO.qMOR = UT.closeFile(fSim)

#== No return value ===================================================

    return

#========================================================================
#  Write E300 Output
#========================================================================

def writeE300(ZMFvD,clsEOS,dicSAM,clsCMP,clsIO,clsUNI) :

#-- Open the E300 File, if not already open ------------------------

    if not clsIO.q300 :
        path300 = clsIO.patR + ".e300"
        f300    = open(path300,'w')
        clsIO.setQ300(True)
        clsIO.setF300(f300)
    else :
        f300 = clsIO.f300

    sCom = "--"

#== Headers ===========================================================

    print("Writing Compositional Description for E300")

    fSim = clsIO.f300
    sInp = clsIO.fInp.name

    OutU = clsCMP.OutU

    if OutU[:3] == "MET" : sUni = "METRIC"
    else                 : sUni = "FIELD "

#-- Write Header Information to Simulator File ----------------------

    WO.outputHeader(fSim,sCom,clsIO)
    WO.outputEOS(fSim,sCom,clsIO,clsEOS)

#-- Header ----------------------------------------------------------

#               123456789012345678901234567890123456789012345678901234567890
    sHead = "--==========================================================\n"
    fSim.write(sHead)
    sLabl = "--  E300 EOS Model generated by PVTfree Program\n"
    fSim.write(sLabl)
    sLabl = "--  From dataset " + sInp + "\n"
    fSim.write(sLabl)
    sLabl = "--  User specified " + sUni + " Units\n"
    fSim.write(sLabl)
    fSim.write(sHead)
    fSim.write("\n")

#-- Number of Components --------------------------------------------

    nCom = clsEOS.nComp

    sLabl = "--  Number of Components\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sLabl = "NCOMPS\n"
    fSim.write(sLabl)
    sLabl = "  {:2d}  /\n".format(nCom)
    fSim.write(sLabl)
    fSim.write("\n")

#-- Equation of State -----------------------------------------------

    EOS = clsEOS.EOS
    if EOS == "SRK" : sExt = "Soave-Redlich-Kwong (SRK)"
    else            : sExt = "Peng-Robinson (PR)"
    sLabl = "--  Equation of State: " + sExt + "\n"
    fSim.write(sLabl)
    fSim.write("\n")
    sLabl = "EOS\n"
    fSim.write(sLabl)
    sLabl = "  " + str(EOS) + "  /\n"
    fSim.write(sLabl)
    fSim.write("\n")

    if EOS == "PR" :
        sLabl = "--  Modified Form of the Peng-Robinson EOS\n"
        fSim.write(sLabl)
        fSim.write("\n")
        sLabl = "PRCORR\n"
        fSim.write(sLabl)
        fSim.write("\n")

#== Component Properties ==============================================

    sVec = [ "" for i in range(nCom)]
    dVec = NP.zeros(nCom)

#-- Component Names -------------------------------------------------

    sCom = "--  Component Names " + "\n"
    for iC in range(nCom) : sVec[iC] = clsEOS.gNM(iC)
    writeVectorS(fSim,sCom,"CNAMES\n",7,8,sVec)

#-- Mole Weights ----------------------------------------------------

    if OutU[:3] == "MET" : sUni = ": [kg/kgmol]"
    else                 : sUni = ": [lb/lbmol]"
    sCom = "--  Molecular Weights " + sUni + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MW",iC)
    writeVectorD(fSim,sCom,"MW\n",7,"{:8.3f}",dVec)

#-- Critical Temperatures -------------------------------------------

    if OutU[:3] == "MET" :
        sUni = ": [Kelvin]"
        for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("TC",iC),"kelv")
    else             :
        sUni = ": [degrees Rankine]"
        for iC in range(nCom) : dVec[iC] = clsEOS.gPP("TC",iC)
    sCom = "--  Critical Temperatures " + sUni + "\n"
    writeVectorD(fSim,sCom,"TCRIT\n",7,"{:8.3f}",dVec)

#-- Critical Pressures ----------------------------------------------

    if OutU[:3] == "MET" :
        sUni = ": [barsa]"
        sFor = "{:8.4f}"
        for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("PC",iC),"bara")
    else             :
        sUni = ": [psia]"
        sFor = "{:8.3f}"
        for iC in range(nCom) : dVec[iC] = clsEOS.gPP("PC",iC)
    sCom = "--  Critical Pressures " + sUni + "\n"
    writeVectorD(fSim,sCom,"PCRIT\n",7,sFor,dVec)

#-- Critical Volumes ------------------------------------------------

    if OutU[:3] == "MET" :
        sUni = ": [m3/kgmol]"
        sFor = "{:8.3f}"
        for iC in range(nCom) : dVec[iC] = clsUNI.I2X(clsEOS.gPP("VC",iC),"m3/kgmol")
    else             :
        sUni = ": [ft3/lbmol]"
        sFor = "{:8.4f}"
        for iC in range(nCom) : dVec[iC] = clsEOS.gPP("VC",iC)
    sCom = "--  Critical Volumes " + sUni + "\n"
    writeVectorD(fSim,sCom,"VCRIT\n",7,sFor,dVec)

#-- Critical Z-Factors ----------------------------------------------

    sCom = "--  Critical Z-Factors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("ZC",iC)
    writeVectorD(fSim,sCom,"ZCRIT\n",7,"{:8.6f}",dVec)

#-- Acentric Factors ------------------------------------------------

    sCom = "--  Acentric Factors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("AF",iC)
    writeVectorD(fSim,sCom,"ACF\n",7,"{:8.6f}",dVec)

#-- Omega-A's -------------------------------------------------------

    sCom = "--  Omega-A Values " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MA",iC)*clsEOS.OA
    writeVectorD(fSim,sCom,"OMEGAA\n",6,"{:11.9f}",dVec)

#-- Omega-B's -------------------------------------------------------

    sCom = "--  Omega-B Values " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("MB",iC)*clsEOS.OB
    writeVectorD(fSim,sCom,"OMEGAB\n",6,"{:11.9f}",dVec)

#-- Parachors -------------------------------------------------------

    sCom = "--  Parachors " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("PA",iC)
    writeVectorD(fSim,sCom,"PARACHOR\n",7,"{:8.3f}",dVec)

#-- Volume Shifts ---------------------------------------------------

    sCom = "--  Volume Shifts " + "\n"
    for iC in range(nCom) : dVec[iC] = clsEOS.gPP("SS",iC)
    writeVectorD(fSim,sCom,"SSHIFT\n",7,"{:9.6f}",dVec)

#== Binary Interation Coefficients ====================================

    fSim.write("-- Binary Iteraction Parameters\n")
    fSim.write("\n")
    fSim.write("BIC\n")

    sCom = ""
    for iC in range(1,nCom) :
        bVec = NP.zeros(iC)
        for jC in range(iC) :
            bVec[jC] = clsEOS.gIJ(iC,jC)
        writeVectorD(fSim,sCom,"",7,"{:9.6f}",bVec)

    fSim.write("/\n")
    fSim.write("\n")

#-- Reservoir Temperature -------------------------------------------

    tRes = clsCMP.Tres

    if OutU[:3] == "MET" :
        sUni = ": [degC]"
        tRes = clsUNI.I2X(tRes,"degC")
    else             :
        sUni = ": [degF]"
        tRes = clsUNI.I2X(tRes,"degF")
    sLabl = "-- Reservoir Temperature " + sUni + "\n"
    fSim.write(sLabl)
    fSim.write("\n")
    fSim.write("RTEMP\n")
    sLabl = "  {:7.3f}".format(tRes) +  "  /\n"
    fSim.write(sLabl)
    fSim.write("\n")

#== Composition (versus Depth? =========================================

    if clsCMP.qDep :

        dGOC = clsCMP.dGOC

        if OutU[:3] == "MET" :
            dUni = "m"
            zUni = "--  Depth/[m]   Composition\n"
        else                 :
            dUni = "ft"
            zUni = "--  Depth/[ft]  Composition\n"

        dGOC = clsUNI.I2X(dGOC,dUni)
        sGOC = "{:10.3f} ".format(dGOC)

        fSim.write("--  Composition versus Depth\n")
        fSim.write("--  Note: d(GOC) = " + sGOC + dUni + "\n")
        fSim.write("\n")
        fSim.write("ZMFVD\n")
        fSim.write(zUni)

        writeZMFVD(ZMFvD,dUni,fSim,"ECL",nCom,clsUNI)

    else :
        sCom = "--  Composition\n"
        for iC in range(nCom) : dVec[iC] = dicSAM[0].gZI(iC)
        writeVectorD(fSim,sCom,"ZI\n",6,"{:10.7f}",dVec)

#== Brine Density at Standard (Stock Tank) Conditions =================

    mFrc = clsCMP.bSalt #-- Mass Fraction of Salt in the Brine

    dSTW,comW = CW.calcRoweChouDen(mFrc,UT.tStand,UT.pStand,clsUNI)  #-- Stock Tank Brine Density

    clsCMP.setDenSTW(dSTW)

    clsCMP.setDenSTO(-1.0)  #-- In EoS Mode, E300 calculates STO Density
    clsCMP.setDenSTG(-1.0)  #-- Ditto

    WB.outputECLDensity(OutU,fSim,clsCMP,clsUNI)

#-- Brine Properties at Reference Pressure & Tres (for PVTW keyword)

    if clsCMP.setBr :

        CW.calcPVTW(clsCMP,clsUNI,clsIO)

#== Write DENSITY and PVTW keywords ===================================

        WB.outputECLPVTW(OutU,fSim,clsCMP,clsUNI)

#== Close the file ====================================================

    clsIO.q300 = UT.closeFile(fSim)

#== No return value ===================================================

    return

#========================================================================
#  Write a Vector of Float (Double) Values
#========================================================================

def writeVectorD(fSim,sComm,sKW,nLen,sForm,dVec) :

    nSETs = 0
    n1SET = nLen
    nSumm = len(dVec)

    nSETa = []

    while (nSumm-n1SET) > 0 :
        nSETs += 1
        nSETa.append(n1SET)
        nSumm = nSumm - n1SET

    nSETs += 1
    nSETa.append(nSumm)

    iCom = 0

    if sKW != "" :
        if sKW == "ROW" :
            fSim.write("  " + sKW)
        else :
            fSim.write(sComm)
            fSim.write("\n")
            fSim.write(sKW)

    for iS in range(nSETs) :

        sLine = "  "
        nThis = nSETa[iS]

        for iC in range(nThis) :
            dThis = dVec[iCom]
            sThis = sForm.format(dThis)
            sLine = sLine + sThis + "  "
            iCom += 1

        if sKW != "" :
            if sKW == "ROW" or sKW[:1] == "*" :
                sLine = sLine + "\n"
            else :
                if   iCom == nSumm : sLine = sLine + "  /\n"
                else               : sLine = sLine + "\n"
        else :
            sLine = sLine + "\n"

        fSim.write(sLine)

    if sKW != "" and sKW != "ROW" : fSim.write("\n")

#========================================================================
#  End of Routine
#========================================================================

    return

#========================================================================
#  Write a Vector of String Values
#========================================================================

def writeVectorS(fSim,sComm,sKW,nLen,nForm,sVec) :

    nSETs = 0
    n1SET = nLen
    nSumm = len(sVec)

    nSETa = []

    while (nSumm-n1SET) > 0 :
        nSETs += 1
        nSETa.append(n1SET)
        nSumm = nSumm - n1SET

    nSETs += 1
    nSETa.append(nSumm)

    iCom = 0

    fSim.write(sComm)
    fSim.write("\n")
    fSim.write(sKW)

    for iS in range(nSETs) :

        sLine = "  "
        nThis = nSETa[iS]

        for iC in range(nThis) :
            sThis = sVec[iCom]
            sThis = sThis.center(nForm)
            sLine = sLine + sThis + "  "
            iCom += 1

        if iCom == nSumm : sLine = sLine + "  /\n"
        else             : sLine = sLine + "\n"

        fSim.write(sLine)

    fSim.write("\n")

#== No return value ===================================================

    return

#========================================================================
#  Write Composition versus Depth Information
#========================================================================

def writeZMFVD(ZMFvD,dUni,fSim,SIM,nCom,clsUNI) :

#          1234567890123456
    s4  = "    "
    s16 = "                "

    nByR = 5
    nRow = int(nCom/nByR) + 1

    for Row in ZMFvD :

        TVD  = Row[0]
        Psat = Row[1]
        zDep = Row[2]

        TVD = clsUNI.I2X(TVD,dUni)
        sTVD = "{:10.3f}  ".format(TVD)

        iCom = 0
        zLin = s4

        for iRow in range(nRow) :
            if iRow == 0 :
                zLin = s4 + sTVD
            else :
                zLin = s16
            for iInR in range(nByR) :
                if iCom == nCom : break
                zCom = zDep[iCom]
                sCom = "{:10.8f}  ".format(zCom)
                zLin = zLin + sCom
                iCom = iCom + 1
            zLin = zLin + "\n"
            fSim.write(zLin)

    fSim.write("/\n")
    fSim.write("\n")

#== No return value ===================================================

    return

#========================================================================
#  End of Module
#========================================================================


fname = input("Enter file name: ")
if len(fname) < 1 :
    fname = "mbox-short.txt"

fh = open(fname)
count = 0

for line in fh:
    l = line.rstrip().split(' ')
    if l[0] == "From":
        count = count+1
        print(l[1])
print("There were", count, "lines in the file with From as the first word")


with open("day02.in", 'r') as fi:
    checksum = 0
    for line in fi:
        numbers = list(map(int, line.split()))
        for n, first in enumerate(numbers[:-1]):
            for second in numbers[n+1:]:
                large = max(first, second)
                small = min(first, second)
                if large % small == 0:
                    checksum += int(large / small)
print(checksum)


from solution import spiral
import pudb

def test():
    R, C = 1, 4
    r0, c0 = 0, 0
    # pudb.set_trace()

    res = spiral(R, C, r0, c0)
    assert res == [[0, 0], [0, 1], [0, 2], [0, 3]]


import itertools
from re import T
from types import GeneratorType
from typing import Any

def get_input(cast: Any, split: str = None):
    while True:
        try:
            inp = input()
            output = [cast(i) for i in inp.split(split)] if split else cast(inp)
        except ValueError:
            continue
        else:
            return output

def main() -> GeneratorType:
    interval_amount: int = get_input(int)
    total_sum: int = get_input(int)
    intervals: list[int] = get_input(int, ' ')

    # checking stuff
    if (0 > interval_amount or interval_amount > 100000) \
        or (0 > total_sum or total_sum > 1000000) :

        return

    [0, 2, 1, 0, 1]
    pointer = 1

    # Process data
    valid_intervals: int = 0
    current_interval: list[int] = []
    enumerated_list: dict = {k:v for k, v in enumerate(intervals)}

    current_pointer = 0
    done = False
    solutions = []
    while not done:
        current_interval = []
        for loop_index in range(interval_amount):
            if loop_index+current_pointer not in enumerated_list:
                done = True
                break

            if loop_index == 0 and current_pointer > 0:
                current_interval.append(enumerated_list[loop_index+current_pointer-1])

            current_interval.append(enumerated_list[loop_index+current_pointer])

            if sum(current_interval) > total_sum:
                current_pointer += 1
                break

            if sum(current_interval) == total_sum and current_interval not in solutions:
                valid_intervals += 1
                if len(current_interval) == interval_amount:
                    done = True
                    break
                solutions.append(current_interval)
                if loop_index != interval_amount-1:
                    if loop_index+current_pointer+1 in enumerated_list:
                        if sum(current_interval) + enumerated_list[loop_index+current_pointer+1] == total_sum:
                            sol = [*current_interval, enumerated_list[loop_index+current_pointer+1]]
                            if sol not in solutions:
                                valid_intervals += 1
                current_pointer += 1
                break

    yield solutions
    yield valid_intervals

if __name__ == '__main__':
    for i in main():
        print(i)


import unittest
import sys, os

sys.path.insert(0, os.path.abspath(__file__ + "/../../cli"))
sys.path.insert(0, os.path.abspath(__file__ + "/../../schema"))
from iroha_cli.built_in_commands import BuildInCommand
from iroha_cli.exception import CliException

class Sample:
    def __init__(self):
        self.sample_account_id_1 = "sample_account_id_1"
        self.sample_account_id_2 = "sample_account_id_2"
        self.sample_account_id_3 = "sample_account_id_3"

        self.sample_asset_id_1 = "sample_asset_id_1"
        self.sample_asset_id_2 = "sample_asset_id_2"
        self.sample_asset_id_3 = "sample_asset_id_3"

        self.sample_account_name = "sonoko_mizuki"

        self.sample_domain_id = "japan"
        self.sample_account_name = "mizuki"
        self.sample_keypair_path = "mizuki_key"

def deleteKeyIfExists(account_id):
    if os.path.exists("{}/.irohac/{}.pub".format(os.environ['HOME'], account_id)):
        os.remove("{}/.irohac/{}.pub".format(os.environ['HOME'], account_id))
    if os.path.exists("{}/.irohac/{}".format(os.environ['HOME'], account_id)):
        os.remove("{}/.irohac/{}".format(os.environ['HOME'], account_id))

class TestKeygen(unittest.TestCase):

    def setUp(self):
        self.commands = BuildInCommand().commands
        self.sample = Sample()

    def tearDown(self):
        base = self.sample.sample_account_name + "@" + self.sample.sample_domain_id
        base_key = self.sample.sample_keypair_path
        deleteKeyIfExists(base)
        deleteKeyIfExists(base_key)
        deleteKeyIfExists(self.sample.sample_account_name)

    def test_normal_with_account_name(self):
        self.commands["keygen"]["function"](
            {"account_id": self.sample.sample_account_name}
        )
        self.assertTrue(
            os.path.exists("{}/.irohac/{}.pub".format(os.environ['HOME'], self.sample.sample_account_name)) and \
            os.path.exists("{}/.irohac/{}".format(os.environ['HOME'], self.sample.sample_account_name))
        )

    def test_normal_with_keypair_name(self):
        self.commands["keygen"]["function"](
            {"account_id": self.sample.sample_account_name,
            "keypair_name": self.sample.sample_keypair_path}
        )
        self.assertTrue(
            os.path.exists("{}/.irohac/{}.pub".format(os.environ['HOME'], self.sample.sample_keypair_path)) and \
            os.path.exists("{}/.irohac/{}".format(os.environ['HOME'], self.sample.sample_keypair_path))
        )

    def test_normal_with_keypair_name(self):
        pass

    def test_error_no_account_name(self):
        pass


__author__ = "Gabriele Pisciotta"

import os
import unittest
from unittest import TestCase

from oc_ocdm.graph import GraphSet
from oc_ocdm.reader import Reader
from rdflib import Graph

from oc_graphenricher.instancematching import InstanceMatching

class TestInstanceMatching(TestCase):

    def setUp(self) -> None:
        self.test_dir = str(__file__).replace("test_instancematching.py", "")
        g = Graph()
        g = g.parse(self.test_dir + 'test_merge_br.rdf', format='nt11')

        reader = Reader()
        g_set = GraphSet(base_iri='https://w3id.org/oc/meta/')
        reader.import_entities_from_graph(g_set,
                                          g,
                                          enable_validation=False,
                                          resp_agent='https://w3id.org/oc/meta/prov/pa/2')

        matcher = InstanceMatching(g_set,
                                   graph_filename=self.test_dir + "matched.rdf",
                                   provenance_filename=self.test_dir + "provenance.rdf",
                                   debug=True)
        matcher.match()

        g = Graph()
        g = g.parse(self.test_dir + 'matched.rdf', format='nt11')

        reader = Reader()
        self.g_set_new = GraphSet(base_iri='https://w3id.org/oc/meta/')
        reader.import_entities_from_graph(self.g_set_new,
                                          g,
                                          enable_validation=False,
                                          resp_agent='https://w3id.org/oc/meta/prov/pa/2')

    def test_ras_merged(self):
        ids = set()
        for ra in self.g_set_new.get_ra():
            for idd in ra.get_identifiers():
                newliteral = str(idd.get_scheme()) + str(idd.get_literal_value())
                if newliteral in ids:
                    self.fail()
                else:
                    ids.add(idd)

    def test_ids_not_duplicated(self):
        ids = set()
        for idd in self.g_set_new.get_id():
            newliteral = str(idd.get_scheme()) + str(idd.get_literal_value())
            if newliteral != "NoneNone" and newliteral in ids:
                print("Ahia")
                self.fail()
            else:
                ids.add(newliteral)

    def test_orphan_ra(self):
        ras_from_ar = set()
        for ar in self.g_set_new.get_ar():
            ras_from_ar.add(ar.get_is_held_by())

        ras = set()
        for ra in self.g_set_new.get_ra():
            ras.add(ra)

        difference = ras_from_ar.difference(ras)
        if len(difference) > 0:
            print(f"AR Orphans: {[str(d) for d in difference]}")
            self.fail()

    def test_orphan_ar(self):
        ars_from_ar = set()
        for br in self.g_set_new.get_br():
            for ar in br.get_contributors():
                ars_from_ar.add(ar)

        ars = set()
        for ar in self.g_set_new.get_ar():
            ars.add(ar)

        difference = ars.difference(ars_from_ar)
        if len(difference) > 0:
            print(f"Orphans: {[str(d) for d in difference]}")
            self.fail()

    def test_brs_merged(self):
        for br in self.g_set_new.get_br():
            if str(br) == 'http://example.com/br/6' and len(br.get_contributors()) != 0:
                print(br, len(br.get_contributors()))
                self.fail()

    def test_brs_have_only_one_list_of_authors(self):
        for br in self.g_set_new.get_br():
            if str(br) == 'http://example.com/br/3' and len(br.get_contributors()) != 2:
                for ar in br.get_contributors():
                    print(ar, ar.get_is_held_by())
                print(f"Contributors len {len(br.get_contributors())}")
                self.fail()

    def test_remove_files(self):
        os.system(f'rm "{self.test_dir}matched.rdf"')
        os.system(f'rm "{self.test_dir}provenance.rdf"')

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


fname = input("Enter file name: ")
if len(fname) < 1 : fname = "mbox.txt"

try:
    fhand = open(fname)
except:
    print('File does not exist.')
    exit()

counts = dict()

for line in fhand:
    if line.startswith('From: '):
        words = line.rstrip().split()
        domain = words[1].split('@')[1]
        counts[domain] = counts.get(domain, 0) + 1

print(counts)

big_count = None
big_domain = None

for domain, count in counts.items():
    if big_count is None or count > big_count:
        big_count = count
        big_domain = domain

print(big_domain, big_count)


def next_permutation(a):
    n = len(a)
    i = n - 1

    while i > 0 and a[i - 1] >= a[i]:
        i -= 1

    if i <= 0:
        return False

    j = n - 1

    while a[i - 1] >= a[j]:
        j -= 1

    a[i - 1], a[j] = a[j], a[i - 1]
    a[i:] = a[i:][::-1]

    return True

n = int(input())
a = list(map(int, input().split()))
if not next_permutation(a):
    print(-1)
else:
    print(*a)


import matplotlib.pyplot as plt
from molmc import MonteCarlo3D
import numpy as np

# define Monte-Carlo parameters
n_steps = 1000
n_particles = 100

# define simulation for liquid Argon
simulator = MonteCarlo3D(box_lenght=16.819, temp=90, epsilon=0.2378, sigma=3.41)

# run simulator
energy = np.array([simulator.calculate_energy(n_particles) for _ in range(n_steps)])

# write results
conv = sum(((energy > -2) & (energy < 0)) / n_steps)

# plot results
fig, ax = plt.subplots(
    figsize=(14, 6))
log_bins = np.logspace(np.log10(min(energy)), np.log10(max(energy)), 20)
ax.hist(energy, bins=[-0.2, 0] + list(log_bins), ec="black", color="tab:blue")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("Mean energy (kcal/mol)")
ax.set_ylabel("Occurance")
ax.set_title(f"Argon box mean energy per particle (log scale)\nrate of acceptance = {conv}")

plt.tight_layout()
plt.show()


"""
Recognition dataset export
"""
import os
import json
import shutil
from pathlib import Path
from nb_utils.file_dir_handling import list_files
import csv
import pandas as pd
from tqdm.auto import tqdm
from functools import reduce
import operator
import numpy as np
from sklearn.model_selection import train_test_split
from image_cropping import crop_img_boxes
import cv2
from PIL import Image
from margin_utils import margins_arg_parse, expand_box
from visualization import draw_boxes
from tqdm.contrib.concurrent import process_map, thread_map  # requires tqdm>=4.42.0
from functools import partial

def wrapper_expand_boxes(raw_annotation_file, margins):
    with open(raw_annotation_file, encoding="utf-8") as json_file:
        raw_annotation_data = json.load(json_file)

    ## If original boxes already modified by previous box expand -- then first restore it
    if (raw_annotation_data.get("is_boxes_expanded")):
        ## remove keys and data
        raw_annotation_data.pop("line_annotations")
        raw_annotation_data.pop("word_annotations")
        ## rename keys
        raw_annotation_data["line_annotations"] = raw_annotation_data.pop("original_line_annotations")
        raw_annotation_data["word_annotations"] = raw_annotation_data.pop("original_word_annotations")
        raw_annotation_data.pop("is_boxes_expanded")

    new_annotation_data = {}
    previous_annotation_data = {}
    for key, item in raw_annotation_data.items():
        if key not in ["word_annotations", "line_annotations"]:
            continue

        ## save previous data copy -- to merge this dict later
        previous_annotation_data[f"original_{key}"] = item

        ## if valid annotation key
        raw_annotations = item

        lst_final_annotations = []
        for idx, annotation in enumerate(raw_annotations):
            final_annotations = {}
            final_annotations['text'] = annotation["text"]

            # import pdb; pdb.set_trace()

            if isinstance(annotation["coordinates"][0], list):
                ## If already 4 points minimal rectangle
                coordinates_4points = annotation["coordinates"]
            else:
                ## If rectangle values -- 4 integer values only
                left_x, top_y, right_x, bottom_y = annotation["coordinates"]

                coordinates_4points = [
                    [left_x, top_y],
                    [right_x, top_y],
                    [right_x, bottom_y],
                    [left_x, bottom_y]
                ]

            ## make int values
            coordinates_4points = np.asarray(coordinates_4points).astype("int").tolist()

            if margins[0]:
                ## add margin around it
                margin_top, margin_left, margin_bottom, margin_right = margins

                coordinates_4points = expand_box(
                    coordinates_4points,
                    margin_top, margin_left, margin_bottom, margin_right
                )

            final_annotations['coordinates'] = coordinates_4points
            lst_final_annotations.append(final_annotations)

        ## append modified data in dict
        new_annotation_data[key] = lst_final_annotations

    ## image
    raw_annotation_path = Path(raw_annotation_file)
    file_suffix_number = raw_annotation_path.name.split("_")[0]
    input_img_filepath = os.path.join(
        raw_annotation_path.parent, f"{file_suffix_number}.png"
    )

    base_parent_folder = os.path.dirname(str(raw_annotation_path.parent))

    ## read image
    img_pil = Image.open(input_img_filepath)

    for key in ['line_annotations', 'word_annotations']:
        bounds = [value["coordinates"] for value in new_annotation_data[key]]
        # import  pdb;pdb.set_trace()

        img_pil_2_draw = img_pil.copy()
        # this function call the visualize method to draw the boxes around text
        draw_boxes(
            img_pil_2_draw, bounds=bounds, color='lime', width=1,
            text_font_size=14, text_fill_color="orange", draw_text_idx=True
        )
        # display(img_pil_2_draw)

        visualized_out_dir = os.path.join(
            base_parent_folder, "visualized_expanded_boxes", key
        )
        os.makedirs(visualized_out_dir, exist_ok=True)
        # print(f"visualized_out_dir: ", visualized_out_dir)

        img_pil_2_draw.save(
            os.path.join(
                visualized_out_dir, f"{file_suffix_number}_visualized.png"
            )
        )

    ## save annotation back to json files
    new_annotation_data["is_boxes_expanded"] = True
    new_annotation_data["margins"] = margins

    ## append original data with modified key such as original_word_annotations
    new_annotation_data.update(previous_annotation_data)
    ## finally overwrite json file
    out_filepath = raw_annotation_file ## same input file as we are overwriting
    with open(out_filepath, "w", encoding="utf-8") as outfile:
        json.dump(new_annotation_data, outfile, indent=4, ensure_ascii=False)

def main():
    import argparse

    # create the argument parser
    parser = argparse.ArgumentParser()
    # add an argument
    parser.add_argument(
        "-i", "--base_input_folder", type=str, required=True,
        help="Base input folder to read generated cards data ex. `out/Qatar-Resident id card - front/synth_cards/`"
    )

    parser.add_argument(
        "-m",
        "--margins",
        type=margins_arg_parse,
        nargs="?",
        help="Define the margins around the main box for cropping. In pixels, If single value then 4 times it will be repeated",
        default=(0, 0, 0, 0),
    )
    parser.add_argument(
        "-w", "--workers", type=int, required=False,
        default=4,
        help="number of CPU workers -- multiprocessing"
    )
    # , nargs='+', type=int
    # parse the arguments
    args = parser.parse_args()

    dir_base_input_folder = args.base_input_folder

    margins = args.margins
    workers = args.workers

    print(f"dir_base_input_folder: {dir_base_input_folder}")
    print(f"margins: {margins}")
    print(f"No of workers -- in multiprocessing: {workers}")

    ### List annotation files
    raw_annotation_files = list_files(dir_base_input_folder, filter_ext=[".json"])

    worker = wrapper_expand_boxes  # function to map
    kwargs = {
        'margins': margins
    }
    jobs = raw_annotation_files

    result = process_map(partial(worker, **kwargs), jobs, max_workers=workers, chunksize=1)

    pass

if __name__ == "__main__":
    main()


from pyspark.sql import SparkSession
from pyspark.sql.types import DoubleType
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.feature import MinMaxScaler
from pyspark.ml.evaluation import RegressionEvaluator
from pyspark.ml.feature import StringIndexer
from pyspark.ml.regression import LinearRegression
from pyspark.sql.functions import udf
from pyspark.sql.types import FloatType

print("Print0")
spark = SparkSession.builder \
    .master("local[20]") \
    .appName("ML_ques") \
    .getOrCreate()

sc = spark.context
sc.setLogLevel("WARN")

dff = spark.read.csv("../Data/train_set.csv", header=True, mode="DROPMALFORMED")
dfff = dff.cache()
dfff=dfff.repartition(10).cache()

for x in dfff.columns:
    dfff = dfff.filter((dfff[x] != '?'))

changedTypedf1 = dfff.withColumn("Row_ID", dfff["Row_ID"].cast(DoubleType()))
changedTypedf2 = changedTypedf1.withColumn("Household_ID", changedTypedf1["Household_ID"].cast(DoubleType()))
changedTypedf3 = changedTypedf2.withColumn("Vehicle", changedTypedf2["Vehicle"].cast(DoubleType()))
changedTypedf4 = changedTypedf3.withColumn("Calendar_Year", changedTypedf3["Calendar_Year"].cast(DoubleType()))
changedTypedf5 = changedTypedf4.withColumn("Model_Year", changedTypedf4["Model_Year"].cast(DoubleType()))
changedTypedf6 = StringIndexer(inputCol="Blind_Make", outputCol="Blind_Make1").fit(changedTypedf5)
changedTypedf7 = changedTypedf6.transform(changedTypedf5)
changedTypedf7=changedTypedf7.drop("Blind_Make")
changedTypedf8 = StringIndexer(inputCol="Blind_Model", outputCol="Blind_Model1").fit(changedTypedf7)
changedTypedf9 = changedTypedf8.transform(changedTypedf7)
changedTypedf9=changedTypedf9.drop("Blind_Model")
changedTypedf10 = StringIndexer(inputCol="Blind_Submodel", outputCol="Blind_Submodel1").fit(changedTypedf9)
changedTypedf11 = changedTypedf10.transform(changedTypedf9)
changedTypedf11=changedTypedf11.drop("Blind_Submodel")
changedTypedf12 = StringIndexer(inputCol="Cat1", outputCol="Cat1_1").fit(changedTypedf11)
changedTypedf13 = changedTypedf12.transform(changedTypedf11)
changedTypedf13=changedTypedf13.drop("Cat1")
changedTypedf14 = StringIndexer(inputCol="Cat2", outputCol="Cat2_1").fit(changedTypedf13)
changedTypedf15 = changedTypedf14.transform(changedTypedf13)
changedTypedf15=changedTypedf15.drop("Cat2")
changedTypedf16 = StringIndexer(inputCol="Cat3", outputCol="Cat3_1").fit(changedTypedf15)
changedTypedf17 = changedTypedf16.transform(changedTypedf15)
changedTypedf17=changedTypedf17.drop("Cat3")
changedTypedf18 = StringIndexer(inputCol="Cat4", outputCol="Cat4_1").fit(changedTypedf17)
changedTypedf19 = changedTypedf18.transform(changedTypedf17)
changedTypedf19=changedTypedf19.drop("Cat4")
changedTypedf20 = StringIndexer(inputCol="Cat5", outputCol="Cat5_1").fit(changedTypedf19)
changedTypedf21 = changedTypedf20.transform(changedTypedf19)
changedTypedf21=changedTypedf21.drop("Cat5")
changedTypedf22 = StringIndexer(inputCol="Cat6", outputCol="Cat6_1").fit(changedTypedf21)
changedTypedf23 = changedTypedf22.transform(changedTypedf21)
changedTypedf23=changedTypedf23.drop("Cat6")
changedTypedf24 = StringIndexer(inputCol="Cat7", outputCol="Cat7_1").fit(changedTypedf23)
changedTypedf25 = changedTypedf24.transform(changedTypedf23)
changedTypedf25=changedTypedf25.drop("Cat7")
changedTypedf26 = StringIndexer(inputCol="Cat8", outputCol="Cat8_1").fit(changedTypedf25)
changedTypedf27 = changedTypedf26.transform(changedTypedf25)
changedTypedf27=changedTypedf27.drop("Cat8")
changedTypedf28 = StringIndexer(inputCol="Cat9", outputCol="Cat9_1").fit(changedTypedf27)
changedTypedf29 = changedTypedf28.transform(changedTypedf27)
changedTypedf29=changedTypedf29.drop("Cat9")
changedTypedf30 = StringIndexer(inputCol="Cat10", outputCol="Cat10_1").fit(changedTypedf29)
changedTypedf31 = changedTypedf30.transform(changedTypedf29)
changedTypedf31=changedTypedf31.drop("Cat10")
changedTypedf32 = StringIndexer(inputCol="Cat11", outputCol="Cat11_1").fit(changedTypedf31)
changedTypedf33 = changedTypedf32.transform(changedTypedf31)
changedTypedf33=changedTypedf33.drop("Cat11")
changedTypedf34 = StringIndexer(inputCol="Cat12", outputCol="Cat12_1").fit(changedTypedf33)
changedTypedf35 = changedTypedf34.transform(changedTypedf33)
changedTypedf35=changedTypedf35.drop("Cat12")
changedTypedf36 = changedTypedf35.withColumn("OrdCat", changedTypedf35["OrdCat"].cast(DoubleType()))
changedTypedf37 = changedTypedf36.withColumn("Var1", changedTypedf36["Var1"].cast(DoubleType()))
changedTypedf38 = changedTypedf37.withColumn("Var2", changedTypedf37["Var2"].cast(DoubleType()))
changedTypedf39 = changedTypedf38.withColumn("Var3", changedTypedf38["Var3"].cast(DoubleType()))
changedTypedf40 = changedTypedf39.withColumn("Var4", changedTypedf39["Var4"].cast(DoubleType()))
changedTypedf41 = changedTypedf40.withColumn("Var5", changedTypedf40["Var5"].cast(DoubleType()))
changedTypedf42 = changedTypedf41.withColumn("Var6", changedTypedf41["Var6"].cast(DoubleType()))
changedTypedf43 = changedTypedf42.withColumn("Var7", changedTypedf42["Var7"].cast(DoubleType()))
changedTypedf44 = changedTypedf43.withColumn("Var8", changedTypedf43["Var8"].cast(DoubleType()))
changedTypedf45 = StringIndexer(inputCol="NVCat", outputCol="NVCat_1").fit(changedTypedf44)
changedTypedf46 = changedTypedf45.transform(changedTypedf44)
changedTypedf46=changedTypedf46.drop("NVCat")
changedTypedf47 = changedTypedf46.withColumn("NVVar1", changedTypedf46["NVVar1"].cast(DoubleType()))
changedTypedf48 = changedTypedf47.withColumn("NVVar2", changedTypedf47["NVVar2"].cast(DoubleType()))
changedTypedf49 = changedTypedf48.withColumn("NVVar3", changedTypedf48["NVVar3"].cast(DoubleType()))
changedTypedf50 = changedTypedf49.withColumn("NVVar4", changedTypedf49["NVVar4"].cast(DoubleType()))
changedTypedf51 = changedTypedf50.withColumn("Claim_Amount", changedTypedf50["Claim_Amount"].cast(DoubleType()))
changedTypedf52 = changedTypedf51.drop("Row_ID")
changedTypedf53 = changedTypedf52.drop("Household_ID")
changedTypedf54 = changedTypedf53.drop("Vehicle")
assembler = VectorAssembler(
    inputCols=["Calendar_Year","Model_Year","OrdCat","Var1","Var2","Var3","Var4","Var5","Var6","Var7","Var8","NVVar1","NVVar2","NVVar3","NVVar4","Blind_Make1","Blind_Model1","Blind_Submodel1","Cat1_1","Cat2_1","Cat3_1","Cat3_1","Cat4_1","Cat5_1","Cat6_1","Cat7_1","Cat8_1","Cat9_1","Cat10_1","Cat11_1","Cat12_1","NVCat_1"],
    outputCol="feature")

output = assembler.transform(changedTypedf54)
output = output.cache()

f1 = output.drop('Calendar_Year')
f2 = f1.drop('Model_Year')
f3 = f2.drop('OrdCat')
f4 = f3.drop('Var1')
f5 = f4.drop('Var2')
f6 = f5.drop('Var3')
f7 = f6.drop('Var4')
f8 = f7.drop('Var5')
f9 = f8.drop('Var6')
f10 = f9.drop('Var7')
f11 = f10.drop('Var8')
f12 = f11.drop('NVVar1')
f13 = f12.drop('NVVar2')
f14 = f13.drop('NVVar3')
f15 = f14.drop('NVVar4')
f16 = f15.drop('Blind_Make1')
f17 = f16.drop('Blind_Model1')
f18 = f17.drop('Blind_Submodel1')
f19 = f18.drop('Cat1_1')
f20 = f19.drop('Cat2_1')
f21 = f20.drop('Cat3_1')
f22 = f21.drop('Cat4_1')
f23 = f22.drop('Cat5_1')
f24 = f23.drop('Cat6_1')
f25 = f24.drop('Cat7_1')
f26 = f25.drop('Cat8_1')
f27 = f26.drop('Cat9_1')
f28 = f27.drop('Cat10_1')
f29 = f28.drop('Cat11_1')
f30 = f29.drop('Cat12_1')
f31 = f30.drop('NVCat_1')
df2 = f31.selectExpr("Claim_Amount as label","feature as features")

assembler1 = VectorAssembler(
    inputCols=["label"],
    outputCol="label1")

output1 = assembler1.transform(df2)
output1 = output1.cache()
f32 = output1.drop("label")
scaler = MinMaxScaler(inputCol="label1", outputCol="label")
scalerModel = scaler.fit(f32)
scaledData = scalerModel.transform(f32)
element=udf(lambda v:float(v[0]),FloatType())
new = scaledData.withColumn('label', element('label'))
(trainingData, testData) = new.randomSplit([0.7, 0.3], 50)
lr = LinearRegression(featuresCol = "features", labelCol = "label", maxIter=10, regParam=0.3, elasticNetParam=0.8)
lrModel = lr.fit(trainingData)
trainingSummary = lrModel.summary
print("Question 2.2(a).............")
print("RMSE for training data: %f" % trainingSummary.rootMeanSquaredError)
predict = lrModel.transform(testData)
evaluator_rmse = RegressionEvaluator\
      (labelCol="label", predictionCol="prediction", metricName="rmse")
rmse = evaluator_rmse.evaluate(predict)
print("RMSE for test data = %g " % rmse)

spark.stop()


import requests
import asyncio
from discord.ext import commands
from discord.ext.commands.core import command

class Stuff(commands.Cog):

    def __init__(self, client):
        self.client = client

    @commands.command(brief="Insults the specified person")
    async def insult(self, ctx, *, person):
        insult = requests.get("https://insult.mattbas.org/api/insult")
        insult = insult.text.replace("Y", "y")
        async with ctx.channel.typing():
            await asyncio.sleep(3)
        await ctx.channel.send(f"{person}, {insult}")

    @commands.command(brief="Get a random dad joke")
    async def joke(self, ctx):
        joke = requests.get("https://icanhazdadjoke.com/", headers={"Accept": "application/json"}).json()['joke']
        async with ctx.channel.typing():
            await asyncio.sleep(2)
        await ctx.channel.send(f"{joke}")

    @commands.command(brief="Give a word to get the definition")
    async def define(self, ctx, word):
        reply = ""
        definition = requests.get(f"https://api.dictionaryapi.dev/api/v2/entries/en_GB/{word}").json()
        try:
            for i in definition[0]["meanings"]:
                reply += f"\r\n**{i['partOfSpeech']}**: "
                for j in i['definitions']:
                    reply += f"\r\n{j['definition']}\r\n"
                    try:
                        reply += f"> {j['example']}\r\n"
                    except:
                        pass
        except:
            reply = f'{definition["message"]}'

        async with ctx.channel.typing():
            asyncio.sleep(2)
        await ctx.channel.send(reply)

def setup(client):
    client.add_cog(Stuff(client))


#Scheduler Class

import os
import sys
import pickle
from Time import Time
from ShiftCal import ShiftDay, ShiftCalendar
from Employee import Employee, Rule

class Scheduler:
    '''Shift Scheduler'''

    def __init__(self, month, year):
        assert type(month) == int and type(year) == int, 'month and year should be integers'
        assert month in range(1,13) and year >= 0, 'month or year out of bounds'

        self.cal = ShiftCalendar(month, year)

        self.year = year
        self.month = month
        self.numDays = self.cal.numDays
        self.firstDay = self.cal.firstDay #which weekday month starts on (0-6)

        self.employeeList = [] #list of employee objects

    def save(self, f, info = False):
        '''
            Saves Scheduler data using python's pickle module
            @params f: open file pointer in "wb" mode
            @params info: T/F whether to print additional info while saving.
            @return: 1 if successful, -1 if unsuccessfull.
        '''
        print("Saving Scheduler data...")
        pickle.dump(self.year, f)
        pickle.dump(self.month, f)
        pickle.dump(self.numDays, f)
        pickle.dump(self.firstDay, f)
        #NOTE: Cannot pickle employeeList, need to pickle each employee individually and then reconstruct list.
        if info: print("  Saved scheduler attributes")
        if info: print("  Checking employee list")

        #save length of employee list
        pickle.dump(len(self.employeeList), f)
        print("")
        #If not 0 then save each employee
        if len(self.employeeList) != 0:
            print("Saving Employee data...")
            print("  %d employees to save\n"%len(self.employeeList))
            for e in self.employeeList:
                if not e.save(f, info):
                    print("An error occured!")
                    return False
                print("")

        else:
            print("No employee data to save...")

        #save shiftCal
        print("")
        if self.cal.save(f, info):
            return True
        else:
            return False

    def load(self, f, info = False):
        '''
            Loads scheduler, shiftcal, & employees from filename
            @params f: an open file pointer in "rb" mode
            @params info: T/F whether to print detailed loading info
            @return: True if no errors occurred, False otherwise
        '''
        try:
            print("Loading Scheduler data...")
            self.year = pickle.load(f)
            if info: print("  Read year: %d"%self.year)
            self.month = pickle.load(f)
            if info: print("  Read month: %d"%self.month)
            self.numDays = pickle.load(f)
            if info: print("  Read number of days: %d"%self.numDays)
            self.firstDay = pickle.load(f)
            if info: print("  Read first day: %d"%self.firstDay)
            print("  Loaded scheduler attributes")
            if info: print("  Checking employee data")

            numEmps = pickle.load(f)
            if info: print("  Read num employees: %d"%numEmps)
            self.employeeList = []
            emp_dict = {}
            print("")
            if numEmps == 0:
                print("No Employee data to load...")
            else:
                print("Loading Employees...")
                print("  %d employees to load\n"%numEmps)
                for i in range(0, numEmps):
                    emp = Employee("dummy", 1) #dummy employee who will be overwritten by loaded emp
                    if emp.load(f, info):
                        self.employeeList.append(emp)
                        emp_dict[emp.getName()] = emp
                    else:
                        return False
                    print("")

            print("")
            self.cal = ShiftCalendar(1,1970) #dummy shiftCal
            if self.cal.load(f, emp_dict, info):
                return True
            else:
                print("Error occured loading calendar...")
                return False

        except FileNotFoundError:
            print("Couldnt find scheduler data file...")
            return False

    def addEmployee(self, employee):
        '''
            Adds an employee to the scheduler
            @params employee: an employee object to be added
        '''
        if employee.__class__.__name__ == "Employee":
            self.employeeList.append(employee)
            print("Employee %s added."%employee.getName())

    def removeEmployee(self, employee):
        '''
            Removes an employee from the scheduler and deletes any shifts assigned to him/her
            @params employee: Employee obect to be removed
            @return: returns 1 on success, -1 for any type of error.
        '''
        if employee.__class__.__name__ == "Employee":
            #IMPROVE THIS TO DELETE ALL THAT EMPLOYEES SHIFTS & RETURN MORE INFO
            if employee in self.employeeList:
                self.cal.removeAllForEmp(employee)
                print("Employee %s removed."%employee.getName())
                self.employeeList.remove(employee)
                return 1
            else:
                print("%s employee does not exist"%employee.getName())
        return -1

    def createShiftW(self, weekdays, times, lunch=False):
        '''
            Creates shifts with given times for each weekday in weekdays
            @params weekdays: list of weekdays to create shifts for (0-6)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if you want to create a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(weekdays) > 0 and len(times) > 0:
            for day in weekdays:
                self.cal.setShiftsByDay(day, times, lunch)
            return 1
        return -1

    def createShiftD(self, days, times, lunch=False):
        '''
            Creates shifts with given times for each day in days
            @params days: list of days to create shifts for (1-31)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if you want to create a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(days) > 0 and len(times) > 0:
            for d in days:
                self.cal.setSingleDay(d, times, lunch)
            return 1
        return -1

    def delShiftW(self, weekdays, times, lunch=False):
        '''
            Deletes shifts with given times for each weekday in weekdays
            @params weekdays: list of weekdays to delete shifts for (0-6)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(weekdays) > 0 and len(times) > 0:
            for day in weekdays:
                for t in times:
                    self.cal.deleteShiftEveryWeek(day, t, lunch)
            return 1
        return -1

    def delShiftD(self, days, times, lunch = False):
        '''
            Deletes shifts with given times for each day in days
            @params days: list of days to delete shifts for (1-31)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(days) > 0 and len(times) > 0:
            for d in days:
                for t in times:
                    if self.cal.deleteSingleShift(d, t, lunch) == -1:
                        print("Failed to delete shift %d - %s"%(d, t))
                        return -1
            return 1
        else:
            return -1

    def assignW(self, emp, weekdays, times, lunch = False):
        '''
            Assigns employee to shifts with given times for each weekday in weekdays
            @params emp: Employee object assigned to each shift
            @params weekdays: list of weekdays to assign shifts for (0-6)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if emp.__class__.__name__=="Employee" and len(weekdays) > 0 and len(times) > 0:
            for d in weekdays:
                for t in times:
                    self.cal.assignShiftEveryWeek(d, t, emp, lunch)
            return 1
        return -1

    def assignD(self, emp, days, times, lunch=False):
        '''
            Assigns employee to shifts with given times for each day in days
            @params emp: Employee object assigned to each shift
            @params days: list of days to assign shifts for (1-31)
            @params times: list of Time objects, start time of each shift for each day
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if emp.__class__.__name__=="Employee" and len(weekdays) > 0 and len(times) > 0:
            for d in days:
                for t in times:
                    self.cal.assignShift(d, t, emp, lunch)
            return 1
        return -1

    def clearW(self, weekdays, times="all", lunch=False):
        '''
            Clears shifts with given times for each weekday in weekdays
            @params weekdays: list of weekdays to clear shifts for (0-6)
            @params times: list of Time objects, start time of each shift for each day
                           can also be a string "all" indicating all shifts for those weekdays should be cleared
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(weekdays) > 0 and len(times) > 0:
            if times == "all": times = [None] #more intuitive way to indicate clearing all shifts
            for day in weekdays:
                for t in times:
                    self.cal.clearShiftsEveryWeek(day, t, lunch)
            return 1
        return -1

    def clearD(self, days, times="all", lunch=False):
        '''
            Clears shifts with given times for each day in days
            @params days: list of days to clear shifts for (1-31)
            @params times: list of Time objects, start time of each shift for each day
                           can also be a string "all" indicating all shifts for those days should be cleared
            @params lunch: boolean if referring to a lunch shift or dinner shift (lunch=False)

            @return: 1 if successful, -1 otherwise
        '''
        if len(days) > 0 and len(times) > 0:
            for d in days:
                for t in times:
                    self.cal.clearSingleShift(d, t, lunch)
            return 1
        return -1

    def matchShift(self, employee, l, t, wd, wn, d):
        '''
            Creates a rule from shift info provided and matches with given employee
            @params employee: Employee object
            @params d: integer (1-31) indicating day to match
            @params l: boolean indicating whether to match a lunch or dinner shift
            @params t: A string representing the time at which shift starts
            @params wd: integer (0-6) indicating which day of the week shift is on
            @params wn: integer (1-6) indicating which number week the shift is on

            @returns: True or False depending on whether employee can work that shift.
        '''
        if employee not in self.employeeList:
            print("Employee not found.")
            return -1

        shift_rule = Rule(lunch=l, time=t, weekday=wd, weeknum=wn, daynum=d)

        return employee.matchRule(shift_rule)

    def run(self, depth):
        '''
            Run scheduler until finding a complete schedule
            Should take into account priority & alternate between all employees equally
        '''
        #Clear previous assignments
        self.cal.clearAllShifts()
        print("\nAll shifts cleared")
        self.cal.printCal()
        print("")
        print(self.employeeList)
        res = self.assignEmployee(1, self.cal.getDay(1), self.employeeList.copy().sort(), depth)
        print("\nScheduling Done: %s"%res)
        return res

    def assignEmployee(self, daynum, shift_day, employeeList, depth=-1):
        '''
            Recursive function, on each call tries to assign employee from employeeList to an open shift in shift_day
            Then removes employee assigned from employeeList and calls itself until day is filled.
            If employeeList empty and day not complete, declare failure
            Else if day is complete, rebuild employee list and call recursively on next day
            If daynum > number of days in month, check if calendar is complete, else return failure.

            @params daynum: integer (1 to numDays in month), day we are working on
            @shift_day: ShiftDay object of that day
            @employeeList: list of employees ordered by priority
            @depth: integer indicating how many recursive calls to execute before stopping, used for testing. -1 disables limiting depth

            @return: True if found a complete schedule, False if not. Modifies the shiftcalendar in place
        '''
        #No more shifts left to schedule
        if self.cal.isComplete():
            return True

        #We are done with all days
        if daynum > self.cal.numDays:
            return self.cal.isComplete()

        #Stop scheduling for testing purposes
        if depth == 0:
            return True

        print("Trying to schedule day %d"%daynum)

        shift = shift_day.getNextEmptyShift()

        #No more shifts left for this day, move on to next day
        if shift == None:
            print("No more shifts left for this day.")
            empList = self.employeeList.copy() #get fresh employee list
            empList.sort()
            sd = self.cal.getDay(daynum+1)
            print("reset emp list to %s"%(str(empList)))
            return self.assignEmployee(daynum+1, sd, empList, depth)

        #Else there is a shift to schedule
        lunch = shift[0]
        time = shift[1]
        weekday = shift_day.weekday
        weeknum = shift_day.weeknum

        print("empList: %s"%(str(employeeList)))

        for e in employeeList:
            print("---------")
            print("Trying employee %s"%(str(e)))
            if self.matchShift(e, lunch, time, weekday, weeknum, daynum): #true if employee can work shift
                print("%s can work that shift!"%(str(e)))
                temp = e
                if lunch:
                    shift_day.setLunchShift(time, e)
                else:
                    shift_day.setDinnerShift(time, e)

                newEmpList = employeeList.copy()
                newEmpList.remove(e)
                print("new emp list: %s"%(newEmpList))
                print("new depth = %d"%(depth-1))

                if not self.assignEmployee(daynum, shift_day, newEmpList, depth-1):
                    #scheduling was unsuccessful, undo assignment
                    if lunch:
                        shift_day.setLunchShift(time, None)
                    else:
                        shift_day.setDinnerShift(time, None)
                    continue #next employee
                else:
                    #everything went well
                    return True
        #We get here if we have gone through all employees so declare failure
        return False


import unittest
from plugins.filter import valid_emails as ve

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual(ve.filter_email('jaswant@ram.com'), ['jaswant@ram.com'])

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


from tvm.relay import FuncType
from . import exec_builder
from . import expr
from . import ty
from . import vm
from . import block_builder
from . import op
from . import analysis
from . import transform
from . import expr_functor

# Expr
Expr = expr.Expr
Span = expr.Span
SourceName = expr.SourceName
Id = expr.Id
GlobalVar = expr.GlobalVar
Var = expr.Var
DataflowVar = expr.DataflowVar
Binding = expr.Binding
MatchShape = expr.MatchShape
VarBinding = expr.VarBinding
BindingBlock = expr.BindingBlock
DataflowBlock = expr.DataflowBlock
SeqExpr = expr.SeqExpr
ShapeExpr = expr.ShapeExpr
RuntimeDepShape = expr.RuntimeDepShape
Tuple = expr.Tuple
TupleGetItem = expr.TupleGetItem
Function = expr.Function
ExternFunc = expr.ExternFunc
Call = expr.Call
If = expr.If

# helper functions
const = expr.const
extern = expr.extern
te_tensor = expr.te_tensor

# Type
Type = ty.Type
ShapeType = ty.ShapeType
ObjectType = ty.ObjectType
DynTensorType = ty.DynTensorType
DimType = ty.DimType
TupleType = ty.TupleType
FuncType = ty.FuncType

# VM
ExecBuilder = exec_builder.ExecBuilder
VirtualMachine = vm.VirtualMachine
load_exec_from_file = vm.load_exec_from_file

# Operator
from .op.base import call_tir, make_closure, invoke_closure
from .op.op_attrs import VMAllocStorageAttrs, VMAllocTensorAttrs

# IRBuilder
BlockBuilder = block_builder.BlockBuilder

# ExprFunctor
ExprFunctor = expr_functor.ExprFunctor
ExprVisitor = expr_functor.ExprVisitor
ExprMutator = expr_functor.ExprMutator