from turtle import distance, speed
from AI_Interface import *
from math import asin, acos, sin, cos, exp, pi
import numpy as np

# class Axis():
#     def __init__(self, a = 0, b = 0, c = 0):#a,b,c依次是偏航角，俯仰角，滚转角
#         GxOy = np.array([[cos((a+pi/2)),  -sin((a+pi/2)),   0        ],
#                          [sin((a+pi/2)), cos((a+pi/2))  ,   0        ],
#                          [0            ,  0             ,   1        ]])
#         GzOx = np.array([[cos(b)       ,  0             ,   -sin(b)  ],
#                          [0            ,  1             ,   0        ],
#                          [sin(b)       ,  0             ,   cos(b)   ]])
#         GyOz = np.array([[1            ,  0             ,   0        ],
#                          [0            ,  -cos(c)       ,   sin(c)   ],
#                          [0            ,  -sin(c)       ,   -cos(c)  ]])
#         self.base = GxOy @ GzOx @ GyOz
#     def transform(self, component, reverse = False):
#         if reverse:#从机体坐标系变换到北天东坐标系
#             return self.base @ component
#         else:#从北天东坐标系变换到机体坐标系
#             return self.base.T @ component

class Axis():
    def __init__(self, a = 0, b = 0, c = 0):#a,b,c依次是偏航角，俯仰角，滚转角
        a = a+pi/2
        b = -b
        c = -c
        e0, e1, e2, e3 = cos(a/2)*cos(b/2)*cos(c/2)+sin(a/2)*sin(b/2)*sin(c/2),\
                         cos(a/2)*cos(b/2)*sin(c/2)-sin(a/2)*sin(b/2)*cos(c/2),\
                         cos(a/2)*sin(b/2)*cos(c/2)+sin(a/2)*cos(b/2)*sin(c/2),\
                         sin(a/2)*cos(b/2)*cos(c/2)-cos(a/2)*sin(b/2)*sin(c/2)
        self.base = np.array([[e0**2+e1**2-e2**2-e3**2, 2*(e1*e2+e0*e3)        , 2*(e1*e3-e0*e2)        ],
                              [2*(e1*e2-e0*e3)        , e0**2-e1**2+e2**2-e3**2, 2*(e2*e3+e0*e1)        ],
                              [2*(e0*e2+e1*e3)        , 2*(e2*e3-e0*e1)        , e0**2-e1**2-e2**2+e3**2]])
    def transform(self, component, reverse = False):
        if reverse:#从机体坐标系变换到北天东坐标系
            return self.base.T @ component
        else:#从北天东坐标系变换到机体坐标系
            return self.base @ component

def getDistance(nextRedInput, nextBlueInput):
    # distance = ((nextRedInput.m_AircraftMoveInfo.m_dSelfLon - nextBlueInput.m_AircraftMoveInfo.m_dSelfLon)**2 +\
    #             (nextRedInput.m_AircraftMoveInfo.m_dSelfLat - nextBlueInput.m_AircraftMoveInfo.m_dSelfLat)**2 +\
    #             (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt - nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt)**2)**0.5
    distance = nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtDis
    return distance

def getSpeed(Input):
    speed = ((Input.m_AircraftMoveInfo.m_fVN)**2 +\
            (Input.m_AircraftMoveInfo.m_fVU)**2 +\
            (Input.m_AircraftMoveInfo.m_fVE)**2)**0.5
    return speed

def getAngleAdvantage(nextRedInput, nextBlueInput, versionID):
    # distance = getDistance(nextRedInput, nextBlueInput)
    redSpeed = getSpeed(nextRedInput)
    # blueSpeed = getSpeed(nextBlueInput)
    redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
                   nextRedInput.m_AircraftMoveInfo.m_fPitch,
                   nextRedInput.m_AircraftMoveInfo.m_fRoll)
    # blueAxis = Axis(nextBlueInput.m_AircraftMoveInfo.m_fYaw,
    #                 nextBlueInput.m_AircraftMoveInfo.m_fPitch,
    #                 nextBlueInput.m_AircraftMoveInfo.m_fRoll)
    if versionID == 0:
        # positionVector = np.array([nextBlueInput.m_AircraftMoveInfo.m_dSelfLon - nextRedInput.m_AircraftMoveInfo.m_dSelfLon,
        #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfLat - nextRedInput.m_AircraftMoveInfo.m_dSelfLat,
        #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt - nextRedInput.m_AircraftMoveInfo.m_dSelfAlt])
        # transformedPositionVectorRed = redAxis.transform(positionVector)
        # redSightAngle = acos(transformedPositionVectorRed[0]/(distance+1e-4))
        # transformedPositionVectorBlue = blueAxis.transform(-positionVector)
        # blueSightAngle = acos(transformedPositionVectorBlue[0]/(distance+1e-4))
        redSightAngle = acos(cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180))
        blueSightAngle = acos(cos(nextBlueInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * cos(nextBlueInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180))
        # reward = (blueSightAngle - redSightAngle)/(2*pi)+0.5
        reward = (blueSightAngle - redSightAngle)/(0.01)
    elif versionID == 1 :
        transformedPositionVectorRed = np.array([cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180),
                                                 cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * sin(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180),
                                                 sin(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180)])
        positionVector = redAxis.transform(transformedPositionVectorRed, reverse=True)
        phiRed = acos((nextRedInput.m_AircraftMoveInfo.m_fVE * positionVector[0] +\
                       nextRedInput.m_AircraftMoveInfo.m_fVU * positionVector[1] +\
                       nextRedInput.m_AircraftMoveInfo.m_fVN * positionVector[2])/(redSpeed+1e-4))
        # phiRed = acos((nextRedInput.m_AircraftMoveInfo.m_fVE * (nextBlueInput.m_AircraftMoveInfo.m_dSelfLon - nextRedInput.m_AircraftMoveInfo.m_dSelfLon) +\
        #                nextRedInput.m_AircraftMoveInfo.m_fVU * (nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt - nextRedInput.m_AircraftMoveInfo.m_dSelfAlt) +\
        #                nextRedInput.m_AircraftMoveInfo.m_fVN * (nextBlueInput.m_AircraftMoveInfo.m_dSelfLat - nextRedInput.m_AircraftMoveInfo.m_dSelfLat))/(redSpeed*distance+1e-4))
        # phiBlue = acos((nextBlueInput.m_AircraftMoveInfo.m_fVE * (nextBlueInput.m_AircraftMoveInfo.m_dSelfLon - nextRedInput.m_AircraftMoveInfo.m_dSelfLon) +\
        #                 nextBlueInput.m_AircraftMoveInfo.m_fVU * (nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt - nextRedInput.m_AircraftMoveInfo.m_dSelfAlt) +\
        #                 nextBlueInput.m_AircraftMoveInfo.m_fVN * (nextBlueInput.m_AircraftMoveInfo.m_dSelfLat - nextRedInput.m_AircraftMoveInfo.m_dSelfLat))/(blueSpeed*distance+1e-4))
        reward = 1 - abs(phiRed)/pi
    return reward

def getDistanceAdvantage(nextRedInput, currentRedInput, versionID):
    # distance = getDistance(nextRedInput, nextBlueInput)
    distance = nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtDis
    pre_distance = currentRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtDis
    if versionID == 1:
        optimalDistance = 200
        D0 = 2000 #D0用于调整奖励梯度
        return exp(-abs(distance - optimalDistance)/D0)
    if versionID == 2:
        if distance > 600:
            return -(distance -  600)/ 10000
        else:
            return -1
    if versionID == 3:
        if distance == 0 or distance < 600:
            return -1
        elif distance > 600:
            if distance-pre_distance <= 0:
                return 1
            else:
                return -1

def getAltitudeAdvantage(nextRedInput, nextBlueInput, currentRedInput, versionID):
    reward = 0
    if versionID == 1:
        optimalAlt = 6000
        if nextRedInput.m_AircraftMoveInfo.m_dSelfAlt < nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt:
            reward = nextRedInput.m_AircraftMoveInfo.m_dSelfAlt / (nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt+1e-4) - 0.5
        else:
            reward = exp(-abs(nextRedInput.m_AircraftMoveInfo.m_dSelfAlt - optimalAlt)/(nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt+1e-4)) #最佳空战高度6000
    elif versionID == 2:
        Delta_h = nextRedInput.m_AircraftMoveInfo.m_dSelfAlt - nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt
        if Delta_h < -5000:
            return -1
        elif Delta_h < 5000:
            return -1 + (Delta_h+5000)/5000
        else:
            return -0.1
    elif versionID == 3:
        if (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt < currentRedInput.m_AircraftMoveInfo.m_dSelfAlt) and \
                (currentRedInput.m_AircraftMoveInfo.m_dSelfAlt<1000):
            return -2
        elif (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt > currentRedInput.m_AircraftMoveInfo.m_dSelfAlt) and (currentRedInput.m_AircraftMoveInfo.m_dSelfAlt<1000):
            return 2
        elif nextRedInput.m_AircraftMoveInfo.m_dSelfAlt > currentRedInput.m_AircraftMoveInfo.m_dSelfAlt and currentRedInput.m_AircraftMoveInfo.m_dSelfAlt>1000:
            return 0.1
        elif nextRedInput.m_AircraftMoveInfo.m_dSelfAlt < currentRedInput.m_AircraftMoveInfo.m_dSelfAlt and currentRedInput.m_AircraftMoveInfo.m_dSelfAlt>1000:
            return -0.1
    elif versionID == 4:
        if (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt < currentRedInput.m_AircraftMoveInfo.m_dSelfAlt) and (currentRedInput.m_AircraftMoveInfo.m_dSelfAlt<1000):
            return -5
        # elif (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt > currentRedInput.m_AircraftMoveInfo.m_dSelfAlt) and (currentRedInput.m_AircraftMoveInfo.m_dSelfAlt<1000):
        #     return 5
    return reward

def getSpeedAdvantage(nextRedInput, nextBlueInput, versionID):
    if versionID == 1:
        redSpeed = getSpeed(nextRedInput)
        blueSpeed = getSpeed(nextBlueInput)
        optimalSpeed = 200
        if 1.5*blueSpeed < optimalSpeed: #最佳空战速度200
            if redSpeed > optimalSpeed:
                reward = exp((optimalSpeed - redSpeed)/optimalSpeed)
            elif 1.5*blueSpeed < redSpeed:
                reward = 1
            elif 0.5*blueSpeed < redSpeed:
                reward = redSpeed/(blueSpeed+1e-4) -0.5
            else:
                reward = 0.1
        else:
            if redSpeed > optimalSpeed:
                reward = exp((optimalSpeed-redSpeed)/optimalSpeed)
            elif 0.5*blueSpeed < redSpeed and 1.5*blueSpeed >= redSpeed:
                reward = 0.4*(redSpeed/optimalSpeed -redSpeed/(blueSpeed+1e-4))
            elif 0.5*blueSpeed >= redSpeed:
                reward = 0.1
        return reward
    if versionID == 2:
        redSpeed = getSpeed(nextRedInput)
        blueSpeed = getSpeed(nextBlueInput)
        if blueSpeed < 0.6 * redSpeed:
            return -0.1
        elif blueSpeed < 1.5 * redSpeed:
            return 0.5 - blueSpeed / redSpeed
        else:
            return -1.0

