from sympy import symbols, preorder_traversal, Float
import re
import sys
import subprocess
import math

def separate(somelist):
    imaginary = []
    real = []
    for expression in somelist:
        if 'i' in expression:
            if len(expression) > 2:
                imaginary.append(expression[:-2])
            elif len(expression) == 2:
                imaginary.append(str(-1))
            else:
                imaginary.append(str(1))
        else:
            real.append(expression)
    return real, imaginary

def transform(pretrans):
    newstring = ""
    for i in pretrans:
        if i == 'a':
            newstring += "(a*i)"
        elif i == 'b':
            newstring += "(b*i)"
        else:
            newstring += i
    return newstring

def angletransform(pretrans, oor):
    angle = 2 * math.pi / oor  # factor of rotation
    tangle = angle
    expressionlist = []
    for j in range(oor - 1):
        sinepart = str(math.sin(tangle))
        cospart = str(math.cos(tangle))
        newstring = ""
        for i in pretrans:
            if i == 'a':
                newstring += "(a*(" + cospart + "+i*" + sinepart + "))"
            elif i == 'b':
                newstring += "(b*(" + cospart + "+i*" + sinepart + "))"
            else:
                newstring += i
        expressionlist.append(newstring)
        print(newstring)
        tangle += angle
    return expressionlist

# a^4 = a(cos0+isin0)^4
# factor of rotation = 4
# angle = 2pi/4 = pi/2
# pi/2, pi, 3pi/2, 2pi

# what gets preserved during these sitautions and why?

def rewrite_imaginary(someList):
    for expression in someList:
        if 'i' in expression and expression[-1] != 'i':
            imagine = expression.split("i**")
            thenumber = int(imagine[1])
            if (thenumber - 3) % 4 == 0:
                if expression[0] == '-':
                    someList[someList.index(expression)] = imagine[0][1:] + "i"
                else:
                    addminus = '-'
                    addminus += imagine[0] + "i"
                    someList[someList.index(expression)] = addminus
            elif (thenumber - 1) % 4 == 0:
                someList[someList.index(expression)] = imagine[0] + "i"
            elif thenumber % 4 == 0:
                someList[someList.index(expression)] = imagine[0][0:-1]
            elif thenumber % 2 == 0:
                if expression[0] == '-':
                    someList[someList.index(expression)] = imagine[0][1:-1]
                else:
                    addminus = '-'
                    addminus += imagine[0][0:-1]
                    someList[someList.index(expression)] = addminus

def import_libraries(filename):
    f = open(filename, "w")
    f.write("import numpy as np\n")
    f.write("import matplotlib.pyplot as plt\n")
    f.write("import sys\n")
    f.close()

def Write_graph(somelist, filename, title):
    if len(somelist) <= 0:
        print("\nno " + title + " part\n")
        return
    title_ext = ""
    f = open(filename, "a")
    f.write("a = np.linspace(-10, 10, 100)\n")
    f.write("b = np.linspace(-10, 10, 100)\n")
    f.write("a, b = np.meshgrid(a, b)\n")
    f.write("z = ")
    sumstring = ""
    for i in somelist:
        sumstring += i
        sumstring += "+"
    sumstring = sumstring[:-1:]
    test = sympy.expand(sumstring)
    newstring = str(test)
    ex2 = test
    for a in preorder_traversal(ex2):
        if isinstance(a, Float):
            ex2 = ex2.subs(
                a, round(a, 7))

    ex2 = str(ex2)

    if ex2.strip() == "0":
        print("\nno " + title + " part\n")
        f.close()
        return
    newlist = ex2.split('+')
    if len(newlist) > 1:
        for i in range(len(newlist) - 1):
            f.write("(" + newlist[i] + ")")
            f.write('+')
            title_ext += (newlist[i] + "+")
        f.write("(" + newlist[-1] + ")\n")
        title_ext += newlist[-1]
    else:
        a = newlist[0]
        if a.isdigit():
            f.write(a + "+ (a-a)\n")
        else:
            f.write(newlist[0] + "\n")
        title_ext += newlist[0]
    f.write("fig = plt.figure(figsize=[12, 8])\n")
    f.write("fig.suptitle(" + "'" + title + ": " + title_ext + "'" + ")\n")
    f.write("ax = plt.axes(projection='3d')\n")
    f.write("ax.plot_surface(a, b, z)\n")
    f.close()

def instructions():
    print("\n -g to enter main function of program, no argument afterwards")
    print("Anything being multiplied must be separated by * EX: ab must be a*b")
    print("Can use a,b for polynomials, and imaginary numbers can be represented by i")
    print("You can select aspects of graph once graph is parsed")
    print("-h to print this message again\n")

def showplot(filename):
    f = open(filename, "a")
    f.write("plt.show()\n")
    subprocess.Popen(["python", filename])

def split(somestring):
    somestring = somestring.lower()
    try:
        ex = sympy.expand(somestring)
    except Exception as e:
        print("\ninvalid input, use -h command for clearer instructions")
        exit(1)

    ex = str(ex)
    # print(ex)
    ostring = ""
    for i in range(len(ex)):
        if ex[i] == '-' and i != 0:
            if ex[i - 1] != 'e':
                ostring += '+-'
            else:
                ostring += '-'
        else:
            ostring += ex[i]

    ostring = re.sub(r"\s+", "", ostring, flags=re.UNICODE)
    returnlist = ostring.split('+')
    return returnlist

def printmenu():
    print("\n[1] for original real part:")
    print("[2] for original imaginary part:")
    print("[3] for transformed real part:")
    print("[4] for transformed imaginary part:")
    print("[5] roots of unity rotation")
    print("[6] print menu")
    print("[q] to quit\n")

def rootsofunity(fraction):
    a_splitlist = angletransform(gfg_exp, int(fraction))
    x = input("enter state of rotation between 1 - " + str(int(fraction)) + ": ")
    while x != 'q':
        if x.isdigit() and (0 < int(x) <= int(fraction)):
            if int(x) == int(fraction):
                print("input is equivalent to original graph")
            else:
                anglegraph = split(a_splitlist[int(x) - 1])
                rewrite_imaginary(anglegraph)
                print(anglegraph)
                r_angle, i_angle = separate(anglegraph)
                import_libraries("myfile.py")
                Write_graph(r_angle, "myfile.py", "Real Rotated by a factor of " + x + "/" + fraction)
                showplot("myfile.py")

                import_libraries("other.py")
                Write_graph(i_angle, "other.py", "Imaginary Rotated by a factor of " + x + "/" + fraction)
                showplot("other.py")
        x = input("enter state of rotation between 1 - " + str(int(fraction)) + " (q to exit to menu): ")

def menuoptions():
    printmenu()
    condition = input("enter input: ")

    while condition != "q":
        if condition == "1":
            import_libraries("myfile.py")
            Write_graph(realist, "myfile.py", "og-real")
            showplot("myfile.py")
        elif condition == "2":
            import_libraries("myfile.py")
            Write_graph(imaginarylist, "myfile.py", "og-imaginary")
            showplot("myfile.py")
        elif condition == "3":
            import_libraries("myfile.py")
            Write_graph(t_realist, "myfile.py", "transformed-real")
            showplot("myfile.py")
        elif condition == "4":
            import_libraries("myfile.py")
            Write_graph(t_imaginarylist, "myfile.py", "transformed-imaginary")
            showplot("myfile.py")
        elif condition == "5":
            fraction = input("Select fraction of rotation: ")
            rootsofunity(fraction)
            printmenu()
        elif condition == "6":
            printmenu()
        elif condition == "q":
            exit(1)
        else:
            print("invalid input\n")
        condition = input("\nenter input: ")

x, y, z = symbols('a b i')

if len(sys.argv) >= 2:
    if sys.argv[1] == "-h":
        instructions()
        exit(1)
else:
    gfg_exp = input("Enter a expression: ")

splitlist = split(gfg_exp)

t_splitlist = split(transform(gfg_exp))
rewrite_imaginary(splitlist)
rewrite_imaginary(t_splitlist)
realist, imaginarylist = separate(splitlist)
t_realist, t_imaginarylist = separate(t_splitlist)

print("og-realpart: " + str(realist))
print("og-imaginarypart: " + str(imaginarylist))
print("transformed-realpart " + str(t_realist))
print("transformed-imaginarypart " + str(t_imaginarylist))

menuoptions()


import importlib
import numpy as np
import traceback
import sys
import vis_pygame as vis
import gzip, pickle
from datetime import datetime
import os
import getopt

# Class avatar is a wrapper for the agent with extra bits required
# for runnin the game
class Avatar:

    # Initialise avatar for an agent of a given player
    def __init__(self,agent,player):
        self.agent = agent
        self.player = player
        self.position = np.zeros((2)).astype('int')
        self.next_position = np.zeros((2)).astype('int')
        self.reset_for_new_game()
        self.reset_for_new_turn()

    # Reset the avatar variables for a new game
    def reset_for_new_game(self):
        self.size = 1
        self.alive = 1
        self.energy = 2.0
        self.turn = 0
        self.strawb_eats = 0
        self.enemy_eats = 0.0

    # Reset the avater variables for a new turn in a game
    def reset_for_new_turn(self):
        self.bounce = False
        self.attackers = list()
        self.attacks = list()
        self.next_position *= 0
        self.size = int(np.floor(np.log2(self.energy)))

    # Execute AgentFunction that maps percepts to actions
    def action(self, percepts):
        try:
            return self.agent.AgentFunction(percepts)
        except Exception as e:
            print("Error! Failed to execute AgentFunction from '%s.py'" % self.playerFile)
            traceback.print_exc()
            sys.exit(-1)

# Class player holds all the agents for a given player
class Player:

    def __init__(self, player, playerFile, nAgents):

        self.player = player
        self.nAgents = nAgents
        self.playerFile = playerFile

        # Import agent file as module
        try:
            self.exec = importlib.import_module(playerFile)
        except Exception as e:
            print("Error! Failed to load '%s.py'" % self.playerFile)
            traceback.print_exc()
            sys.exit(-1)

        if hasattr(self.exec, 'playerName'):
            self.name = self.exec.playerName
        else:
            self.name = playerFile

        # Create the initial population of agents by creating
        # new instance of the agent using provided MyCreature class
        agents = list()
        for n in range(self.nAgents):
            try:
                agent = self.exec.MyCreature()
            except Exception as e:
                print("Error! Failed to execute MyCreature() from '%s.py'" % self.playerFile)
                traceback.print_exc()
                sys.exit(-1)
            agents.append(agent)

        # Convert list of agents to list of avatars
        self.agents_to_avatars(agents)

    def reset_for_new_game(self):
        self.fitness = list()

        for avatar in self.avatars:
            avatar.reset_for_new_game()

    # Convert list of agents to list of avatars
    def agents_to_avatars(self, agents):
        self.avatars = list()
        self.stats = list()

        for agent in agents:
            avatar = Avatar(agent,player=self)
            self.avatars.append(avatar)
            self.stats.append(dict())

    # Get a new generation of agents
    def new_generation_agents(self):

        # Record game stats in the agent objects
        old_population = list()
        for avatar in self.avatars:
            agent = avatar.agent
            agent.alive = avatar.alive
            agent.turn = avatar.turn
            agent.size = avatar.size
            agent.energy = avatar.energy
            agent.strawb_eats = avatar.strawb_eats
            agent.enemy_eats = avatar.enemy_eats
            old_population.append(agent)

        sys.stdout.write("  %s avg_fitness: " % self.playerFile)
        sys.stdout.flush()

        # Get a new population of agents by calling
        # the provided newGeneration method
        try:
            (new_population, fitness) = self.exec.newGeneration(old_population)
            sys.stdout.write(" %.2e\n" % fitness)
            sys.stdout.flush()
            self.fitness.append(fitness)

        except Exception as e:
            print("Error! Failed to execute newGeneration() from '%s.py'" % self.playerFile)
            traceback.print_exc()
            sys.exit(-1)

        # Convert agents to avatars
        self.agents_to_avatars(new_population)

