import pygame
import random
import numpy as np

class Explosion(pygame.sprite.Sprite):
    def __init__(self, frames, xcoord, ycoord, scale=1.5, update_n=1):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        self.frame = 0
        self.frames = frames
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect()
        self.x = xcoord
        self.y = ycoord
        self.scale = scale
        self.update_n = update_n
        self.update_counter = self.update_n

    def update(self):
        self.update_counter -= 1
        if self.frame >= len(self.frames) - 1:
            self.kill()
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect()
        self.image = pygame.transform.scale(self.image, (int(self.rect.size[0] * self.scale),
                                                         int(self.rect.size[1] * self.scale)))
        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y
        if self.update_counter == 0:
            self.frame += 1
            self.update_counter = self.update_n

        gameDisplay.blit(self.image, self.rect)

    def update_moving(self, xspeedboss, yspeedboss):
        if self.frame >= len(self.frames) - 1:
            self.kill()
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect()
        self.image = pygame.transform.scale(self.image, (int(self.rect.size[0] * 1.5), int(self.rect.size[1] * 1.5)))
        self.rect = self.image.get_rect()
        self.x += xspeedboss
        self.y += yspeedboss
        self.rect.x = self.x
        self.rect.y = self.y
        self.frame += 1
        gameDisplay.blit(self.image, self.rect)

class Explosion2(pygame.sprite.Sprite):
    def __init__(self, frames, xcoord, ycoord):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        self.frame = 0
        self.frames = frames
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect()
        self.x = xcoord
        self.y = ycoord
        self.expansion = 0.8
        self.update_counter = 3

    def update(self):
        self.update_counter -= 1
        if self.frame >= len(self.frames) - 1:
            self.kill()
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect()
        self.image = pygame.transform.scale(self.image, (int(self.rect.size[0] * self.expansion),
                                                         int(self.rect.size[1] * self.expansion)))
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        self.rect.centerx = self.x
        self.rect.centery = self.y
        if self.update_counter == 0:
            self.expansion += 0.045
            self.frame += 1
            self.update_counter = 4
        gameDisplay.blit(self.image, self.rect)