def SRadarDetectRange(nextRedInput, nextBlueInput, nextRedOutput, nextBlueOutput):
    # distance = getDistance(nextRedInput, nextBlueInput)
    # speed = getSpeed(nextRedInput)

    # if not nextRedInput.m_FCInfo.m_eAircraftMainState:  # 超视距
    #     speedPitch = asin(nextRedInput.m_AircraftMoveInfo.m_fVU/(speed+1e-4))
    #     redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
    #                    speedPitch,
    #                    nextRedInput.m_AircraftMoveInfo.m_fRoll)
    # else:
    #     redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
    #                    nextRedInput.m_AircraftMoveInfo.m_fPitch,
    #                    nextRedInput.m_AircraftMoveInfo.m_fRoll)

    # positionVector = np.array([nextBlueInput.m_AircraftMoveInfo.m_dSelfLon -nextRedInput.m_AircraftMoveInfo.m_dSelfLon,
    #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfLat -nextRedInput.m_AircraftMoveInfo.m_dSelfLat,
    #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt -nextRedInput.m_AircraftMoveInfo.m_dSelfAlt])
    # transformedPositionVectorRed = redAxis.transform(positionVector)

    # positionEle = asin(transformedPositionVectorRed[2]/(distance+1e-4))*180/pi
    # positionAzi = acos(transformedPositionVectorRed[0]/(distance*abs(cos(positionEle))+1e-4))*180/pi
    positionEle = nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC
    positionAzi = nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC

    if nextRedInput.m_FCInfo.m_eAircraftMainState:  # 视距内
        if positionAzi > -5 and positionAzi < 5 and \
            positionEle >= -7 and positionEle <= 53 :
            return True
        else:
            return False
    else:
        if positionAzi  > nextRedOutput.m_RadarCtrlCmd.m_fAziScanCent - nextRedOutput.m_RadarCtrlCmd.m_eAziScanRange/2 and\
            positionAzi < nextRedOutput.m_RadarCtrlCmd.m_fAziScanCent + nextRedOutput.m_RadarCtrlCmd.m_eAziScanRange/2 and\
            positionEle > nextRedOutput.m_RadarCtrlCmd.m_fEleScanCent - 4.5 * nextRedOutput.m_RadarCtrlCmd.m_eEleScanLine/2 and\
            positionEle < nextRedOutput.m_RadarCtrlCmd.m_fEleScanCent + 4.5 * nextRedOutput.m_RadarCtrlCmd.m_eEleScanLine/2 :
            return True
        else:
            return False

def SMRAAMCaptured(nextRedInput):
    for i in range(int(nextRedInput.m_MRAAMDataMsgSet.m_uiMsgNum)):
        if nextRedInput.m_MRAAMDataMsgSet.m_MRAAMDataMsg[i].m_bCapture:
            return True
    return False

def SMRAAMCapturedInRange(nextRedInput, nextBlueInput):
    distance = getDistance(nextRedInput, nextBlueInput)
    if (SMRAAMCaptured(nextRedInput)):
        if (distance > nextRedInput.m_FCInfo.m_fRmin and \
            distance < nextRedInput.m_FCInfo.m_fRmax):
            if (distance < nextRedInput.m_FCInfo.m_fRnoescape):
                return 0.8
            else:
                return 0.55
        else:
            return 0.3
    else:
        return 0

def SRadarLocked(nextRedInput, nextBlueInput):
    # maxRadarLockedTolerence = 10000 #人为设定的雷达误差
    # minRadarLockedDistance = 100000
    speed = getSpeed(nextRedInput)

    redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
                   nextRedInput.m_AircraftMoveInfo.m_fPitch,
                   nextRedInput.m_AircraftMoveInfo.m_fRoll)
    transformedPositionVectorRed = np.array([cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180),
                                             cos(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180) * sin(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtAziC*pi/180),
                                             sin(nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtEleC*pi/180)])
    positionVector = redAxis.transform(transformedPositionVectorRed, reverse=True)

    if not nextRedInput.m_FCInfo.m_eAircraftMainState:  # 视距外
        speedPitch = asin(nextRedInput.m_AircraftMoveInfo.m_fVU/(speed+1e-4))
        redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
                       speedPitch,
                       nextRedInput.m_AircraftMoveInfo.m_fRoll)
    # else:
    #     redAxis = Axis(nextRedInput.m_AircraftMoveInfo.m_fYaw,
    #                    nextRedInput.m_AircraftMoveInfo.m_fPitch,
    #                    nextRedInput.m_AircraftMoveInfo.m_fRoll)
    # positionVector = np.array([nextBlueInput.m_AircraftMoveInfo.m_dSelfLon -nextRedInput.m_AircraftMoveInfo.m_dSelfLon,
    #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfLat -nextRedInput.m_AircraftMoveInfo.m_dSelfLat,
    #                            nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt -nextRedInput.m_AircraftMoveInfo.m_dSelfAlt])
    transformedPositionVectorRed = redAxis.transform(positionVector)

    # for i in range(int(nextRedInput.m_RadarInfo.m_uiTgtNum)):
        # SRadarLockedPositionAlt = nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtDis * \
        #                           sin(nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtEle*180/pi)
        # projectedDistance = nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtDis * \
        #                     cos(nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtEle*180/pi)
        # SRadarLockedPositionLon = projectedDistance * \
        #                           cos(nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtAzi*180/pi)
        # SRadarLockedPositionLat = projectedDistance * \
        #                           sin(nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtAzi*180/pi)
        # SRadarLockedDistance = (((SRadarLockedPositionLon - transformedPositionVectorRed[0])**2) + \
        #                         ((SRadarLockedPositionLat - transformedPositionVectorRed[1])**2) + \
        #                         ((SRadarLockedPositionAlt - transformedPositionVectorRed[2])**2))**0.5

    #     SRadarLockedDistance = abs(nextRedInput.m_RadarInfo.m_TgtInfo[i].m_fTgtDis - nextRedInput.m_HMDInfo.m_TgtInfo[0].m_fTgtDis)
    #     if SRadarLockedDistance < minRadarLockedDistance:
    #         minRadarLockedDistance = SRadarLockedDistance
    # if minRadarLockedDistance < maxRadarLockedTolerence:
    #     return True
    # else:
    #     return False
    if int(nextRedInput.m_RadarInfo.m_uiTgtNum) > 0:
        return True
    else:
        return False

def AAMHit(nextRedInput):
    for i in range(int(nextRedInput.m_AAMDataSet.m_iAAMNum)):
        if nextRedInput.m_AAMDataSet.m_AAMData[i].m_fTgtDis < 30 and \
            nextRedInput.m_AAMDataSet.m_AAMData[i].m_fTgtDis > 0.001:
            if nextRedInput.m_AAMDataSet.m_AAMData[i].m_uiPlaneID == nextRedInput.m_AircraftBasicInfo.m_ID:
                return 2
            else:
                return -2
    return 0

def getStabilityReward(nextRedInput, currentRedOutput):
    from scipy.interpolate import interpn
    import numpy as np
    if currentRedOutput.m_FlyCtrlCmd.m_fThrottle >= 0.62 and currentRedOutput.m_FlyCtrlCmd.m_fThrottle <= 0.65:
        throttleType = 1
    elif currentRedOutput.m_FlyCtrlCmd.m_fThrottle > 0.65 and currentRedOutput.m_FlyCtrlCmd.m_fThrottle < 1:
        throttleType = 2
    elif currentRedOutput.m_FlyCtrlCmd.m_fThrottle == 1:
        throttleType = 3
    else:
        throttleType = 0

    if nextRedInput.m_AircraftMoveInfo.m_fMach < 0.3 or nextRedInput.m_AircraftMoveInfo.m_fMach > 1.9\
    or nextRedInput.m_AircraftMoveInfo.m_dSelfAlt < 1000 or nextRedInput.m_AircraftMoveInfo.m_dSelfAlt > 15000:
        return -1

    altIndex = np.array([1000.,3000.,5000.,7000.,9000.,11000.,13000.,15000.])
    # machIndexType1 = np.array([0.3,0.4,0.5,0.6,0.7,0.8,0.9])
    machIndexType3 = np.array([0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9])
    type1NormalAccelPre = np.array([[1.267,0    ,0    ,0    ,0    ,0    ,0    ,0    ],
                                    [2.186,1.724,1.357,1.056,0    ,0    ,0    ,0    ],
                                    [3.208,2.537,2.006,1.570,1.218,0    ,0    ,0    ],
                                    [4.188,3.332,2.658,2.098,1.643,1.263,0    ,0    ],
                                    [5.053,4.031,3.215,2.546,2.005,1.573,1.231,0    ],
                                    [5.865,4.678,3.737,2.976,2.409,1.903,1.486,1.156],
                                    [6.536,5.230,4.174,3.367,2.800,2.227,1.738,1.334]])
    type3NormalAccel = np.array([[2.662,2.163,1.723,1.338,0    ,0    ,0    ,0    ],
                                 [3.946,3.163,2.523,1.994,1.576,1.206,0    ,0    ],
                                 [5.365,4.338,3.491,2.763,2.146,1.623,1.204,0    ],
                                 [6.893,5.559,4.464,3.545,2.779,2.118,1.578,1.148],
                                 [8.239,6.758,5.514,4.393,3.437,2.616,1.948,1.417],
                                 [9.000,7.865,6.442,5.202,4.139,3.153,2.347,1.707],
                                 [9.000,8.421,7.003,5.725,4.599,3.557,2.676,1.943],
                                 [6.650,7.082,6.416,5.523,4.606,3.642,2.767,2.005],
                                 [0    ,6.787,6.790,6.003,5.068,4.031,3.072,2.225],
                                 [0    ,0    ,6.787,6.351,5.481,4.392,3.360,2.432],
                                 [0    ,0    ,3.188,6.567,5.877,4.751,3.653,2.646],
                                 [0    ,0    ,0    ,6.276,6.140,5.073,3.905,2.825],
                                 [0    ,0    ,0    ,5.137,6.225,5.309,4.146,2.991],
                                 [0    ,0    ,0    ,0    ,5.784,5.410,4.312,3.111],
                                 [0    ,0    ,0    ,0    ,4.825,5.392,4.411,3.165],
                                 [0    ,0    ,0    ,0    ,0    ,2.655,4.354,3.076],
                                 [0    ,0    ,0    ,0    ,0    ,0    ,2.662,1.482]])
    zeroNormalAccel = np.zeros_like(type3NormalAccel)
    type1NormalAccel = np.zeros_like(type3NormalAccel)
    m, n = type1NormalAccelPre.shape
    type1NormalAccel[:m,:] = type1NormalAccelPre
    table = np.array([zeroNormalAccel, type1NormalAccel, type3NormalAccel])
    index = (np.array([0.0, 0.635, 1.0]), machIndexType3, altIndex)
    query = np.array([currentRedOutput.m_FlyCtrlCmd.m_fThrottle,
                      nextRedInput.m_AircraftMoveInfo.m_fMach,
                      nextRedInput.m_AircraftMoveInfo.m_dSelfAlt])

    value = interpn(index, table, query, method='linear')

    if value[0] <= 0:
        return -1
    elif nextRedInput.m_AircraftMoveInfo.m_fNormalAccel > value:
        # return -(value - nextRedInput.m_AircraftMoveInfo.m_fNormalAccel)**2
        return -1
    else:
        return 0