# Class that runs the entire game
class Game:

    # Initialises the game
    def __init__(self, gridSize, nTurns, nAgents, nWalls, nGames):
        self.rnd = np.random.RandomState()
        self.gridSize = gridSize
        self.nTurns = nTurns
        self.nAgents = nAgents
        self.nGames = nGames
        self.nPercepts = 75
        self.nActions = 7
        self.nFood = self.nAgents
        self.nWalls = nWalls

    def init_wall_map(self):
        # Create wall map - this stays constant for all games
        self.wall_map = np.zeros((self.gridSize, self.gridSize), dtype='int8')

        range_mid = self.gridSize / 2 - 0.5
        init_range_low = int(self.gridSize % 2)
        init_range_high = int(self.gridSize / 2)

        for n in range(int(self.nWalls/2)):
            while True:
                rand_offset = self.rnd.randint(init_range_low, init_range_high, size=(2)).astype('float')
                if self.gridSize % 2 == 0:
                    rand_offset += 0.5

                rand_flip = 2 * self.rnd.randint(0, 2, size=(2)) - 1

                rand_offset *= rand_flip

                position_wall_1 = np.array(
                    [int(range_mid + rand_offset[0]), int(range_mid + rand_offset[1])]).astype('int')
                position_wall_2 = np.array(
                    [int(range_mid - rand_offset[0]), int(range_mid - rand_offset[1])]).astype('int')

                x_w1 = position_wall_1[0]
                y_w1 = position_wall_1[1]
                x_w2 = position_wall_2[0]
                y_w2 = position_wall_2[1]

                if self.wall_map[x_w1, y_w1] != 0 or self.wall_map[x_w2, y_w2] != 0:
                    continue

                self.wall_map[x_w1, y_w1] = 1
                self.wall_map[x_w2, y_w2] = 1
                break

    # Create the new agent and food map - new for every epoch
    def init_agent_and_food_maps(self):
        self.agent_map = np.ndarray((self.gridSize, self.gridSize), dtype=Player)
        self.food_map = np.zeros((self.gridSize, self.gridSize), dtype='int8')

        range_mid = self.gridSize / 2 - 0.5
        init_range_low = int(self.gridSize % 2)
        init_range_high = int(self.gridSize / 2)

        for n in range(self.nAgents):
            while True:
                rand_offset = self.rnd.randint(init_range_low, init_range_high, size=(2)).astype('float')
                if self.gridSize % 2 == 0:
                    rand_offset += 0.5

                rand_flip = 2 * self.rnd.randint(0, 2, size=(2)) - 1

                rand_offset *= rand_flip

                position_player_1 = np.array([int(range_mid + rand_offset[0]), int(range_mid + rand_offset[1])]).astype('int')
                position_player_2 = np.array([int(range_mid - rand_offset[0]), int(range_mid - rand_offset[1])]).astype('int')

                x_p1 = position_player_1[0]
                y_p1 = position_player_1[1]
                x_p2 = position_player_2[0]
                y_p2 = position_player_2[1]

                if self.wall_map[x_p1,y_p1] != 0 or self.wall_map[x_p2,y_p2] != 0:
                    continue

                # Check that the agents are not positions too close by
                tryAgain = False
                for i in range(-1, 2):
                    for j in range(-1, 2):
                        n_x = (x_p1 + i) % self.gridSize
                        n_y = (y_p1 + j) % self.gridSize

                        if (self.agent_map[n_x, n_y] != None):
                            tryAgain = True
                            break

                        n_x = (x_p2 + i) % self.gridSize
                        n_y = (y_p2 + j) % self.gridSize

                        if (self.agent_map[n_x, n_y] != None):
                            tryAgain = True
                            break

                    if tryAgain:
                        break

                if not tryAgain:
                    break

            self.agent_map[x_p1, y_p1] = self.players[0].avatars[n]
            self.players[0].avatars[n].position = np.array([x_p1, y_p1])

            self.agent_map[x_p2, y_p2] = self.players[1].avatars[n]
            self.players[1].avatars[n].position = np.array([x_p2, y_p2])

        for n in range(self.nAgents):
            while True:
                rand_offset = self.rnd.randint(init_range_low, init_range_high, size=(2)).astype('float')
                if self.gridSize % 2 == 0:
                    rand_offset += 0.5

                rand_flip = 2 * self.rnd.randint(0, 2, size=(2)) - 1

                rand_offset *= rand_flip

                position_food_1 = np.array([int(range_mid + rand_offset[0]), int(range_mid + rand_offset[1])]).astype('int')
                position_food_2 = np.array([int(range_mid - rand_offset[0]), int(range_mid - rand_offset[1])]).astype('int')

                x_f1 = position_food_1[0]
                y_f1 = position_food_1[1]
                x_f2 = position_food_2[0]
                y_f2 = position_food_2[1]

                if self.wall_map[x_f1, y_f1] != 0 or self.wall_map[x_f2,y_f2] != 0:
                    continue

                if self.agent_map[x_f1,y_f1] != None or self.agent_map[x_f2,y_f2] != None:
                    continue

                self.food_map[x_f1,y_f1] = 1
                self.food_map[x_f2,y_f2] = 1
                break

    # Update the agent map base on positions of agent after a
    def update_agent_map(self):
        self.agent_map = np.ndarray((self.gridSize, self.gridSize), dtype=Player)

        for p in range(2):
            for avatar in self.players[p].avatars:
                if not avatar.alive:
                    continue

                x = avatar.position[0]
                y = avatar.position[1]

                self.agent_map[x,y]=avatar

    # Update the stats for the visualiser
    def update_vis_agents(self,creature_state):
        for p in range(2):
            for n in range(self.nAgents):
                i = n + p * self.nAgents
                avatar = self.players[p].avatars[n]

                creature_state[i, 0] = avatar.position[0]
                creature_state[i, 1] = avatar.position[1]
                creature_state[i, 2] = avatar.alive
                creature_state[i, 3] = p
                creature_state[i, 4] = avatar.size

    # Run the game
    def run(self,player1File, player2File,show_games, save_games, visResolution=(720,480), visSpeed='normal'):

        self.players = list()

        # Load player 1
        try:
            self.players.append(Player(0,player1File, self.nAgents))
        except Exception as e:
            print('Error! ' + str(e))
            sys.exit(-1)

        # Load player 2
        try:
            self.players.append(Player(1,player2File, self.nAgents))
        except Exception as e:
            print('Error! ' + str(e))
            sys.exit(-1)

        # Create the visualiser
        if len(show_games)>0:
            self.vis = vis.visualiser(speed=visSpeed,gridSize=self.gridSize, playerStrings=(self.players[0].name,self.players[1].name),
                                  resolution=visResolution)

        # Initialise agents on new grid
        self.init_wall_map()

        vis_walls = list()
        for x in range(self.gridSize):
            for y in range(self.gridSize):
                if self.wall_map[x, y] == 1:
                    vis_walls.append((x, y))

        # Play the game a number of times
        for game in range(1,self.nGames+1):

            sys.stdout.write("\nGame %3d/%d..." % (game, self.nGames))
            sys.stdout.flush()

            # Reset avatars for a new game
            for p in range(2):
                self.players[p].reset_for_new_game()

            #Initialise agents on new grid
            self.init_agent_and_food_maps()

            #self.comp_vis_state(creature_state, creature_prev_state)
            vis_agents = np.zeros((self.nAgents * 2, 5, self.nTurns + 1)).astype('int')
            vis_food = list()

            if game in show_games:
                self.vis.reset()

            # Play the game over a number of turns
            for turn in range(self.nTurns):

                food_array = list()
                for x in range(self.gridSize):
                    for y in range(self.gridSize):
                        if self.food_map[x, y] == 1:
                            food_array.append((x, y))
                vis_food.append(food_array)
                self.update_vis_agents(vis_agents[:,:,turn])

                if game in show_games:
                    self.vis.show(creature_state=vis_agents[:,:,turn],food_array=vis_food[turn],wall_array=vis_walls,game=game, turn=turn)

                perceptBlock = 5
                pBHalf = int(perceptBlock / 2)

                # Create new agent map based on actions
                new_agent_map = np.ndarray((self.gridSize,self.gridSize), dtype=object)

                # Get actions of the agents
                for p in range(2):
                    for avatar in self.players[p].avatars:

                        if not avatar.alive:
                            continue

                        avatar.turn = turn+1
                        avatar.reset_for_new_turn()

                        position = avatar.position

                        # Percepts
                        percepts = np.zeros((perceptBlock,perceptBlock,3))

                        # Add nearby agents to percepts
                        for i in range(-pBHalf,pBHalf):
                            for j in range(-pBHalf,pBHalf):
                                x = (position[0] + i)%self.gridSize
                                y = (position[1] + j)%self.gridSize

                                if self.food_map[x,y] != 0:
                                   percepts[pBHalf + i, pBHalf + j, 1] = self.food_map[x,y]

                                if self.wall_map[x,y] != 0:
                                    percepts[pBHalf + i, pBHalf + j, 2] = self.wall_map[x, y]

                                if i==0 and j==0:
                                    percepts[pBHalf, pBHalf,0] = avatar.size
                                    continue

                                other_agent = self.agent_map[ x, y]

                                if other_agent is not None:
                                    if other_agent.player.player == p:
                                        s = 1
                                    else:
                                        s = -1

                                    percepts[pBHalf+i,pBHalf+j,0] = s*other_agent.size

                        # Get action from agent
                        try:
                            action = np.argmax(avatar.action(percepts))
                        except Exception as e:
                            traceback.print_exc()
                            sys.exit(-1)

                        # Action 6 is a random movement
                        if action==6:
                            action = self.rnd.randint(0,4)

                        x = avatar.position[0]
                        y = avatar.position[1]

                        # Action 0 is move left
                        if action == 0:
                            x -= 1
                        # Action 1 is move up
                        elif action == 1:
                            y -= 1
                        # Action 2 is move right
                        elif action == 2:
                            x += 1
                        # Action 3 is move down
                        elif action == 3:
                            y += 1

                        # Action 4 is do nothing

                        x %= self.gridSize
                        y %= self.gridSize

                        # Action 5 is eat
                        if action==5 and self.food_map[x,y] != 0:
                            self.food_map[x, y] = 0
                            avatar.energy += 1
                            avatar.strawb_eats += 1

                        # Can't walk onto the wall
                        if self.wall_map[x,y] != 0:
                            x = avatar.position[0]
                            y = avatar.position[1]

                        if new_agent_map[x,y] is None:
                            new_agent_map[x,y] = list()

                        new_agent_map[x,y].append(avatar)
                        avatar.next_position[0]= x
                        avatar.next_position[1]= y

                # Check for agents bouncing (going into field occupied by other agents)
                for x in range(self.gridSize):
                    for y in range(self.gridSize):
                        if new_agent_map[x,y] is not None:
                            if len(new_agent_map[x,y])>1 or self.agent_map[x, y] is not None:
                               for avatar in new_agent_map[x,y]:
                                   avatar.bounce = True

                # Check for attacks
                for p in range(2):
                    for avatar in self.players[p].avatars:
                        if not avatar.alive:
                            continue

                        x = avatar.position[0]
                        y = avatar.position[1]
                        if new_agent_map[x,y] is not None:
                            for other_avatar in new_agent_map[x,y]:
                                if other_avatar != avatar:
                                    avatar.attackers.append(other_avatar)
                                    other_avatar.attacks.append(avatar)

                # Resolve attacks
                dead_avatars = list()
                for p in range(2):
                    for n in range(self.nAgents):
                        avatar = self.players[p].avatars[n]
                        if not avatar.alive:
                            continue

                        attack_size = -avatar.energy
                        enemy_attackers = 0
                        for attacker in avatar.attackers:
                            if attacker.player == avatar.player:
                                attack_size -= attacker.energy
                            else:
                                enemy_attackers += 1
                                attack_size += attacker.energy

                        if attack_size > 0:
                            booty_share = float(avatar.energy)/float(enemy_attackers)
                            for attacker in avatar.attackers:
                                if attacker.player != avatar.player:
                                   attacker.energy += booty_share
                                   attacker.enemy_eats += booty_share

                            dead_avatars.append(avatar)

                # Mark any as not alive if successfully attacked by the enemy
                for avatar in dead_avatars:
                    avatar.alive = False

                # Move the agents that performed a legal movement
                for p in range(2):
                    for avatar in self.players[p].avatars:
                        if not avatar.alive:
                            continue

                        if not avatar.bounce:
                            avatar.position[0] = avatar.next_position[0]
                            avatar.position[1] = avatar.next_position[1]

                # Update the agent map according to new positions
                self.update_agent_map()

                # Check for winner
                gameOver = True
                for p in range(2):
                    for avatar in self.players[p].avatars:
                        if avatar.alive:
                           gameOver = False
                           break
                    if gameOver:
                        break
                if gameOver:
                    break

            food_array = list()
            for x in range(self.gridSize):
                for y in range(self.gridSize):
                    if self.food_map[x, y] == 1:
                        food_array.append((x, y))
            vis_food.append(food_array)
            self.update_vis_agents(vis_agents[:,:,turn+1])
            vis_agents = vis_agents[:,:,:turn+2]

            if game in show_games:
                self.vis.show(creature_state=vis_agents[:,:,turn+1],food_array=vis_food[turn+1],wall_array=vis_walls,game=game,turn=turn+1)

            survivorCount = np.zeros((2)).astype('int')
            for p in range(2):
                for avatar in self.players[p].avatars:
                    if avatar.alive:
                        survivorCount[p] += 1

            if survivorCount[0]>survivorCount[1]:
                sys.stdout.write('won by %s (blue) %d-%d\n' % (self.players[0].name,survivorCount[0],survivorCount[1]))
            elif survivorCount[1]>survivorCount[0]:
                sys.stdout.write('won by %s (red) %d-%d\n' % (self.players[1].name,survivorCount[1],survivorCount[0]))
            else:
                sys.stdout.write('drawn %d-%d\n' % (survivorCount[0],survivorCount[1]))
            sys.stdout.flush()

            for player in self.players:
                player.new_generation_agents()

            if game in save_games:
                #Save a game
                if not os.path.isdir("saved"):
                    os.mkdir('saved')

                now = datetime.now()
                # Month abbreviation, day and year
                saveStr = now.strftime("%b-%d-%Y-%H-%M-%S")
                saveStr += "-%s-vs-%s" % (self.players[0].name,self.players[1].name)
                saveStr += "-game%03d.pickle.gz" % game

                saveFile = os.path.join("saved", saveStr)

                with gzip.open(saveFile, 'w') as f:
                    pickle.dump((self.players[0].name,self.players[1].name,self.gridSize,vis_walls,vis_food,vis_agents), f)

    # Play visualisation of a saved game
    @staticmethod
    def load(loadGame,visResolution=(720,480), visSpeed='normal'):
        if not os.path.isfile(loadGame):
            print("Error! Saved game file '%s' not found." % loadGame)
            sys.exit(-1)

        # Open the game file and read data
        try:
            with gzip.open(loadGame) as f:
              (player1Name,player2Name,gridSize,vis_walls,vis_food,vis_agents) = pickle.load(f)
        except:
            print("Error! Failed to load %s." % loadGame)

        # Create an instance of visualiser
        v = vis.visualiser(speed=visSpeed, gridSize=gridSize, playerStrings=(player1Name, player2Name),
                       resolution=visResolution)

        # Show visualisation
        for t in range(vis_agents.shape[2]):
            v.show(creature_state=vis_agents[:, :, t], food_array=vis_food[t], wall_array=vis_walls,turn=t)