class Ship(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        self.image = player_ship
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = (display_width - self.width) * 0.5
        self.y = display_height - self.height * 1.2
        self.speed = 0  # This variable changes with key presses
        self.endspeed = 1
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        # Update variables of the game for next update
        self.x += self.speed
        if self.x > display_width - self.width:
            self.x = display_width - self.width  # boundaries for ship
        elif self.x < 0:
            self.x = 0  # boundaries for ship

        self.rect.x = self.x
        self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
        gameDisplay.blit(self.image, self.rect)

    def to_end_position(self, xcoord):
        statement = False
        self.speed = 0
        if self.x < xcoord - 1:
            self.x += self.endspeed
        elif self.x > xcoord + 1:
            self.x -= self.endspeed
        else:
            statement = True

        self.rect.x = self.x
        self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
        gameDisplay.blit(self.image, self.rect)

        return statement

class Meteor(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        meteor_choices = [meteor1, meteor2, meteor3, meteor4]
        self.image = meteor_choices[random.randrange(0, 3)]
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = random.randrange(0, display_width - self.width)
        self.y = -200
        self.mask = pygame.mask.from_surface(self.image)
        self.speed = 7

    def update(self):
        self.y += self.speed
        self.rect.x = self.x
        self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
        gameDisplay.blit(self.image, self.rect)

class Laser(pygame.sprite.Sprite):
    def __init__(self, xcoord, ycoord):
        pygame.sprite.Sprite.__init__(self)
        self.image = laser_blue
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = xcoord - 0.5 * self.width  # depends on ship location
        self.y = ycoord  # These will be set at spawn because it depends on ship location
        self.speed = -20
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        self.y += self.speed
        if self.y < 0 - self.height:
            self.kill()
        else:
            self.rect.x = self.x
            self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
            gameDisplay.blit(self.image, self.rect)

class EnemyGoon(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        enemy_choices = [enemy1, enemy2, enemy3]
        self.image = enemy_choices[random.randrange(0, 2)]
        self.rect = self.image.get_rect()
        self.image = pygame.transform.scale(self.image, (int(self.rect.size[0] / 1.5), int(self.rect.size[1] / 1.5)))
        self.rect = self.image.get_rect()  # after transforming need to acquire new rect
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = random.choice(np.linspace(0, display_width - self.width, 10))
        self.y = 100 + self.height
        self.mask = pygame.mask.from_surface(self.image)
        self.update_timer = fps * 2  # update every 60 frames
        self.x_speed = random.choice([-3, 3])

    def update(self):
        self.update_timer -= 1
        if self.update_timer == 0:
            self.fire()
            self.update_timer = fps * 2
        self.y = 100 * np.sin(timer / 500) + 100

        self.x += self.x_speed
        if self.x > display_width - self.width:
            self.x = display_width - self.width  # boundaries for enemy
            self.x_speed = -self.x_speed  # flip speed so that enemy moves into opposite direction
        elif self.x < 0:
            self.x = 0  # boundaries for ship
            self.x_speed = -self.x_speed  # flip speed so that enemy moves into opposite direction
        self.rect.x = self.x
        self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
        gameDisplay.blit(self.image, self.rect)

    def fire(self):
        enemy_lasers.add(EnemyLaser(self.x + 0.5 * self.width, self.y))
        pygame.mixer.Channel(2).play(enemy_laser_sound)

class EnemyLaser(pygame.sprite.Sprite):
    def __init__(self, xcoord, ycoord):
        pygame.sprite.Sprite.__init__(self)
        self.image = laser_red
        self.image = pygame.transform.flip(self.image, 0, 1)
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = xcoord - 0.5 * self.width  # depends on ship location
        self.y = ycoord  # These will be set at spawn because it depends on ship location
        self.speed = 7
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        self.y += self.speed
        if self.y > display_height:
            self.kill()
        else:
            self.rect.x = self.x
            self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
            gameDisplay.blit(self.image, self.rect)

class ChooseFont(object):
    def __init__(self, fonttype, fontsize, color):
        self.font = pygame.font.Font(fonttype, fontsize)
        self.color = color

    def message(self, text, xcoord, ycoord, centered=False):
        text_surface = self.font.render(text, True, self.color)
        text_rect = text_surface.get_rect()
        if centered is True:
            text_rect.center = (xcoord, ycoord)
        elif centered is False:
            text_rect.x = xcoord
            text_rect.y = ycoord
        gameDisplay.blit(text_surface, text_rect)

class Boss(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        self.image = boss_image
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = display_width * 0.5 - self.width * 0.5
        self.y = 50
        self.y_speed = 0
        self.mask = pygame.mask.from_surface(self.image)
        self.laser_timer_max = fps * 2  # update every 120 frames
        self.laser_timer = fps * 2  # update every 120 frames
        self.laser_list = [5, 10, 15, 20, 25]
        self.bomb_timer_max = fps * 4
        self.bomb_timer = self.bomb_timer_max
        self.x_speed = 3
        self.hp = 100
        self.maxhp = self.hp
        self.dead_timer = 170
        self.add_explosion_timer = 10
        self.randx = None
        self.randy = None
        self.hp_50 = False
        self.hp_25 = False

    def update(self):
        if self.hp > 0:
            self.laser_timer -= 1
            self.bomb_timer -= 1
            if self.laser_timer in self.laser_list:  # frames at which ship fires
                self.fire_laser()
            if self.laser_timer == 0:
                self.laser_timer = self.laser_timer_max
            if self.bomb_timer == 0:
                self.bomb_timer = self.bomb_timer_max
                self.fire_bomb()

            if self.hp < self.maxhp * 0.5 and self.hp_50 is False:
                if self.x_speed > 0:
                    self.x_speed = 5
                elif self.x_speed < 0:
                    self.x_speed = -5
                self.laser_timer_max = fps * 1.7
                self.bomb_timer_max = fps * 3.5
                self.hp_50 = True

            if self.hp < self.maxhp * 0.25 and self.hp_25 is False:
                if self.x_speed > 0:
                    self.x_speed = 7
                elif self.x_speed < 0:
                    self.x_speed = -7
                self.laser_timer_max = fps * 1.5
                self.bomb_timer_max = fps * 3
                self.hp_25 = True

        elif self.dead_timer > 0:
            self.x_speed = 1
            self.add_explosion_timer -= 1
            self.dead_timer -= 1
            if self.add_explosion_timer == 0:
                self.add_explosions()

                self.add_explosion_timer = 10

            for explosion in explosions_boss:
                explosion.update_moving(self.x_speed, self.y_speed)

        self.x += self.x_speed
        if self.x > display_width - self.width:
            self.x = display_width - self.width  # boundaries for enemy
            self.x_speed = -self.x_speed  # flip speed so that enemy moves into opposite direction
        elif self.x < 0:
            self.x = 0  # boundaries for ship
            self.x_speed = -self.x_speed  # flip speed so that enemy moves into opposite direction
        self.rect.x = self.x
        self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
        gameDisplay.blit(self.image, self.rect)

        self.draw_health()

    def fire_laser(self):
        enemy_lasers.add(EnemyLaser(self.x + 0.35 * self.width, self.y + 0.8 * self.height))
        enemy_lasers.add(EnemyLaser(self.x + 0.65 * self.width, self.y + 0.8 * self.height))
        pygame.mixer.Channel(2).play(enemy_laser_sound)

    def fire_bomb(self):
        boss_bomb.add(BossBomb(self.x, self.y))
        pygame.mixer.Channel(4).play(bomb_release_sound)

    def draw_health(self):
        color = red
        width_hp = self.width * (self.hp / self.maxhp)
        healthbar = pygame.Rect((self.x, self.y - 10, width_hp, 10))
        pygame.draw.rect(gameDisplay, color, healthbar)

    def add_explosions(self):
        for i in range(2):
            self.randx = random.randint(np.round(self.x) + 10 - 32, np.round(self.x) + self.width - 10 - 32)
            self.randy = random.randint(np.round(self.y) + 10 - 64, np.round(self.y) + self.height - 10 - 64)
            explosions_boss.add(Explosion(explosion1, self.randx, self.randy))
        pygame.mixer.Channel(3).play(explosion_sound)

class BossBomb(pygame.sprite.Sprite):
    def __init__(self, xcoord, ycoord):
        pygame.sprite.Sprite.__init__(self)
        self.image = missile
        self.image = pygame.transform.flip(self.image, 0, 1)
        self.rect = self.image.get_rect()
        self.width = self.rect.size[0]
        self.height = self.rect.size[1]
        self.x = xcoord - 0.5 * self.width  # depends on ship location
        self.y = ycoord  # These will be set at spawn because it depends on ship location
        self.xspeed = 0
        self.xspeedincr = 0.3
        self.xspeedmax = 5
        self.yspeed = 3
        self.mask = pygame.mask.from_surface(self.image)

    def update(self, xship, yship):
        if xship > self.x:
            if self.xspeed < self.xspeedmax:
                self.xspeed += self.xspeedincr
        elif xship < self.x:
            if self.xspeed > -self.xspeedmax:
                self.xspeed -= self.xspeedincr
        self.x += self.xspeed

        self.y += self.yspeed

        if self.y >= display_height - 200:
            self.kill()
            explosions.add(Explosion2(explosion2, self.x, self.y))
            pygame.mixer.Channel(5).play(bomb_explosion_sound)
        else:
            self.rect.x = self.x
            self.rect.y = self.y  # set the rect (not just blit) or collision won't work!
            gameDisplay.blit(self.image, self.rect)

def main_menu():
    button_width = start_button.get_rect().size[0]
    scheme_width = controlscheme.get_rect().size[0]
    button_x_center = (display_width - button_width) * 0.5
    scheme_x_center = (display_width - scheme_width) * 0.5

    # End game when this becomes true
    in_main_menu = True
    # Play the soundtrack
    pygame.mixer.Channel(0).play(game_music, loops=-1)

    # This is the game loop where all game logic happens
    while in_main_menu:

        # This checks all events that happen (which are located in pygame.event.get()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                pos = pygame.mouse.get_pos()
                if startbutton.collidepoint(pos):
                    pygame.mixer.Channel(1).play(button_sound)
                    global time_since_startbutton
                    time_since_startbutton = pygame.time.get_ticks()
                    game_loop()
                elif creditbutton.collidepoint(pos):
                    credit_loop()
                elif quitbutton.collidepoint(pos):
                    pygame.mixer.Channel(1).play(button_sound)
                    pygame.quit()
                    quit()

        # Update main menu
        gameDisplay.blit(background, (0, 0))
        startbutton = gameDisplay.blit(start_button, (button_x_center, display_height * 0.4))
        creditbutton = gameDisplay.blit(credit_button, (button_x_center, display_height * 0.5))
        quitbutton = gameDisplay.blit(quit_button, (button_x_center, display_height * 0.6))
        gameDisplay.blit(controlscheme, (scheme_x_center, display_height * 0.7))
        pygame.display.update()

def credit_loop():
    credits = True
    while credits:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    credits = False
        # Update
        gameDisplay.blit(credit_background, (0, 0))

        pygame.display.update()

def game_loop():

    # Instantiate Ship & Meteor and create a group for lasersprites
    global ship, ship_group, meteors, lasers, score_count, enemies, fps, timer, enemy_lasers, score_count
    global boss_bomb, explosions, explosions_boss
    ship_group = pygame.sprite.GroupSingle()
    boss_group = pygame.sprite.GroupSingle()
    boss_bomb = pygame.sprite.Group()
    enemies = pygame.sprite.Group()
    meteors = pygame.sprite.Group()
    lasers = pygame.sprite.Group()
    enemy_lasers = pygame.sprite.Group()
    explosions = pygame.sprite.Group()
    explosions_boss = pygame.sprite.Group()

    # Set variables and events needed for meteor shower
    add_meteor_event = pygame.USEREVENT + 1
    add_meteor_timer = 300  # add new meteor evert 300 ms
    ms_event = pygame.USEREVENT + 2
    ms_start = 60000  # ms after which meteor shower arrives
    ms_duration = 20000
    pygame.time.set_timer(add_meteor_event, add_meteor_timer)
    pygame.time.set_timer(ms_event, ms_start)
    ms_passed = False
    ms_announcement = False

    # Set variables needed to spawn enemies
    add_enemies_event = pygame.USEREVENT + 3
    add_enemies_timer = 5000  # add new enemies every 5000 ms
    pygame.time.set_timer(add_enemies_event, add_enemies_timer)
    num_enemies = 3
    enemies_meteors_spawning = True

    # Set variables for boss battle
    boss_battle = False
    won = False
    ship_centered = False
    boss_announcement = False

    # Instatiate other variables
    score_count = 0  # score
    meteors_dodged = 0
    enemies_killed = 0
    bosses_killed = 0
    fps = 60
    ship = Ship()
    ship_group.add(ship)  # Add ship once before playing loop starts

    # This is the game loop where all game logic happens
    playing = True
    while playing:
        timer = pygame.time.get_ticks() - time_since_startbutton  # ms that have passed since start

        if 30000 < timer <= 40000:
            num_enemies = 4
        elif 40000 < timer <= 50000:
            num_enemies = 5
        elif 50000 < timer <= 60000:
            num_enemies = 6

        # Check for global events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if not won:
                # Check for user-inputted event
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        ship.speed = -10
                    elif event.key == pygame.K_RIGHT:
                        ship.speed = 10
                    elif event.key == pygame.K_SPACE:
                        lasers.add(Laser(ship.x + 0.5*ship.width, ship.y))
                        pygame.mixer.Channel(1).play(laser_sound)

                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                        ship.speed = 0

            if ship_centered is True:
                # Button to return to main menu after defeating boss
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN:
                        playing = False

            # Check for events that only happen within certain time range
            if event.type == ms_event and ms_passed is False:  # This only occurs once
                ms_announcement_timer = timer
                ms_announcement = True
                enemies_meteors_spawning = False

            if event.type == add_enemies_event and enemies_meteors_spawning:
                for i in range(num_enemies):
                    enemies.add(EnemyGoon())

            try:
                if timer - ms_announcement_timer < 2000 and ms_announcement is True:  # display message 2000 ms
                    continue
                elif ms_announcement is True:
                    ms_announcement = False  # This makes sure announcement doesn't return anymore
                    ms_start_timer = timer  # Timestamp start of meteor shower
            except UnboundLocalError:
                continue
            try:
                if timer - ms_start_timer < ms_duration and ms_passed is False:
                    if event.type == add_meteor_event:  # add a meteor every time event is in event queue
                        meteors.add(Meteor())
                elif ms_passed is False:
                    ms_passed = True  # This makes sure ms doesn't return after it passed event is queued again
                    boss_announcement_timer = timer
                    boss_announcement = True
            except UnboundLocalError:
                continue

            try:
                if timer - boss_announcement_timer < 2000 and boss_announcement is True:
                    continue
                elif boss_announcement is True:
                    boss_announcement = False
                    boss_battle = True
                    boss = Boss()
                    boss_group.add(boss)
            except UnboundLocalError:
                continue

        # Update display and sprites
        gameDisplay.blit(background, (0, 0))
        ship.update()

        if len(meteors) < 1 and enemies_meteors_spawning:
            meteors.add(Meteor())
        for meteor in meteors:
            meteor.update()
            if meteor.y > display_height:
                meteor.kill()
                meteors_dodged += 1
                score_count += 10

        for laser in lasers:
            laser.update()

        for enemy in enemies:
            enemy.update()

        for laser in enemy_lasers:
            laser.update()

        if boss_battle is True:
            boss.update()
            for bomb in boss_bomb:
                bomb.update(ship.x + 0.5 * ship.width, ship.y + 0.5 * ship.height)

            boss_hit = pygame.sprite.groupcollide(lasers, boss_group, 1, 0, pygame.sprite.collide_mask)
            for sprite in boss_hit:
                if boss_hit[sprite]:
                    explosions_boss.add(Explosion(explosion1, sprite.x - 32, sprite.y - 64))  # 64 is w/l of explosion
                    pygame.mixer.Channel(3).play(explosion_sound)
                    boss.hp -= 1

            for explosion in explosions_boss:
                explosion.update_moving(boss.x_speed, boss.y_speed)

            if boss.dead_timer <= 0:
                explosions.add(Explosion(explosion3, boss.x - boss.width*0.5, boss.y - boss.height*0.5, 3, 5))
                del boss
                boss_battle = False
                won = True
                score_count += 1000
                bosses_killed += 1

        for explosion in explosions:
            explosion.update()

            if boss_battle is True:
                burned = pygame.sprite.groupcollide(ship_group, explosions, 0, 0, pygame.sprite.collide_mask)
                if burned:
                    explosions.add(Explosion(explosion3, ship.x - ship.width * 0.5, ship.y - ship.height * 0.5, 2, 5))
                    crashed_text.message('you died. BUT DO NOT PANIC!',
                                         display_width * 0.5, display_height * 0.5, centered=True)
                    pygame.display.update()
                    waiting = True
                    while waiting:
                        for event in pygame.event.get():
                            if event.type == pygame.QUIT:
                                pygame.quit()
                                quit()
                            if event.type == pygame.KEYDOWN:
                                if event.key == pygame.K_RETURN:
                                    waiting = False
                                    playing = False
                        for explosion in explosions:
                            explosion.update()
                        performance_text.message('Return to main menu by pressing Enter and try again.',
                                                 display_width * 0.5, 500, centered=True)
                        pygame.display.update()

        if boss_battle is False and won is True:
            if ship_centered is False:
                ship_centered = ship.to_end_position(display_width*0.5 - ship.width * 0.5)

        # Check for collisions after new display if updated
        crashed = pygame.sprite.groupcollide(ship_group, meteors, 0, 0, pygame.sprite.collide_mask)
        hit = pygame.sprite.groupcollide(enemy_lasers, ship_group, 1, 0, pygame.sprite.collide_mask)
        if crashed or hit:
            explosions.add(Explosion(explosion3, ship.x - ship.width * 0.5, ship.y - ship.height * 0.5, 2, 5))
            crashed_text.message('you died. BUT DO NOT PANIC!',
                                 display_width * 0.5, display_height * 0.5, centered=True)
            pygame.display.update()
            waiting = True
            while waiting:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        quit()

                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_RETURN:
                            waiting = False
                            playing = False

                for explosion in explosions:
                    explosion.update()
                performance_text.message('Return to main menu by pressing Enter and try again.',
                                         display_width * 0.5, 500, centered=True)
                pygame.display.update()

        # Kill sprites after collision
        pygame.sprite.groupcollide(lasers, meteors, 1, 0, pygame.sprite.collide_mask)
        pygame.sprite.groupcollide(enemy_lasers, meteors, 1, 0, pygame.sprite.collide_mask)

        enemy_hit = pygame.sprite.groupcollide(enemies, lasers, 1, 1, pygame.sprite.collide_mask)
        for sprite in enemy_hit:
            if enemy_hit[sprite]:
                explosions.add(Explosion(explosion1, sprite.x, sprite.y))
                pygame.mixer.Channel(3).play(explosion_sound)
                score_count += 100
                enemies_killed += 1

        # Lastly, show text
        performance_text.message('score: ' + str(score_count), 5, 0)
        performance_text.message('%i' % (timer/1000), display_width - 45, 0)

        if ms_announcement:
            shower_text.message('METEOR SHOWER INCOMING', display_width * 0.5, display_height * 0.5, centered=True)

        if boss_announcement:
            shower_text.message('FINAL BOSS INCOMING', display_width * 0.5, display_height * 0.5, centered=True)

        if ship_centered is True:
            performance_text.message('meteors dodged: %i' % meteors_dodged, display_width * 0.5, 360, centered=True)
            performance_text.message('enemies destroyed: %i:' % enemies_killed, display_width * 0.5, 380, centered=True)
            performance_text.message('bosses destroyed: %i' % bosses_killed, display_width * 0.5, 400, centered=True)
            endgame_score_text.message('Final score: %i' % score_count, display_width * 0.5, 430, centered=True)
            performance_text.message('press enter to return to main menu', display_width * 0.5, 500, centered=True)

        pygame.display.update()

        # Set FPS
        clock.tick(fps)

# Here we initialize pygame, set variables and start the actual game
pygame.init()
# pygame.mouse.set_cursor(*pygame.cursors.diamond)
pygame.mouse.set_cursor(*pygame.cursors.broken_x)

# Define some colors
black = (0, 0, 0)  # (R,G,B)
red = (255, 0, 0)
green = (0, 255, 0)

# Setup a window for the game
display_width = 800
display_height = 800
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('MyFirstGame')  # Window Title

# -- Load sprites from spritesheets
spritesheet_explosion1 = pygame.image.load('Textures/explosions.png')
explosion1 = []
x_all = [628, 628, 628, 628, 576, 566, 562, 562, 562, 562, 924, 858, 792, 726, 660, 594, 924, 858, 792, 726, 660, 594,
         924, 764]
y_all = [772, 706, 640, 574, 938, 872, 772, 706, 640, 574, 502, 496, 496, 496, 496, 496, 436, 430, 430, 430, 430, 430,
         370, 826]
height = 64
width = 64

for i in range(24):
    frame = str(i)
    if len(frame) is 1:
        frame = '0' + frame
    x = x_all[i]
    y = y_all[i]
    explosion1.append(spritesheet_explosion1.subsurface(pygame.Rect(x, y, width, height)))

explosion3 = []
x_all = [100, 100, 100, 100, 888, 790, 692, 594, 496, 398, 300, 202, 104, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 100]
y_all = [398, 300, 202, 104, 2, 2, 2, 2, 2, 2, 2, 2, 2, 884, 786, 688, 590, 492, 394, 296, 198, 100, 2, 496]
h = 96
w = 96

for i in range(24):
    frame = str(i)
    if len(frame) is 1:
        frame = '0' + frame
    x = x_all[i]
    y = y_all[i]

    explosion3.append(spritesheet_explosion1.subsurface(pygame.Rect(x, y, h, w)))

spritesheet_explosion2 = pygame.image.load('Textures/particlefx_06.png')
height_exp = 128
width_exp = 128
explosion2 = []
for i in range(8):
    for j in range(8):
        explosion2.append(spritesheet_explosion2.subsurface(pygame.Rect(
            i*height_exp, j*width_exp, height_exp, width_exp)))

spritesheetspace = pygame.image.load('Textures/spritesheet_space.png')
start_button = spritesheetspace.subsurface(pygame.Rect(0, 117, 222, 39))
credit_button = spritesheetspace.subsurface(pygame.Rect(0, 78, 222, 39))
quit_button = spritesheetspace.subsurface(pygame.Rect(0, 0, 222, 39))
enemy1 = spritesheetspace.subsurface(pygame.Rect(423, 728, 93, 84))
enemy2 = spritesheetspace.subsurface(pygame.Rect(120, 604, 104, 84))
enemy3 = spritesheetspace.subsurface(pygame.Rect(144, 156, 103, 84))
laser_blue = spritesheetspace.subsurface(pygame.Rect(856, 421, 9, 54))
laser_red = spritesheetspace.subsurface(pygame.Rect(858, 230, 9, 54))
meteor1 = spritesheetspace.subsurface(pygame.Rect(224, 664, 101, 84))
meteor2 = spritesheetspace.subsurface(pygame.Rect(0, 520, 120, 98))
meteor3 = spritesheetspace.subsurface(pygame.Rect(518, 810, 89, 82))
meteor4 = spritesheetspace.subsurface(pygame.Rect(327, 452, 98, 96))
player_ship = spritesheetspace.subsurface(pygame.Rect(224, 832, 99, 75))
spritesheetspace2 = pygame.image.load('Textures/spritesheet_space2.png')
missile = spritesheetspace2.subsurface(pygame.Rect(1093, 711, 19, 40))
boss_image = spritesheetspace2.subsurface(pygame.Rect(276, 0, 172, 151))
controlscheme = pygame.image.load('Textures/controlscheme.png')
background = pygame.image.load('Textures/space_background.png').convert()
credit_background = pygame.image.load('Textures/credits.png').convert()

# Load files used in the game
game_music = pygame.mixer.Sound('Sounds/desert-travel.ogg')  # Channel 0
game_music.set_volume(0.5)
button_sound = pygame.mixer.Sound('Sounds/click_menu_sound.wav')  # Channel 1
laser_sound = pygame.mixer.Sound('Sounds/laser5.wav')  # Channel 1
enemy_laser_sound = pygame.mixer.Sound('Sounds/laser8.wav')  # Channel 2
enemy_laser_sound.set_volume(0.5)
explosion_sound = pygame.mixer.Sound('Sounds/explodemini.wav')  # Channel 3
bomb_release_sound = pygame.mixer.Sound('Sounds/weaponfire4.wav')  # Channel 4
bomb_explosion_sound = pygame.mixer.Sound('Sounds/explosion2.wav')  # Channel 5

# Load fonts to use in the game
performance_text = ChooseFont('Fonts/xirod.ttf', 15, green)
endgame_score_text = ChooseFont('Fonts/xirod.ttf', 30, green)
crashed_text = ChooseFont('Fonts/xirod.ttf', 30, red)
shower_text = ChooseFont('Fonts/xirod.ttf', 30, red)

# Define game clock to time things
clock = pygame.time.Clock()

main_menu()


# ---------------------------------------------------
#
# 필수 import 파일임:
# scripts 폴더의 스크립트들이 서로 import하기 위해서는
# scripts 폴더를 pythonpath에 등록해야한다.
#
# ---------------------------------------------------

import os

dirpath = os.path.dirname(os.path.realpath(__file__))
dirpath = dirpath + "\\scripts"

print('Using modified Pythonpath from PYTHONPATH.py')
os.sys.path.append(dirpath)


from QLearning import Game
from collections import Counter
import pandas as pd
import matplotlib.pyplot as plt

gamma = 0.1

def Menu():
    usr_op = None
    while usr_op != 0:
        print('//-//-//-// Card-Jitsu Menu //-//-//-//')
        print('\nSelect an option to continue: ')
        print('1. Play game vs AI.')
        print('2. Get Strategy Metrics.')
        print('3. Get Random Metrics.')
        print('4. Train Ai Manual.')
        print('5. Train Ai Random.')
        print('0. Exit.')

        usr_op = int(input('\n Option selected: '))
        if usr_op == 1:
            Game(gamma)
        elif usr_op == 2:
            get_metrics(is_random = False, train = False, show_game = True)
        elif usr_op == 3:
            get_metrics(is_random = True, train = False, show_game = False)
        elif usr_op == 4:
            get_metrics(is_random = False, train = True, show_game = True)
        elif usr_op == 5:
            get_metrics(is_random = True, train = True, show_game = False, show_metrics = False)

        print('\n\n')

def get_metrics(is_random, train, show_game, show_metrics = True):

    history = {
        'Game': [],
        'Round': [],
        'AI': [],
        'Player': [],
        'Winner': [],
        'Game Winner': []
    }

    game = 0
    g = int(input('Numero de juegos a realizar: '))

    while game < g:
        winrecord , winner = Game(gamma, is_random, train, show_game)

        for round in range(len(winrecord)):
            history['Game'].append(game)
            history['Game Winner'].append(winner)
            history['Round'].append(round)
            history['AI'].append(winrecord[round]['AI'])
            history['Player'].append(winrecord[round]['Player'])
            history['Winner'].append(winrecord[round]['Winner'])

        game += 1

    if not show_metrics: return 0

    history = pd.DataFrame.from_dict(history)

    # Histograma de Rondas y juegos
    game_winrate = Counter(list(history['Game Winner']))
    game_winrate = pd.DataFrame.from_dict(game_winrate, orient='index', columns=['Games Won'])
    game_winrate.plot(kind='pie', y='Games Won', autopct='%1.0f%%', explode=(0.01, 0.01), startangle=20)
    plt.title('Frecuency of Games Won')
    plt.ylabel('')
    plt.show()

    # Diagrama de Pie de rondas ganadas

    round_winrate = Counter(list(history['Winner']))
    round_winrate = pd.DataFrame.from_dict(round_winrate, orient='index', columns=['Rounds Won'])
    round_winrate.plot(kind='pie', y='Rounds Won', autopct='%1.0f%%', explode=(0.01, 0.01, 0.01), startangle=60)

    plt.title('Frecuency of Rounds Won and Tied')
    plt.ylabel('')
    plt.show()

    # Histograma de cartas
    ai_cardrate = Counter(list(history['AI']))
    ai_cardrate = pd.DataFrame.from_dict(ai_cardrate, orient='index', columns=['AI Cards'])

    player_cardrate = Counter(list(history['Player']))
    player_cardrate = pd.DataFrame.from_dict(player_cardrate, orient='index', columns=['Player Cards'])

    hist_cardrate = ai_cardrate.merge(player_cardrate, how='outer', left_index=True, right_index=True).fillna(0)
    hist_cardrate.plot(kind = 'bar')

    plt.title('Frecuency of Cards Used')
    plt.show()

Menu()


"""Basic status commands to check the health of the bot."""
import datetime

import discord
from discord.ext import commands

from metricity.config import BotConfig

DESCRIPTIONS = (
    "Command processing time",
    "Last event received",
    "Discord API latency",
)
ROUND_LATENCY = 3
INTRO_MESSAGE = "Hello, I'm {name}. I insert all your data into a GDPR-compliant database."

class Status(commands.Cog):
    """Get the latency between the bot and Discord."""

    def __init__(self, bot: commands.Bot) -> None:
        self.bot = bot

    @commands.Cog.listener()
    async def on_socket_event_type(self, _: str) -> None:
        """Store the last event received as an int."""
        self.last_event_received = int(datetime.datetime.now(datetime.UTC).timestamp())

    @commands.command()
    @commands.has_any_role(BotConfig.staff_role_id)
    @commands.guild_only()
    async def status(self, ctx: commands.Context) -> None:
        """Respond with an embed with useful status info for debugging."""
        if ctx.guild.id != BotConfig.guild_id:
            return

        bot_ping = (datetime.datetime.now(datetime.UTC) - ctx.message.created_at).total_seconds() * 1000
        if bot_ping <= 0:
            bot_ping = "Your clock is out of sync, could not calculate ping."
        else:
            bot_ping = f"{bot_ping:.{ROUND_LATENCY}f} ms"

        discord_ping = f"{self.bot.latency * 1000:.{ROUND_LATENCY}f} ms"

        last_event = f"<t:{self.last_event_received}>"

        embed = discord.Embed(
            title="Status",
            description=INTRO_MESSAGE.format(name=ctx.guild.me.display_name),
        )

        for desc, latency in zip(DESCRIPTIONS, (bot_ping, last_event, discord_ping), strict=True):
            embed.add_field(name=desc, value=latency, inline=False)

        await ctx.send(embed=embed)

async def setup(bot: commands.Bot) -> None:
    """Load the status extension."""
    await bot.add_cog(Status(bot))


#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
test_pyredatam

Tests for `pyredatam` module.
"""

from __future__ import unicode_literals
import unittest
import nose

import pyredatam
import queries

class RedatamTestCase(unittest.TestCase):

    def test_arealist_query(self):

        # Test case AREALIST1
        area_level = "FRAC"
        variables = "PERSONA.CONDACT"

        area_filter = {"PROV": ["02", "03"]}
        universe_filter = "1 = 1"
        title = "El titulo"

        query = pyredatam.arealist_query(area_level, variables, area_filter,
                                         universe_filter, title)
        self.assertEqual(query, queries.AREALIST1.strip())

        # Test case AREALIST2
        variables = ["PERSONA.CONDACT"]
        query = pyredatam.arealist_query(area_level, variables)
        self.assertEqual(query, queries.AREALIST2.strip())

        # Test case AREALIST3
        area_filter = {"PROV": "02"}
        query = pyredatam.arealist_query(area_level, variables, area_filter)
        self.assertEqual(query, queries.AREALIST3.strip())

    def test_counter_query(self):

        # Test case COUNTER1
        area_level = "RADIO"
        entity_count = "PERSONA"

        area_filter = {"PROV": "02"}
        universe_filter = "1 = 1"
        title = "El titulo"

        query = pyredatam.counter_query(area_level, entity_count, area_filter,
                                        universe_filter, title)
        self.assertEqual(query, queries.COUNTER1.strip())

        # Test case COUNTER2
        area_level = "DPTO"
        entity_count = "FRAC"
        incl_area_name = True
        incl_total = True
        query = pyredatam.counter_query(area_level, entity_count, area_filter,
                                        universe_filter, title, incl_area_name,
                                        incl_total)
        self.assertEqual(query, queries.COUNTER2.strip())

    def test_median_query(self):

        # Test case MEDIAN1
        variable = "PERSONA.P03"
        by_var1 = "PERSONA.CONDACT"
        by_var2 = "PERSONA.P02"
        incl_name = True
        area_break = "PROV"

        area_filter = None
        universe_filter = "1 = 1"
        title = "El titulo"

        query = pyredatam.median_query(variable, by_var1, by_var2, incl_name,
                                       area_break, area_filter,
                                       universe_filter, title)
        self.assertEqual(query, queries.MEDIAN1.strip())

        # Test case MEDIAN2
        variable = "PERSONA.P03"
        incl_name = None
        area_break = None

        universe_filter = None
        title = None
        query = pyredatam.median_query(variable, by_var1, by_var2, incl_name,
                                       area_break, area_filter,
                                       universe_filter, title)
        self.assertEqual(query, queries.MEDIAN2.strip())

        # Test case MEDIAN3
        variable = "PERSONA.P03"
        by_var1 = None
        by_var2 = None
        query = pyredatam.median_query(variable, by_var1, by_var2, incl_name,
                                       area_break, area_filter,
                                       universe_filter, title)
        self.assertEqual(query, queries.MEDIAN3.strip())

if __name__ == '__main__':
    nose.run(defaultTest=__name__)


import cv2
import numpy as np
from imageclassifier import ImageClassifier

n_clusters = [3, 4, 5, 6, 7, 8]
kmeans_keys = [
    [0], [1], [2],
    [0, 1], [0, 2], [1, 2],
    [0, 1, 2]
]

sorting_lambdas = [
    lambda pixel: pixel[0],
    lambda pixel: pixel[1],
    lambda pixel: pixel[2],
    lambda pixel: sum(pixel),
    lambda pixel: max(pixel)
]

cl_sorting_lambdas = [
    lambda cluster: cluster[0][0][0],
    lambda cluster: cluster[0][0][1],
    lambda cluster: cluster[0][0][2],
    lambda cluster: sum(cluster[0][0]),
    lambda cluster: max(cluster[0][0])
]

coeffs = []
for i in range(5):
    for j in range(5):
        for k in range(5):
            coeffs.append([i, j, k])

sorting_keys = [i for i in range(len(sorting_lambdas))]

colorspaces = [None, cv2.COLOR_BGR2HSV, cv2.COLOR_BGR2LAB, cv2.COLOR_BGR2HLS]

def str_colorspace(colorspace):
    if colorspace == None:
        return "BGR"
    if colorspace == cv2.COLOR_BGR2HSV:
        return "HSV"
    if colorspace == cv2.COLOR_BGR2LAB:
        return "LAB"
    if colorspace == cv2.COLOR_BGR2HLS:
        return "HLS"

def save(folder, img, n_cluster, key, color_in, sorting_key, color_sort):

    filename = folder + "/c{0}_k".format(n_cluster)
    filename = filename + '-'.join([str(s) for s in key])
    filename = filename + '_' + str_colorspace(color_in) + "_"
    filename = filename + 's{0}_'.format(sorting_key)
    filename = filename + str_colorspace(color_sort) + ".png"
    cv2.imwrite(filename, img)
    print("saved: " + filename)

def bruteforce(target, folder):
    for n_cluster in n_clusters:
        classifier = ImageClassifier(n_cluster, target)
        for color_in in colorspaces:
            df = classifier.get_dataframe(colorspace=color_in)
            for key in kmeans_keys:
                cluster_map = classifier.run_kmeans(df, key)
                clusters = classifier.get_clusters(cluster_map)
                clusters_bak = clusters.copy()
                for color_sort in colorspaces:
                        for sorting_key in sorting_keys:
                            cmp1 = sorting_lambdas[sorting_key]
                            cmp2 = cl_sorting_lambdas[sorting_key]
                            clusters = classifier.sort_clusters(clusters, cmp1, color_sort=color_sort)
                            res = classifier.merge_clusters(clusters, cmp2)
                            save(folder, res, n_cluster, key, color_in, sorting_key, color_sort)
                            clusters = clusters_bak.copy()

def process():
    n_cluster = 4
    classifier = ImageClassifier(n_cluster, 'src.jpg')
    df = classifier.get_dataframe(colorspace=cv2.COLOR_BGR2HSV)
    cluster_map = classifier.run_kmeans(df, [0])
    clusters = classifier.get_clusters(cluster_map)

    clusters_bak = clusters.copy()

    #cmp = lambda pixel: (255 - int(pixel[1])) * 2 - (200 if pixel[1] < pixel[2] else 0)
    cmp = lambda pixel: int(pixel[0])
    #cmp = lambda pixel: pixel[1]
    clusters = classifier.sort_clusters(clusters, cmp, color_sort=cv2.COLOR_BGR2LAB)
    res = classifier.merge_clusters(clusters, lambda cluster: sum(cluster[0][0]))
    #filename = 'res_sort/res_{0}_{1}_{2}.png'.format(coeff[0], coeff[1], coeff[2])
    filename="res.png"
    cv2.imwrite(filename, res)
    print('saved {0}'.format(filename))

    clusters = clusters_bak.copy()

def compare(target1, target2):

    cl1 = ImageClassifier(4, target1)
    cl2 = ImageClassifier(4, target2)

    df1 = cl1.get_dataframe()
    df2 = cl2.get_dataframe()

    print(df1.describe())
    print(df2.describe())
    exit()
    img1 = cv2.imread(target1)
    img2 = cv2.imread(target2)
    shape1 = img1.shape
    shape2 = img2.shape

    img1 = np.reshape(img1, (shape1[0] * shape1[1], 3))
    img2 = np.reshape(img2, (shape2[0] * shape2[1], 3))

    img1 = sorted(img1, key = lambda pixel: sum(pixel))
    img2 = sorted(img2, key = lambda pixel: sum(pixel))

    img1 = np.reshape(img1, (shape1))
    img2 = np.reshape(img2, (shape2))

    cv2.imwrite('img1.png', img1)
    cv2.imwrite('img2.png', img2)

# bruteforce("town.jpg", "result/town")
# compare("res.png", "town.jpg")
process()


'''
7. Reverse Integer

https://leetcode.com/problems/reverse-integer/description/

Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0.

Assume the environment does not allow you to store 64-bit integers (signed or unsigned).

Example 1:

Input: x = 123
Output: 321
Example 2:

Input: x = -123
Output: -321
Example 3:

Input: x = 120
Output: 21

Constraints:

-231 <= x <= 231 - 1
'''

class Solution:
    def reverse(self, x: int) -> int:
        s = str(x)

        if x >= 0 : return  int(s[::-1]) if int(s[::-1]) <= (2**31 - 1) else 0
        else:
                s = str(abs(x))
                return int('-'+s[::-1]) if int(s[::-1]) <= (2**31) else 0


import os

import wx
from wx.lib.colourchooser.canvas import Canvas

class ImageCanvas(wx.Panel):
    """
    Image Panel

    """
    def __init__(self, parent, image_path=None, *args, **kwargs):
        """
        Constructor

        :param parent:
        """
        wx.Panel.__init__(self, parent=parent, *args, **kwargs)

        self.image_path = image_path
        if self.image_path:
            bmp = wx.Bitmap(self.image_path)

            padding = 10
            self.SetMinClientSize((bmp.GetWidth() + padding,
                                   bmp.GetHeight() + padding))

        self.glyphs = []

        # self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.frame = parent

        # img = wx.EmptyImage(240, 240)

        self.main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.main_sizer.Add((1, 1), 0, wx.EXPAND, 75)
        # self.main_sizer.Add(img, 0, wx.EXPAND)
        self.main_sizer.Add((1,1), 0, wx.ALL, 75)

        self.SetSizer(self.main_sizer)

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase_background)
        self.Bind(wx.EVT_SIZE, self.on_size)

    def set_sizer(self):
        """

        :param sizer:
        :return:
        """
        sizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)

        for num in range(4):
            label = "Button %s" % num
            btn = wx.Button(self, label=label)
            sizer.Add(btn, 0, wx.ALL, 5)

        hSizer.Add((1,1), 1, wx.EXPAND)
        hSizer.Add(sizer, 0, wx.TOP, 100)
        hSizer.Add((1,1), 0, wx.ALL, 75)

        self.SetSizer(hSizer)

    def on_size(self, event):
        """

        :param event:
        """

        event.Skip()
        self.Refresh()

    def scale_image(self, image, max_width=None, max_height=None):
        """

        :param image:
        :param max_width:
        :param max_height:
        :return:
        """
        width = image.GetWidth()
        height = image.GetHeight()
        ratio = min(max_width / width, max_height / height)
        image = image.Scale(ratio * width, ratio * height, wx.IMAGE_QUALITY_HIGH)
        result = wx.BitmapFromImage(image)

        return result

    def on_erase_background(self, event):
        """
        Add a picture to the background

        :param event:
        """

        # self.Freeze()

        dc = event.GetDC()
        w, h = self.GetClientSize()

        if not dc:
            dc = wx.ClientDC(self)
            rect = self.GetUpdateRegion().GetBox()
            dc.SetClippingRect(rect)
        dc.Clear()

        if self.image_path:
            bmp = wx.Bitmap(self.image_path)
            # bmp = self.scale_image(bmp, 100, 200)
            size = bmp.GetSize()

            x = int(w/2.0 - size.x/2.0)
            y = int(h/2.0 - size.y/2.0)

            dc.DrawBitmap(bmp, x, y)

        self.draw_model(dc)

        # self.Thaw()

    def draw_model(self, dc):
        """
        Draw glyps

        :param dc:
        :return:
        """
        for glyph in self.glyphs:
            glyph.draw(dc)

class Glyph(object):
    def __init__(self, *args, **kwargs):
        self.pen_color = kwargs.get('pen_color', wx.BLACK)
        self.pen_width = kwargs.get('pen_width', 5)

        self.coordinates = kwargs.get('coordinates', [])

    def set_pen(self, dc):
        dc.SetPen(self.pen_color, self.pen_width)

    def pre_draw(self, dc):
        self.set_pen()

    def post_draw(self, dc):
        pass

    def _draw_(self, dc):
        pass

    def draw(self, dc):
        self.pre_draw(dc)
        self._draw_(dc)
        self.post_draw(dc)

class Arc(Glyph):
    """

    """
    def _draw_(self, dc):
        pass

class Line(Glyph):
    """

    """
    def _draw_(self, dc):
        xy1 = self.coordinates[0]
        xy2 = self.coordinates[1]

        dc.DrawLine(xy1[0], xy1[1], xy2[0], xy2[1])

class Circle(Glyph):
    """

    """
    def _draw_(self, dc):
        xy = self.coordinates[0]

        dc.DrawCircle(xy[0], xy[1], 100)

class Rectangle(Glyph):
    """

    """
    def _draw_(self, dc):
        pass


import unittest

from zag import *
from zag.configable import ConfigException

class ConfigTest(unittest.TestCase):

    def test_stage(self):
        foo = PyTask("zag.foo")

        workflow = Sequence("foo-flow", stages=[
            Stage("run-foo",
                foo,
                args=[
                    ("--foo-type", "$type")
                ])
        ])

        self.assertEqual(workflow.get_config(), {})

        my_config = {"type": "ponies"}

        nw = workflow.apply_config(my_config)

        self.assertEqual(nw.stages[0].args, [("--foo-type", "ponies")])

    def test_missing_value(self):
        foo = PyTask("zag.foo")

        workflow = Sequence("foo-flow", stages=[
            Stage("run-foo",
                foo,
                args=[
                    ("--foo-type", "$type"),
                    ("--missing-val", "$mv")
                ])
        ])

        self.assertEqual(workflow.get_config(), {})

        my_config = {"type": "ponies"}

        with self.assertRaises(ConfigException):
            nw = workflow.apply_config(my_config)

    def test_nested_workflows(self):
        foo = PyTask("zag.foo")

        simple_stage = Stage("run-foo",
            foo,
            args=[
                ("--foo-type", "$type")
            ])

        bar = Sequence('bar-flow',
            config={
                "type": "bar"
            },
            stages=[simple_stage])

        baz = Sequence('baz-flow',
            config={
                "type": "baz"
            },
            stages=[simple_stage])

        qux = Sequence('qux-flow',
            config={
                "type": "qux"
            },
            stages=[baz])

        workflow = Sequence("all-workflows", stages=[
            bar,
            qux,
            baz
        ])

        config = {}
        nw = workflow.apply_config(config)

        self.assertEqual(nw.stages[0].stages[0].args, [("--foo-type", "bar")])
        self.assertEqual(nw.stages[1].stages[0].stages[0].args, [("--foo-type", "qux")])
        self.assertEqual(nw.stages[2].stages[0].args, [("--foo-type", "baz")])

    def test_tags(self):
        simple_stage = Stage("run-foo",
            PyTask("zag.foo"),
            args=[
                ("--foo-type", "$type")
            ],
            tags=['$tag'])

        baz = Sequence('baz-flow',
            config={
                "type": "baz"
            },
            stages=[simple_stage],
            tags=["fomo"])

        with self.assertRaises(ConfigException):
            baz.apply_config({})

        nw = baz.apply_config({"tag": "TAG"})
        self.assertEqual(nw.stages[0].tags, {"TAG"})

    def test_inherit_tags(self):
        simple_stage = Stage("run-foo",
            PyTask("zag.foo"),
            args=[
                ("--foo-type", "$type")
            ],
            tags=['foo'])

        baz = Sequence('baz-flow',
            config={
                "type": "baz"
            },
            stages=[simple_stage],
            tags=['all-baz'])

        stages = baz.apply_config({"tag": "TAG"}).resolve_stages()
        stages = list(stages)
        self.assertEqual(stages[0].tags, {"foo", "baz-flow", "all-baz"})

class ZagTest(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_identity(self):
        pass

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


#!/usr/bin/env python

__author__ = 'j5wagner@ucsd.edu'

import commands
from d3r.celppade.custom_protein_prep import ProteinPrep

class chimera_dockprep(ProteinPrep):
    """Abstract class defining methods for a custom docking solution
    for CELPP
    """

    ProteinPrep.OUTPUT_PROTEIN_SUFFIX = '.mol2'

    def receptor_scientific_prep(self,
                                 protein_file,
                                 prepared_protein_file,
                                 targ_info_dict={}):
        """
        Protein 'scientific preparation' is the process of generating
        a dockable representation of the candidate protein from a
        single-chain PDB file.
        :param protein_file: PDB file containing candidate protein.
        :param prepared_protein_file: The result of preparation should have this file name.
        :param targ_info_dict: A dictionary of information about this target and the candidates chosen for docking.
        :returns: True if preparation was successful. False otherwise.
        """

        #####################################################################
        ### $ python  clean_receptor.py  receptor.pdb  clean_receptor.pdb ###
        #####################################################################

        # Implements the logic that was formerly in clean_receptor.py
        orig_pdb = open(protein_file).readlines()
        with open('clean_receptor.pdb','wb') as of:
            for line in orig_pdb:
                if len(line) > 4:
                    if line[:4] == 'ATOM':
                        of.write(line)

        #####################################################################
        ### $ chimera  --nogui  --script  "chimeraPrep.py  clean_receptor.pdb  prepared_receptor.mol2"
        #####################################################################

        # Write the chimera-interpreted code to a script file
        chimera_prep_text = '''import chimera
import sys
opened = chimera.openModels.open(sys.argv[1])
mol = opened[0]

import DockPrep

DockPrep.prep([mol])
from WriteMol2 import writeMol2
with open(sys.argv[2],'wb') as of:
    writeMol2([mol], of)
'''
        with open('chimera_prep.py','wb') as of:
            of.write(chimera_prep_text)

        # Run chimera with the script as an input
        prep_cmd = 'chimera  --nogui  --script  "chimera_prep.py  clean_receptor.pdb ' + prepared_protein_file + ' " 1> prep.stdout 2> prep.stderr'
        commands.getoutput(prep_cmd)

        return True

if ("__main__") == (__name__):
    import logging
    import os
    import shutil
    from argparse import ArgumentParser
    parser = ArgumentParser()
    parser.add_argument("-p", "--pdbdb", metavar = "PATH", help = "PDB DATABANK which we will dock into")
    parser.add_argument("-c", "--challengedata", metavar="PATH", help = "PATH to the unpacked challenge data package")
    parser.add_argument("-o", "--prepdir", metavar = "PATH", help = "PATH to the output directory")
    logger = logging.getLogger()
    logging.basicConfig( format  = '%(asctime)s: %(message)s', datefmt = '%m/%d/%y %I:%M:%S', filename = 'final.log', filemode = 'w', level = logging.INFO )
    opt = parser.parse_args()
    pdb_location = opt.pdbdb
    challenge_data_path = opt.challengedata
    prep_result_path = opt.prepdir

    #running under this dir
    abs_running_dir = os.getcwd()
    log_file_path = os.path.join(abs_running_dir, 'final.log')
    log_file_dest = os.path.join(os.path.abspath(prep_result_path), 'final.log')

    prot_prepper = chimera_dockprep()
    prot_prepper.run_scientific_protein_prep(challenge_data_path, pdb_location, prep_result_path)

    #move the final log file to the result dir
    shutil.move(log_file_path, log_file_dest)


import datetime
import json
import os
import re
import shutil

class Fileop():
    def isDirectory(self, fDir):
        return os.path.isdir(fDir)

    def countDir(self, dPath):
        dirListing = next(os.walk(dPath))[2]
        return len(dirListing)

    def CjsonLoad(self, jfile):
        fdir = os.path.join(Fileop.dwnDir(''), "conf")
        condir = Fileop.isDirectory('', fdir)
        if condir:
            confile = os.path.join(fdir, jfile)
            with open(confile, "r") as j:
                return json.load(j)

    def SjsonLoad(self, jfile):
        fdir = Fileop.dwnDir('')
        condir = Fileop.isDirectory('', fdir)
        if condir:
            confile = os.path.join(fdir, jfile)
            with open(confile, "r") as j:
                return json.load(j)

    def curWorkDir(self):
        return os.path.dirname(os.path.realpath(__file__))

    def makDir(self, Folder):
        try:
            os.makedirs(Folder)
        except OSError as e:
            print("Warning making {0} : MSG - {1}".format(Folder, e))

    def dwnDir(self):
        return os.path.normpath(os.getcwd() + os.sep + os.pardir)

    def newDirec(self, nDirName):
        return os.mkdir(nDirName)

    def RecFileDir(self, dirName):
        new_Folder = os.path.join(Fileop.dwnDir(''), dirName)
        dFlag = Fileop.isDirectory('', new_Folder)
        if not dFlag:
            # make directory
            try:
                Fileop.newDirec('', new_Folder)
            except OSError:
                print("Creation of the directory %s failed. \n" % new_Folder)
            else:
                print("Successfully created the directory %s.\n " % new_Folder)
        else:
            print("Directory ( %s ) already exists.\n" % new_Folder)
        return new_Folder

    def newest(self, path):
        files = os.listdir(path)
        lenfile = len(files)
        if lenfile != 0:
            paths = [os.path.join(path, basename) for basename in files]
            return max(paths, key=os.path.getctime)
        else:
            print("Directory ( %s ) is empty\n", path)

    def removefiles(self, folder):
        files_in_directory = os.listdir(folder)
        filtered_files = [file for file in files_in_directory if file.endswith(".wav")]
        dircount = Fileop.countDir('', folder)
        if dircount > 1:
            for file in filtered_files:
                path_to_file = os.path.join(folder, file)
                os.remove(path_to_file)
        else:
            print('Failed to delete files, {0} is empty: \n'.format(folder))

    def moveFiles(self, froDir, toDir, froFile, toFile):
        try:
            shutil.move(os.path.join(froDir, froFile), os.path.join(toDir, toFile))
            print("Successfully moved {0}.\n".format(os.path.join(froDir, froFile)))
        except OSError:
            print("Could not move file ({0}) operation.\n".format(os.path.join(froDir, froFile)))

    def main(self):
        # Check if directories have been created
        source_param = Fileop.CjsonLoad('', "conf.json")
        source_rep = os.path.join(Fileop.dwnDir(''), "reports")
        Fileop.RecFileDir('', source_rep)
        dwn_dir = source_param['download_dir']
        # Recordings directory based on current date
        recFolder = "Recordings" + datetime.datetime.now().strftime("%Y%m%d")
        dirRecs = Fileop.RecFileDir('', recFolder)
        # print(dirRecs)
        # get latest data report file
        newFile = Fileop.newest('', source_rep)
        # print (newFile)
        count = 0
        if Fileop.countDir('', dwn_dir) != 0:
            with open(newFile, "r") as nf:
                lines = nf.readlines()
                for line in lines:
                    count += 1
                    line_id = ' '.join(re.findall(r'\b\w+\b', line)[:+1])
                    line_data = ' '.join(re.findall(r'\b\w+\b', line)[:]).replace(line_id, "")
                    line_data = "_".join(line_data.split())
                    print("line {0} - file ID : {1} file metadata :- {2} \n".format(count, line_id, line_data))
                    # move and rename files
                    Fileop.moveFiles("", dwn_dir, dirRecs, line_id + ".wav", line_data + ".wav")
        else:
            print("Warning: Call recordings download did not run!\n")
# if __name__ == "__main__":
#     main()


from typing import Any, Dict

def play_game() -> None:
    print('playing game')

def update_state(current_state: Dict) -> Dict:
    print('here we change things')

    possible_actions = {
        'mod status': lambda : print('modifting status'),
        'remove status': lambda : print('removing status'),
        'go back': lambda : print('saving updates')
    }
    show_commands('update status menu', possible_actions)
    return current_state

def quit():
    print('good bye m8')

def show_commands(title: str, commands: Dict) -> Any:

    print(title.upper())
    idxs = {}
    for idx, op in enumerate(commands):
        print(f'{op} -> press [{idx}]')
        idxs[str(idx)] = commands[op]

    while True:
        user_op =  input('select an option > ')
        if user_op in idxs:
            return idxs[user_op]()

def main():
    state = {
        'user_name': 'santi'
    }

    commands = {
        'play': play_game,
        'quit': quit,
        'update_satus': lambda : update_state(state)
    }

    show_commands('main menu', commands=commands)

main()


# Licensed under a 3-clause BSD style license - see LICENSE
from __future__ import print_function, division

from astropy.table import Table, Column

from .import_modules import *

##----- ----- ----- ----- ----- ----- ----- ----- ----- -----##
## Miscellaneous utilities
## Contain functions that do not pertain to a particular class.
##----- ----- ----- ----- ----- ----- ----- ----- ----- -----##

def Fit_linear(y, x=None, err=1.0, m=None, b=None, output=None, inline=False):
    """
    Fit_linear(y, x=None, err=1.0, m=None, b=None, output=None, inline=False):
    return (sol, res, rank, s)
    Uses the scipy.linalg.lstsq function to solve the equation y = mx + b
    sol -> [b, m]
    N.B. Uses the scipy.linalg.lstsq algorithm.
    If inline = True, flattens the results.
    """
    #x = array([52997., 53210., 53310., 53380.])
    #y = array([1.66, 1.54, 1.4, 1.4])
    # standard error of the y-variable:
    #sy = array([0.05, 0.05, 0.05, 0.05])

    if x is None:
        x = np.arange(y.shape[0], dtype=float)
    if (b is not None) and (m is not None):
        sol = [b, m]
        res = (((b + m*x - y)/err)**2).sum()
        rank = 0.
        s = 0.
    else:
        if b is not None:
            A = np.reshape(x/err,(x.shape[0],1))
            y1 = y-b
            y1 /= err
            sol, res, rank, s = scipy.linalg.lstsq(A, y1)
            sol = [b,sol[0]]
        elif m is not None:
            A = np.resize(1/err,(x.shape[0],1))
            y1 = y-m*x
            y1 /= err
            sol, res, rank, s = scipy.linalg.lstsq(A, y1)
            sol = [sol[0],m]
        else:
            A = (np.vstack([np.ones(x.shape[0], dtype=float),x])/err).T
            y1 = y/err
            sol, res, rank, s = scipy.linalg.lstsq(A, y1)
    if output:
        b, m = sol
        fit_y = b + m*x
        print('b -> ' + str(b))
        print('m -> ' + str(m))
        print('Reduced chi-square: ' + str(res/(len(y)-rank)))
        plotxy(y, x, line=None, symbol=2, color=2)
        plotxy(fit_y, x)
    if res.shape == (0,):
        res = np.r_[0.]
    if inline:
        return np.hstack((sol, res, rank, s))
    else:
        return (sol, res, rank, s)

def Pprint(arr, show_index=False, max_lines=None):
    arr = np.atleast_2d(arr)
    if show_index:
        cols = np.arange(arr.shape[1]).astype(str)
        #rows = np.arange(arr.shape[0]).astype(str)
        rows = np.array([r+' |' for r in np.arange(arr.shape[0]).astype(str)])
        t = Table(data=arr, names=cols, copy=True)
        t.add_column(Column(data=rows, name=' '), index=0)
    else:
        t = Table(data=arr, copy=True)
    t.pprint(show_name=show_index, max_lines=max_lines)

def Sort_list(lst, cols):
    """Sort_list(lst, cols)
    Sorts inplace a list by multiple columns.

    lst: List to be sorted.
    cols: Columns to be sorted, cols[0] first,
        cols[1] second, etc.

    >>> lst = [(1,2,4),(3,2,1),(2,2,2),(2,1,4),(2,4,1)]
    >>> Sort_list(lst, [2,1])
    """
    from operator import itemgetter
    for keycolumn in reversed(cols):
        lst.sort(key=itemgetter(keycolumn))
    return


#!/usr/bin/env python3

import numpy as np
import re

position_re = re.compile('(\d+),(\d+).*?(\d+),(\d+)')

def execute(cmd: str, a: np.array, a2: np.array):
    items = position_re.search(cmd)
    pos1 = (int(items.group(1)), int(items.group(2)))
    pos2 = (int(items.group(3)) + 1, int(items.group(4)) + 1)

    if cmd.startswith('toggle'):
        a[pos1[0]:pos2[0], pos1[1]:pos2[1]] = np.invert(a[pos1[0]:pos2[0], pos1[1]:pos2[1]])
        a2[pos1[0]:pos2[0], pos1[1]:pos2[1]] += 2

    elif cmd.startswith('turn on'):
        a[pos1[0]:pos2[0], pos1[1]:pos2[1]] = True
        a2[pos1[0]:pos2[0], pos1[1]:pos2[1]] += 1

    elif cmd.startswith('turn off'):
        a[pos1[0]:pos2[0], pos1[1]:pos2[1]] = False
        a2[pos1[0]:pos2[0], pos1[1]:pos2[1]] -= 1
        a2[a2 < 0] = 0

a = np.zeros((1000, 1000), bool)
a2 = np.zeros((1000, 1000), int)

for cmd in open('6.input').readlines():
    execute(cmd, a, a2)

print('part 1', np.sum(a == True))
print('part 2', np.sum(a2))


from functools import wraps
from typing import Callable

from util.threading import Thread, TimeoutException
from util.typing import P

from .AbstractHandler import PAYLOAD_TYPE, RESPONSE_TYPE, CONTEXT_TYPE, AbstractHandler

class AbstractTimeoutHandler(AbstractHandler[PAYLOAD_TYPE, RESPONSE_TYPE, CONTEXT_TYPE]):
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.handle_request = cls._wrap_timeout(cls.handle_request)

    def __init__(self, timeout: float = None, default: PAYLOAD_TYPE = None, **kwargs):
        super().__init__(**kwargs)
        self.timeout = timeout
        self.default = default

    @staticmethod
    def _wrap_timeout(
        handle_request: Callable[P, RESPONSE_TYPE]
    ) -> Callable[P, RESPONSE_TYPE]:

        if (
            hasattr(handle_request, "_AbstractTimeoutHandler_wrapped")
            and handle_request._AbstractTimeoutHandler_wrapped == True
        ):
            return handle_request

        @wraps(handle_request)
        def execute_with_timeout(self: "AbstractTimeoutHandler") -> RESPONSE_TYPE:
            result = None
            completed = False

            def run_execute_and_store_result():
                nonlocal result
                nonlocal completed
                try:
                    result = handle_request()
                    completed = True
                except TimeoutException:
                    pass

            thread = Thread(target=run_execute_and_store_result, daemon=True)
            thread.start()
            thread.join(self.timeout)

            if not completed:
                result = self.default

            return result  # type: ignore

        execute_with_timeout._AbstractTimeoutHandler_wrapped = True

        return execute_with_timeout


import numpy as np
from typing import Callable, Dict, List, Optional, Tuple, Union

import fvcore.nn.weight_init as weight_init
import torch
from torch import nn
from torch.nn import functional as F
from torch.nn.init import xavier_uniform_, constant_, uniform_, normal_
from torch.cuda.amp import autocast

from detectron2.config import configurable
from detectron2.layers import Conv2d, ShapeSpec, get_norm
from detectron2.modeling import SEM_SEG_HEADS_REGISTRY

from mask2former.modeling.pixel_decoder.msdeformattn import  MSDeformAttnTransformerEncoderOnly
from mask2former.modeling.transformer_decoder.position_encoding import PositionEmbeddingSine

@SEM_SEG_HEADS_REGISTRY.register()
class MSSharePixelDecoder(nn.Module):
    @configurable
    def __init__(
        self,
        input_shape: Dict[str, ShapeSpec],
        *,
        transformer_dropout: float,
        transformer_nheads: int,
        transformer_dim_feedforward: int,
        transformer_enc_layers: int,
        conv_dim: int,
        mask_dim: int,
        norm: Optional[Union[str, Callable]] = None,
        # deformable transformer encoder args
        transformer_in_features: List[str],
        common_stride: int,
    ):
        """
        NOTE: this interface is experimental.
        Args:
            input_shape: shapes (channels and stride) of the input features
            transformer_dropout: dropout probability in transformer
            transformer_nheads: number of heads in transformer
            transformer_dim_feedforward: dimension of feedforward network
            transformer_enc_layers: number of transformer encoder layers
            conv_dims: number of output channels for the intermediate conv layers.
            mask_dim: number of output channels for the final conv layer.
            norm (str or callable): normalization for all conv layers
        """
        super().__init__()
        transformer_input_shape = {
            k: v for k, v in input_shape.items() if k in transformer_in_features
        }

        # this is the input shape of pixel decoder
        input_shape = sorted(input_shape.items(), key=lambda x: x[1].stride)
        self.in_features = [k for k, v in input_shape]  # starting from "res2" to "res5"
        self.feature_strides = [v.stride for k, v in input_shape]
        self.feature_channels = [v.channels for k, v in input_shape]

        # this is the input shape of transformer encoder (could use less features than pixel decoder
        transformer_input_shape = sorted(transformer_input_shape.items(), key=lambda x: x[1].stride)
        self.transformer_in_features = [k for k, v in transformer_input_shape]  # starting from "res2" to "res5"
        transformer_in_channels = [v.channels for k, v in transformer_input_shape]
        self.transformer_feature_strides = [v.stride for k, v in transformer_input_shape]  # to decide extra FPN layers

        self.transformer_num_feature_levels = len(self.transformer_in_features)
        if self.transformer_num_feature_levels > 1:
            input_proj_list = []
            # from low resolution to high resolution (res5 -> res2)
            for in_channels in transformer_in_channels[::-1]:
                input_proj_list.append(nn.Sequential(
                    nn.Conv2d(in_channels, conv_dim, kernel_size=1),
                    nn.GroupNorm(32, conv_dim),
                ))
            self.input_proj = nn.ModuleList(input_proj_list)
        else:
            self.input_proj = nn.ModuleList([
                nn.Sequential(
                    nn.Conv2d(transformer_in_channels[-1], conv_dim, kernel_size=1),
                    nn.GroupNorm(32, conv_dim),
                )])

        for proj in self.input_proj:
            nn.init.xavier_uniform_(proj[0].weight, gain=1)
            nn.init.constant_(proj[0].bias, 0)

        self.transformer = MSDeformAttnTransformerEncoderOnly(
            d_model=conv_dim,
            dropout=transformer_dropout,
            nhead=transformer_nheads,
            dim_feedforward=transformer_dim_feedforward,
            num_encoder_layers=transformer_enc_layers,
            num_feature_levels=self.transformer_num_feature_levels,
        )
        N_steps = conv_dim // 2
        self.pe_layer = PositionEmbeddingSine(N_steps, normalize=True)

        '''
        self.mask_dim = mask_dim
        # use 1x1 conv instead
        self.mask_features = Conv2d(
            conv_dim,
            mask_dim,
            kernel_size=1,
            stride=1,
            padding=0,
        )
        weight_init.c2_xavier_fill(self.mask_features)
        '''

        self.maskformer_num_feature_levels = 3  # always use 3 scales
        self.common_stride = common_stride

        # extra fpn levels
        stride = min(self.transformer_feature_strides)
        self.num_fpn_levels = int(np.log2(stride) - np.log2(self.common_stride))

        lateral_convs = []
        output_convs = []

        use_bias = norm == ""
        for idx, in_channels in enumerate(self.feature_channels[:self.num_fpn_levels]):
            lateral_norm = get_norm(norm, conv_dim)
            output_norm = get_norm(norm, conv_dim)

            lateral_conv = Conv2d(
                in_channels, conv_dim, kernel_size=1, bias=use_bias, norm=lateral_norm
            )
            output_conv = Conv2d(
                conv_dim,
                conv_dim,
                kernel_size=3,
                stride=1,
                padding=1,
                bias=use_bias,
                norm=output_norm,
                activation=F.relu,
            )
            weight_init.c2_xavier_fill(lateral_conv)
            weight_init.c2_xavier_fill(output_conv)
            self.add_module("adapter_{}".format(idx + 1), lateral_conv)
            self.add_module("layer_{}".format(idx + 1), output_conv)

            lateral_convs.append(lateral_conv)
            output_convs.append(output_conv)
        # Place convs into top-down order (from low to high resolution)
        # to make the top-down computation in forward clearer.
        self.lateral_convs = lateral_convs[::-1]
        self.output_convs = output_convs[::-1]

        '''
        share_mask_branch = []
        for idx in range(self.maskformer_num_feature_levels):
            share_norm = get_norm(norm, mask_dim)
            share_mask_conv = Conv2d(
                conv_dim,
                mask_dim,
                kernel_size=3,
                stride=2,
                padding=1,
                norm=share_norm,
                activation=F.relu,
            )
            weight_init.c2_xavier_fill(share_mask_conv)

            self.add_module("share_{}".format(idx + 1), share_mask_conv)
            share_mask_branch.append(share_mask_conv)

        self.share_mask_branch = share_mask_branch
        '''

    @classmethod
    def from_config(cls, cfg, input_shape: Dict[str, ShapeSpec]):
        ret = {}
        ret["input_shape"] = {
            k: v for k, v in input_shape.items() if k in cfg.MODEL.SEM_SEG_HEAD.IN_FEATURES
        }
        ret["conv_dim"] = cfg.MODEL.SEM_SEG_HEAD.CONVS_DIM
        ret["mask_dim"] = cfg.MODEL.SEM_SEG_HEAD.MASK_DIM
        ret["norm"] = cfg.MODEL.SEM_SEG_HEAD.NORM
        ret["transformer_dropout"] = cfg.MODEL.MASK_FORMER.DROPOUT
        ret["transformer_nheads"] = cfg.MODEL.MASK_FORMER.NHEADS
        # ret["transformer_dim_feedforward"] = cfg.MODEL.MASK_FORMER.DIM_FEEDFORWARD
        ret["transformer_dim_feedforward"] = 1024  # use 1024 for deformable transformer encoder
        ret[
            "transformer_enc_layers"
        ] = cfg.MODEL.SEM_SEG_HEAD.TRANSFORMER_ENC_LAYERS  # a separate config
        ret["transformer_in_features"] = cfg.MODEL.SEM_SEG_HEAD.DEFORMABLE_TRANSFORMER_ENCODER_IN_FEATURES
        ret["common_stride"] = cfg.MODEL.SEM_SEG_HEAD.COMMON_STRIDE
        return ret

    @autocast(enabled=False)
    def forward_features(self, features):
        srcs = []
        pos = []
        # Reverse feature maps into top-down order (from low to high resolution)
        for idx, f in enumerate(self.transformer_in_features[::-1]):
            x = features[f].float()  # deformable detr does not support half precision
            srcs.append(self.input_proj[idx](x))
            pos.append(self.pe_layer(x))

        y, spatial_shapes, level_start_index = self.transformer(srcs, pos)
        bs = y.shape[0]

        split_size_or_sections = [None] * self.transformer_num_feature_levels
        for i in range(self.transformer_num_feature_levels):
            if i < self.transformer_num_feature_levels - 1:
                split_size_or_sections[i] = level_start_index[i + 1] - level_start_index[i]
            else:
                split_size_or_sections[i] = y.shape[1] - level_start_index[i]
        y = torch.split(y, split_size_or_sections, dim=1)

        out = []
        multi_scale_features = []
        num_cur_levels = 0
        for i, z in enumerate(y):
            out.append(z.transpose(1, 2).view(bs, -1, spatial_shapes[i][0], spatial_shapes[i][1]))

        # append `out` with extra FPN levels
        # Reverse feature maps into top-down order (from low to high resolution)
        for idx, f in enumerate(self.in_features[:self.num_fpn_levels][::-1]):
            x = features[f].float()
            lateral_conv = self.lateral_convs[idx]
            output_conv = self.output_convs[idx]
            cur_fpn = lateral_conv(x)
            # Following FPN implementation, we use nearest upsampling here
            y = cur_fpn + F.interpolate(out[-1], size=cur_fpn.shape[-2:], mode="bilinear", align_corners=False)
            y = output_conv(y)
            out.append(y)

        for o in out:
            if num_cur_levels < self.maskformer_num_feature_levels:
                multi_scale_features.append(o)
                num_cur_levels += 1

        '''
        mask_feats = []
        feat = features['res2'].float()
        for idx in range(self.maskformer_num_feature_levels):
            feat = self.share_mask_branch[idx](feat)
            mask_feats.append(feat)

        feat = features['res2']
        mask_feat = mask_feats[0]
        for idx in range(self.maskformer_num_feature_levels-1, 0, -1):
            mask_feat = mask_feats[idx] + F.interpolate(mask_feat, size=mask_feats[idx].shape[-2:], mode="bilinear", align_corners=False)
        mask_feat = feat  + F.interpolate(mask_feat, size=feat.shape[-2:], mode="bilinear", align_corners=False)
        '''

        return out[-1], out[0], multi_scale_features
        #return self.mask_features(mask_feat), out[0], multi_scale_features


from django.urls import path

from widgets.views import HomePageView, UserProfilePageView, SharedWidgetsPageView, \
    PrivateWidgetsPageView, MemoryWidgetsView

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
    path('home/shared-widgets/', SharedWidgetsPageView.as_view(), name='shared-widgets'),
    path('user-profile/<slug:slug>/', UserProfilePageView.as_view(), name='user-profile'),
    path('user-profile/<slug:slug>/widgets/', PrivateWidgetsPageView.as_view(), name='private-widgets'),
    path('memory-widgets/<int:pk>', MemoryWidgetsView.as_view(), name='memory-widgets'),
]


from setuptools import setup
import sys

VERSION = '1.2.1263'

plist = dict(
    CFBundleName='VisTrails',
    CFBundleShortVersionString=VERSION,
    CFBundleGetInfoString=' '.join(['VisTrails', VERSION]),
    CFBundleExecutable='vistrails',
    CFBundleIdentifier='edu.utah.sci.vistrails',
)

sys.path.append('../..')
APP = ['../../vistrails/run.py']
#comma-separated list of additional data files and
#folders to include (not for code!)
#DATA_FILES = ['/usr/local/graphviz-2.12/bin/dot',]
OPTIONS = {'argv_emulation': True,
           'iconfile': 'vistrails/resources/vistrails_icon.icns',
           'includes': 'sip,pylab,xml,netCDF3,netCDF4_utils,netcdftime,\
            libxml2,libxslt, Cookie, BaseHTTPServer, multifile, shelve,itk, itkBase, itkConfig, itkLazy, itkTypes, itkExtras',
           'packages': 'PyQt4,vtk,MySQLdb,matplotlib,vistrails,numpy,ZSI,api',
           'plist': plist,
           }

setup(
    app=APP,
 #   data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)


# Реализовать базовый класс Worker (работник), в котором определить атрибуты:
# name, surname, position (должность), income (доход). Последний атрибут должен быть защищенным и
# ссылаться на словарь, содержащий элементы: оклад и премия, например, {"wage": wage, "bonus": bonus}.
# Создать класс Position (должность) на базе класса Worker. В классе Position реализовать методы
# получения полного имени сотрудника (get_full_name) и дохода с учетом премии (get_total_income).
# Проверить работу примера на реальных данных (создать экземпляры класса Position, передать данные,
# проверить значения атрибутов, вызвать методы экземпляров).

salary_dict = {'Сергей Петров': {'wage': 30000, 'bonus': 7000},
               'Михаил Смирнов': {'wage': 10000, 'bonus': 5000}
               }

class Worker:
    name: str
    surname: str
    position: str
    _income = salary_dict

    def __init__(self, name, surname, position):
        self.name = name
        self.surname = surname
        self.position = position

class Position(Worker):
    def __init__(self, name, surname, position):
        super().__init__(name, surname, position)

    def get_full_name(self):
        print(f'\nСотрудник: {self.name} {self.surname}\nДолжность: {self.position}')

    def get_total_income(self):
        if f"{self.name} {self.surname}" in self._income.keys():
            print(f'Доход с учетом премии: {sum(self._income[f"{self.name} {self.surname}"].values())} рублей.')
        else:
            print('Такого сотрудника нет!')

petrov = Position('Сергей', 'Петров', 'Менеджер')
petrov.get_full_name()
petrov.get_total_income()

smirnov = Position('Михаил', 'Смирнов', 'Грузчик')
smirnov.get_full_name()
smirnov.get_total_income()

tenev = Position('Михаил', 'Тенев', 'Иллюминат')
tenev.get_full_name()
tenev.get_total_income()


from os.path import abspath, dirname, join

from preggy import expect
from tornado.testing import gen_test

from tests.base import TestCase
from thumbor.compatibility.storage import Storage
from thumbor.config import Config
from thumbor.context import Context, ServerParameters
from thumbor.importer import Importer

STORAGE_PATH = abspath(join(dirname(__file__), "../fixtures/images/"))

class CompatibilityStorageTestCase(TestCase):
    def get_image_path(self, name):
        return f"./tests/fixtures/images/{name}"

    def get_image_bytes(self, name):
        with open(self.get_image_path(name), "rb") as img:
            return img.read()

    def get_image_url(self, name):
        return f"s.glbimg.com/some/{name}"

    def get_context(self):
        config = Config(
            FILE_LOADER_ROOT_PATH=STORAGE_PATH,
            COMPATIBILITY_LEGACY_STORAGE="tests.compatibility.legacy_file_storage",
            STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True,
        )
        importer = Importer(config)
        importer.import_modules()
        server = ServerParameters(
            8889, "localhost", "thumbor.conf", None, "info", None
        )
        server.security_key = "ACME-SEC"
        return Context(server, config=config, importer=importer)

    @gen_test
    async def test_should_raise_for_invalid_compatibility_storage(self):
        config = Config(
            FILE_LOADER_ROOT_PATH=STORAGE_PATH,
            STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True,
        )
        importer = Importer(config)
        importer.import_modules()
        server = ServerParameters(
            8889, "localhost", "thumbor.conf", None, "info", None
        )
        server.security_key = "ACME-SEC"
        ctx = Context(server, config=config, importer=importer)
        storage = Storage(ctx)

        with expect.error_to_happen(
            RuntimeError,
            message=(
                "The 'COMPATIBILITY_LEGACY_STORAGE' configuration should "
                "point to a valid storage when using compatibility storage."
            ),
        ):
            await storage.get("invalid-path")

    @gen_test
    async def test_should_return_none_for_invalid_image(self):
        storage = Storage(self.context)

        result = await storage.get("invalid-path")

        expect(result).to_be_null()

    @gen_test
    async def test_should_get(self):
        url = self.get_image_url("image.jpg")
        image_bytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)
        await storage.put(url, image_bytes)

        result = await storage.get(url)

        expect(result).not_to_be_null()
        expect(result).not_to_be_an_error()
        expect(result).to_equal(image_bytes)

    @gen_test
    async def test_should_put(self):
        url = self.get_image_url("image.jpg")
        image_bytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)

        await storage.put(url, image_bytes)

        result = await storage.get(url)
        expect(result).not_to_be_null()
        expect(result).not_to_be_an_error()
        expect(result).to_equal(image_bytes)

    @gen_test
    async def test_should_put_detector_data(self):
        iurl = self.get_image_url("image_7.jpg")
        ibytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)
        await storage.put(iurl, ibytes)

        await storage.put_detector_data(iurl, "some-data")

        got = await storage.get_detector_data(iurl)
        expect(got).not_to_be_null()
        expect(got).not_to_be_an_error()
        expect(got).to_equal("some-data")

    @gen_test
    async def test_should_put_crypto(self):
        iurl = self.get_image_url("image_7.jpg")
        ibytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)
        await storage.put(iurl, ibytes)

        await storage.put_crypto(iurl)

        got = await storage.get_crypto(iurl)
        expect(got).not_to_be_null()
        expect(got).not_to_be_an_error()
        expect(got).to_equal("ACME-SEC")

    @gen_test
    async def test_exists(self):
        iurl = self.get_image_url("image_7.jpg")
        ibytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)
        await storage.put(iurl, ibytes)

        exists = await storage.exists(iurl)
        not_exists = await storage.exists("some-invalid-random-file.jpg")

        expect(exists).to_be_true()
        expect(not_exists).to_be_false()

    @gen_test
    async def test_remove(self):
        iurl = self.get_image_url("image_7.jpg")
        ibytes = self.get_image_bytes("image.jpg")
        storage = Storage(self.context)
        await storage.put(iurl, ibytes)
        exists = await storage.exists(iurl)
        expect(exists).to_be_true()

        await storage.remove(iurl)

        not_exists = await storage.exists(iurl)
        expect(not_exists).to_be_false()


# https://www.codewars.com/kata/58fd9f6213b00172ce0000c9

def split_exp(n):
    lenn = len(n)
    res  = []
    pnt = n.find('.')
    if pnt < 0:
        res = [c + '0'*(lenn-i-1) for i, c in enumerate(n) if c != '0']
    else:
        for i,j in zip(range(0, pnt), range(pnt-1,-1,-1)):
            if n[i]!= '0': res.append(n[i] + '0'*j)
        for i, j in zip(range(pnt+1, lenn), range(lenn)):
            if n[i]!= '0': res.append('.' + '0'*j + n[i])
    return res


# Layers are stacked in order of drawing
level_0 = {
    'tiles_sheet_path': '../imgs/terrain/mario_terrain.png',
    'layers': {
        'terrain': {
            'path': '../levels/level_data/0/level0_Level.csv',
            'type': 'static',
        },
        'ghost_passage': {
            'path': '../levels/level_data/0/level0_GhostPassage.csv',
            'type': 'passage',
        },
        'scenery': {
            'path': '../levels/level_data/0/level0_Scenery.csv',
            'type': 'static',
        },
        'scenery2': {
            'path': '../levels/level_data/0/level0_Additional Scenery.csv',
            'type': 'static',
        },
        'player': {
            'path': '../levels/level_data/0/level0_Mario.csv',
            'type': 'player',
        },
        'ghosts': {
            'path': '../levels/level_data/0/level0_Pacman.csv',
            'type': 'ghosts',
        },
        'coins': {
            'path': '../levels/level_data/0/level0_Coins.csv',
            'type': 'coin',
        },
        'question_blocks': {
            'path': '../levels/level_data/0/level0_Question_blocks.csv',
            'type': 'question_block',
        },
        'pipe_head_pair_0': {
            'path': '../levels/level_data/0/level0_Pipe_head_pair_0.csv',
            'type': 'pipe_head',
        },
        'pipe_head_pair_1': {
            'path': '../levels/level_data/0/level0_Pipe_head_pair_1.csv',
            'type': 'pipe_head',
        },
        'pipe_head_pair_2': {
            'path': '../levels/level_data/0/level0_Pipe_head_pair_2.csv',
            'type': 'pipe_head',
        },
    }
}

player = {
    'sprite_sheet_path': '../imgs/player/shroomaddict.png',
    'animation_idle': {
        'frames': [0],
        'fps': 1,
    },
    'animation_walking': {
        'frames': [1, 2, 3],
        'fps': 10
    },
    'animation_running': {
        'frames': [1, 2, 3],
        'fps': 16
    },
    'animation_jumping': {
        'frames': [5],
        'fps': 1
    },
    'animation_dede': {
        'frames': [6],
        'fps': 1
    }
}

ghosts = {
    'sprite_sheet_path': '../imgs/ghosts/ghost_sprites.png',
    'seconds_following': 12,
    'seconds_spreading': 8,
    'animation_idle': {
        'frames': [0],
        'fps': 1
    },
    'animation_right': {
        'frames': [0, 1],
        'fps': 7,
    },
    'animation_left': {
        'frames': [2, 3],
        'fps': 7
    },
    'animation_up': {
        'frames': [4, 5],
        'fps': 7
    },
    'animation_down': {
        'frames': [6, 7],
        'fps': 7
    },
    'animation_scared': {
        'frames': [8, 9],
        'fps': 7
    }, 'animation_scared_white': {
        'frames': [10, 11],
        'fps': 7
    }, 'animation_dead_right': {
        'frames': [12],
        'fps': 1
    }, 'animation_dead_left': {
        'frames': [13],
        'fps': 1
    }, 'animation_dead_up': {
        'frames': [14],
        'fps': 1
    }, 'animation_dead_down': {
        'frames': [15],
        'fps': 1
    }
}

coins = {
    'sprite_sheet_path': '../imgs/coin/coin.png',
    'animation_idle': {
        'frames': [0, 1, 2, 3, 4, 5, 6, 7],
        'fps': 10
    }
}

question_block = {
    'sprite_sheet_path': '../imgs/question_block/question_block.png',
    'animation_idle': {
        'frames': [0, 0, 0, 1, 2],
        'fps': 4
    },
    'animation_hit': {
        'frames': [3, 3],
        'fps': 1
    }
}

pipe_head = {
    'sprite_sheet_path': '../imgs/terrain/mario_terrain.png',
    'animation_idle': {
        'frames': [0],
        'fps': 1
    },
}

ui = {
    'sprite_sheet_path': '../imgs/ui/ui.png'
}