def getIncidentReward(currentRedInput,
                      currentBlueInput,
                      nextRedInput,
                      nextBlueInput):
    if (currentRedInput.m_AircraftBasicInfo.m_bAlive and \
        (not nextRedInput.m_AircraftBasicInfo.m_bAlive)):
        return -1#被击毁
    if (currentRedInput.m_AircraftBasicInfo.m_fFuel > 0 and \
        nextRedInput.m_AircraftBasicInfo.m_fFuel <=0):
        return -1#油尽
    if (nextRedInput.m_AircraftMoveInfo.m_dSelfAlt <= 500):
        return -1#撞地
    if (currentBlueInput.m_AircraftBasicInfo.m_bAlive and \
        (not nextBlueInput.m_AircraftBasicInfo.m_bAlive)):
        return 1#击毁敌机
    if (currentBlueInput.m_AircraftBasicInfo.m_fFuel > 0 and \
        nextBlueInput.m_AircraftBasicInfo.m_fFuel <=0):
        return 1#敌机油尽
    # if (nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt <= 500):
    #     return 1#敌机撞地
    # if (currentRedInput.m_AircraftBasicInfo.m_bAlive and \
    #     (not nextRedInput.m_AircraftBasicInfo.m_bAlive) and \
    #     currentBlueInput.m_AircraftBasicInfo.m_bAlive and \
    #     (not nextBlueInput.m_AircraftBasicInfo.m_bAlive)):
    #     return 0#同归于尽
    else:
        return 0

def getReward(currentRedInput,
              currentBlueInput,
              currentRedOutput,
              currentBlueOutput,
              nextRedInput,
              nextBlueInput):
    reward = 0
    reward += getIncidentReward(currentRedInput,
                                currentBlueInput,
                                nextRedInput,
                                nextBlueInput)

    # if (SRadarDetected(nextRedInput, nextBlueInput, currentRedOutput, currentBlueOutput)):
    #     reward += 0.05
    # if (SRadarDetected(nextBlueInput, nextRedInput, currentBlueOutput, currentRedOutput)):
    #     reward -= 0.05

    # if (SRadarLocked(nextRedInput, nextBlueInput)):
    #     reward += 0.2#火控雷达探测到信息
    # if (SRadarLocked(nextBlueInput, nextRedInput)):
    #     reward -= 0.2#被火控雷达探测到信息

    # reward += SMRAAMCapturedInRange(nextBlueInput, nextRedInput)
    reward += 0.1 * getAngleAdvantage(nextRedInput, nextBlueInput, 0)
    # reward += 0.5 * getSpeedAdvantage(nextRedInput, nextBlueInput, 1)
    # reward += 0.001 * getDistanceAdvantage(nextRedInput, nextBlueInput, currentRedInput, 3)
    reward += 0.1 * getAltitudeAdvantage(nextRedInput, nextBlueInput,currentRedInput, 3)
    reward += 0.1 * AAMHit(nextRedInput)
    #reward += 0.05 * getStabilityReward(nextRedInput, currentRedOutput)
    return reward

if __name__ == '__main__':
    currentRedInput = AIPilotInput()
    currentBlueInput = AIPilotInput()
    currentRedOutput = AIPilotOutput()
    currentBlueOutput = AIPilotOutput()
    nextRedInput = AIPilotInput()
    nextBlueInput = AIPilotInput()

    nextBlueInput.m_AircraftMoveInfo.m_dSelfLon =1
    nextBlueInput.m_AircraftMoveInfo.m_fVN = 1
    nextRedInput.m_AircraftMoveInfo.m_fVN = 2
    nextRedInput.m_AircraftMoveInfo.m_dSelfAlt = 3
    nextBlueInput.m_AircraftMoveInfo.m_dSelfAlt = 4
    r = getReward(currentRedInput,
              currentBlueInput,
              currentRedOutput,
              currentBlueOutput,
              nextRedInput,
              nextBlueInput)
    axis = Axis()
    print(r)

    # import matplotlib.pyplot as plt
    # reward = []
    # for i in range(100, 9000, 100):
    #     redInput = AIPilotInput()
    #     redInput.m_AircraftMoveInfo.m_dSelfAlt = i
    #     blueInput = AIPilotInput()
    #     blueInput.m_AircraftMoveInfo.m_dSelfAlt = i-100
    #     reward.append(getAltitudeAdvantage(redInput, blueInput, 1))
    # plt.plot(reward)
    # plt.show()
    # print(reward)


def pick_your_path():
    print('Welcome to Treasure Island.\n Your mission is to find the treasure.')
    road = input(' You are at a crossroad will you go left or right?\n').lower()
    if road == 'left':
        lake = input('You come across a lake. There is an island in the middle. Will you "wait" for a boat or "swim" '
                     'across.\n').lower()
        if lake == 'wait':
            color = input('You arrive at the lake unharmed. There is a house with three doors. One red, one yellow '
                          'and one green. Which will you choose?\n ')
            if color == 'red':
                print('The room is filled with fire, Game Over.')
            elif color == 'yellow':
                print('You entered a room of beasts, Game Over.')
            elif color == 'green':
                print('You found the treasure! You win!')
            else:
                print('You did\'nt choose a real door, Game Over')
        else:
            print('You got attacked by sharks! Game over.')
    else:
        print('You fell into a hole, Game Over.')

pick_your_path()

def leap_year():
    year = int(input("What Year do you want to check?"))
    if year % 4 == 0:
        if year % 100 == 0:
            if year % 400 == 0:
                print('Leap Year!')
            else:
                print('not leap year')
        else:
            print('leap year')
    else:
        print('Not leap year')

def roller_coaster():
    print('Welcome to the the RollerCoaster!')
    height = int(input('What is your height in inches?'))
    bill = 0
    if height >= 48:
        print('You can ride the ride!')
        age = int(input("What is your age?"))
        if age < 12:
            bill = 5
            print('please pay $5')
        elif age <= 18:
            bill = 7
            print('please pay $7')
        else:
            bill = 12
            print('Please pay $12')
        photo = input("Do you want a photo taken? Y or N")
        if photo == "y":
            bill += 3
        print(f'Your bill is {bill}')
    else:
        print('You must be 48 inches tall to ride the ride, sorry come again.')

roller_coaster()

def pizza_order():
    size = input('What size Pizza do you want? s $5, m 7$, l $10, xl $14')
    add_pep = input('Would you like pepperoni? Y or N')
    extra_cheese = input("Would you like extra cheese? Y or N")

    bill = 0
    if size == 's':
        bill += 5
    elif size == 'm':
        bill += 7
    elif size == 'l':
        bill += 10
    else:
        bill += 14

    if add_pep == 'y':
        if size == 's':
            bill += 2
        else:
            bill += 3

    if extra_cheese == 'y':
        bill += 1

    print(f"Your final bill is {bill}")

pizza_order()

def love_calc():
    print('Welcome to the Love Calculator')
    name1 = input('What is your name?')
    name2 = input('What is their name?')

    string = name1 + name2
    lower_case = string.lower()
    t = lower_case.count('t')
    r = lower_case.count('r')
    u = lower_case.count('u')
    e = lower_case.count('e')
    true = t + r + u + e

    l = lower_case.count('l')
    o = lower_case.count('o')
    v = lower_case.count('v')
    e = lower_case.count('e')
    love = l + o + v + e
    love_score = int(str(true) + str(love))
    if (love_score < 10) or (love_score > 90):
        print(f"Your love score is {love_score}, you go together like coke and mentos.")
    elif (love_score >= 40) or (love_score <= 50):
        print(f"Your love score is {love_score}, you are okay together.")
    else:
        print(f'your score is {love_score}')

love_calc()


import  numpy as np

# 传入一个数组，是所有个体所选择所有特征的个数
def softmax(numberOfAllFeatureSelect):
    # 转化为array类型
    numSelect = np.asarray(numberOfAllFeatureSelect)
    # 得到平均数
    meanNum = numSelect.mean()
    # 计算方差
    numSelect = meanNum - numSelect
    #   均差 由 sigma表示
    sigma = np.power(numSelect,2).sum()
    sigma = sigma/len(numSelect)
    # 计算 softmax后的值
    # 指数
    exponent = -(numSelect - meanNum)/sigma
    Wij = np.exp(exponent)
    Wij = 1/(1 + Wij)
    return Wij


import requests
import json
import sys
import win32com.client

class Post:
    def post(self):

        Bigname = list1[0]
        url = "https://open.feishu.cn/open-apis/wiki/v2/spaces/7188039318182002689/nodes"  # 知识空间的id  需要在一开始就固定好
        payload = json.dumps({
            "node_type": "origin",
            "obj_type": "doc",
            "origin_node_token": "",
            "parent_node_token": "",  # 创建大节点的，不需要token   后续字节点需要用到token
            "title": PojName
        })

        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer u-08wSadwft2SbcIeXE_WkbH055I2A05QFra00l4Uay1kG'  # token随时会变化
        }

        response = requests.request("POST", url, headers=headers, data=payload)

        m = response.json()
        global node_token
        node_token = m['data']['node']['node_token']
        print(node_token)  # 将创建好的大节点放入excel中（模板中吗？） 可以

class easyExcel:

    def __init__(self, filename=None):  # 打开文件或者新建文件（如果不存在的话）
        self.xlApp = win32com.client.Dispatch('Excel.Application')
        if filename:
            self.filename = filename
            self.xlBook = self.xlApp.Workbooks.Open(filename)
        else:
            self.xlBook = self.xlApp.Workbooks.Add()
            self.filename = ''

    def save(self, newfilename=None):  # 保存文件
        if newfilename:
            self.filename = newfilename
            self.xlBook.SaveAs(newfilename)
        else:
            self.xlBook.Save()

    def close(self):  # 关闭文件
        self.xlBook.Close(SaveChanges=0)
        del self.xlApp

    def setCell(self, sheet, row, col, value):  # 设置单元格的数据
        "set value of one cell"
        sht = self.xlBook.Worksheets(sheet)
        sht.Cells(row, col).Value = value

    # 下面是一些测试代码。
    def GetToken(self):
        print()