def main(argv):
    # Load the defaults
    from defaults import game_params

    # Check of arguments from command line
    try:
        opts, args = getopt.getopt(argv, "p:r:v:s:f:l:g:",["players=", "res=", "vis=", "save=", "fast=", "load=", "games="])
    except getopt.GetoptError:
        print("Error! Invalid argument.")
        sys.exit(2)

    # Process command line arguments
    loadGame = None
    for opt, arg in opts:
        if opt in ("-p", "--players"):
            players = arg.split(',')
            if len(players) != 2:
               print("Error! The -p/players= argument must be followed with two comma separated file name (no spaces).")
               sys.exit(-1)

            game_params['player1'] = players[0]
            game_params['player2'] = players[1]

        elif opt in ("-r", "--res"):
            res = arg.split('x')
            if len(res) != 2:
               print("Error! The -r/res= argument must be followed with <width>x<height> specifiction of resolution (no spaces).")
               sys.exit(-1)

            game_params['visResolution'] = (int(res[0]), int(res[1]))
        elif opt in ("-v", "--vis"):
            if arg[0] == '[' and arg[-1] != ']':
                print(
                    "Error! The -v/vis= argument must be followed with [...] giving the list of games to visualise (no spaces).")
                sys.exit(-1)
            game_params['show_games'] = list()
            if len(arg)>2:
                arg = arg[1:-1]
                games = arg.split(',')
                for g in games:
                    game_params['show_games'].append(int(g))

        elif opt in ("-s", "--save"):
            if arg[0] == '[' and arg[-1] != ']':
                print(
                    "Error! The -s/save= argument must be followed with [...] giving the list of games to save (no spaces).")
                sys.exit(-1)
            game_params['save_games'] = list()
            if len(arg)>2:
                arg = arg[1:-1]
                games = arg.split(',')
                for g in games:
                    game_params['save_games'].append(int(g))
        elif opt in ("-f", "--fast"):
            game_params['visSpeed'] = arg

        elif opt in ("-l", "--load"):
            loadGame = arg

        elif opt in ("-g", "--games"):
            game_params['nGames'] = int(arg)

    if game_params['visSpeed'] != 'normal' and game_params['visSpeed'] != 'fast' and game_params['visSpeed'] != 'slow':
        print("Error! Invalid setting '%s' for visualisation speed.  Valid choices are 'slow','normal',fast'" % game_params['visSpeed'])
        sys.exit(-1)

    if loadGame is None:
        # Create a new game and run it

        g = Game(gridSize=game_params['gridSize'],
                 nTurns=game_params['nTurns'],
                 nAgents=game_params['nAgents'],
                 nWalls=game_params['nWalls'],
                 nGames=game_params['nGames'])

        g.run(game_params['player1'],
              game_params['player2'],
              visResolution=game_params['visResolution'],
              visSpeed=game_params['visSpeed'],
              show_games=game_params['show_games'],
              save_games=game_params['save_games'])
    else:
        # Load a previously saved game
        Game.load(loadGame,visResolution=game_params['visResolution'],
               visSpeed=game_params['visSpeed'])

if __name__ == "__main__":
   main(sys.argv[1:])


from matplotlib import pyplot as plt
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import roc_curve, auc, roc_auc_score
import numpy as np

def multiclass_roc_auc_score(y_test, y_pred, target_list, multiclass=True, average="macro"):
    #returns roc_auc score and plots roc curve
    plt.figure(figsize=(6, 6))

    if multiclass:
        lb = LabelBinarizer()
        lb.fit(y_test)
        y_test = lb.transform(y_test)
        y_pred = lb.transform(y_pred)

        for (idx, c_label) in enumerate(target_list):
            fpr, tpr, thresholds = roc_curve(y_test[idx, :], y_pred[idx, :])
            plt.plot(fpr, tpr, label='%s (AUC:%0.2f)' % (c_label, auc(fpr, tpr)))

    else:
        fpr, tpr, thresholds = roc_curve(y_test, y_pred)
        plt.plot(fpr, tpr, label='AUC:%0.2f' % auc(fpr, tpr))

    plt.plot(fpr, fpr, 'b-', label='Random Guessing')
    plt.legend()
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.show()

    return roc_auc_score(y_test, y_pred, average=average)

def get_errors(x_test, test_probs, pred_probs, num_errors=4):
    """
    x_test is test dataset

    test_probs and pred_probs are respectively the one hot encoded test labes and
    the predicted probabilities vectors (arranged in a tensor) that the sofmtax gives at test time

    num_errors is how many misslabeled images to show
    """

    test_labels = np.argmax(test_probs, axis=1)
    pred_labels = np.argmax(pred_probs, axis=1)

    error_labels = (pred_labels - test_labels != 0)

    pred_probs_errors = pred_probs[error_labels]
    test_labels_errors = test_labels[error_labels]
    pred_labels_errors = pred_labels[error_labels]
    x_test_errors = x_test[error_labels]

    # Probabilities of the wrong predicted numbers
    y_pred_errors_prob = np.max(pred_probs_errors, axis=1)

    # Predicted probabilities of the true values in the error set
    true_prob_errors = np.diagonal(np.take(pred_probs_errors, test_labels_errors, axis=1))

    # Difference between the probability of the predicted label and the true label
    delta_pred_true_errors = y_pred_errors_prob - true_prob_errors

    # Sorted list of the delta prob errors
    sorted_delta_errors = np.argsort(delta_pred_true_errors)

    # Top errors
    most_important_errors = sorted_delta_errors[-num_errors:]

    return most_important_errors, pred_probs_errors, test_labels_errors, x_test_errors, pred_labels_errors

def display_errors(target_dict, x_test, test_labels, predictions, nrows=2, ncols=2):
    """
    target_dict is a dictionary that associates numbers from 0 to num classes to
    the name of the classes e.g.

    target_dict = {
        '0': class_0,
        '1': class_1,
     ...etc
    }
    """

    n = 0
    fig, ax = plt.subplots(nrows, ncols)
    fig.subplots_adjust(hspace=0.5, wspace=0.5)

    errors_index, \
    pred_probs_errors, \
    test_labels_errors, \
    img_errors, \
    pred_labels_errors = get_errors(x_test, test_labels, predictions)

    for row in range(nrows):
        for col in range(ncols):
            error = errors_index[n]
            ax[row, col].imshow(img_errors[error])
            ax[row, col].set_title("Predicted label: {}\nTrue label: {}".format(target_dict[str(pred_labels_errors[error])],
                                                                                target_dict[str(test_labels_errors[error])]))
            n += 1

    plt.show()


from tokenizers import ByteLevelBPETokenizer

tokenizer = ByteLevelBPETokenizer('vocab/vocab.json', 'vocab/merges.txt')

tokenizer.enable_truncation(max_length=512)

token_text = tokenizer.encode("<number> hdG jRGd JYGWj GdehGO GdGajhfjI, dG SjeG aj Tcd GdgjQhjf, jJSHH aj eYXe WdH YdGL JYGWj GdeNOQGJ aj eYXe HdOGf hSW hTQb hLfhH TQb GSjG.")
print(token_text)

print("done")


from DataBase import DB_movie,DB_proxy
from web import web
import time

class spider_master(object):
    def __init__(self):
        self.spider = None
        self.movie_db().clear()

    def movie_db(self):
        tmp=DB_movie()
        return tmp.operator
    def scrapy_main(self):

        self.scrapy_slave("http://www.80s.tw/movie/list/-----p",1)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/ju/list/----0--p",1)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/dm/list/----14--p",1)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/zy/list/----4--p",1)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/mv/list/-----p",2)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/video/list/-----p",2)
        time.sleep(30)
        self.scrapy_slave("http://www.80s.tw/course/list/-----p",2)

    def scrapy_slave(self,other_url,mon):
        self.spider = web(35)
        length=self.spider.get_page_length(other_url+str(1))
        print("len={0}".format(length))
        count = 0
        step = 5
        while True:

            self.spider.get_overall_info(other_url,count,count+step,mon)
            self.spider.get_downlink()
            self.update_data()
            self.spider.reset()
            count = count + step
            if count + step > length:
                break
            time.sleep(30)
        self.spider.get_overall_info(other_url,count,length,mon)
        self.spider.get_downlink()
        self.update_data()
        self.spider.reset()

    def update_data(self):
        res=self.spider.return_result()
        for one in res:
            #print(one)
            self.movie_db().insert(one)

if __name__ == '__main__':
    my_spider=spider_master()
    my_spider.scrapy_main()


import csv
import threading
import time

import cv2
import numpy as np
import os
import queue
import random

class CSI_Camera:

    def __init__(self, sensor_id=None):
        self.video_capture = None
        self.frame = None
        self.grabbed = False
        self.read_thread = None
        self.read_lock = threading.Lock()
        self.running = False
        self.sensorID = sensor_id
        self.isOpened = False
        self.sensorIsReady = False
        self.postprocess = None
        self.logObj = None
        self.writerObj = None

    def open(self, gstreamer_pipeline_string):
        try:
            self.video_capture = cv2.VideoCapture(
                gstreamer_pipeline_string, cv2.CAP_GSTREAMER
            )
            # Grab the first frame to start the video capturing
            self.grabbed, self.frame = self.video_capture.read()
            self.sensorIsReady = self.grabbed

        except:
            self.video_capture = None
            print("Unable to open camera")
            print("Pipeline: " + gstreamer_pipeline_string)

    def start(self):
        if self.running:
            print('Video capturing is already running')
            return None
        # create a thread to read the camera image
        if self.video_capture != None:
            self.running = True
            self.read_thread = threading.Thread(target=self.updateCamera)
            self.read_thread.start()
            self.isOpened = self.video_capture.isOpened()
        return self

    def stop(self):
        self.running = False
        # Kill the thread
        self.read_thread.join()
        self.read_thread = None
        if self.video_capture != None:
            self.video_capture.release()
            self.video_capture = None
        print(f'[OK]{self.sensorID} is closed')

    def updateCamera(self):
        while self.running:
            try:
                grabbed, frame = self.video_capture.read()
                with self.read_lock:
                    self.grabbed = grabbed
                    self.frame = frame
            except RuntimeError:
                print("Could not read image from camera")

    def read(self):
        with self.read_lock:
            time_stamp = time.time()
            frame = self.frame
            grabbed = self.grabbed
            self.frame = None
            self.grabbed = 0
        return grabbed, frame, time_stamp

    def release(self):
        if self.video_capture != None:
            self.video_capture.release()
            self.video_capture = None
        if self.read_thread != None:
            self.read_thread.join()

    def log(self, tempObj):
        filename = f"frame_{self.sensorID}_{tempObj.index}"
        if tempObj.data_is_ok:
            self.logger.writerow([
                tempObj.index,
                tempObj.time,
                filename
            ])
        else:
            self.logger.writerow([
                tempObj.index,
                tempObj.time,
                "",
            ])

    def logP(self, log_buffer):
        log_file = open(f'{os.getpid()}.csv', 'w', newline='')
        file_header = ["index", "time", "imageName"]
        logger = csv.writer(log_file)
        logger.writerow(file_header)
        while self.logObj.running.value or not log_buffer.empty():
            try:
                tempObj = log_buffer.get(0)
                filename = f"{tempObj.source}/{tempObj.source}_{tempObj.index}.jpg"
                logger.writerow([
                    tempObj.index,
                    tempObj.time,
                    filename if tempObj.data_is_ok else None
                ])
            except RuntimeError:
                print('[ERROR] Could not save an frame')
            except queue.Empty:
                pass
        else:
            log_file.close()
            os.rename(f'{os.getpid()}.csv', f'{tempObj.source}.csv')
            print(f"[OK] Process id: {self.logObj.name} has joined")

    def video_writer(self, data_buffer, cap_size):
        pWriter = cv2.VideoWriter(f'{os.getpid()}.mp4',
                        0x7634706d,
                        30,
                        cap_size,
                        )
        with open(f'{os.getpid()}.txt', 'w') as f:
            while self.writerObj.running.value or not data_buffer.empty():
                try:
                    if random.random() < .9:
                        tempObj = data_buffer.get(0)
                        if tempObj.data_is_ok:
                            pWriter.write(tempObj.data)
                            f.write(f'{tempObj.source}_{tempObj.index}\n')
                except RuntimeError:
                    print('[ERROR] Could not save an frame')
                except queue.Empty:
                    time.sleep(.01)
            else:
                pWriter.release()
                print(f"[OK] Process id: {os.getpid()} has joined")

    def image_writer(self, data_buffer):
        while self.writerObj.running.value or not data_buffer.empty():
            try:
                if random.random() < .9:
                    tempObj = data_buffer.get(0)
                    if tempObj.data_is_ok:
                        filename = f"{tempObj.source}/{tempObj.source}_{tempObj.index}.jpg"
                        cv2.imwrite(filename, tempObj.data)
            except RuntimeError:
                print('[ERROR] Could not save an frame')
            except queue.Empty:
                time.sleep(.01)
        else:
            print(f"[OK] process id: {os.getpid()} has joined")

"""
gstreamer_pipeline returns a GStreamer pipeline for capturing from the CSI camera
Flip the image by setting the flip_method (most common values: 0 and 2)
display_width and display_height determine the size of each camera pane in the window on the screen
Default 1920x1080
"""

def gstreamer_pipeline(
        sensor_id=0,
        capture_width=1920,
        capture_height=1080,
        display_width=1920,
        display_height=1080,
        framerate=30,
        flip_method=0,
):
    return (
            "nvarguscamerasrc sensor-id=%d ! "
            "video/x-raw(memory:NVMM), width=(int)%d, height=(int)%d, framerate=(fraction)%d/1 ! "
            "nvvidconv flip-method=%d ! "
            "video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
            "videoconvert ! "
            "video/x-raw, format=(string)BGR ! appsink"
            % (
                sensor_id,
                capture_width,
                capture_height,
                framerate,
                flip_method,
                display_width,
                display_height,
            )
    )

def run_cameras():
    window_title = "Dual CSI Cameras"
    left_camera = CSI_Camera()
    left_camera.open(
        gstreamer_pipeline(
            sensor_id=0,
            capture_width=1920,
            capture_height=1080,
            flip_method=0,
            display_width=960,
            display_height=540,
        )
    )
    left_camera.start()

    right_camera = CSI_Camera()
    right_camera.open(
        gstreamer_pipeline(
            sensor_id=1,
            capture_width=1920,
            capture_height=1080,
            flip_method=0,
            display_width=960,
            display_height=540,
        )
    )
    right_camera.start()

    if left_camera.video_capture.isOpened() and right_camera.video_capture.isOpened():

        cv2.namedWindow(window_title, cv2.WINDOW_AUTOSIZE)

        try:
            while True:
                _, left_image = left_camera.read()
                _, right_image = right_camera.read()
                # Use numpy to place images next to each other
                camera_images = np.hstack((left_image, right_image))
                # Check to see if the user closed the window
                # Under GTK+ (Jetson Default), WND_PROP_VISIBLE does not work correctly. Under Qt it does
                # GTK - Substitute WND_PROP_AUTOSIZE to detect if window has been closed by user
                if cv2.getWindowProperty(window_title, cv2.WND_PROP_AUTOSIZE) >= 0:
                    cv2.imshow(window_title, camera_images)
                else:
                    break

                # This also acts as
                keyCode = cv2.waitKey(30) & 0xFF
                # Stop the program on the ESC key
                if keyCode == 27:
                    break
        finally:

            left_camera.stop()
            left_camera.release()
            right_camera.stop()
            right_camera.release()
        cv2.destroyAllWindows()
    else:
        print("Error: Unable to open both cameras")
        left_camera.stop()
        left_camera.release()
        right_camera.stop()
        right_camera.release()

# if __name__ == "__main__":
#     run_cameras()


from dataclasses import dataclass
from typing import List, Optional

from neoclient import Service, base_url, get

@dataclass
class Repository:
    id: int
    name: str
    description: Optional[str]

@base_url("https://api.github.com/")
class GitHub(Service):
    @get("users/{user}/repos")
    def list_repos(self, user: str) -> List[Repository]:
        ...

service: GitHub = GitHub()

repositories: List[Repository] = service.list_repos("octocat")

repository: Repository
for repository in repositories:
    print(repository)


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

import torch
from torch import nn, Tensor

from abc import ABC, abstractmethod

from ctp.kernels import BaseKernel
from ctp.reformulators.util import AttentiveLinear

from typing import List, Optional

import logging

logger = logging.getLogger(__name__)

class BaseReformulator(ABC, nn.Module):
    def __init__(self):
        super().__init__()

    @abstractmethod
    def forward(self, rel: Tensor) -> List[Tensor]:
        raise NotImplementedError

    @abstractmethod
    def forward(self, rel: Tensor) -> List[Tensor]:
        raise NotImplementedError

    def prior(self, rel: Tensor) -> Optional[Tensor]:
        # batch_size = rel.shape[0]
        # res = torch.ones(batch_size, dtype=rel.dtype)
        res = None
        return res