if __name__ == "__main__":

    list1 = sys.argv[1].split('>')
    #list1[2]
    PojName=list1[0]
    ExcelPath = list1[1]
    xls = easyExcel(r''+ExcelPath)
    xls.setCell('sheet1', 1, 3,node_token)
    print("*******beginsetCellformat********")
    xls.save()
    xls.close()


import requests
import json
import mongo

class Spider(object):
    def __init__(self):
        conn = mongo.get_mongo_db_client(
          mongo_url="mongodb://127.0.0.1:27017",
          max_pool_size=20
        )
        self.url = "https://perromart.com.sg/search?q=*&type=product&options%5Bprefix%5D=last&view=json"
        self.db = conn['perromart']
        self.start = False
        self.current_page = 0
        self.page_size = 10
        self.page_count = 0
        self.data_count = 0

    def getRawData(self):
        self.current_page += 1
        data = requests.get(self.url + "&page=" + str(self.current_page)).text
        data = json.loads(data)
        self.data_count = data['results_count']
        self.page_count = int(self.data_count / 10)
        if self.data_count % 10 != 0:
            self.page_count += 1
        return data['results']

    def run(self):
        while True:
            if self.current_page == self.page_count and self.start:
                print("Done")
                break
            self.start = True
            products = self.getRawData()
            for product in products:
                price = product['price']
                price = float(price.replace("$", ""))
                compare_at_price = product['compare_at_price']
                compare_at_price = float(compare_at_price.replace("$", ""))
                product['price'] = price
                product['compare_at_price'] = compare_at_price
                self.db['product'].insert_one(product)
            print("Current Page: " + str(self.current_page))

s = Spider()
s.run()


class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        start = intervals[0][0]
        end = intervals[0][1]

        out = []
        cur = 0

        while cur < len(intervals):
            if len(out) == 0 and cur == (len(intervals) - 1):
                out.append([start, intervals[cur][1]])
                continue
            if intervals[cur] == [start, end] and cur is (len(intervals) - 1):
                out.append([start, end])
                cur += 1
                continue
            if intervals[cur] == [start, end]:
                cur += 1
                continue
            if intervals[cur][0] is end or intervals[cur][0] is start:
                end = intervals[cur][1]
                out.append([start, end])
                cur += 1
                continue
            if intervals[cur][0] > end:
                out.append([start, end])
                start = intervals[cur][0]
                end = intervals[cur][1]
            else:
                end = intervals[cur][1]
                cur += 1

        temp = []
        for i in out:
            if i not in temp:
                temp.append(i)
            else:
                continue
        out = temp
        return out

    # https://www.youtube.com/watch?v=44H3cEC2fFM
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        # O(nLogn)
        intervals.sort(key = lambda i : i[0])
        output = [intervals[0]]

        for start, end in intervals[1:]:
            lastEnd = output[-1][1]

            if start <= lastEnd:
                output[-1][1] = max(lastEnd, end)
            else:
                out.append([start, end])
        return output


from . import *
from flask import jsonify, request
import requests