class StaticReformulator(BaseReformulator):
    def __init__(self,
                 nb_hops: int,
                 embedding_size: int,
                 init_name: Optional[str] = "uniform",
                 lower_bound: float = -1.0,
                 upper_bound: float = 1.0):
        super().__init__()

        self.nb_hops = nb_hops
        self.embedding_size = embedding_size
        self.init_name = init_name

        self.lower_bound = lower_bound
        self.upper_bound = upper_bound

        def make_memory() -> Tensor:
            return self._param(1, self.embedding_size)
        self.memory_lst = nn.ParameterList([make_memory() for _ in range(self.nb_hops)])

    def _param(self, dim_in: int, dim_out: int, std: float = 1.0) -> Tensor:
        w = torch.zeros(dim_in, dim_out)

        if self.init_name in {"uniform"}:
            nn.init.uniform_(w, self.lower_bound, self.upper_bound)
        elif self.init_name in {"normal"}:
            nn.init.normal_(w, std=std)

        return nn.Parameter(w, requires_grad=True)

    def forward(self, rel: Tensor) -> List[Tensor]:
        batch_size = rel.shape[0]
        res = [memory.repeat(batch_size, 1) for memory in self.memory_lst]
        return res

class NTPReformulator(StaticReformulator):
    def __init__(self,
                 kernel: BaseKernel,
                 **kwargs):
        super().__init__(**kwargs)
        self.kernel = kernel
        self.head = self._param(1, self.embedding_size)

    def forward(self, rel: Tensor) -> List[Tensor]:
        batch_size = rel.shape[0]
        res = [memory.repeat(batch_size, 1) for memory in self.memory_lst]
        return res

    def prior(self, rel: Tensor) -> Tensor:
        res = self.kernel(rel, self.head)
        return res.view(-1)

class GNTPReformulator(BaseReformulator):
    def __init__(self,
                 kernel: BaseKernel,
                 head: Tensor,
                 body: List[Tensor]):
        super().__init__()
        self.kernel = kernel
        self.head = head
        self.body = body

    def forward(self, rel: Tensor) -> List[Tensor]:
        for e in self.body:
            # print(rel.shape, e.shape)
            assert rel.shape[0] == e.shape[0]
        return self.body

    def prior(self, rel: Tensor) -> Tensor:
        assert rel.shape[0] == self.head.shape[0]
        res = self.kernel(rel, self.head)
        # print('XXX', rel.shape, self.head.shape, res.shape)
        return res.view(-1)

class LinearReformulator(BaseReformulator):
    def __init__(self,
                 nb_hops: int,
                 embedding_size: int,
                 init_name: Optional[str] = "uniform",
                 lower_bound: float = -1.0,
                 upper_bound: float = 1.0):
        super().__init__()

        self.nb_hops = nb_hops
        self.embedding_size = embedding_size
        self.init_name = init_name

        self.lower_bound = lower_bound
        self.upper_bound = upper_bound

        def make_hop(std: float = 1.0) -> nn.Module:
            res = nn.Linear(embedding_size, embedding_size)

            if self.init_name in {"uniform"}:
                nn.init.uniform_(res.weight, self.lower_bound, self.upper_bound)
            elif self.init_name in {"normal"}:
                nn.init.normal_(res.weight, std=std)

            return res

        self.hops_lst = nn.ModuleList([make_hop() for _ in range(nb_hops)])

    def forward(self, rel: Tensor) -> List[Tensor]:
        res = [hop(rel) for hop in self.hops_lst]
        return res

class AttentiveReformulator(BaseReformulator):
    def __init__(self,
                 nb_hops: int,
                 embeddings: nn.Embedding,
                 init_name: Optional[str] = "uniform",
                 lower_bound: float = -1.0,
                 upper_bound: float = 1.0):
        super().__init__()

        self.nb_hops = nb_hops
        self.embeddings = embeddings
        self.init_name = init_name

        self.lower_bound = lower_bound
        self.upper_bound = upper_bound

        def make_hop(std: float = 1.0) -> nn.Module:
            res = AttentiveLinear(embeddings)

            if self.init_name in {"uniform"}:
                nn.init.uniform_(res.projection.weight, self.lower_bound, self.upper_bound)
            elif self.init_name in {"normal"}:
                nn.init.normal_(res.projection.weight, std=std)

            return res
        self.hops_lst = nn.ModuleList([make_hop() for _ in range(nb_hops)])

    def forward(self, rel: Tensor) -> List[Tensor]:
        res = [hop(rel) for hop in self.hops_lst]
        return res

class MemoryReformulator(BaseReformulator):

    class Memory(nn.Module):
        def __init__(self,
                     nb_hops: int,
                     nb_rules: int,
                     embedding_size: int,
                     init_name: Optional[str] = "uniform",
                     lower_bound: float = -1.0,
                     upper_bound: float = 1.0):
            super().__init__()
            self.nb_hops = nb_hops
            self.nb_rules = nb_rules
            self.embedding_size = embedding_size
            self.init_name = init_name

            self.lower_bound = lower_bound
            self.upper_bound = upper_bound

            def _param(dim_in: int, dim_out: int, std: float = 1.0) -> Tensor:
                w = torch.zeros(dim_in, dim_out)

                if self.init_name in {"uniform"}:
                    nn.init.uniform_(w, self.lower_bound, self.upper_bound)
                elif self.init_name in {"normal"}:
                    nn.init.normal_(w, std=std)

                return nn.Parameter(w, requires_grad=True)

            def make_memory() -> Tensor:
                return _param(self.nb_rules, self.embedding_size)

            self.memory = nn.ParameterList([make_memory() for _ in range(self.nb_hops)])

    def __init__(self,
                 memory: Memory):
        # Note: this init_name governs the attention weights over the memory, I think it's fine to keep it as it is
        super().__init__()
        self.memory = memory
        self.projection = nn.Linear(self.memory.embedding_size, self.memory.nb_rules)

    def forward(self, rel: Tensor) -> List[Tensor]:
        attn_logits = self.projection(rel)
        attn = torch.softmax(attn_logits, dim=1)
        res = [attn @ cell for cell in self.memory.memory]
        return res

class SymbolicReformulator(BaseReformulator):
    def __init__(self,
                 embeddings: nn.Embedding,
                 indices: Tensor):
        super().__init__()
        self.embeddings = embeddings
        self.indices = indices

    def forward(self, rel: Tensor) -> List[Tensor]:
        batch_size = rel.shape[0]
        # [I, E]
        res = self.embeddings(self.indices)
        nb_indices, embedding_size = res.shape[0], res.shape[1]
        # [B, I, E]
        res = res.view(1, nb_indices, embedding_size).repeat(batch_size, 1, 1)

        # res = list(torch.split(res, split_size_or_sections=1, dim=1))
        res = [a.view(res.shape[0], res.shape[2]) for a in torch.split(res, split_size_or_sections=1, dim=1)]
        return res


from aiounittest import AsyncTestCase
from aiounittest.mock import AsyncMockIterator
from unittest.mock import Mock

async def fetch_some_text(source):
    res = ''
    async for txt in source.paginate():
        res += txt
    return res

class MyAsyncMockIteratorTest(AsyncTestCase):

    async def test_add(self):
        source = Mock()
        mock_iter = AsyncMockIterator([
            'asdf', 'qwer', 'zxcv'
        ])
        source.paginate.return_value = mock_iter

        res = await fetch_some_text(source)
        self.assertEqual(res, 'asdfqwerzxcv')
        mock_iter.assertFullyConsumed()
        mock_iter.assertIterCount(3)


import os
from PIL import Image
import numpy as np

bs_dir = '/mnt/lustre/fnzhan/datasets/CVPR2022/night2day/'
sv_dir = bs_dir + 'split/test/'

im_dir = bs_dir + 'test/'

nms = os.listdir(im_dir)
# n = 0
for nm in nms:
    im_path = im_dir + nm
    im = Image.open(im_path)
    im = np.array(im)
    inp, gt = im[:, 0:256, :], im[:, 256:, :]
    inp, gt = Image.fromarray(inp), Image.fromarray(gt)
    inp.save(sv_dir + 'input/' + nm)
    gt.save(sv_dir + 'gt/' + nm)


import cv2 as cv

img =cv.imread('photos/dog.jpg')
img =cv.resize(img, (400,250))
cv.imshow('Dog', img)

gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
cv.imshow('Gray', gray)

#Simple Thresholding
threshold, thresh = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)
cv.imshow('Thresholded Simple', thresh)

#Simle thersholding Inversed
threshold, thresh_inv = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)
cv.imshow('Thresholded Simple-Inverse', thresh_inv)

#Adaptive Thresholding
adaptive_thres = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 3)
cv.imshow('Adaptive Threshold', adaptive_thres)

#Adaptive Thresholding Inversed
adaptive_thres_inv = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 11, 3)
cv.imshow('Adaptive Threshold-Inversed', adaptive_thres_inv)
cv.waitKey(0)


import pika
import json
import time
import os
import logging

import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
django.setup()

from users.models import User, Notification, NotificationInfo
from feedback.models import Playlist
from config import settings
from podcast.models import Podcast
from main.utils import authentication_log_format, rss_log_format

logger = logging.getLogger('elastic-logger')

def login_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        user = User.objects.get(username=data['username'])
        notification_info = NotificationInfo.objects.create(message=data['message'])
        Notification.objects.create(user = user, message = notification_info)
        log_data = authentication_log_format(user,data)
        logger.info(json.dumps(log_data))

    except Exception as error:
        log_data = authentication_log_format(user, data, error)
        logger.error(json.dumps(log_data))

def login_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='login')
    chanel.basic_consume(queue='login', on_message_callback=login_callback)

    chanel.start_consuming()

def register_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        user = User.objects.get(username=data['username'])
        notification_info = NotificationInfo.objects.create(message=data['message'])
        Notification.objects.create(user = user, message = notification_info)
        log_data = authentication_log_format(user,data)
        logger.info(json.dumps(log_data))
    except Exception as error:
        log_data = authentication_log_format(user, data, error)
        logger.error(json.dumps(log_data))

def register_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='register')
    chanel.basic_consume(queue='register', on_message_callback=login_callback)

    chanel.start_consuming()

def update_podcast_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        playlists = Podcast.objects.get(id=data['podcast']).playlist_set.all()
        for playlist in playlists:
                    notification = NotificationInfo.objects.create(message = data['message'])
                    user = User.objects.get(id=playlist.account.id)
                    Notification.objects.create(user = user, message = notification)
        log_data = rss_log_format(data)
        logger.info(json.dumps(log_data))
    except Exception as error:
        log_data = rss_log_format(data, error)
        logger.error(json.dumps(log_data))

def update_podcast_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='update_podcast')

    chanel.basic_consume(queue='update_podcast', on_message_callback=update_podcast_callback)

    chanel.start_consuming()


from PyQt6.QtWidgets import QApplication, QPushButton, QMainWindow, QVBoxLayout, QWidget, QLabel, QColorDialog, QHBoxLayout
from PyQt6.QtCore import QTimer
import sys
import glob
from time import sleep
import serial
import threading

def setInterval(func,time):
    e = threading.Event()
    while not e.wait(time):
        func()