class GetClassesController(AppDevController):

  def get_path(self):
    return '/getClasses'

  def get_methods(self):
    return ['GET']

  def get_subjects(self):
    r = requests.get("https://classes.cornell.edu/api/2.0/config/subjects.json?roster=FA18")
    json = r.json()
    data = json['data']
    subjects = data['subjects']
    acc = []
    for subj in subjects:
       acc.append(subj["value"])
    return acc

  def get_class_roster(self,subjects):
    acc =[]
    for subject in subjects:
      try:
        r = requests.get("https://classes.cornell.edu/api/2.0/search/classes.json?roster=FA18&subject="+subject)
        json = r.json()
        data = json["data"]
        classes = data["classes"]
        for cla in classes:
          cname = cla["subject"]+" " + cla["catalogNbr"]
          title = cla["titleLong"]
          description = cla["description"]
          dist = cla["catalogDistr"]
          try:
            firstname = cla["enrollGroups"][0]["classSections"][0]["meetings"][0]["instructors"][0]["firstName"]
            lastname = cla["enrollGroups"][0]["classSections"][0]["meetings"][0]["instructors"][0]["lastName"]
            profname = firstname + " " + lastname
          except Exception as e:
              profname = ""
          acc.append({"class":cname,"title":title,"description":description,"dist":dist,"prof":profname})
      except Exception as e:
        acc=acc
    return acc

  def get_class_for_dist(self,classes,dist):
    acc =[]
    for cl in classes:
        if(cl["dist"]!=None and dist in cl["dist"]):
            acc.append(cl)
    return acc

  def in_list(self,lst,name):
    for cl in lst:
      if cl["class"].lower() == name.lower():
        return True
    return False

  def get_4000(self,classes):
    acc =[]
    for cl in classes:
      if("CS 4" in cl["class"] or "CS 5" in cl["class"]):
        acc.append(cl)
    return acc

  def content(self, **kwargs):
    classes= self.get_class_roster(self.get_subjects())
    major_name = request.args.get('major')
    major_name = major_name.lower().strip().replace(' ','')
    mqr = self.get_class_for_dist(classes,"MQR")
    pbs = self.get_class_for_dist(classes,"PBS")
    sba = self.get_class_for_dist(classes,"SBA-AS")
    la = self.get_class_for_dist(classes,"LA-AS")
    kcm = self.get_class_for_dist(classes,"KCM-AS")
    ha = self.get_class_for_dist(classes,"HA-AS")
    ca = self.get_class_for_dist(classes,"CA-AS")
    fourT = self.get_4000(classes)
    classes_taken = request.args.get('classes_taken').split(",")
    json = {"completed":[],"incomplete":[]}
    reqs = requirements_dao.get_major_requirements(major_name)
    reqs = [requirements_dao.serialize_reqs(req) for req in reqs]
    for cla in classes_taken:
      found = False
      class_name = cla.lower().strip().replace(' ','')
      space = cla.strip().find(" ")
      class_code = cla[:space]
      class_number = int(cla[space + 1:])
      for req in reqs:
        if(not found):
          name = req["distribution_name"]
          req_class = req["req_class"]
          possible_classes = req_class.split(",")
          req_level = req["class_level"]
          for pc in possible_classes:
            if(pc.lower().strip().replace(' ','') == class_name):
              json["completed"].append({"requirement":name,"class_taken":cla.upper()})
              reqs.remove(req)
              found = True
              break
      if(not found):
        for req in reqs:
          name = req["distribution_name"]
          req_class = req["req_class"]
          req_level = req["class_level"]
          if(class_code.lower()=="cs" and class_number>=req_level and (not found)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "MQR" and self.in_list(mqr,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "PBS" and self.in_list(pbs,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "SBA-AS" and self.in_list(sba,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "LA-AS" and self.in_list(la,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "KCM-AS" and self.in_list(kcm,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "HA-AS" and self.in_list(ha,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
          elif(name == "CA-AS" and self.in_list(ca,cla)):
            json["completed"].append({"requirement":name,"class_taken":cla.upper()})
            reqs.remove(req)
    for req in reqs:
      name = req["distribution_name"]
      req_class = req["req_class"]
      req_level = req["class_level"]
      if(len(req_class)>0):
        required_class = req_class.split(",")
        json["incomplete"].append({"requirement":name,"required_class":required_class, "suggested_classes":[]})
        reqs.remove(req)
      elif(name.replace(' ','') == "CS4000"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":fourT})
        reqs.remove(req)
      elif(name == "MQR"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":mqr})
        reqs.remove(req)
      elif(name == "PBS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":pbs})
        reqs.remove(req)
      elif(name == "SBA-AS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":sba})
        reqs.remove(req)
      elif(name == "LA-AS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":la})
        reqs.remove(req)
      elif(name == "KCM-AS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":kcm})
        reqs.remove(req)
      elif(name == "HA-AS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":ha})
        reqs.remove(req)
      elif(name == "CA-AS"):
        json["incomplete"].append({"requirement":name,"required_class":[], "suggested_classes":ca})
        reqs.remove(req)
    return json


"""Profile

Revision ID: f38f79d4b7d1
Revises: bb1f5e515779
Create Date: 2018-09-15 16:09:31.604206

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'f38f79d4b7d1'
down_revision = 'bb1f5e515779'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('users_comment_id_fkey', 'users', type_='foreignkey')
    op.drop_column('users', 'comment_id')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('users', sa.Column('comment_id', sa.INTEGER(), autoincrement=False, nullable=True))
    op.create_foreign_key('users_comment_id_fkey', 'users', 'comments', ['comment_id'], ['id'])
    # ### end Alembic commands ###


from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from pathlib import Path

from admin import router as admin_router

app = FastAPI(
    docs_url=None,
    redoc_url=None,
)

app.include_router(admin_router)

@app.get('/{image_name}')
async def get_image(image_name: str):
    filepath = f'originals/{image_name}'

    if not Path(filepath).is_file():
        raise HTTPException(status_code=404, detail='image not found')

    return FileResponse(
        path=filepath,
    )


"""Provides lenses for decoding hidden states into logits."""
import abc
import inspect
import json
import logging
from copy import deepcopy
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Dict, Generator, Optional, Union

import torch as th
from transformers import PreTrainedModel

from tuned_lens import load_artifacts
from tuned_lens.nn.unembed import Unembed

logger = logging.getLogger(__name__)

class Lens(abc.ABC, th.nn.Module):
    """Abstract base class for all Lens."""

    unembed: Unembed

    def __init__(self, unembed: Unembed):
        """Create a Lens.

        Args:
            unembed: The unembed operation to use.
        """
        super().__init__()

        self.unembed = unembed

    @abc.abstractmethod
    def transform_hidden(self, h: th.Tensor, idx: int) -> th.Tensor:
        """Convert a hidden state to the final hidden just before the unembedding.

        Args:
            h: The hidden state to convert.
            idx: The layer of the transformer these hidden states come from.
        """
        ...

    @abc.abstractmethod
    def forward(self, h: th.Tensor, idx: int) -> th.Tensor:
        """Decode hidden states into logits."""
        ...

class LogitLens(Lens):
    """Unembeds the residual stream into logits."""

    unembed: Unembed

    def __init__(
        self,
        unembed: Unembed,
    ):
        """Create a Logit Lens.

        Args:
            unembed: The unembed operation to use.
        """
        super().__init__(unembed)

    @classmethod
    def from_model(
        cls,
        model: PreTrainedModel,
    ) -> "LogitLens":
        """Create a LogitLens from a pretrained model.

        Args:
            model: A pretrained model from the transformers library you wish to inspect.
        """
        unembed = Unembed(model)
        return cls(unembed)

    def transform_hidden(self, h: th.Tensor, idx: int) -> th.Tensor:
        """For the LogitLens, this is the identity function."""
        del idx
        return h

    def forward(self, h: th.Tensor, idx: int) -> th.Tensor:
        """Decode a hidden state into logits.

        Args:
            h: The hidden state to decode.
            idx: the layer of the transformer these hidden states come from.
        """
        del idx
        return self.unembed.forward(h)

@dataclass
class TunedLensConfig:
    """A configuration for a TunedLens."""

    # The name of the base model this lens was tuned for.
    base_model_name_or_path: str
    # The hidden size of the base model.
    d_model: int
    # The number of layers in the base model.
    num_hidden_layers: int
    # whether to use a bias in the linear translators.
    bias: bool = True
    # The revision of the base model this lens was tuned for.
    base_model_revision: Optional[str] = None
    # The hash of the base's unembed model this lens was tuned for.
    unembed_hash: Optional[str] = None
    # The name of the lens type.
    lens_type: str = "linear_tuned_lens"

    def to_dict(self):
        """Convert this config to a dictionary."""
        return asdict(self)

    @classmethod
    def from_dict(cls, config_dict: Dict):
        """Create a config from a dictionary."""
        config_dict = deepcopy(config_dict)
        # Drop unrecognized config keys
        unrecognized = set(config_dict) - set(inspect.getfullargspec(cls).args)
        for key in unrecognized:
            logger.warning(f"Ignoring config key '{key}'")
            del config_dict[key]

        return cls(**config_dict)

class TunedLens(Lens):
    """A tuned lens for decoding hidden states into logits."""

    config: TunedLensConfig
    unembed: Unembed
    layer_translators: th.nn.ModuleList

    def __init__(
        self,
        unembed: Unembed,
        config: TunedLensConfig,
    ):
        """Create a TunedLens.

        Args:
            unembed: The unembed operation to use.
            config: The configuration for this lens.
        """
        super().__init__(unembed)

        self.config = config
        unembed_hash = unembed.unembedding_hash()
        config.unembed_hash = unembed_hash

        # The unembedding might be int8 if we're using bitsandbytes
        w = unembed.unembedding.weight
        dtype = w.dtype if th.is_floating_point(w) else th.float16

        translator = th.nn.Linear(
            config.d_model, config.d_model, bias=config.bias, dtype=dtype
        )
        translator.weight.data.zero_()
        translator.bias.data.zero_()

        # Don't include the final layer since it does not need a translator
        self.layer_translators = th.nn.ModuleList(
            [deepcopy(translator) for _ in range(self.config.num_hidden_layers)]
        )

    def __getitem__(self, item: int) -> th.nn.Module:
        """Get the probe module at the given index."""
        return self.layer_translators[item]

    def __iter__(self) -> Generator[th.nn.Module, None, None]:
        """Get iterator over the translators within the lens."""
        yield from self.layer_translators

    @classmethod
    def from_model(
        cls,
        model: PreTrainedModel,
        model_revision: Optional[str] = None,
        bias: bool = True,
    ) -> "TunedLens":
        """Create a lens from a pretrained model.

        Args:
            model: The model to create the lens from.
            model_revision: The git revision of the model to used.
            bias: Whether to use a bias in the linear translators.

        Returns:
            A TunedLens instance.
        """
        unembed = Unembed(model)
        config = TunedLensConfig(
            base_model_name_or_path=model.config.name_or_path,
            base_model_revision=model_revision,
            d_model=model.config.hidden_size,
            num_hidden_layers=model.config.num_hidden_layers,
            bias=bias,
        )

        return cls(unembed, config)

    @classmethod
    def from_model_and_pretrained(
        cls,
        model: PreTrainedModel,
        lens_resource_id: Optional[str] = None,
        **kwargs,
    ) -> "TunedLens":
        """Load a tuned lens from a folder or hugging face hub.

        Args:
            model: The model to create the lens from.
            lens_resource_id: The resource id of the lens to load. Defaults to the
                model's name_or_path.
            **kwargs: Additional arguments to pass to
                :func:`tuned_lens.load_artifacts.load_lens_artifacts` and
                `th.load <https://pytorch.org/docs/stable/generated/torch.load.html>`_.

        Returns:
            A TunedLens instance whose unembedding is derived from the given model
            and whose layer translators are loaded from the given resource id.
        """
        if lens_resource_id is None:
            lens_resource_id = model.config.name_or_path

        return cls.from_unembed_and_pretrained(
            Unembed(model), lens_resource_id, **kwargs
        )

    @classmethod
    def from_unembed_and_pretrained(
        cls,
        unembed: Unembed,
        lens_resource_id: str,
        **kwargs,
    ) -> "TunedLens":
        """Load a tuned lens from a folder or hugging face hub.

        Args:
            unembed: The unembed operation to use for the lens.
            lens_resource_id: The resource id of the lens to load.
            **kwargs: Additional arguments to pass to
                :func:`tuned_lens.load_artifacts.load_lens_artifacts` and
                `th.load <https://pytorch.org/docs/stable/generated/torch.load.html>`_.

        Returns:
            A TunedLens instance.
        """
        # Validate kwargs
        load_artifact_varnames = load_artifacts.load_lens_artifacts.__code__.co_varnames

        config_path, ckpt_path = load_artifacts.load_lens_artifacts(
            resource_id=lens_resource_id,
            **{k: v for k, v in kwargs.items() if k in load_artifact_varnames},
        )

        with open(config_path, "r") as f:
            config = TunedLensConfig.from_dict(json.load(f))

        # validate the unembed is the same as the one used to train the lens
        if config.unembed_hash and unembed.unembedding_hash() != config.unembed_hash:
            logger.warning(
                "The unembedding matrix hash does not match the lens' hash."
                "This lens may have been trained with a different unembedding."
            )

        # Create the lens
        lens = cls(unembed, config)

        th_load_kwargs = {
            **{k: v for k, v in kwargs.items() if k not in load_artifact_varnames}
        }
        # Load parameters
        state = th.load(ckpt_path, **th_load_kwargs)

        lens.layer_translators.load_state_dict(state)

        return lens

    def save(
        self,
        path: Union[Path, str],
        ckpt: str = "params.pt",
        config: str = "config.json",
    ) -> None:
        """Save the lens to a directory.

        Args:
            path : The path to the directory to save the lens to.
            ckpt : The name of the checkpoint file to save the parameters to.
            config : The name of the config file to save the config to.
        """
        path = Path(path)
        path.mkdir(exist_ok=True, parents=True)
        state_dict = self.layer_translators.state_dict()

        th.save(state_dict, path / ckpt)
        with open(path / config, "w") as f:
            json.dump(self.config.to_dict(), f)

    def transform_hidden(self, h: th.Tensor, idx: int) -> th.Tensor:
        """Transform hidden state from layer `idx`."""
        # Note that we add the translator output residually, in contrast to the formula
        # in the paper. By parametrizing it this way we ensure that weight decay
        # regularizes the transform toward the identity, not the zero transformation.
        return h + self[idx](h)

    def forward(self, h: th.Tensor, idx: int) -> th.Tensor:
        """Transform and then decode the hidden states into logits."""
        h = self.transform_hidden(h, idx)
        return self.unembed.forward(h)

    def __len__(self) -> int:
        """Return the number of layer translators in the lens."""
        return len(self.layer_translators)

    @th.inference_mode()
    def generate(
        self,
        model: PreTrainedModel,
        layer: int,
        input_ids: th.Tensor,
        do_sample: bool = True,
        temp: float = 1.0,
        max_new_tokens: int = 100,
    ) -> th.Tensor:
        """Generate from the tuned lens at the given layer.

        Args:
            model: The base model the generate from. Usually the model this lens trained
                on.
            layer: The layer to generate from.
            input_ids: (batch x prompt_len) The input ids to generate from.
            do_sample: Whether to use sampling or greedy decoding.
            temp: The temperature to use for sampling.
            max_new_tokens: The maximum number of tokens to generate.

        Returns:
            The prompt concatenated with the newly generated tokens.
        """
        eos_token = model.generation_config.eos_token_id

        tokens = input_ids
        if tokens.ndim == 1:
            tokens = tokens.unsqueeze(0)
        batch, prompt_len = tokens.shape
        del prompt_len
        past_key_values = None
        done = th.zeros(batch, dtype=th.bool)

        for _ in range(max_new_tokens):
            output = model(
                input_ids=tokens,
                output_hidden_states=True,
                use_cache=True,
                past_key_values=past_key_values,
            )
            past_key_values = output.past_key_values
            hidden = output.hidden_states[layer]
            new_hidden = hidden[:, -1, :]
            new_logits = self.forward(new_hidden, layer)
            if do_sample:
                new_logits = new_logits / temp
                probs = new_logits.softmax(dim=-1)
                new_tokens = th.multinomial(probs, num_samples=1)
            else:
                new_tokens = new_logits.argmax(dim=-1, keepdim=True)

            # Once a sequence has generated an EOS token, it should not generate any
            # other tokens.
            done = done | (new_tokens == eos_token)
            new_tokens = new_tokens.masked_fill(done, eos_token)
            tokens = th.cat([tokens, new_tokens], dim=-1)
            # Halt generation if all sequences have generated an EOS token.
            if done.all():
                break

        return tokens


"""
    Himanshu Gwalani
    2017ucp1356
"""
from core.color import *
global path,history,running_module,name,headless_browser,visible_browser
global previous

update_history  = lambda h:history.append(h)
update_previous = lambda:previous.append(running_module)

name = W+underline+"him's bot"+end
def add_module(p): global name;name = W+underline+"him's bot"+end+ W+" Module("+R+p+W+")"+end # Fuck lambda
def reset_name() : global name;name = W+underline+"him's bot"+end

path             = None
running_module   = False
headless_browser = False
visible_browser  = False
previous   = []
history    = []


from __future__ import annotations

from asyncio import Lock, iscoroutinefunction
from contextlib import AbstractAsyncContextManager
from types import TracebackType
from typing import (
    Any,
    AsyncContextManager,
    Awaitable,
    Callable,
    Generic,
    Optional,
    ParamSpec,
    Type,
    TypeVar,
)

_V = TypeVar("_V")
_L = TypeVar("_L", bound=AsyncContextManager[Any])

class CustomAsyncLocked(AbstractAsyncContextManager[_V], Generic[_V, _L]):
    """
    Locks any reference using the provided lock.
    """

    def __init__(self, val: _V, *, lock: _L) -> None:
        self._val = val
        self._lock = lock

    async def replace(self, val: _V) -> _V:
        """
        Replaces the reference in a concurrent safe way.
        :returns: The old reference.
        """
        async with self._lock:
            last, self._val = self._val, val
        return last

    async def update(self, fn: Callable[[_V], _V | Awaitable[_V]]) -> _V:
        """
        Updates the reference using a provided callable.
        :returns: The old reference.
        """
        async with self._lock:
            if iscoroutinefunction(fn):
                ref = await fn(self._val)
            else:
                ref = fn(self._val)
            last, self._val = self._val, ref
        return last

    async def __aenter__(self) -> _V:
        await self._lock.__aenter__()
        return self._val

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        await self._lock.__aexit__(exc_type, exc_val, exc_tb)

class AsyncLocked(CustomAsyncLocked[_V, Lock]):
    """
    Implements :class:`pylocked.asyncio.CustomAsyncLocked` using :py:class:`asyncio.Lock`
    """

    def __init__(self, val: _V, *, lock: Optional[Lock] = None):
        """
        Initializes :class:`pylocked.asyncio.AsyncLocked`
        :param val: The reference to lock
        :param lock: If provided, :class:`pylocked.asyncio.AsyncLocked` will use it as the internal lock
        """
        super().__init__(val, lock=lock if lock else Lock())

_P = ParamSpec("_P")
_R = TypeVar("_R")

def custom_locked(
    f: Callable[_P, Awaitable[_R]], *, lock: _L
) -> Callable[_P, Awaitable[_R]]:
    locked_f = CustomAsyncLocked[Callable[_P, Awaitable[_R]], _L](f, lock=lock)
    """
    Decorator to lock functions
    """

    async def inner(*args: _P.args, **kwargs: _P.kwargs) -> _R:
        async with locked_f as unlocked_f:
            res = await unlocked_f(*args, **kwargs)
        return res

    return inner

def async_locked(
    f: Callable[_P, Awaitable[_R]], *, lock: Optional[Lock] = None
) -> Callable[_P, Awaitable[_R]]:
    return custom_locked(f, lock=lock if lock else Lock())

__all__ = [
    CustomAsyncLocked.__name__,
    AsyncLocked.__name__,
    custom_locked.__name__,
    async_locked.__name__,
]


import pygame
import random

# Initialize Pygame
pygame.init()

# Set the window size
size = (700, 500)
screen = pygame.display.set_mode(size)

# Set the title of the window
pygame.display.set_caption("Sort Visualizer")

# Create an empty list to hold the values
values = []

# Fill the list with random values
for i in range(100):
    values.append(random.randint(0, 100))

# Set the sorting algorithm
sorting_algorithm = "bubble"

# Run the sorting algorithm
if sorting_algorithm == "bubble":
    for i in range(len(values)):
        for j in range(len(values) - 1):
            if values[j] > values[j + 1]:
                values[j], values[j + 1] = values[j + 1], values[j]
                # Draw the current state of the list
                for k in range(len(values)):
                    pygame.draw.rect(screen, (255, 255, 255), (k * 7, 0, 7, values[k]))
                pygame.display.update()
                pygame.time.wait(10)

# Quit Pygame
pygame.quit()


from django.contrib import admin
from .models import Apartment, ApartmentImage

class ApartmentImageInline(admin.StackedInline):
    model = ApartmentImage
    list_display = ("image", )
    extra = 1
    min_num = 1
    max_num = 15

@admin.register(Apartment)
class ApartmentModel(admin.ModelAdmin):
    list_display = (
        "title",
        "image_tag",
        "for_sale",
        "for_rent",
        "bedrooms",
        "baths",
    )
    list_filter = (
        "for_sale",
        "for_rent",
        "bedrooms",
        "baths",
        "self_contained",
        "verified",
    )
    search_fields = (
        "title",
        "description",
        "location",
    )
    readonly_fields = (
        "total_rent_payment",
        "agent_fee",
        "image_tag",
    )
    inlines = [ApartmentImageInline]
    save_on_top = True


bl_info = {
	"name": "MMD tools helper",
	"author": "Hogarth-MMD",
	"version": (2, 4),
	"blender": (2, 79, 0),
	"location": "View3D > Tool Shelf > MMD Tools Helper",
	"description": "various mmd_tools helper scripts",
	"warning": "",
	"wiki_url": "",
	"category": "Object",
	}

import bpy

class MMDToolsHelperPanel(bpy.types.Panel):
	"""Creates the MMD Tools Helper Panel in a VIEW_3D TOOLS tab"""
	bl_label = "MMD Tools Helper"
	bl_idname = "OBJECT_PT_mmd_tools_helper"
	bl_space_type = "VIEW_3D"
	bl_region_type = "TOOLS"
	bl_category = "mmd_tools_helper"

	def draw(self, context):
		layout = self.layout
		row = layout.row()

from . import model
from . import mmd_view
from . import mmd_lamp_setup
from . import convert_to_blender_camera
from . import background_color_picker
from . import boneMaps_renamer
from . import replace_bones_renaming
from . import armature_diagnostic
from . import add_foot_leg_ik
from . import add_hand_arm_ik
from . import display_panel_groups
from . import toon_textures_to_node_editor_shader
from . import toon_modifier
from . import reverse_japanese_english
from . import miscellaneous_tools
from . import blender_bone_names_to_japanese_bone_names

import imp
imp.reload(model)
imp.reload(mmd_view)
imp.reload(mmd_lamp_setup)
imp.reload(convert_to_blender_camera)
imp.reload(background_color_picker)
imp.reload(boneMaps_renamer)
imp.reload(replace_bones_renaming)
imp.reload(armature_diagnostic)
imp.reload(add_foot_leg_ik)
imp.reload(add_hand_arm_ik)
imp.reload(display_panel_groups)
imp.reload(toon_textures_to_node_editor_shader)
imp.reload(toon_modifier)
imp.reload(reverse_japanese_english)
imp.reload(miscellaneous_tools)
imp.reload(blender_bone_names_to_japanese_bone_names)

def register():
	bpy.utils.register_module(__name__)

def unregister():
	bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
	register()


from data.color import munroecorpus
from ref import RefTask

import cairo
import colorsys
from collections import defaultdict
import numpy as np
import os

MIN_COUNT = 5
EXCLUDED = ["shit", "very"]

VAL_FRAC = 0.1
TEST_FRAC = 0.1

class ColorRefTask(RefTask):
    def __init__(self):
        n_features = 3
        super(ColorRefTask, self).__init__(n_features)
        train_corpus = munroecorpus.get_training_handles()
        val_corpus = munroecorpus.get_dev_handles()
        test_corpus = munroecorpus.get_test_handles()
        self.vocab = {"_": 0, "UNK": 1}
        self.reverse_vocab = {0: "_", 1: "UNK"}
        self.colors = {
            "train": [],
            "val": [],
            "test": []
        }
        self.names = {
            "train": [],
            "val": [],
            "test": []
        }
        self.reps = {
            "train": [],
            "val": [],
            "test": []
        }
        self.randoms = {
            "train": np.random.RandomState(0),
            "val": np.random.RandomState(0),
            "test": np.random.RandomState(0)
        }

        word_counts = defaultdict(lambda: 0)
        for name in train_corpus[0]:
            name = name.replace("-", " ")
            for word in name.split(" "):
                word_counts[word] += 1
        common_words = [w for w, c in word_counts.items() if c >= MIN_COUNT and
                w not in EXCLUDED]

        for word in common_words:
            index = len(self.vocab)
            self.vocab[word] = index
            self.reverse_vocab[index] = word
        self.lexicon = [[0]] + [[i] for i in range(2, len(self.vocab))]
        self.empty_desc = np.zeros(len(self.lexicon))
        self.empty_desc[0] = 1

        for name in train_corpus[0]:
            words = name.replace("-", " ").split(" ")
            rep = np.zeros(len(self.lexicon))
            out = []
            for i_l, l in enumerate(self.lexicon):
                if all(self.reverse_vocab[w] in words for w in l):
                    rep[i_l] = 1
                    out += l
            if len(out) == 0:
                continue
            assert rep.any()
            rep /= np.sum(rep)

            files = [c[name] for c in train_corpus]
            colors = np.array([munroecorpus.open_datafile(f) for f in files]).T
            to_val = int(len(colors) * (1 - VAL_FRAC - TEST_FRAC))
            to_test = int(len(colors) * (1 - TEST_FRAC))
            train_colors = colors[:to_val].copy()
            val_colors = colors[to_val:to_test].copy()
            test_colors = colors[to_test:].copy()
            for color in train_colors:
                self.colors["train"].append(color)
                self.names["train"].append(out)
                self.reps["train"].append(rep)
            for color in val_colors:
                self.colors["val"].append(color)
                self.names["val"].append(out)
                self.reps["val"].append(rep)
            for color in test_colors:
                self.colors["test"].append(color)
                self.names["test"].append(out)
                self.reps["test"].append(rep)

        for fold in ("train", "val", "test"):
            self.colors[fold] = np.asarray(self.colors[fold])
            self.colors[fold][:, 0] /= 360.
            self.colors[fold][:, 1:] /= 100.
            assert np.max(self.colors[fold]) <= 1

        self.image_counter = 0

    def reset_test(self):
        self.randoms["val"] = np.random.RandomState(0)
        self.randoms["test"] = np.random.RandomState(0)

    def get_pair(self, fold):
        colors = self.colors[fold]
        reps = self.reps[fold]
        i1, i2 = self.randoms[fold].randint(colors.shape[0], size=2)
        rep = reps[i1]
        return colors[i1, :], colors[i2, :], rep, None, None

    def visualize(self, state, agent):
        r1, g1, b1 = colorsys.hsv_to_rgb(*state.left)
        r1 = int(100 * r1)
        g1 = int(100 * g1)
        b1 = int(100 * b1)

        r2, g2, b2 = colorsys.hsv_to_rgb(*state.right)
        r2 = int(100 * r2)
        g2 = int(100 * g2)
        b2 = int(100 * b2)

        block1 = "" % (r1, g1, b1)
        block2 = "" % (r2, g2, b2)
        if agent == 0 and state.target == 1:
            block1, block2 = block2, block1
        #return block1 + " " + block2
        return block1

    def turk_visualize(self, state, agent, loc):
        data1 = np.zeros((200, 200, 4), dtype=np.uint8)
        surf1 = cairo.ImageSurface.create_for_data(data1, cairo.FORMAT_ARGB32, 200, 200)
        ctx1 = cairo.Context(surf1)
        rgb1 = colorsys.hsv_to_rgb(state.left[0], state.left[1], state.left[2])
        ctx1.set_source_rgb(*rgb1)
        ctx1.paint()
        ctx1.fill()

        data2 = np.zeros((200, 200, 4), dtype=np.uint8)
        surf2 = cairo.ImageSurface.create_for_data(data2, cairo.FORMAT_ARGB32, 200, 200)
        ctx2 = cairo.Context(surf2)
        rgb2 = colorsys.hsv_to_rgb(state.right[0], state.right[1], state.right[2])
        ctx2.set_source_rgb(*rgb2)
        ctx2.paint()
        ctx2.fill()

        if agent == 0 and state.target == 1:
            surf1, surf2 = surf2, surf1

        name1 = "%d_a.png" % self.image_counter
        name2 = "%d_b.png" % self.image_counter

        surf1.write_to_png(os.path.join(loc, name1))
        surf2.write_to_png(os.path.join(loc, name2))
        self.image_counter += 1

        return name1, name2

    def pp(self, indices):
        return " ".join([self.reverse_vocab[i] for i in indices])


class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        visited = set()
        def dfs(start):
            nonlocal visited
            visited.add(start)
            i,j = start
            neighs = []

            if i != 0 and grid[i - 1][j] == "1":
                neighs.append((i-1, j))
            if i != len(grid) - 1 and grid[i+1][j] == "1":
                neighs.append((i+1, j))
            if j != 0 and grid[i][j-1] == "1":
                neighs.append((i, j - 1))
            if j != len(grid[0]) - 1 and grid[i][j+1] == "1":
                neighs.append((i, j + 1))

            for neigh in neighs:
                if neigh not in visited:
                    dfs(neigh)

        res = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if (i,j) not in visited and grid[i][j] == "1":
                    dfs((i,j))
                    print()
                    res += 1
        return res


from pgzrun import *
WIDTH = 696
HEIGHT = 800

bg = Actor("bg.png")

start = Actor("start.png",[358,626])
pause = Actor("pause.png",[183,550])
change = Actor("change.png",[355,550])
unpause = Actor("unpause.png",[528,550])

def draw():
    bg.draw()

num = 1
def on_mouse_down(pos):
    if start.collidepoint(pos):
        music.play("0.mp3")
        bg.image = "bg1.png"
        sounds.button.play()
    elif pause.collidepoint(pos):
        music.pause()
        bg.image = "bg2.png"
        sounds.button.play()
    elif unpause.collidepoint(pos):
        music.unpause()
        bg.image = "bg3.png"
        sounds.button.play()
    elif change.collidepoint(pos):
        global num
        music.play(str(num) + ".mp3")
        num = num + 1
        if num > 4:
          num = 0
        bg.image = "bg4.png"
        sounds.button.play()
def on_mouse_up():
    bg.image = "bg1.png"

go()


import datetime
from typing import List
import pandas as pd

from MTMS import db_session
from MTMS.Models.courses import CourseUser
from MTMS.Models.users import Users
from MTMS.Models.courses import Course, Term, RoleInCourse

# Course

def add_course(args):
    if not_exist_termID(args['termID']):
        return (False, 'TermID:{} not existed'.format(args['termID']))
    if exist_course_in_term(courseNum=args['courseNum'], termID=args['termID']):
        return (False, 'Course existed,  {} with termID:{}'.format(args['courseNum'], args['termID']))
    new_course = Course(courseNum=args['courseNum'],
                        courseName=args['courseName'],
                        termID=args['termID'])
    for key, value in args.items():
        if key not in ['courseNum', 'courseName', 'termID']:
            temp_value = value
            exec(f"new_course.{key} = temp_value")
    if 'markerDeadLine' not in args:
        markerDeadLine = db_session.query(Term.defaultMarkerDeadLine).filter(
            Term.termID == args['termID']).one_or_none()
        if markerDeadLine:
            new_course.markerDeadLine = markerDeadLine[0]
    if 'tutorDeadLine' not in args:
        tutorDeadLine = db_session.query(Term.defaultTutorDeadLine).filter(Term.termID == args['termID']).one_or_none()
        if tutorDeadLine:
            new_course.tutorDeadLine = tutorDeadLine[0]

    db_session.add(new_course)
    db_session.commit()
    return (True, "append {} with termID:{} successfully".format(new_course.courseNum, new_course.termID))

def exist_course_in_term(courseNum, termID) -> bool:
    if db_session.query(Course).filter(Course.courseNum == courseNum, Course.termID == termID).one_or_none() is None:
        return False
    return True

def get_course_by_id(courseID):
    return db_session.query(Course).filter(Course.courseID == courseID).one_or_none()

def get_Allcourses():
    courses = db_session.query(Course).all()
    coourse_list = []
    for i in range(len(courses)):
        coourse_list.append(courses[i].serialize())
    return coourse_list

def get_course_by_term(termID):
    courses = db_session.query(Course).filter(Course.termID == termID).all()
    coourse_list = []
    for i in range(len(courses)):
        coourse_list.append(courses[i].serialize())
    return coourse_list

def get_simple_course_by_term(termID):
    courses: Course = db_session.query(Course).filter(Course.termID == termID).all()
    coourse_list = []
    for i in range(len(courses)):
        coourse_list.append(courses[i].serialize_simple())
    return coourse_list

def get_simple_course_by_term_and_position(termID, position):
    if position == 'tutor':
        courses: Course = db_session.query(Course).filter(Course.termID == termID, Course.needTutors).all()
    elif position == 'marker':
        courses: Course = db_session.query(Course).filter(Course.termID == termID, Course.needMarkers).all()
    elif position == 'all':
        courses: Course = db_session.query(Course).filter(Course.termID == termID).all()
    else:
        return False, 'Invalid position', 400
    coourse_list = []
    for i in range(len(courses)):
        coourse_list.append(courses[i].serialize_simple())
    return coourse_list

def get_simple_course_by_courseNum(termID, courseNum, position):
    if position == 'tutor':
        courses = db_session.query(Course).filter(Course.courseNum.like(f"%{courseNum}%"), Course.termID == termID,
                                                  Course.needTutors).all()
    elif position == 'marker':
        courses = db_session.query(Course).filter(Course.courseNum.like(f"%{courseNum}%"), Course.termID == termID,
                                                  Course.needMarkers).all()
    elif position == 'all':
        courses = db_session.query(Course).filter(Course.courseNum.like(f"%{courseNum}%"),
                                                  Course.termID == termID).all()
    else:
        return False, 'Invalid position', 400
    coourse_list = []
    for i in range(len(courses)):
        coourse_list.append(courses[i].serialize_simple())
    return coourse_list

def modify_course_info(info: dict, courseID):
    '''
        required parameter:
            :param courseNum
            :param termID

        not required, update parameter:
            courseName
            totalAvailableHours
            estimatedNumofStudents
            currentlyNumofStudents
            needTutors
            needMarkers
            numOfAssignments
            numOfLabsPerWeek
            numOfTutorialsPerWeek
            tutorResponsibility
            markerResponsibility
            canPerAssign

        eg input {'courseNum': 'cs123', 'termID': 74, 'courseName': 'software Eng', 'totalAvailableHours': 5.1}
        update courseName', totalAvailableHours
    '''
    try:
        course = get_course_by_id(courseID)
        if 'termID' in info and not_exist_termID(info['termID']):
            return (False, f"termID:{info['termID']} does not existed")
        if course is not None:
            course_filter = db_session.query(Course).filter(
                Course.courseID == courseID
            )
            for key, value in info.items():
                course_filter.update(
                    {key: value}
                )
            db_session.commit()
            db_session.refresh(course)
            return (True, f"update courseID:{courseID}({course.courseNum} - {course.term.termName}) successfully")
        else:
            return (False, f"courseID:{courseID} does not existed")
    except:
        return (False, "Unexpected Error")

def delete_Course(courseID):
    course = get_course_by_id(courseID)

    if course:
        courseNum = course.courseNum
        termName = course.term.termName
        db_session.delete(course)
        db_session.commit()
        return (True, f"delete courseID:{courseID}({courseNum} - {termName}) successfully", 200)
    else:
        return (False, f"courseID:{courseID} does not existed", 404)

# Term
def not_exist_termID(termID):
    if db_session.query(Term).filter(Term.termID == termID).one_or_none() is None:
        return True
    return False

def exist_termName(termName):
    if db_session.query(Term).filter(Term.termName == termName.strip()).one_or_none() is None:
        return False
    return True

def get_term_by_id(termID):
    return db_session.query(Term).filter(Term.termID == termID).one_or_none()

def delete_Term(termID):
    term = get_term_by_id(termID)
    if term:
        db_session.delete(term)
        db_session.commit()
        return True, f"delete termID:{termID} successfully", 200
    else:
        return False, f"termID:{termID} does not existed", 404

def get_Allterms():
    terms = db_session.query(Term).all()
    terms_list = []
    for i in range(len(terms)):
        terms_list.append(terms[i].serialize())
    return terms_list

# Enrolment (That is, the correspondence between each course and the user)
def add_CourseUser(courseID, userID, roleName, estimatedHours):
    try:
        # existence checking
        course = db_session.query(Course).filter(Course.courseID == courseID).first()
        user = db_session.query(Users).filter(Users.id == userID).first()
        if course is None and user is None:
            return False, f"course:{courseID} and user:{userID} does not existed", 404
        elif user is None:
            return False, "user:{} does not existed".format(userID), 404
        elif course is None:
            return False, "course:'{}' does not existed".format(courseID), 404
        role = get_RoleInCourse_by_name(roleName)
        if role is None:
            return False, f"role '{roleName}' does not existed", 404
        courseUser = db_session.query(CourseUser).filter(CourseUser.courseID == courseID,
                                                         CourseUser.userID == userID,
                                                         CourseUser.roleID == role.roleID).one_or_none()
        if courseUser and courseUser.isPublished:
            return False, f"{userID} has already enrolled in {course.courseNum} - {course.term.termName}", 400
        elif courseUser and not courseUser.isPublished:
            return False, f"You have approved {userID} as a {roleName} but have not published yet", 400

        # create new CourseUser
        course_user = CourseUser(
            courseID=courseID,
            userID=userID,
            roleID=role.roleID,
            isPublished=True,
            estimatedHours=estimatedHours if estimatedHours else None
        )
        db_session.add(course_user)
        db_session.commit()
        return True, "Successful Enrolment", 200
    except:
        return False, "Unexpected Error", 400

def modify_CourseUser(course, user: Users, role):
    try:
        courseUser: list[CourseUser] = db_session.query(CourseUser).filter(CourseUser.courseID == course.courseID,
                                                                           CourseUser.userID == user.id).all()
        # Delete
        for cu in courseUser:
            if cu.role.Name not in role:
                db_session.delete(cu)

        # Add
        for roleName in role:
            roleObj = get_RoleInCourse_by_name(roleName)
            if roleObj is None:
                db_session.rollback()
                return False, f"role '{roleName}' does not existed", 404
            if roleName in [cu.role.Name for cu in courseUser]:
                continue
            course_user = CourseUser(
                courseID=course.courseID,
                userID=user.id,
                roleID=roleObj.roleID,
                isPublished=True
            )
            db_session.add(course_user)
        db_session.commit()
        return True, "update role successfully", 200
    except:
        db_session.rollback()
        return False, "Unexpected Error", 400

def get_enrolment_role(courseID, userID):
    course_user: CourseUser = db_session.query(CourseUser).filter(CourseUser.courseID == courseID,
                                                                  CourseUser.userID == userID).one_or_none()
    if course_user is None:
        return None
    else:
        role: RoleInCourse = get_RoleInCourse_by_id(course_user.roleID)
        if role is None:
            return None
        else:
            return role.Name

def get_user_enrolment(userID):
    course_user = db_session.query(CourseUser).filter(CourseUser.courseID == Course.courseID,
                                                      CourseUser.isPublished == True).filter(
        CourseUser.userID == userID).all()
    result = []
    for cu in course_user:
        result.append({
            "userID": userID,
            "courseID": cu.courseID,
            "role": cu.role.Name,
            "courseNum": cu.course.courseName,
            "termName": cu.course.term.termName if cu.course.term else None,
            "termID": cu.course.termID,
            "courseName": cu.course.courseName,
        })
    return result

def get_user_enrolment_in_term(userID, termID):
    course_user = db_session.query(CourseUser).join(Course).filter(
        Course.termID == termID, CourseUser.userID == userID, CourseUser.isPublished == True).all()
    return course_user

def get_course_user_by_courseID_isPublish(courseID, isPublished):
    course_user = db_session.query(CourseUser).filter(CourseUser.courseID == courseID,
                                                      CourseUser.isPublished == isPublished).all()
    result = []
    for i in course_user:
        user_dict = i.user.profile_serialize()
        user_dict.update({"roleInCourse": i.role.Name})
        result.append(user_dict)
    return result

def get_course_user_with_public_information(courseID):
    course_user: List[CourseUser] = db_session.query(CourseUser).filter(CourseUser.courseID == courseID).all()
    result = []
    for i in course_user:
        if i.user is None:
            return False, "Enrollment Information Error", 400
        user_dict = i.user.profile_serialize()
        user_dict.update(
            {"roleInCourse": i.role.Name, "isPublished": i.isPublished, "estimatedHours": i.estimatedHours,
             "workingHours": [wh.serialize() for wh in i.WorkingHours]})
        result.append(user_dict)
    return True, result, 200

def get_course_user_by_roleInCourse(courseID, roleInCourseList: list):
    course_user = db_session.query(CourseUser).join(RoleInCourse).filter(CourseUser.courseID == courseID,
                                                                         CourseUser.isPublished == True,
                                                                         RoleInCourse.Name.in_(roleInCourseList)).all()
    return course_user

def delete_CourseUser(courseID, userID, roleName):
    course_user = db_session.query(CourseUser).join(RoleInCourse).filter(CourseUser.courseID == courseID,
                                                                         CourseUser.userID == userID,
                                                                         RoleInCourse.Name == roleName).one_or_none()
    if course_user is None:
        return False, "{} in CourseID: {}(role: {}) does not existed".format(userID, courseID, roleName), 404
    else:
        db_session.delete(course_user)
        db_session.commit()
        return True, "Delete {} in CourseID: {}(role: {}) successfully".format(userID, courseID, roleName), 200

def get_RoleInCourse_by_name(roleName):
    role = db_session.query(RoleInCourse).filter(RoleInCourse.Name == roleName).one_or_none()
    return role

def get_RoleInCourse_by_id(roleID):
    role = db_session.query(RoleInCourse).filter(RoleInCourse.roleID == roleID).one_or_none()
    return role

def get_termName_termID(termID):
    term = db_session.query(Term).filter(Term.termID == termID).first()
    return term.termName

def get_CourseBy_userID(userID, termID):
    course_user = db_session.query(CourseUser).filter(CourseUser.userID == userID, CourseUser.isPublished).all()
    result = []
    for i in course_user:
        if i.course.termID == termID:
            result.append(i.serialize())
    return result

def Load_Courses(termID, filestream):
    df = pd.read_excel(filestream)
    headers = df.columns.values.tolist()
    if 'courseNum' not in headers or 'courseName' not in headers:  # 未找到必传参数
        return False, "Missing required parameters"
    else:
        for i in range(len(headers) - 1, -1, -1):
            attr = headers[i]
            try:
                getattr(Course, attr)
                # setattr(Course, attr, row[attr])
            except:
                headers.remove(attr)
                df.drop(attr, axis=1, inplace=True)

        feedback = []
        for index, row in df.iterrows():
            course = db_session.query(Course).filter(Course.termID == termID, Course.courseNum == row['courseNum'])
            # course = db_session.query(Course).filter(Course.courseNum == row['courseNum'] and Course.termID == termID)
            if course.one_or_none() == None:
                course = Course(
                    courseNum=row['courseNum'],
                    courseName=row['courseName'],
                    termID=termID,
                )

                try:
                    feedback.append("Add course {} successfully".format(row['courseNum']))

                    for attr in headers:
                        # course.attr = row[attr]
                        attribute = attr  # 用于记录错误信息
                        if str(row[attr]).lower() == 'nan' or str(row[attr]).lower() == 'nat':
                            setattr(course, attr, None)
                        elif attr == 'courseNum' or attr == 'courseName' or attr == 'termID':
                            continue
                        elif attr == 'estimatedNumOfStudents' or attr == 'currentlyNumOfStudents' or attr == 'numOfAssignments' or attr == 'numOfLabsPerWeek' or attr == 'numOfTutorialsPerWeek':
                            if not isinstance(row[attr], float) and not isinstance(row[attr], int):
                                feedback.append(
                                    "Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                        row['courseNum'], attr, row[attr]))
                            else:
                                setattr(course, attr, int(row[attr]))
                        elif attr == 'tutorResponsibility' or attr == 'markerResponsibility' or attr == 'prerequisite':
                            if not isinstance(row[attr], str):
                                feedback.append(
                                    "Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                        row['courseNum'], attr, row[attr]))
                            else:
                                setattr(course, attr, row[attr])
                        elif attr == 'needTutors' or attr == 'needMarkers' or attr == 'canPreAssign':
                            if row[attr] == 'Y':
                                setattr(course, attr, True)
                            elif row[attr] == 'N':
                                setattr(course, attr, False)
                            else:
                                feedback.append(
                                    "Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                        row['courseNum'], attr, row[attr]))
                        elif attr == 'totalAvailableHours':
                            if not isinstance(row[attr], float) and not isinstance(row[attr], int):
                                feedback.append(
                                    "Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                        row['courseNum'], attr, row[attr]))
                            else:
                                setattr(course, attr, row[attr])
                        elif attr == 'markerDeadLine' or attr == 'tutorDeadLine':
                            if not isinstance(row[attr], datetime.datetime):
                                feedback.append(
                                    "Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                        row['courseNum'], attr, row[attr]))
                            else:
                                setattr(course, attr, row[attr])

                        else:
                            feedback.append("Update attribute {} failed, because `{}` has incorrect result `{}`".format(
                                row['courseNum'], attr, row[attr]))
                    db_session.add(course)

                except Exception as e:
                    feedback.append("Add course {} failed".format(row['courseNum']))
            else:
                feedback.append(
                    "Add course {} fail. {} already existed in this term".format(row['courseNum'], row['courseNum']))
        db_session.commit()
        return True, feedback
        # return []

def get_the_course_working_hour(user: Users, course_id, roleName: str, isPublished: bool):
    role: RoleInCourse = get_RoleInCourse_by_name(roleName.lower())
    if role is None:
        return False, "Role not found", 404
    course_user: CourseUser = db_session.query(CourseUser).filter(CourseUser.userID == user.id,
                                                                  CourseUser.isPublished == isPublished,
                                                                  CourseUser.roleID == role.roleID,
                                                                  CourseUser.courseID == course_id).one_or_none()
    if course_user is None:
        return False, "Enrollment Information not found", 404
    return True, course_user.serialize_with_working_hours(), 200

def get_available_course_by_term(term_id, roleName):
    term = get_term_by_id(term_id)
    role = get_RoleInCourse_by_name(roleName.lower())
    if term is None:
        return False, "Term not found", 404
    if role is None:
        return False, "Role not found", 404
    if role.Name == 'tutor':
        courses = db_session.query(Course).filter(Course.termID == term_id, Course.needTutors).all()
    elif role.Name == 'marker':
        courses = db_session.query(Course).filter(Course.termID == term_id, Course.needMarkers).all()
    else:
        return False, "Role not found", 404
    return True, [course.serialize() for course in courses if course.getCurrentPublishedAvailableHours() > 0], 200


import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib import gridspec

# 读取图片并显示
img = cv2.imread('images/fruit.png')
cv2.imshow('Fruit Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 理解 Image Shape
# 彩色图片的 shape 一般由三个数字组成:  height(# of rows), width(# of columns) 和 color
# planes (BGR)
height, width, channels = img.shape
print('Image height: {}, Width: {}, # of channels: {}'.format(height, width,
                                                              channels))

# 显示不同颜色平面( plane)
# OpenCV读取的方式是 BGR, 因此 channel 0 是蓝色, 1是绿色, 2是红色
fruit_blues = img[:, :, 0]
fruit_greens = img[:, :, 1]
fruit_reds = img[:, :, 2]

# 显示不同颜色平面
cv2.imshow('Blue Fruit', fruit_blues)
cv2.imshow('Green Fruit', fruit_greens)
cv2.imshow('Red Fruit', fruit_reds)
cv2.waitKey(0) & 0xff
cv2.destroyAllWindows()

# 通过单行数据检验颜色平面数值
# plot values for each color plane on a specific row
fig = plt.figure(figsize=(10, 4))
gs = gridspec.GridSpec(1, 2, width_ratios=[1, 1])

# original image
ax0 = plt.subplot(gs[0])
ax0.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax0.axhline(50, color='black')
ax0.axvline(100, color='k'), ax0.axvline(255, color='k')

# image slice
ax1 = plt.subplot(gs[1])
ax1.plot(fruit_blues[49, :], color='blue')
ax1.plot(fruit_greens[49, :], color='green')
ax1.plot(fruit_reds[49, :], color='red')
ax1.axvline(100, color='k', linewidth=2), ax1.axvline(255, color='k',
                                                      linewidth=2)

plt.suptitle('Examining Color Plane Values for a Single Row.')
plt.show()


"""
7. Učitajte s tipkovnice 2 niza znakova, svaki od tih nizova znakova
spremite u zasebnu varijablu. Ispišite indekse na kojima se pojavljuju
ista slova neovisno o veličini ('a' i 'A' tretirati jednako).
"""

a = "abcAA"; b = "AhChSJjsakA"

for i, (cA, cB) in enumerate(zip(a, b)): #zip enumerira do najkraćeg niza
    if cA.lower() == cB.lower():
        print(i)


def removeDuplicateLetters(s):
    sortedStr = ""
    answer = ""
    temp = sorted(s)
    for i in range(len(temp)):
        if temp[i] != temp[i - 1]:
            sortedStr += temp[i]
    for i in range(len(sortedStr)):
        answer += s[s.index(sortedStr[i])]
    return answer

print(removeDuplicateLetters("cbacdcbc"))


import OurLib
import colors
import os
import sys
# meta exercice

# function

# Disable
def blockPrint():
    sys.stdout = open(os.devnull, 'w')

# Restore
def enablePrint():
    sys.stdout = sys.__stdout__

def metaTry():

    # prequisite

    files = []
    arg = []

    # take the name of files
    for i in range(13):
        nums= f'{i:02}'
        files.append(f'epAir{nums}.py')

    # take our arg in the txt file
    f = open('arguments.txt', 'r')
    lines = f.readlines()

    for i in lines:
        arg.append(i.replace('\n', ''))

    f.close()
    # let's start our files

    for (i, j) in zip(files, arg):
        try:
            blockPrint()
            print(os.system(f'python3 {i} {j}'))
            enablePrint()
            print(colors.bcolors.OKGREEN, f"{i}: success", colors.bcolors.ENDC)
        except ValueError:
            print(colors.bcolors.FAIL, f"{i} : failure", colors.bcolors.ENDC)

metaTry()

# finished