def serial_ports():
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')

    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    return result

ser = serial.Serial(serial_ports()[0], 115200)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.currentData = []
        ser.write(bytearray([0xFF]))
        self.get_data()

        self.temp = QLabel("Температура воздуха: " + str(self.currentData[3]) + "°C")
        self.humidity = QLabel("Влажность воздуха: " + str(self.currentData[-3]) + "%")

        self.airLayout = QHBoxLayout()
        self.airLayout.addWidget(self.temp)
        self.airLayout.addWidget(self.humidity)

        self.pressure = QLabel("Давление воздуха: " + str(self.currentData[5]) + "hPa")
        self.soiltemp = QLabel("Температура почвы: " + str(self.currentData[9]) + "°C")

        self.soilLayout = QHBoxLayout()
        self.soilLayout.addWidget(self.pressure)
        self.soilLayout.addWidget(self.soiltemp)

        self.soilhumidity = QLabel("Влажость почвы: " + str(self.currentData[10]) + "%")
        self.light = QLabel("Интенсивность света: " + str(self.currentData[6]) + "Люкс")

        self.otherLayout = QHBoxLayout()
        self.otherLayout.addWidget(self.soilhumidity)
        self.otherLayout.addWidget(self.light)

        self.color = QColorDialog()

        self.submitColor = QPushButton("Задать цвет")
        self.submitColor.clicked.connect(self.onSubmitColor)

        self.signalButton = QPushButton("Включить сирену" if self.currentData[-6] == 0 else "Выключить сирену")
        self.signalButton.clicked.connect(self.onsignalButtonClick)

        self.windButton = QPushButton("Включить вентилятор" if self.currentData[-2] == 0 else "Выключить вентилятор")
        self.windButton.clicked.connect(self.onWindButtonClick)

        self.doorButton = QPushButton("Закрыть дверь" if self.currentData[-1] == 32 else "Открыть дверь")
        self.doorButton.clicked.connect(self.ondoorButtonClick)

        self.melodyButton = QPushButton("Включить мелодию")
        self.melodyButton.clicked.connect(self.onMelodyButtonClick)

        layout = QVBoxLayout()
        layout.addWidget(self.humidity)
        layout.addWidget(self.color)
        layout.addWidget(self.submitColor)
        layout.addWidget(self.signalButton)
        layout.addWidget(self.windButton)
        layout.addWidget(self.doorButton)
        layout.addWidget(self.melodyButton)

        container = QWidget()
        container.setLayout(layout)

        self.setWindowTitle("Умный дом")

        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.updateData)
        self.timer.start()

        self.setCentralWidget(container)

    def updateData(self):
        ser.write(bytearray([0xFF]))
        self.get_data()
        self.reloadSensors()

    def reloadSensors(self):
        self.humidity.setText("Влажность воздуха: " + str(self.currentData[-3]) + "%")

    def onSubmitColor(self):
        _currentColor = self.color.currentColor()
        _writeRGB = bytearray([0xA3])
        self.reloadSensors()

        _writeRGB.append(_currentColor.red())
        _writeRGB.append(_currentColor.green())
        _writeRGB.append(_currentColor.blue())

        ser.write(_writeRGB)
        self.get_data()
        self.color.show()

    def onsignalButtonClick(self):
        ser.write(bytearray([0xA0, 0x1]))
        self.get_data()
        self.reloadSensors()
        self.signalButton.setText("Включить сирену" if self.currentData[-6] == 0 else "Выключить сирену")

    def onWindButtonClick(self):
        ser.write(bytearray([0xA1, 0x1]))
        self.get_data()
        self.reloadSensors()
        self.windButton.setText("Включить вентилятор" if self.currentData[-2] == 0 else "Выключить вентилятор")

    def ondoorButtonClick(self):
        if (self.currentData[-1] == 32):
            ser.write(bytearray([0xA2, 0x96]))
            self.doorButton.setText("Открыть дверь")
        else:
            ser.write(bytearray([0xA2, 0x20]))
            self.doorButton.setText("Закрыть дверь")

        self.get_data()

    def onMelodyButtonClick(self):
        ser.write(bytearray([0xA6, 0x1]))

    def get_data (self):
        sleep(0.1)
        _currentData = str(ser.read_all())
        _currentData = _currentData[2:_currentData.find('\\r\\n')]
        if (_currentData!=''):
            currentDataList = list(map(float, _currentData.split('|')))
            self.currentData = currentDataList
            print(currentDataList)

app = QApplication(sys.argv)
window = MainWindow()

window.show()
sys.exit(app.exec())


#!/usr/bin/env python
"""Create a reduced image of the detector readings from a Mantid workspace.

This reduces the detector readings for each pixel by integrating in the time
dimension.

"""
from __future__ import print_function
from __future__ import division

import string

import mantid.simpleapi

import plotly
import plotly.offline
import plotly.graph_objs

import numpy as np

import scipy.stats

TOF_TEMPLATE = '''
<button id="plotly-slice-decrement" type="button">[-]</button>
<input id="plotly-slice-range" type="range"></input>
<button id="plotly-slice-increment" type="button">[+]</button>
<script>
(function() {
var graphDivs = document.getElementsByClassName('plotly-graph-div');
var graphDiv = graphDivs[0];
var index = 0;

function changeSlice() {
  for (var i=0; i<graphDiv.data.length; ++i) {
    graphDiv.data[i].visible = false;
  }

  graphDiv.data[index].visible = true;

  Plotly.redraw(graphDiv);
}

var range = document.getElementById("plotly-slice-range");
range.style.marginTop = "20px";
range.style.width = "80%";
range.min = 0;
range.max = graphDiv.data.length - 1;
range.value = 0;
range.addEventListener('change', function(e) {
  index = +e.target.value;
  changeSlice();
});

var decrement = document.getElementById("plotly-slice-decrement");
decrement.addEventListener('click', function(e) {
  e.preventDefault();
  if (index > 0) {
    index--;
  }
  range.value = index;
  changeSlice();
});

var increment = document.getElementById("plotly-slice-increment");
increment.addEventListener('click', function(e) {
  e.preventDefault();
  if (index < graphDiv.data.length - 2) {
    index++;
  }
  range.value = index;
  changeSlice();
});

})();
</script>
'''

def restructure_histogram_data(det_lookup, data, bins=None):
    Y = []
    X = []
    Z = []
    for index, val in enumerate(data):
        (i, j, _) = det_lookup[index]
        X.append(j)
        Y.append(i)
        Z.append(val)
    Y = np.array(Y)
    X = np.array(X)
    Z = np.array(Z)

    det_width = len(np.unique(X))
    det_height = len(np.unique(Y))

    if bins is None:
        bins = [det_width // 2, det_height // 2]

    Zp, xedges, yedges, _ = scipy.stats.binned_statistic_2d(
        X, Y, Z,
        bins=bins,
        statistic='mean',
    )

    Xp = xedges[1:] - (xedges[1] - xedges[0]) / 2
    Yp = yedges[1:] - (yedges[1] - yedges[0]) / 2

    return Zp

def main(filename, outdir, output_type, include_plotly_js, plot_type, bin_width,
         num_bins):
    # Load the workspace
    workspace = mantid.simpleapi.Load(filename)
    run_number = workspace.getRunNumber()

    # Get the detector width and height from the workspace
    instrument = workspace.getInstrument()
    component = instrument[instrument.nelements() - 1]
    det_width = component.nelements()
    det_height = component[0][0].nelements()
    det_lookup = {
        component[i][0][j].getID(): component[i][0][j].getPos()
        for i in xrange(component.nelements())
        for j in xrange(component[i][0].nelements())
    }

    # Get the number of time units from workspace and calculate bin width
    blocksize = workspace.blocksize()
    if not bin_width:
        bin_width = blocksize // num_bins
    else:
        num_bins = blocksize // bin_width

    maximum = 0

    if plot_type == 'tof' or plot_type == 'both':
        # Rebin data
        rebinned_workspace = mantid.simpleapi.Rebin(
            workspace,
            Params='{},{},{}'.format(0, bin_width, bin_width * num_bins),
            FullBinsOnly=True,
        )

        rebinned_y = rebinned_workspace.extractY()
        maximum = max(maximum, np.log(np.max(rebinned_y)))

        all_rebinned = [
            restructure_histogram_data(det_lookup, rebinned_y[:, i])
            for i in range(num_bins)
        ]

    if plot_type == 'integrated' or plot_type == 'both':
        # Integrate along the time dimension to consolidate the data
        integration_workspace = mantid.simpleapi.Integration(workspace)

        # Get Y data
        integrated_y = integration_workspace.extractY()
        maximum = max(maximum, np.log(np.max(integrated_y)))

        # Restructure Y data
        integrated = restructure_histogram_data(det_lookup, integrated_y)

    rebinned_traces = []
    if plot_type == 'tof' or plot_type == 'both':
        for i, rebinned in enumerate(all_rebinned):
            # Mask out any values that will make taking the log difficult
            rebinned_z = rebinned
            rebinned_z = np.ma.masked_invalid(rebinned_z)
            mask = (0 < rebinned_z) & (rebinned_z < np.e)
            rebinned_z = np.ma.masked_where(mask, rebinned_z)
            rebinned_z = np.ma.log(rebinned_z)

            # Actually plot the data
            rebinned_trace = plotly.graph_objs.Heatmap(
                z=rebinned_z,
                zmax=maximum,
                visible=True if (i == 0) else 'legendonly',
                showlegend=True,
                name='Rebinned {}'.format(i),
            )

            rebinned_traces.append(rebinned_trace)

    import json
    import gzip
    with gzip.open('rebinned.json.gz', 'w') as f:
        json.dump([x.z.tolist() for x in rebinned_traces], f)

    integrated_traces = []
    if plot_type == 'integrated' or plot_type == 'both':
        # Mask out any values that will make taking the log difficult
        integrated_z = integrated
        integrated_z = np.ma.masked_invalid(integrated_z)
        mask = (0 < integrated_z) & (integrated_z < np.e)
        integrated_z = np.ma.masked_where(mask, integrated_z)
        integrated_z = np.ma.log(integrated_z)

        integrated_trace = plotly.graph_objs.Heatmap(
            z=Z,
            zmax=maximum,
        )

        integrated_traces.append(integrated_trace)

    layout = plotly.graph_objs.Layout(
        xaxis=dict(title='Tube'),
        yaxis=dict(title='Pixel'),
        showlegend=True,
    )

    print(len(integrated_traces + rebinned_traces))

    fig = plotly.graph_objs.Figure(
        data=integrated_traces + rebinned_traces,
        layout=layout,
    )

    # Save image to the disk
    output_filename = "EQSANS_{}_autoreduced.html".format(run_number)
    output_path = os.path.join(outdir, output_filename)

    if output_type == 'div':
        div = plotly.offline.plot(fig, output_type='div',
                                  include_plotlyjs=include_plotly_js)
        with open(output_path, 'w') as f:
            f.write(div)

    else: # output_type == 'file':
        plotly.offline.plot(fig, filename=output_path,
                            include_plotlyjs=include_plotly_js)

    if plot_type == 'tof' or plot_type == 'integrated':
        with open(output_path, 'a') as f:
            f.write(TOF_TEMPLATE)

if __name__ == "__main__":
    import argparse
    import os

    def path_exists(path):
        """Ensures that the paths provided by the user exist"""
        if not os.path.exists(path):
            raise argparse.ArgumentTypeError("{} does not exist".format(path))
        return path

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', type=path_exists)
    parser.add_argument('outdir', type=path_exists)
    parser.add_argument('--output-type', choices=('div', 'file'), default='div')
    include_plotly_js = parser.add_mutually_exclusive_group(required=False)
    include_plotly_js.add_argument('--include-plotly-js',
                                   dest='include_plotly_js',
                                   action='store_true')
    include_plotly_js.add_argument('--no-include-plotly-js',
                                   dest='include_plotly_js',
                                   action='store_false')
    parser.set_defaults(include_plotly_js=True)
    parser.add_argument('--plot-type', choices=('integrated', 'tof', 'both'),
                        default='integrated')
    parser.add_argument('--bin-width', type=int, default=None)
    parser.add_argument('--num-bins', type=int, default=1)
    args = parser.parse_args()

    main(**vars(args))


import os
import re
from collections import deque
from gi import require_version
from gi.repository import Gtk
from gi.repository.GLib import timeout_add, source_remove, idle_add, unix_signal_add, PRIORITY_HIGH
require_version('AppIndicator3', '0.1')
from gi.repository import AppIndicator3 as appIndicator

from cpulib.run import run, run_nowait
from cpulib.config import config

def get_cpu_jiffies():
    result = run("grep 'cpu ' /proc/stat", shell=True)
    splitted = re.split(' +', result)
    assert splitted[0] == 'cpu'
    return list(map(int, splitted[1:5]))

def get_cpu_usage(hist):
    first = hist[0]
    second = hist[-1]
    used = second[0] + second[1] + second[2] - first[0] - first[1] - first[2]
    total = used + second[3] - first[3]
    if not total:
        return 0
    return 100 * used / total

class TaskBarIcon():
    def __init__(self):
        self.cur_icon = ''
        self.ind = appIndicator.Indicator.new(
            "CpuIndicator",
            os.path.abspath("img/unknown.png"),
            appIndicator.IndicatorCategory.APPLICATION_STATUS)
        self.ind.set_status(appIndicator.IndicatorStatus.ACTIVE)
        self.create_menu()
        self.ind.set_menu(self.menu)

        self.hist = deque()

        timeout_add(config['GUI_MS_BETWEEN_REDRAWS'], self.update)

    def update(self):
        self.update_icon()
        return True

    def update_icon(self):
        self.hist.append(get_cpu_jiffies())
        if len(self.hist) > config['SMOOTH_CYCLES']:
            self.hist.popleft()
        percent = get_cpu_usage(self.hist)
        if percent < 10:
            rounded = int(percent) + 1
        else:
            rounded = int((percent // 10 + 1) * 10)
        if rounded > 100:
            rounded = 100

        self.set_icon(rounded)

    def set_icon(self, percent):
        full_path = 'img/red-percent-' + str(percent) + '.png'
        if self.cur_icon == full_path:
            return
        self.cur_icon = os.path.abspath(full_path)

        self.ind.set_icon_full(self.cur_icon, '')

    def create_menu(self):
        self.menu = Gtk.Menu()

        self.menu.monitor = Gtk.MenuItem(label='Open System monitor')
        self.menu.monitor.connect("activate", self.on_monitor)
        self.menu.append(self.menu.monitor)

        self.menu.append(Gtk.SeparatorMenuItem.new())

        self.menu.exit = Gtk.MenuItem(label='Exit CPU indicator')
        self.menu.exit.connect("activate", self.on_exit)
        self.menu.append(self.menu.exit)

        self.menu.show_all()

    def on_monitor(self, widget):
        run_nowait('gnome-system-monitor', shell=True)

    def on_exit(self, widget):
        self.exit()

    def exit(self):
        Gtk.main_quit()


import rasterio
import fiona
import rasterio.warp as warp
from rasterio.mask import mask
from rasterio.warp import Resampling
import os
from glob import glob
import numpy as np
from shapely.geometry import mapping, shape
from affine import Affine
from pyproj import Proj, transform
from s2cloudless import S2PixelCloudDetector
import subprocess

def resampling_method(method):
    if method == 'nearest':
        return Resampling.nearest
    elif method == 'bilinear':
        return Resampling.bilinear
    elif method == 'cubic':
        return Resampling.cubic
    elif method == 'cubic_spline':
        return Resampling.cubic_spline
    elif method == 'lanczos':
        return Resampling.lanczos
    elif method == 'average':
        return Resampling.average
    elif method == 'mode':
        return Resampling.mode
    elif method == 'max':
        return Resampling.max
    elif method == 'min':
        return Resampling.min
    elif method == 'med':
        return Resampling.med
    elif method == 'q1':
        return Resampling.q1
    elif method == 'q3':
        return Resampling.q3
    else:
        raise ValueError("Invalid method, does not exist, check rasterio.warp.Resampling for reference.")

def read_S2TOA(S2_SAFE_fp, pixel_res, temp=None, resample='average'):
    bands = ['B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08', 'B8A', 'B09','B10', 'B11', 'B12']
    res = np.array([60, 10, 10, 10, 20, 20, 20, 10, 20, 60,60, 20, 20])
    # list of rasters
    S2rasters = [glob(os.path.join(S2_SAFE_fp, 'GRANULE', 'L*', 'IMG_DATA', '*{}*'.format(band)))[0]
                 for band in bands]
    afftr = res / pixel_res
    S2_bands = []
    for i, band in enumerate(S2rasters):
        print("Band ", i + 1)
        with rasterio.open(band) as src:
            arr = src.read().astype('float32') / 10000
            kwargs = src.profile
            if res[i] == pixel_res:
                S2_bands.append(arr)
                if temp is not None:
                    temp_raster = os.path.join(temp, 'temp_raster.tif')
                    kwargs.update({'width': arr.shape[1],
                                   'height': arr.shape[2],
                                   "driver": 'GTiff',
                                   "dtype": arr.dtype,
                                   "nodata": src.profile['nodata']})
                    with rasterio.open(temp_raster, 'w', **kwargs) as dst:
                        dst.write(arr)
                continue
            else:
                aff = src.transform
                new_aff = Affine(aff.a / afftr[i], aff.b, aff.c,
                                 aff.d, aff.e / afftr[i], aff.f)

                kwargs.update({"transform": new_aff,
                               "driver": 'GTiff',
                               "dtype": arr.dtype,
                               "nodata": src.profile['nodata']})
                newarr = np.empty(shape=(arr.shape[0],
                                         int(round(arr.shape[1] * afftr[i])),
                                         int(round(arr.shape[2] * afftr[i]))), dtype='float32')
                warp.reproject(arr, newarr,
                               src_transform=aff,
                               dst_transform=new_aff,
                               src_crs=src.crs,
                               dst_crs=src.crs,
                               resampling=resampling_method(resample))
                S2_bands.append(newarr)

    S2_bands = np.concatenate(S2_bands, axis=0).transpose(1, 2, 0)
    if temp is not None:
        return S2_bands, temp_raster
    else:
        return S2_bands

def apply_acolite(S2_SAFE_fp,output, S2_target_res):

    """
    Create settings file for ACOLITE AC processor for multiple tiles and saves it in the
    working directory as "aculite_settings.txt". For any other settings, look at the aculite_config.txt
    in aculite_py_win/config folder

    :param inputfolder: folder with all the S2 level 1 products in SAFE format
    :param output: Output folder for
    :param s2_target_res: Resolotion for processed produce
    :param merge_tiles: if you do not wish to merge, make this False
    :return: settings
    """
    inputfiles = 'inputfile='+S2_SAFE_fp+'\n'
    outputfile = 'output=' + output + '\n'
    l2w = 'l2w_parameters=rhos_*\n'
    target_res = 's2_target_res=' + str(S2_target_res) + '\n'
    settings = inputfiles + outputfile + l2w + target_res

    with open("acolite_settings.txt", 'w') as dst:
        dst.write(settings)

    cwd = os.getcwd()
    acolitefp = r'acolite_py_win/dist/acolite'
    os.chdir(acolitefp)
    comm = r'acolite.exe --cli --settings="..\..\..\acolite_settings.txt"'
    subprocess.run(comm, shell=True)
    os.chdir(cwd)

def read_acolite(Acolite_fp):

    if os.path.basename(glob(os.path.join(Acolite_fp,'S2*'))[0])[:3]=='S2B':
        bands = ['442', '492', '559', '665', '704', '739', '780', '833', '864', '1610', '2186', ]
    else:
        bands = ['443', '492', '560', '665', '704', '740', '783', '833', '865', '1614', '2202']
    S2_BOA_bands = []
    """
    afftr = 10 / pixel_res
    for i, band in enumerate(bands):
        print("Band ", i+1, ':', bands[i])
        rhos_ = glob(os.path.join(Acolite_fp, '*rhos_' + band + '.tif'))[0]
        with rasterio.open(rhos_) as acsrc:
            arr = acsrc.read()
            aff = acsrc.transform
            new_aff = Affine(aff.a / afftr, aff.b, aff.c,
                             aff.d, aff.e / afftr, aff.f)
            kwargs = acsrc.profile
            kwargs.update({"transform": new_aff,
                           "driver": 'GTiff',
                           "dtype": arr.dtype,
                           "nodata": acsrc.profile['nodata']})
            newarr = np.empty(shape=(arr.shape[0],
                                     int(round(arr.shape[1] * afftr)),
                                     int(round(arr.shape[2] * afftr))), dtype='float32')
            warp.reproject(arr, newarr,
                           src_transform=aff,
                           dst_transform=new_aff,
                           src_crs=acsrc.crs,
                           dst_crs=acsrc.crs,
                           resampling=resampling_method(resample))
            S2_BOA_bands.append(newarr)
            print(newarr.shape)
            #S2_BOA_bands.append(arr)
    """
    for i, band in enumerate(bands):
        print("Band ", i + 1, ':', bands[i])
        rhos_ = glob(os.path.join(Acolite_fp, '*rhos_' + band + '.tif'))[0]
        with rasterio.open(rhos_) as acsrc:
            arr = acsrc.read()
            S2_BOA_bands.append(arr)

    S2_BOA_bands = np.concatenate(S2_BOA_bands, axis=0).transpose(1, 2, 0)

    return S2_BOA_bands

def createFootprint(pathname):
    """
    Function for creating footprint from geotiff raster file

    :param pathname: path to geotiff raster
    :return: geojson like object defining the footprint
    """
    # Read raster
    with rasterio.open(pathname) as r:
        T0 = r.transform  # upper-left pixel corner affine transform
        p1 = Proj(r.crs)
        A = r.read(1)  # pixel values

    # All rows and columns
    cols, rows = np.meshgrid(np.arange(A.shape[1]), np.arange(A.shape[0]))

    # Get affine transform for pixel centres
    T1 = T0 * Affine.translation(0.5, 0.5)
    # Function to convert pixel row/column index (from 0) to easting/northing at centre
    rc2en = lambda r, c: (c, r) * T1

    # All eastings and northings (there is probably a faster way to do this)
    eastings, northings = np.vectorize(rc2en, otypes=[np.float, np.float])(rows, cols)

    # Project all longitudes, latitudes
    p2 = Proj(proj='latlong', datum='WGS84')
    longs, lats = transform(p1, p2, eastings, northings)

    lonlat = np.zeros((longs.shape + (2,)))

    lonlat[..., 0] = longs
    lonlat[..., 1] = lats

    # Take only the edge pixels of the raster
    right = lonlat[:, 0, :][0::100]  # right
    down = lonlat[-1, :, :][0::100]  # down
    left = np.flip(lonlat[:, -1, :][0::100], axis=0)  # left
    up = np.flip(lonlat[0, :, :][0::100], axis=0)  # up
    up[-1] = right[0]
    footprint_arr = np.concatenate((right, down, left, up), axis=0).tolist()
    # Create geojson like file
    geom = {
        "type": "Polygon",
        "coordinates": [

        ]
    }
    # Append the footprint coordinates to the json
    geom["coordinates"].append(footprint_arr)

    return geom

def apply_landmask(rasterfp, detail=True, keep_land=False, mask_only=False):
    """
    Function for applying landmask, using a landmask shapefile in the included folder

    rasterfp - path to raster
    detail - Get detailed high resolution land mask if True (slow, high memory), else using a more rough, but much faster
    and efficient
    keep_land - Mask out land (False), or keep only the land pixels (True)
    mask_only - return just the mask (True), or remove the masked part from the raster (False)
    """
    # create Footprint for raster
    footprint = createFootprint(rasterfp)

    if detail:
        landpoly = r"include/land_polygons.shp"
    else:
        landpoly = r"include/GSHHS_i_L1.shp"

    with fiona.open(landpoly) as shapefile:
        # Use shapely for finding intersections between raster and land shapefile
        # by checking the shape intersects with the created footprint
        # Saves memory by not loading the whole shape, though it takes some time
        intersections = [mapping(shape(feature['geometry'])) for feature in shapefile
                         if shape(feature['geometry']).intersects(shape(footprint))]
        # Get shapefiles crs
        crsShape = shapefile.crs

    # Check if there are any intersections, if there are none, just return a message.
    if len(intersections) == 0:
        print("There are no lands within the raster. Returning None")
        return None

    # If there are, apply the mask:
    else:
        # Use rasterio.warp's transform_geom to transform the intersection shapes crs to the rasters crs
        # then mask out the pixels that's within the shapes using rasterio.mask's mask method
        with rasterio.open(rasterfp) as src:
            kwargs = src.profile
            intersect_trans = [warp.transform_geom(crsShape, src.crs, land) for land in intersections]
            landmasked_raster, transform = mask(src, intersect_trans, invert=~keep_land)

        if mask_only:
            mask_only_raster = np.zeros_like(landmasked_raster)
            mask_only_raster[0] = (landmasked_raster[0] == 0).astype('uint16')
            return mask_only_raster
        else:
            return landmasked_raster

def apply_cloudmask(S2DotSafefp=None, bands=None, threshold=0.4, dilation_size=3,
                    average_over=1, resolution_safe=100, save_mask=None, crs=None,
                    affine=None):
    """
    Function for applying cloud mask to either S2 product in safe format or a multiple rasters
    in numpy ndarray format. ndarray format is reccomended

    :param S2DotSafefp: path to S2 file
    :param bands: ndarray (N, H, W, B) N is the number of rasters, H is height, W is width, B are bands
    :param resolution_safe: Pixel resolution for cloud mask for .safe format in meters,
                            recommended to use higher than 60 as it's much more efficient.
    :param dilation_size: dilation for cloud pixels
    :param threshold: threshold for the cloud probability
    :param average_over: neighborhood of averaging
    :param save_mask:
    :param crs: If save_mask => crs for the saved mask
    :param affine: Affine transformation for the saved mask
    :return: cloud mask (N, H, W) cloud mask for each raster, if .safe format the output shape will be
            (1, H, W)

    """
    # If the input is in safe format
    if S2DotSafefp is not None:
        # resolutions for each band
        res = np.array([60, 10, 10, 20, 10, 20, 60, 60, 20, 20])
        # Valid bands
        bands_ = ['B01', 'B02', 'B04', 'B05', 'B08', 'B8A', 'B09', 'B10', 'B11', 'B12']
        # list of rasters
        S2rasters = [glob(os.path.join(S2DotSafefp, 'GRANULE', 'L*', 'IMG_DATA', '*{}*'.format(band)))[0]
                     for band in bands_]
        # Affine transformation list
        afftr = res / resolution_safe
        S2_cloud_bands = []

        # iterate through band rasters
        for i, raster in enumerate(S2rasters):
            with rasterio.open(raster) as src:
                # Divide by 10000 to get TOA values
                arr = src.read().astype('float32') / 10000
                aff = src.transform
                # Define new affine transform
                new_aff = Affine(aff.a / afftr[i], aff.b, aff.c,
                                 aff.d, aff.e / afftr[i], aff.f)
                # Empty array for destination
                newarr = np.empty(shape=(arr.shape[0],
                                         int(round(arr.shape[1] * afftr[i])),
                                         int(round(arr.shape[2] * afftr[i]))), dtype='float32')
                # Apply downsampling
                warp.reproject(arr, newarr,
                               src_transform=aff,
                               dst_transform=new_aff,
                               src_crs=src.crs,
                               dst_crs=src.crs)
                # Append to list
                S2_cloud_bands.append(newarr)
        # Concatenate the list and add a dim for compatibility with S2Cloudless function
        S2_cloud_bands = np.concatenate(S2_cloud_bands, axis=0)

        S2_cloud_bands = np.expand_dims(S2_cloud_bands, axis=0)
        # Apply cloudmask
        cloudmask = S2PixelCloudDetector(threshold=threshold,
                                         dilation_size=dilation_size,
                                         average_over=average_over,
                                         all_bands=False).get_cloud_masks(S2_cloud_bands)

        # save mask if path is specified
        if save_mask is not None:
            with rasterio.open(S2rasters[0]) as src:
                kwargs = src.profile
                kwargs['width'] = cloudmask.shape[1]
                kwargs['height'] = cloudmask.shape[2]
                kwargs['transform'] = new_aff
                kwargs['driver'] = 'Gtiff'
                kwargs['dtype'] = cloudmask.dtype
                kwargs['blockxsize'] = 128
                kwargs['blockysize'] = 128

                with rasterio.open(save_mask, 'w', **kwargs) as dst:
                    dst.write(cloudmask)
        # return the cloudmask as np ndarray
        return cloudmask
    # If valid bands are given
    elif bands is not None:

        cloudmask = S2PixelCloudDetector(threshold=threshold,
                                         dilation_size=dilation_size,
                                         average_over=average_over,
                                         all_bands=False).get_cloud_masks(bands)

        # save mask if path is specified
        if save_mask is not None and crs is not None:
            kwargs = {
                'driver': 'GTiff',
                'interleave': 'band',
                'tiled': True,
                'blockxsize': 128,
                'blockysize': 128,
                'nodata': 0,
                'dtype': cloudmask.dtype,
                'height': cloudmask.shape[1],
                'width': cloudmask.shape[2],
                'crs': crs,
                'transform': affine
            }

            with rasterio.open(save_mask, 'w', **kwargs) as dst:
                dst.write(cloudmask)
        elif save_mask is not None and crs is None:
            raise ValueError("To save the mask, crs needs to be provided")
        # return the cloudmask as np ndarray
        return cloudmask
    else:
        raise ValueError(
            "You need to provide a path to a Sentinel-2 .safe file, or a numpy ndarray consisting of the bands")

def Water_mask(S2_ndarray, threshold):

    pass

def apply_dos_all(S2_array):
    S2_dos = np.zeros_like(S2_array)
    for i in range(S2_dos.shape[-1]):
        S2_dos[..., i] = apply_dos(S2_array[..., i])

    return S2_dos

def apply_dos(S2_band):
    do = S2_band[S2_band!=0].min()
    S2_band[S2_band!=0] = S2_band[S2_band!=0]-do
    return S2_band

def estimate_albedo(S2_arr, BOA=False):
    weights = np.loadtxt('models/albedo_weights.txt')
    if BOA:
        weights_BOA = weights[[0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12]]
        S2_tot_alb = np.zeros((S2_arr.shape[0],S2_arr.shape[1]))
        for i in range(S2_arr.shape[2]):
            S2_tot_alb += S2_arr[..., i] * weights_BOA[i]
    else:
        S2_tot_alb = np.zeros((S2_arr.shape[0],S2_arr.shape[1]))
        for i in range(S2_arr.shape[2]):
            S2_tot_alb += S2_arr[..., i] * weights[i]

    return S2_tot_alb


from socket import *
import sys
from threading import *
from datetime import datetime
import os
import art

def clear():

    if os.name == 'nt':
        _ = os.system('cls')
    else:
        _ = os.system('clear')
clear()

print(art.text2art("                                         Port  Scanner"))

try:
    host = input("\nEnter the Domain name/ ip address =  ")
    resolvedip = gethostbyname(host)
except:
    sys.exit("Check your domain , Entered domain not found")

normalPortStart = 1
normalPortEnd = 1024
allPort = 1
allPortEnd = 65535
customPortStart = 0
customPortEnd = 0

print('\n')
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Select your scan type: ")
print("[+] Select 1 for Normal Ports scaning")
print("[+] Select 2 for All Ports scaning")
print("[+] Select 3 for custom port scaning")
print("[+] Select 4 for exit \n")

mode = int(input("[+] Select any option: "))
print()

if mode == 3:
    customPortStart = int(input("[+] Enter starting port number: "))
    customPortEnd = int(input("[+] Enter ending port number: "))

print("-"*50)
print(f"Target IP: {host}")
print("Scanning started at:" + str(datetime.now()))
print("-"*50)

allports = []
def get_ports(mode):
    if mode == 1:
        print("\n[+] scaning..\n")
        for port in range(normalPortStart, normalPortEnd+1):
            allports.append(port)
    elif mode == 2:
        print("\n[+] scaning..\n")
        for port in range(allPort, allPortEnd+1):
            allports.append(port)
    elif mode == 3:
        print("\n[+] scaning..\n")
        for port in range(customPortStart, customPortEnd+1):
            allports.append(port)
    elif mode == 4:
        print("[-] Exiting...")
        sys.exit()

setdefaulttimeout(0.01)
lock = Lock()
thread_array = []
main_array = []

def conn(ipx,portx,lock,mode):
    addr = (ipx,portx)
    s = socket(AF_INET,SOCK_STREAM)
    result = s.connect_ex(addr)
    s.close()
    lock.acquire()
    if(result == 0):
        main_array.append(portx)
        print("Port ",format(portx)," is open")
    else:
        print("Port ",format(portx)," is not open")
    lock.release()

get_ports(mode)
for port in allports:
    t = Thread(target = conn , args = (host,port,lock,mode))
    thread_array.append(t)
    t.start()

for thread in thread_array:
    thread.join()

print("-"*50)
print("port that are open are ",main_array)
print("-"*50)

print(f"Scanning compleate in: {current_time}")