import time
import sys
import os

import pygame

#  import game object classes
from level import Level
from player import Player
from robot import Robot
from apple import Apple

#  import constant definitions
from macros import *

#  for mathematical operations
import numpy as np

class Game:
    def __init__(self, game_window_name="Hamham"):
        #  initialize pygame stuff
        pygame.display.init()
        pygame.mixer.init()
        pygame.display.set_caption(game_window_name)
        self.screen = pygame.display.set_mode(game_window_size)
        self.clock = pygame.time.Clock()

        #wall_width = self.wall.get_width()
        wall_width = 36

		# Load images
        self.wall = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/wall.png').convert(), (wall_width, wall_width))

        self.apple = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/apple_bg.png').convert(), (wall_width, wall_width))
        self.floor = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/floor.png').convert(), (wall_width, wall_width))
        self.grass = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/grass.png').convert(), (wall_width, wall_width))

        self.player_right = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/pacman_bg.png').convert(), (wall_width, wall_width))
        self.player_up = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/pacman_bg.png').convert(), (wall_width, wall_width)), 90.0)
        self.player_left = pygame.transform.flip(pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/pacman_bg.png').convert(), (wall_width, wall_width)), True, False)
        self.player_down = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/pacman_bg.png').convert(), (wall_width, wall_width)), -90.0)
        self.player_image = self.player_right
        self.player_images = [self.player_right, self.player_up, self.player_left, self.player_down]

        self.robot = pygame.transform.scale(pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + '/images/robot_bg.png').convert(), (wall_width, wall_width))

        #  load sounds
        self.win_sound = pygame.mixer.Sound(os.path.dirname(os.path.abspath(__file__)) + '/sounds/tada.wav')
        self.lose_sound = pygame.mixer.Sound(os.path.dirname(os.path.abspath(__file__)) + '/sounds/fail_trombone_4s.wav')

		# Dictionary to map images to characters in level matrix
        self.images = {'W': self.wall,
                    'A': self.apple,
                    'F': self.floor,
                    'G': self.grass,
                    'P': self.player_image,
                    'R': self.robot}

        self.current_level = None
        self.current_level_number = 0

		#  player object
        self.player = None

		#  robots
        self.robots = []

        self.game_finished = False
        self.player_alive = True

        """
        Current level statistics
        """
        #  number of apples player collected so far in curret level
        self.collected_apple_count = 0

        #  number of all apples in the initial level configuration
        self.total_apple_count = 0

        #  number of time steps elapsed in a level
        self.elapsed_time_step = 0

        #
        self.distance_to_closest_apple = 0

        self.crashed_into_wall = False

    def draw_level(self, level_matrix):
        # Get image size to print on screen
        box_size = self.wall.get_width()

        # Print images for matrix
        for i in range(0, len(level_matrix)):
            for c in range(0, len(level_matrix[i])):
                self.screen.blit(self.images[level_matrix[i][c]], (c * box_size, i * box_size))
        pygame.display.update()

    def init_level(self, level):
        self.current_level = Level(level)
        #self.draw_level(self.current_level.get_matrix())

        #  mark game as not finished
        self.game_finished = False
        self.player_alive = True

        #  number of time steps elapsed in a level
        self.elapsed_time_step = 0

        #  initialize number of apples player collected so far in curret level
        self.collected_apple_count = 0

        #  create player object
        player_pos = self.current_level.get_player_pos()
        player_current_row = player_pos[0]
        player_current_col = player_pos[1]
        self.player = Player(player_current_row, player_current_col)

        #  create robots
        self.robots = []
        robot_positions = self.current_level.get_robot_positions()
        for pos in robot_positions:
            r = pos[0]
            c = pos[1]
            self.robots.append(Robot(r, c, self.current_level.get_matrix()))

        #  create apples
        self.apples = []
        apple_positions = self.current_level.get_apple_positions()
        for pos in apple_positions:
            r = pos[0]
            c = pos[1]
            self.apples.append(Apple(r, c))

        #  count number of apples
        self.total_apple_count = len(self.apples)
        #print("Number of apples in the level ", self.total_apple_count)

        #  whether played tried to move into wall at last step
        self.crashed_into_wall = False

    """
    Calculates distance between player and the closest apple to player
    """
    def get_closest_apple_to_player(self):
        player_pos = self.player.get_pos()
        pr = player_pos[0]
        pc = player_pos[1]

        minDist = 1000
        closestApple = None
        for apple in self.apples:
            apple_pos = apple.get_pos()
            rr = apple_pos[0]
            rc = apple_pos[1]
            dist = np.abs(pr - rr) + np.abs(pc - rc)
            if (dist < minDist):
                minDist = dist
                closestApple = apple

        return (closestApple, minDist)

    def step(self, player_direction, render=True):
        matrix = self.current_level.get_matrix()
        self.current_level.save_history(matrix)

        #Print apples
        #print(self.current_level.get_apple_positions())

        #  robots movement
        for robot in self.robots:
            #robot_old_pos = robot.get_pos()
            #robot_old_row = robot_old_pos[0]
            #robot_old_col = robot_old_pos[1]

            robot_dir = robot.choose_dir()
            robot_new_pos = robot.move(robot_dir)
            robot_next_row = robot_new_pos[0]
            robot_next_col = robot_new_pos[1]

		#  save old position of the player
        player_current_pos = self.player.get_pos()
        player_current_row = player_current_pos[0]
        player_current_col = player_current_pos[1]

		#  calculate new position of the player
        player_next_pos = self.player.move(player_direction)
        player_next_row = player_next_pos[0]
        player_next_col = player_next_pos[1]

        #  resolve static collision for robots
        for robot in self.robots:
            robot_prev_pos = robot.get_prev_pos()
            robot_prev_row = robot_prev_pos[0]
            robot_prev_col = robot_prev_pos[1]

            robot_next_pos = robot.get_pos()
            robot_next_row = robot_next_pos[0]
            robot_next_col = robot_next_pos[1]

            next_cell = matrix[robot_next_row][robot_next_col]
            if next_cell == "F":
                #  next cell is floor
                pass
            elif ((next_cell == "G")
                  or (next_cell == "W")
                  or (next_cell == "A")):
                #  next cell is grass or wall or apple
                #robot cant pass here
                robot.current_pos = robot_prev_pos
            elif (next_cell == "R"):
                #  go into another robot
                pass
            elif (next_cell == "P"):
                #  will resolve later
                pass

        #  resolve static collisions for player
        next_cell = matrix[player_next_row][player_next_col]
        if (next_cell == "F"):
            #  next cell is floor
            pass
        elif (next_cell == "W"):
            #  next cell is wall
            #player cant pass here
            self.player.current_pos = self.player.prev_pos
            self.crashed_into_wall = True
        elif (next_cell == "G"):
            #  next cell is grass
            #player removes grass
            matrix[player_next_row][player_next_col] = "P"
        elif (next_cell == 'A'):
            #  next cell is apple
            #player removes apple
            matrix[player_next_row][player_next_col] = "P"
        elif (next_cell == "R"):
            #  next square is robot
            #will resolve later
            pass

        #  check if player collected an apple
        #  TO DO: create a 2d apple grid for faster check
        new_apples = []
        for apple in self.apples:
            apple_pos = apple.get_pos()
            apple_row = apple_pos[0]
            apple_col = apple_pos[1]
            if (player_next_row == apple_row and player_next_col == apple_col):
                #player removes apple
                #  check if game is finished
                self.collected_apple_count += 1
                if (self.collected_apple_count == self.total_apple_count):
                    self.game_finished = True
            else:
                new_apples.append(apple)
        self.apples = new_apples

        player_next_row = self.player.current_pos[0]
        player_next_col = self.player.current_pos[1]

        #  resolve dynamic player-robot collisions
        for robot in self.robots:
            robot_prev_pos = robot.get_prev_pos()
            robot_prev_row = robot_prev_pos[0]
            robot_prev_col = robot_prev_pos[1]

            robot_next_pos = robot.get_pos()
            robot_next_row = robot_next_pos[0]
            robot_next_col = robot_next_pos[1]

            #  CASE 1
            #player and robot moves into same cell
            if (robot_next_row == player_next_row and robot_next_col == player_next_col):
                #print("CASE 1: Player and robot {} moved into same cell!".format(robot.get_id()))
                self.player_alive = False
                self.game_finished = True

            #  CASE 2
            #player in cell C1, robot in cell C2
            #player moves from C1 to C2
            #robot moves from C3 to C4
            #C1 == C4 AND C2 == C3
            if (player_current_pos == robot_next_pos and player_next_pos == robot_prev_pos):
                #print("CASE 2: Player and robot {} passed by!".format(robot.get_id()))
                self.player_alive = False
                self.game_finished = True

        #  update game matrix
        level_matrix = self.current_level.get_matrix()
        for robot in self.robots:
            robot_old_pos = robot.get_prev_pos()
            robot_old_row = robot_old_pos[0]
            robot_old_col = robot_old_pos[1]
            robot_new_pos = robot.get_pos()
            robot_next_row = robot_new_pos[0]
            robot_next_col = robot_new_pos[1]

            level_matrix[robot_old_row][robot_old_col] = "F"
            level_matrix[robot_next_row][robot_next_col] = "R"
        player_prev_row = self.player.get_prev_row()
        player_prev_col = self.player.get_prev_col()
        player_next_row = self.player.get_row()
        player_next_col = self.player.get_col()

        #  if there is not a robot in the previous cell of player, clear it
        if (level_matrix[player_prev_row][player_prev_col] != "R"):
            level_matrix[player_prev_row][player_prev_col] = "F"
        level_matrix[player_next_row][player_next_col] = "P"

        #  draw
        if (render):
            self.images["P"] = self.player_images[self.player.current_facing_index]
            self.draw_level(matrix)

        self.elapsed_time_step += 1

        #remaining_apple_count = len(self.current_level.get_apple_positions())
        #print("Number of remaining apples: ", remaining_apple_count)

        #  check if game is finished
        if (self.game_finished):
            if (self.player_alive):
                #  player collected all apples
                #print("Level completed!")
                return RESULT_PLAYER_WON
            else:
                #  player is dead
                #print("Player is killed by the robot!")
                return RESULT_PLAYER_DEAD
        else:
            return RESULT_GAME_CONTINUE

    #  function when a human player plays the game
    def start_level_human(self, level_index):
        self.init_level(level_index)
        self.draw_level(self.current_level.get_matrix())

		#  number of all apples in the initial level configuration
        self.total_apple_count = len(self.apples)

        #  at each time step, distance of player to the closest apple
        apple_distance_rewards = []

        #  negative reward if crash into wall
        wall_crash_penalties = []

        self.distance_to_closest_apple = self.get_closest_apple_to_player()[1]

        #  game loop
        while True:
            result = 0

            #  manual input
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    #self.craft_features()

                    if event.key == pygame.K_RIGHT:
                        result = self.step("R", render=True)
                    elif event.key == pygame.K_UP:
                        result = self.step("U", render=True)
                    elif event.key == pygame.K_LEFT:
                        result = self.step("L", render=True)
                    elif event.key == pygame.K_DOWN:
                        result = self.step("D", render=True)
                    elif event.key == pygame.K_SPACE:
                        result = self.step("PASS", render=True)
                    #elif event.key == pygame.K_u:
                    #    self.draw_level(self.current_level.undo())
                    elif event.key == pygame.K_r:
                        self.init_level(self.current_level_number)
                        result = RESULT_GAME_CONTINUE
                    elif event.key == pygame.K_ESCAPE:
                        pygame.quit()
                        sys.exit()

                elif event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

            if (result == RESULT_PLAYER_WON or result == RESULT_PLAYER_DEAD):
                sound_channel = None
                if (result == RESULT_PLAYER_WON):
                    #print("WON")
                    sound_channel = self.win_sound.play()
                else:
                    #print("LOSE")
                    sound_channel = self.lose_sound.play()

                #  wait for sound to end
                while sound_channel.get_busy() == True:
                    continue
                break
            else:
                #
                new_closest_apple_dist = self.get_closest_apple_to_player()[1]
                if (new_closest_apple_dist > self.distance_to_closest_apple):
                    apple_distance_rewards.append(MOVING_AWAY_FROM_APPLE)
                elif (new_closest_apple_dist < self.distance_to_closest_apple):
                    apple_distance_rewards.append(GETTING_CLOSER_TO_APPLE_REWARD)
                self.distance_to_closest_apple = new_closest_apple_dist

                if (self.crashed_into_wall):
                    self.crashed_into_wall = False
                    wall_crash_penalties.append(WALL_CRASH_PENALTY)

        #  if killed by robot, give penalty
        robot_death_penalty = 0
        if (result == RESULT_PLAYER_DEAD):
            robot_death_penalty = ROBOT_DEATH_PENALTY

        #  return a tuple of
        #(number of collected apples, elapsed time step)
        return (self.collected_apple_count, apple_distance_rewards, wall_crash_penalties,
                self.elapsed_time_step, robot_death_penalty)

    """
    R T L U blocked (4)
    R T L U contains a robot or is adjacent to a robot (4)
    closest apple vector components (2)

    returns a feature vector containing above 10 features
    """
    def craft_features(self):
        player_pos = self.player.get_pos()
        pr = player_pos[0]
        pc = player_pos[1]
        matrix = self.current_level.get_matrix()

        #  features showing whether 4 cardinal direction cells blocked or not
        checked_cell = matrix[pr][pc+1]
        right_blocked = int( (checked_cell == "W") )
        checked_cell = matrix[pr-1][pc]
        up_blocked = int( (checked_cell == "W") )
        checked_cell = matrix[pr][pc-1]
        left_blocked = int( (checked_cell == "W") )
        checked_cell = matrix[pr+1][pc]
        down_blocked = int( (checked_cell == "W") )

        #  features showing whether 4 cardinal direction cells contains robot danger or not
        drs = [0, -1, 0, 1]
        dcs = [1, 0, -1, 0]
        matrix_height = len(matrix)
        matrix_width = len(matrix[0])
        robot_vector = np.zeros(4)
        for c in range(4):
            #  calculate cth adjacent cell
            adj_cell_row = pr + drs[c]
            adj_cell_col = pc + dcs[c]

            #  check if there is a robot in the cell
            if (matrix[adj_cell_row][adj_cell_col] == "R"):
                robot_vector[c] = 1.0
                continue

            #  check if there is a robot danger in the cell
            for dr in drs:
                for dc in dcs:
                    if (adj_cell_row + dr >= 0 and adj_cell_row + dr < matrix_height
                        and adj_cell_col + dc >= 0 and adj_cell_col + dc < matrix_width
                        and matrix[adj_cell_row + dr][adj_cell_col + dc] == "R"):
                        robot_vector[c] = 1.0
                        break

        #right_robot = int( (checked_cell == "R") )
        #up_robot = int( (checked_cell == "R") )
        #left_robot = int( (checked_cell == "R") )
        #down_robot = int( (checked_cell == "R") )

        #
        blocked_vector = np.array([right_blocked, up_blocked, left_blocked, down_blocked])
        #robot_vector = np.array([right_robot, up_robot, left_robot, down_robot])

        #  calculate vector that shows the apple direction
        closest_apple = self.get_closest_apple_to_player()[0]
        closest_apple_pos = closest_apple.get_pos()
        closest_apple_row = closest_apple_pos[0]
        closest_apple_col = closest_apple_pos[1]
        closest_apple_vector = np.array([closest_apple_row - pr, closest_apple_col - pc])

        #  normalize direction vector
        closest_apple_vector_norm = np.linalg.norm(closest_apple_vector)
        if (closest_apple_vector_norm == 0):
            closest_apple_vector_norm = len(matrix)
        closest_apple_vector = closest_apple_vector / closest_apple_vector_norm

        #  obtain feature vector by merging blocked and direction vectors
        feature_vector = np.concatenate([blocked_vector, robot_vector, closest_apple_vector])

        #print("--- MATRIX ---")
        #print(matrix)
        #print("--- FEATURES ---")
        #print(feature_vector)

        #  return feature vector
        return feature_vector

    def start_level_computer(self, level_index, agent,
                             render=False, play_sound=False,
                             max_episode_length=150,
                             use_crafted_features=True,
                             test=False):
        self.init_level(level_index)

        if (render):
            self.draw_level(self.current_level.get_matrix())

		#  number of all apples in the initial level configuration
        self.total_apple_count = len(self.apples)

        #  at each time step, distance of player to the closest apple
        apple_distance_rewards = []

        #  negative reward if crash into wall
        wall_crash_penalties = []

        self.distance_to_closest_apple = self.get_closest_apple_to_player()[1]

        while True:
            result = 0

            #  input source will use matrix to decide
            matrix = self.current_level.get_matrix()

            network_input = None
            if (use_crafted_features):
                network_input = self.craft_features()
            else:
                #  convert grid to network input
                network_input = agent.grid_to_network_input(matrix)
            chosen_action = agent.decide_move(network_input)

            #  apply decided action
            result = self.step(chosen_action, render=render)

            #  if we want to render our agent, wait some time
            if (render):
                self.clock.tick(FPS)

            #  check if game finished
            if (result == RESULT_PLAYER_WON or result == RESULT_PLAYER_DEAD):
                if (play_sound):
                    sound_channel = None
                    if (result == RESULT_PLAYER_WON):
                        sound_channel = self.win_sound.play()
                    else:
                        sound_channel = self.lose_sound.play()

                    #  wait for sound to end
                    while sound_channel.get_busy() == True:
                        continue
                break
            else:
                #
                new_closest_apple_dist = self.get_closest_apple_to_player()[1]
                if (new_closest_apple_dist > self.distance_to_closest_apple):
                    apple_distance_rewards.append(MOVING_AWAY_FROM_APPLE)
                elif (new_closest_apple_dist < self.distance_to_closest_apple):
                    apple_distance_rewards.append(GETTING_CLOSER_TO_APPLE_REWARD)
                self.distance_to_closest_apple = new_closest_apple_dist

                if (self.crashed_into_wall):
                    self.crashed_into_wall = False
                    wall_crash_penalties.append(WALL_CRASH_PENALTY)

            #  check if we reached episode length
            if (self.elapsed_time_step >= max_episode_length):
                break

        #  if killed by robot, give penalty
        robot_death_penalty = 0
        if (result == RESULT_PLAYER_DEAD):
            robot_death_penalty = ROBOT_DEATH_PENALTY

        #  return a tuple of
        #(number of collected apples, elapsed time step)
        return (self.collected_apple_count, apple_distance_rewards, wall_crash_penalties,
                self.elapsed_time_step, robot_death_penalty)


import time
import json
import random
import requests
from tqdm import tqdm
import pandas as pd
from bs4 import BeautifulSoup

'''
Workspace : Colab
It takes about 2 Hours 22 minutes to collect 300 reviews for each 10000 games.
get_n_appids(n=10000) takes about 15 minutes
more details in steam api 'reference' section in the readme.md

'''

def get_n_reviews(appid, n=300):
    '''
    Latest game reviews like Hades are not loaded.
    '''
    global reviews
    start = time.time()
    cursor = '*'
    params = {
            'json' : 1,
            'filter' : 'all',
            'language' : 'korean', #if you want english replace the parameter with 'english'.
            'day_range' : 9223372036854775807,
            'review_type' : 'all',
            'purchase_type' : 'all'
            }

    params['cursor'] = cursor.encode()
    params['num_per_page'] = 100

    while len(reviews) < n:
        url = 'https://store.steampowered.com/appreviews/'
        response = requests.get(url=url+str(appid), params=params, headers={'User-Agent': 'Mozilla/5.0'}).json()
        reviews += response['reviews']
        if len(response['reviews']) < 100:
            break
        params['cursor'] = response['cursor'].encode()
        time.sleep(random.random()+1) # for Max retries error

def get_n_appids(n=1000, mode='all'):
    '''
    mode = all, topselleres, etc..
    if mode == all : About 100K games can be viewd
    if mode == topsellers : only 3K games can be viewed

    '''
    appids = []
    if mode == 'all':
        url = f'https://store.steampowered.com/search/?&page='
    if mode == 'topselleres':
        url = f'https://store.steampowered.com/search/?category1=998&filter={mode}&page='
    page = 1

    while page*25 < n:
        start = time.time()
        page += 1
        response = requests.get(url=url+str(page), headers={'User-Agent': 'Mozilla/5.0'})
        soup = BeautifulSoup(response.text, 'html.parser')
        for row in soup.find_all(class_='search_result_row'):
            try:
                app_id = int(row['data-ds-appid'])
                #If the game has dlc, multiple lists are created here
            except ValueError:
                app_id = int(row['data-ds-appid'][0])
            except KeyError:
                app_id = int(json.loads(row['data-ds-bundle-data'])['m_rgItems'][0]['m_rgIncludedAppIDs'][0])
            appids.append(app_id)

        time.sleep(random.random()+1) # for Max retries error

        if page==2:
            print(f'only one loop spending time :{time.time()-start}')

    return appids[:n]

if __name__ == '__main__':

    #It takes about 24 minutes to load a list of 10K games.
    app_ids = get_n_appids(n=10000)

    reviews = []
    user_ids = []
    game_ids = []
    num_games = []
    num_reviews = []
    play_times = []
    ratings = []
    vote_conf = []
    weights = []
    game_reviews = []

    for game_id in tqdm(app_ids[:3000]):
        get_n_reviews(game_id) #make reviews

        #print(f'Complete {i}th game review collection')

        if len(reviews) == 0:
            continue

        #start = time.time()
        for idx in range(len(reviews)):
            user_ids.append(reviews[idx]['author']['steamid'])
            game_ids.append(game_id)
            try:
                play_times.append(reviews[idx]['author']['playtime_at_review'])
            except KeyError:
                '''
                many game reivews have no 'playtime_at_review' property
                in this caes replace playtime_at_review -> playtime_forever
                '''
                play_times.append(reviews[idx]['author']['playtime_forever'])
            num_games.append(reviews[idx]['author']['num_games_owned'])
            num_reviews.append(reviews[idx]['author']['num_reviews'])
            ratings.append(1 if reviews[idx]['voted_up'] else 0)
            vote_conf.append(int(reviews[idx]['votes_up']) + int(reviews[idx]['votes_funny']))
            weights.append(reviews[idx]['weighted_vote_score'])
            game_reviews.append(reviews[idx]['review'])

        reviews = [] #global variable initialization
        #print(f'inner loop spending time : {time.time()-start}')

    steam_ratings = pd.DataFrame({'user_ids':user_ids,
                              'game_ids':game_ids,
                              'num_games_owned':num_games,
                              'num_reviews':num_reviews,
                              'play_times':play_times,
                              'ratings':ratings,
                              'vote_conf':vote_conf,
                              'weights':weights,
                              'game_reviews':game_reviews})
    steam_ratings.to_csv('ratings.csv', encoding='utf-8-sig')


from pymongo import MongoClient
import pefile
import gridfs
import hashlib

client = MongoClient("mongodb://localhost:27017")
#connect to the files db
db = client.filesDB

grid_fs = gridfs.GridFS(db)

def start_cleanup(md5):

	# step 1 - get file from gridfs
	grid_fs_file = grid_fs.find_one({"md5": md5}, no_cursor_timeout=True) # type GridOut

	# step 2 - clean
	byte_data = grid_fs_file.read(size=grid_fs_file.length) # byte

	pe = pefile.PE(data=byte_data, fast_load=True)

	print(pe.sections[0].Name.decode('utf-8'))

	# change the virtual address of the .text section
	pe.sections[0].VirtualAddress = 1100
	print(pe.sections[0].VirtualAddress)

	# step 3 - insert file in bd
	with grid_fs.new_file(filename=grid_fs_file.filename) as fp:
                fp.write(pe.write())

	# step 4 - compute md5 clean file
	md5_clean_file = hashlib.md5(pe.dump_info().encode()).hexdigest()

	result = {}

	# step 5 return job result, md5 clean file
	if md5_clean_file:

		result['md5'] = md5_clean_file

		return result
	else:
		return "wait a second"


from typing import List

class Solution:
    data = [1, 2, 3, 4, 5, 6, 7, 8, 9]

    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        res = []
        self.back_trace(0, 9, res, [], k, n)
        return res

    def back_trace(self, start, total, res, path, k, n):
        # 递归跳出条件
        if len(path) == k:
            res.append(path)
            return

        for i in range(start, total):
            # 跳过
            if len(path) == k - 1:
                if sum(path) + self.data[i] != n:
                    continue
            self.back_trace(i + 1, total, res, path + [self.data[i]], k, n)

print(Solution().combinationSum3(3, 7))
print(Solution().combinationSum3(3, 9))


from dataclasses import dataclass, field
from typing import List, Optional
from xsdata_ech.e_ch_0058_5_0 import HeaderType as HeaderType
from xsdata_ech.e_ch_0155_5_0 import (
    ContestType as ContestType,
    ElectronicBallotType as ElectronicBallotType,
    ExtensionType as ExtensionType,
    VoteType as VoteType,
)

__NAMESPACE__ = "http://www.ech.ch/xmlns/eCH-0159/5"

@dataclass
class EventInitialDelivery:
    class Meta:
        name = "eventInitialDelivery"

    contest: Optional[ContestType] = field(
        default=None,
        metadata={
            "type": "Element",
            "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
            "required": True,
        }
    )
    vote_information: List["EventInitialDelivery.VoteInformation"] = field(
        default_factory=list,
        metadata={
            "name": "voteInformation",
            "type": "Element",
            "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
            "min_occurs": 1,
        }
    )
    extension: Optional[ExtensionType] = field(
        default=None,
        metadata={
            "type": "Element",
            "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
        }
    )

    @dataclass
    class VoteInformation:
        vote: Optional[VoteType] = field(
            default=None,
            metadata={
                "type": "Element",
                "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
                "required": True,
            }
        )
        electronic_ballot: List[ElectronicBallotType] = field(
            default_factory=list,
            metadata={
                "name": "electronicBallot",
                "type": "Element",
                "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
                "min_occurs": 1,
            }
        )

@dataclass
class Delivery:
    class Meta:
        name = "delivery"
        namespace = "http://www.ech.ch/xmlns/eCH-0159/5"

    delivery_header: Optional[HeaderType] = field(
        default=None,
        metadata={
            "name": "deliveryHeader",
            "type": "Element",
            "required": True,
        }
    )
    initial_delivery: Optional[EventInitialDelivery] = field(
        default=None,
        metadata={
            "name": "initialDelivery",
            "type": "Element",
            "required": True,
        }
    )
    minor_version: Optional[int] = field(
        default=None,
        metadata={
            "name": "minorVersion",
            "type": "Attribute",
            "namespace": "http://www.ech.ch/xmlns/eCH-0159/5",
        }
    )


from nets.resnet import ResNet50
from tensorflow.keras.utils import plot_model
from utils import load_image
from tensorflow.keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
from tensorflow.keras import optimizers

import tensorflow as tf

if __name__ == "__main__":
    gpus = tf.config.list_physical_devices(device_type="GPU")
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(device=gpu, enable=True)

    train_dir = "datasets/train"
    val_dir = "datasets/val"
    batch_size = 2048
    image_size = 224
    model = ResNet50(input_shape=(image_size, image_size, 3), classes=2)
    # model.load_weights("ResNet50.h5")
    model.summary()
    opt = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
    model.compile(optimizer=opt,
                  loss=tf.keras.losses.sparse_categorical_crossentropy,
                  metrics=[tf.keras.metrics.sparse_categorical_accuracy])

    plot_model(model, to_file='models/ResNet50.png',show_shapes=True, show_layer_names=True)

    logging = TensorBoard(log_dir="logs")
    checkpoint = ModelCheckpoint("models" + "/ResNet_{epoch:04d}-{val_loss:.4f}.h5", monitor="val_loss", mode="min",
                                 verbose=1, save_weights_only=True, save_best_only=True, period=3)

    early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=15, verbose=1)
    reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=1)

    train_dataset = load_image(train_dir, batch_size, image_size)
    val_dataset = load_image(val_dir, batch_size, image_size)
    model.fit(
        train_dataset,
        epochs=2,
        callbacks=[reduce_lr, logging, checkpoint, early_stopping],
        validation_data=val_dataset,
        initial_epoch=0,
        max_queue_size=20,
        workers=4)

    # 保存keras特有的h5文件模型，这个可以直接加载
    model.save("models" + "/ResNet-model.h5")
    # 保存keras的权重文件，这个需要先搭建模型然后加载权重文件
    model.save_weights("models" + "/ResNet-weights.h5")
    # 保存pb文件，用于tf直接加载模型
    tf.saved_model.save(model, "models/pb")


import requests
import json
import logging
import logging.handlers
import os

from aliyunsdkcore import client
from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest
from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest

KEY_FILE_NAME = 'key.json'

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory, mode=0o777)

class DNS(object):
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    ensure_dir('logs/')
    fh = logging.handlers.RotatingFileHandler('logs/aliyun_ddns_record.log',
                                                          mode='a',
                                                          maxBytes=10 * 1024 * 1024,
                                                          backupCount=10)
    formatter = logging.Formatter(
        '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    def __init__(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        with open(dir_path+'/' + KEY_FILE_NAME, 'r') as f:
            self.s = json.loads(f.read())[0]
        self.clt = client.AcsClient(self.s['AccessKeyId'], self.s['AccessKeySecret'])
        self.dns_domain, self.rc_format = self.s['rc_domain'], self.s['rc_format']

    def check_records(self):
        request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
        request.set_DomainName(self.dns_domain)
        request.set_accept_format(self.rc_format)
        result = self.clt.do_action_with_exception(request)
        result = result.decode()
        result_dict = json.JSONDecoder().decode(result)
        result_list = result_dict['DomainRecords']['Record']
        for j in result_list:
            self.logger.info('\nSubdomain | {0}\nRecordId | {1}\n'.format(j['RR'], j['RecordId']))
            if j['RR'] == 'usdb':
                rc_rr, rc_type, rc_value, rc_record_id, rc_ttl = j['RR'], j[
                    'Type'], j['Value'], j['RecordId'], j['TTL']
                return (rc_rr, rc_type, rc_value, rc_record_id, rc_ttl)
        return ([None] * 5)

    def getMyIp(self):
        try:
            u = requests.get('https://api.ipify.org/?format=text')
            return u.text
        except requests.HTTPError as e:
            self.logger.exception('getMyIp:' + str(e))
            return None

    def update_dns(self, rc_rr, rc_type, rc_value, rc_record_id, rc_ttl):
        self.logger.info('about to update ip : {}'.format(rc_value))
        request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
        request.set_RR(rc_rr)
        request.set_Type(rc_type)
        request.set_Value(rc_value)
        request.set_RecordId(rc_record_id)
        request.set_TTL(rc_ttl)
        request.set_accept_format(self.rc_format)
        result = self.clt.do_action_with_exception(request)
        self.logger.info(result)

    def worker(self):
        rc_rr, rc_type, rc_value, rc_record_id, rc_ttl = self.check_records()
        cur_ip = self.getMyIp()
        if cur_ip != rc_value:
            self.update_dns(rc_rr, rc_type, cur_ip, rc_record_id, rc_ttl)

if __name__ =='__main__':
    logging.basicConfig(level=20)
    d = DNS()
    d.worker()


from time import sleep
from typing import Sequence, Optional, Tuple

from boltons.iterutils import first

from apiserver.apierrors import errors
from apiserver.config_repo import config
from apiserver.database.model import EntityVisibility
from apiserver.database.utils import id as db_id
from apiserver.tests.api_client import APIClient
from apiserver.tests.automated import TestService

class TestSubProjects(TestService):
    def test_project_aggregations(self):
        """This test requires user with user_auth_only... credentials in db"""
        user2_client = APIClient(
            api_key=config.get("apiclient.user_auth_only"),
            secret_key=config.get("apiclient.user_auth_only_secret"),
            base_url=f"http://localhost:8008/v2.13",
        )

        child = self._temp_project(name="Aggregation/Pr1", client=user2_client)
        project = self.api.projects.get_all_ex(name="^Aggregation$").projects[0].id
        child_project = self.api.projects.get_all_ex(id=[child]).projects[0]
        self.assertEqual(child_project.parent.id, project)

        user = self.api.users.get_current_user().user.id

        # test aggregations on project with empty subprojects
        res = self.api.users.get_all_ex(active_in_projects=[project])
        self.assertEqual(res.users, [])
        res = self.api.projects.get_all_ex(id=[project], active_users=[user])
        self.assertEqual(res.projects, [])
        res = self.api.models.get_frameworks(projects=[project])
        self.assertEqual(res.frameworks, [])
        res = self.api.tasks.get_types(projects=[project])
        self.assertEqual(res.types, [])
        res = self.api.projects.get_task_parents(projects=[project])
        self.assertEqual(res.parents, [])

        # test aggregations with non-empty subprojects
        task1 = self._temp_task(project=child)
        self._temp_task(project=child, parent=task1)
        framework = "Test framework"
        self._temp_model(project=child, framework=framework)
        res = self.api.users.get_all_ex(active_in_projects=[project])
        self._assert_ids(res.users, [user])
        res = self.api.projects.get_all_ex(id=[project], active_users=[user])
        self._assert_ids(res.projects, [project])
        res = self.api.projects.get_task_parents(projects=[project])
        self._assert_ids(res.parents, [task1])
        res = self.api.models.get_frameworks(projects=[project])
        self.assertEqual(res.frameworks, [framework])
        res = self.api.tasks.get_types(projects=[project])
        self.assertEqual(res.types, ["testing"])

    def _assert_ids(self, actual: Sequence[dict], expected: Sequence[str]):
        self.assertEqual([a["id"] for a in actual], expected)

    def test_project_operations(self):
        # create
        with self.api.raises(errors.bad_request.InvalidProjectName):
            self._temp_project(name="/")
        project1 = self._temp_project(name="Root1/Pr1")
        project1_child = self._temp_project(name="Root1/Pr1/Pr2")
        with self.api.raises(errors.bad_request.ExpectedUniqueData):
            self._temp_project(name="Root1/Pr1/Pr2")

        # update
        with self.api.raises(errors.bad_request.CannotUpdateProjectLocation):
            self.api.projects.update(project=project1, name="Root2/Pr2")
        res = self.api.projects.update(project=project1, name="Root1/Pr2")
        self.assertEqual(res.updated, 1)
        res = self.api.projects.get_by_id(project=project1_child)
        self.assertEqual(res.project.name, "Root1/Pr2/Pr2")

        # move
        res = self.api.projects.move(project=project1, new_location="Root2")
        self.assertEqual(res.moved, 2)
        res = self.api.projects.get_by_id(project=project1_child)
        self.assertEqual(res.project.name, "Root2/Pr2/Pr2")

        # merge
        project_with_task, (active, archived) = self._temp_project_with_tasks(
            "Root1/Pr3/Pr4"
        )
        project1_parent = self._getProjectParent(project1)
        self._assertTags(project1_parent, tags=[], system_tags=[])
        self._assertTags(project1_parent, tags=[], system_tags=[])
        project_with_task_parent = self._getProjectParent(project_with_task)
        self._assertTags(project_with_task_parent)
        # self._assertTags(project_id=None)

        merge_source = self.api.projects.get_by_id(
            project=project_with_task
        ).project.parent
        res = self.api.projects.merge(
            project=merge_source, destination_project=project1
        )
        self.assertEqual(res.moved_entities, 0)
        self.assertEqual(res.moved_projects, 1)
        res = self.api.projects.get_by_id(project=project_with_task)
        self.assertEqual(res.project.name, "Root2/Pr2/Pr4")
        with self.api.raises(errors.bad_request.InvalidProjectId):
            self.api.projects.get_by_id(project=merge_source)

        self._assertTags(project1_parent)
        self._assertTags(project1)
        self._assertTags(project_with_task_parent, tags=[], system_tags=[])
        # self._assertTags(project_id=None)

        # delete
        with self.api.raises(errors.bad_request.ProjectHasTasks):
            self.api.projects.delete(project=project1)
        res = self.api.projects.delete(project=project1, force=True)
        self.assertEqual(res.deleted, 3)
        self.assertEqual(res.disassociated_tasks, 2)
        res = self.api.tasks.get_by_id(task=active).task
        self.assertIsNone(res.get("project"))
        for p_id in (project1, project1_child, project_with_task):
            with self.api.raises(errors.bad_request.InvalidProjectId):
                self.api.projects.get_by_id(project=p_id)

        self._assertTags(project1_parent, tags=[], system_tags=[])
        # self._assertTags(project_id=None, tags=[], system_tags=[])

    def _getProjectParent(self, project_id: str):
        return self.api.projects.get_all_ex(id=[project_id]).projects[0].parent.id

    def _assertTags(
        self,
        project_id: Optional[str],
        tags: Sequence[str] = ("test",),
        system_tags: Sequence[str] = (EntityVisibility.archived.value,),
    ):
        if project_id:
            res = self.api.projects.get_task_tags(
                projects=[project_id], include_system=True
            )
        else:
            res = self.api.organization.get_tags(include_system=True)

        self.assertEqual(set(res.tags), set(tags))
        self.assertEqual(set(res.system_tags), set(system_tags))

    def test_get_all_search_options(self):
        project1 = self._temp_project(name="project1")
        project2 = self._temp_project(name="project1/project2")
        self._temp_project(name="project3")

        # local search finds only at the specified level
        res = self.api.projects.get_all_ex(
            name="project1", shallow_search=True
        ).projects
        self.assertEqual([p.id for p in res], [project1])
        res = self.api.projects.get_all_ex(name="project1", parent=[project1]).projects
        self.assertEqual([p.id for p in res], [project2])

        # global search finds all or below the specified level
        res = self.api.projects.get_all_ex(name="project1").projects
        self.assertEqual(set(p.id for p in res), {project1, project2})
        project4 = self._temp_project(name="project1/project2/project1")
        res = self.api.projects.get_all_ex(name="project1", parent=[project2]).projects
        self.assertEqual([p.id for p in res], [project4])

        self.api.projects.delete(project=project1, force=True)

    def test_get_all_with_check_own_contents(self):
        project1, _ = self._temp_project_with_tasks(name="project1x")
        project2 = self._temp_project(name="project2x")
        self._temp_project_with_tasks(name="project2x/project22")
        self._temp_model(project=project1)

        res = self.api.projects.get_all_ex(
            id=[project1, project2], check_own_contents=True
        ).projects
        res1 = next(p for p in res if p.id == project1)
        self.assertEqual(res1.own_tasks, 2)
        self.assertEqual(res1.own_models, 1)

        res2 = next(p for p in res if p.id == project2)
        self.assertEqual(res2.own_tasks, 0)
        self.assertEqual(res2.own_models, 0)

    def test_get_all_with_stats(self):
        project4, _ = self._temp_project_with_tasks(name="project1/project3/project4")
        project5, _ = self._temp_project_with_tasks(name="project1/project3/project5")
        project2 = self._temp_project(name="project2")
        res = self.api.projects.get_all(shallow_search=True).projects
        self.assertTrue(any(p for p in res if p.id == project2))
        self.assertFalse(any(p for p in res if p.id in [project4, project5]))

        project1 = first(p.id for p in res if p.name == "project1")
        res = self.api.projects.get_all_ex(
            id=[project1, project2], include_stats=True
        ).projects
        self.assertEqual(set(p.id for p in res), {project1, project2})
        res1 = next(p for p in res if p.id == project1)
        self.assertEqual(res1.stats["active"]["status_count"]["created"], 0)
        self.assertEqual(res1.stats["active"]["status_count"]["stopped"], 2)
        self.assertEqual(res1.stats["active"]["total_runtime"], 2)
        self.assertEqual(res1.stats["active"]["completed_tasks"], 2)
        self.assertEqual(res1.stats["active"]["total_tasks"], 2)
        self.assertEqual(res1.stats["active"]["running_tasks"], 0)
        self.assertEqual(
            {sp.name for sp in res1.sub_projects},
            {
                "project1/project3",
                "project1/project3/project4",
                "project1/project3/project5",
            },
        )
        res2 = next(p for p in res if p.id == project2)
        self.assertEqual(res2.stats["active"]["status_count"]["created"], 0)
        self.assertEqual(res2.stats["active"]["status_count"]["stopped"], 0)
        self.assertEqual(res2.stats["active"]["total_runtime"], 0)
        self.assertEqual(res2.stats["active"]["completed_tasks"], 0)
        self.assertEqual(res2.stats["active"]["total_tasks"], 0)
        self.assertEqual(res2.stats["active"]["running_tasks"], 0)
        self.assertEqual(res2.sub_projects, [])

    def _run_tasks(self, *tasks):
        """Imitate 1 second of running"""
        for task_id in tasks:
            self.api.tasks.started(task=task_id)
        sleep(1)
        for task_id in tasks:
            self.api.tasks.stopped(task=task_id)

    def _temp_project_with_tasks(self, name) -> Tuple[str, Tuple[str, str]]:
        pr_id = self._temp_project(name=name)
        task_active = self._temp_task(project=pr_id)
        task_archived = self._temp_task(
            project=pr_id, system_tags=[EntityVisibility.archived.value], tags=["test"]
        )
        self._run_tasks(task_active, task_archived)
        return pr_id, (task_active, task_archived)

    delete_params = dict(can_fail=True, force=True)

    def _temp_project(self, name, client=None, **kwargs):
        return self.create_temp(
            "projects",
            delete_params=self.delete_params,
            name=name,
            description="",
            client=client,
            **kwargs,
        )

    def _temp_task(self, **kwargs):
        return self.create_temp(
            "tasks",
            delete_params=self.delete_params,
            type="testing",
            name=db_id(),
            input=dict(view=dict()),
            **kwargs,
        )

    def _temp_model(self, **kwargs):
        return self.create_temp(
            service="models",
            delete_params=self.delete_params,
            name="test",
            uri="file:///a",
            labels={},
            **kwargs,
        )


import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, 2, 1)
        self.conv2 = nn.Conv2d(16, 32, 2, 1)
        self.dropout1 = nn.Dropout(0.25)
        self.dropout2 = nn.Dropout(0.5)
        self.fc1 = nn.Linear(18432, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = nn.ReLU()(x)
        x = nn.MaxPool2d(2, 1)(x)
        x = self.dropout1(x)
        x = self.conv2(x)
        x = nn.ReLU()(x)
        x = nn.MaxPool2d(2, 1)(x)
        x = self.dropout2(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = nn.ReLU()(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output

class Mclr_Logistic(nn.Module):
    def __init__(self, input_dim = 784, output_dim = 10):
        super(Mclr_Logistic, self).__init__()
        self.fc1 = nn.Linear(input_dim, output_dim)

    def forward(self, x):
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        output = F.log_softmax(x, dim=1)
        return output

class Mclr_CrossEntropy(nn.Module):
    def __init__(self, input_dim = 784, output_dim = 10):
        super(Mclr_CrossEntropy, self).__init__()
        self.linear = torch.nn.Linear(input_dim, output_dim)

    def forward(self, x):
        x = torch.flatten(x, 1)
        outputs = self.linear(x)
        return outputs

class DNN(nn.Module):
    def __init__(self, input_dim = 784, mid_dim = 100, output_dim = 10):
        super(DNN, self).__init__()
        # define network layers
        self.fc1 = nn.Linear(input_dim, mid_dim)
        self.fc2 = nn.Linear(mid_dim, output_dim)

    def forward(self, x):
        # define forward pass
        x = torch.flatten(x, 1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        x = F.log_softmax(x, dim=1)
        return x

class CifarNet(nn.Module):
    def __init__(self):
        super(CifarNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return F.log_softmax(x, dim=1)

#################################
##### Neural Network model #####
#################################

cfg = {
    'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}

class VGG(nn.Module):
    def __init__(self, vgg_name):
        super(VGG, self).__init__()
        self.features = self._make_layers(cfg[vgg_name])
        self.classifier = nn.Sequential(
            nn.Linear(512, 512),
            nn.ReLU(True),
            nn.Linear(512, 512),
            nn.ReLU(True),
            nn.Linear(512, 10)
        )

    def forward(self, x):
        out = self.features(x)
        out = out.view(out.size(0), -1)
        out = self.classifier(out)
        output = F.log_softmax(out, dim=1)
        return output

    def _make_layers(self, cfg):
        layers = []
        in_channels = 3
        for x in cfg:
            if x == 'M':
                layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
            else:
                layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1),
                           nn.BatchNorm2d(x),
                           nn.ReLU(inplace=True)]
                in_channels = x
        layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
        return nn.Sequential(*layers)

class CNNCifar(nn.Module):
    def __init__(self, num_classes):
        super(CNNCifar, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 100)
        self.fc3 = nn.Linear(100, num_classes)

        self.weight_keys = [['fc1.weight', 'fc1.bias'],
                            ['fc2.weight', 'fc2.bias'],
                            ['fc3.weight', 'fc3.bias'],
                            ['conv2.weight', 'conv2.bias'],
                            ['conv1.weight', 'conv1.bias'],
                            ]

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return F.log_softmax(x, dim=1)


import sys
import requests
from typing import List, Union
import xmltodict
import json
class BaseQuery:
    # class atributes

    PACKAGE_ROOT = '.'

    HEADERS = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36',
    }
    @classmethod
    def __build_params__(cls, *args,**kwargs):
        raise NotImplemented

    @classmethod
    def __query__(cls, url:str, params:dict):
        '''

        :param url:
        :param params:
        :return: list of dicts, each dict contains info of a paper
        '''
        response = requests.get(url=url,params=params,headers=cls.HEADERS)
        return response

class PaperWithCodeQuery(BaseQuery):
    ENDPOINT = 'https://paperswithcode.com/api/v1/papers/'

    @classmethod
    def __build_params__(cls,query: str,
        page = 1,
        items_per_page = 50
        ):

        return {
            'page': page,
            'items_per_page': items_per_page,
            'title': query
        }

    @classmethod
    def __query__(cls, url: str, params: dict):
        return super().__query__(url, params)

    @classmethod
    def query(cls, query: str, page = 1, items_per_page = 50):
        params =  cls.__build_params__(query,page,items_per_page)
        return cls.__query__(cls.ENDPOINT, params).json()['results']

class ArxivQuery(BaseQuery):
    ENDPOINT = 'http://export.arxiv.org/api/query?'
    '''
    an example request:
    'http://export.arxiv.org/api/query?search_query=bert&max_results=1'
    '''
    @classmethod
    def __build_params__(cls,
                         query: str,
                         id_list: str = '',
                         start: int = 0,
                         max_results: int = 50
                         ):

        return {
            'search_query': query,
            'id_list': id_list,
            'start': start,
            'max_results': max_results
        }

    @classmethod
    def query(cls,
              query: str,
              id_list: str= '',
              start: int = 0,
              max_results: int = 50
              ) -> Union[dict, List[dict]]:
        params = cls.__build_params__(query,id_list,start,max_results)
        xml = cls.__query__(cls.ENDPOINT,params).content
        tmp = xmltodict.parse(xml)
        return tmp['feed']['entry']

class IEEEQuery(BaseQuery):
    '''
    an example query url:
    https://ieeexploreapi.ieee.org/api/v1/search/articles?parameter&apikey={API_KEY}&querytext=BERT&max_records=200&start_year=2019&end_year=2021
    '''

    '''
    README:
    Please make sure a .config.json file is stored under the package root
    A template would be like this:
    {
        "api_key": "my api key"
    }
    '''
    ENDPOINT = 'https://ieeexploreapi.ieee.org/api/v1/search/articles?parameter&apikey='

    @classmethod
    def __build_params__(cls, query: str,start_year: int ,end_year: int,num_papers: int = 200 ):
        num_papers = min(num_papers,200)
        end_year = max(start_year,end_year)
        return {
            'querytext': query,
            'max_records': num_papers,
            'start_year': start_year,
            'end_year': end_year
        }

    @classmethod
    def query(cls,
              query: str,
              start_year: int ,
              end_year: int,
              num_papers: int = 200
              ) -> Union[dict, List[dict]]:
        try:
            with open(f"{cls.PACKAGE_ROOT}/.config.json", 'r', encoding='UTF-8') as f:
                api_key = json.load(f)['api_key']
        except Exception:
            print('Please first call "IEEEQuery.__setup_api_key__(<your api key>)" to store the api key first.',file=sys.stderr)
            sys.exit()

        endpoint = cls.ENDPOINT + api_key + '&'
        params = cls.__build_params__(query,start_year,end_year,num_papers)
        papers = cls.__query__(endpoint,params).json()['articles']
        return papers

    @classmethod
    def __setup_api_key__(cls, api_key:str):
        config = {
            'api_key': api_key
        }

        jsObj = json.dumps(config)
        with open(f'{cls.PACKAGE_ROOT}/.config.json', 'w') as f:
            f.write(jsObj)


from django.http import HttpResponse
from django.shortcuts import render
from post.models import Post

def post_list(request):
    posts = Post.objects.all()
    context = {
        'posts': posts
    }
    return render(request, 'post/post_list.html', context=context)

def post_detail(request, post_pk):
    post = Post.objects.get(id=post_pk)
    context = {
        'post': post,
    }
    return render(request, 'post/post_detail.html', context=context)


from revere.sources.base import BaseRevereSource
from sqlalchemy import create_engine

class DatabaseSource(BaseRevereSource):
    name = 'Database'

    def __init__(self, description=None, config={}):
        super(DatabaseSource, self).__init__(description, config)

        required_params = ['connection_string']
        for param in required_params:
            if param not in config or not config[param]:
                raise Exception('Database Source Improperly Configured: missing parameter: %s' % param)
        self.config = config
        self.conn = create_engine(config['connection_string'], pool_recycle=config.get('pool_recycle', 3600))
        self.conn.connect()

    def _convert_to_dict(self, row, keys):
        return dict(zip(keys, row))

    def execute(self, sql, as_dict=False):
        result = self.conn.execute(sql)
        if result.rowcount == 0:
            return None

        if as_dict:
            keys = result.keys()
            return [self._convert_to_dict(row, keys) for row in result]

        return result


from difflib import SequenceMatcher

import pandas as pd
import cv2
from pytesseract import image_to_string
import pytesseract
import os

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

labels = ["croaked растаял", "величии лишил", "Вот он ваш знак", "гидов лавки", "дружбу cloudless", "застыло безопасно",
          "земляного родилась", "охотно нанял", 'серьги корону']
special_symbol = "".join(['-' for _ in range(100)])

def rotate_and_recognize(image_path):
    # Загружаем изображение
    img = cv2.imread(image_path)

    # Перебираем углы поворота от -20 до 20 с шагом 1
    all_results = []
    for angle in range(-20, 21):
        # Поворачиваем изображение
        rotated_img = rotate_image(img, angle)

        # Применяем Tesseract OCR
        result = image_to_string(rotated_img, lang='rus+eng')
        all_results.append(result)

    # Сформируем итоговый ответ на основе результатов для каждого угла поворота
    final_result = " ".join(all_results)

    return final_result

def rotate_image(image, angle):
    # Получаем размеры изображения
    height, width = image.shape[:2]

    # Вычисляем центр изображения
    center = (width // 2, height // 2)

    # Получаем матрицу поворота
    rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)

    # Поворачиваем изображение
    rotated_image = cv2.warpAffine(image, rotation_matrix, (width, height))

    return rotated_image

def calculate_accuracy_percentage(generated_text, expected_text):
    # Используем SequenceMatcher для сравнения строк посимвольно
    matcher = SequenceMatcher(None, generated_text, expected_text)
    match_percentage = matcher.ratio() * 100
    return match_percentage

def test_rotation_and_recognition(dataset_folder):
    output_file = "result_rotation_and_recognition.txt"
    is_correct_list = []

    with open(output_file, 'w', encoding="utf-8") as result_file:
        for image_filename in os.listdir(dataset_folder):
            index = int(str(image_filename)[0]) - 1
            print(index)

            image_path = os.path.join(dataset_folder, image_filename)

            # Получаем итоговый ответ с использованием Tesseract OCR
            recognized_text = rotate_and_recognize(image_path)

            expected_text = labels[index]

            # Сравниваем результат с ожидаемым текстом
            is_correct = int(calculate_accuracy_percentage(recognized_text, expected_text))

            # Записываем результат в файл
            result_file.write(
                f"Исходник: {expected_text} || Распознано: {recognized_text} || Корректность: {is_correct}\n{special_symbol}\n")

            is_correct_list.append(is_correct)

    return is_correct_list

if __name__ == "__main__":
    original_dataset_folder = "cap"

    # Тестирование нового метода на исходном датасете
    rotation_and_recognition_results = test_rotation_and_recognition(original_dataset_folder)

    # Запись результатов тестирования в сводную таблицу
    results_df = pd.DataFrame({"Rotation and Recognition": rotation_and_recognition_results})
    results_df.to_csv("rotation_and_recognition_results.csv", index=False)


import os.path as osp
import time
from argparse import ArgumentParser, Namespace

from mmengine import Config, DictAction, mkdir_or_exist

from uce.edit import EDITORS, load_editor, parse_concepts, save_editor
from uce.utils import setup_logger

def parse_args() -> Namespace:
    parser = ArgumentParser('Edit model weights.')
    parser.add_argument('config', help='Path to the config file.')
    parser.add_argument(
        'edit_concepts',
        help="Concepts to edit. You can enter multiple concepts, separated by ','.  "
        "If an argument has format of 'xxx.txt', then concepts are read from "
        'a txt file, where each line is a concept. ')
    parser.add_argument(
        '--guided-concepts',
        '-g',
        help='Target concepts of the editing. You can enter multiple concepts, '
        "separated by ','. If an argument has format of 'xxx.txt', then concepts "
        'are read from a txt file, where each line is a concept. Note that the '
        'number of guided concepts must be equal to the number of edit concepts, '
        'or be 1, which means that all the editing concepts will be guided '
        'towards this single target concept.')
    parser.add_argument(
        '--preserve-concepts',
        '-p',
        help='Concepts to preserve. You can enter multiple concepts, '
        "separated by ','. If an argument has format of 'xxx.txt', "
        'then concepts are read from a txt file, where '
        'each line is a concept. ')
    parser.add_argument(
        '--np',
        type=int,
        help='Number of preserve concepts. If it is given, then randomly sample '
        'this number of concepts from the preserve concepts.')
    parser.add_argument(
        '--with-extra',
        choices=['artist', 'object'],
        help='Type of the extra prompts. If it is artist, then some extra prompts '
        "such as 'painting by {concept}' will be added to the set of "
        "edit concepts. If it is 'object', then extra prompts are like "
        "'image of {concept}'. Otherwise, no extra concepts will be used.")
    parser.add_argument(
        '--work-dir',
        '-w',
        default='./workdirs/default/',
        help='Directory to save the output files.')
    parser.add_argument(
        '--editor-ckpt',
        '-c',
        help='Checkpoint of an editor. If it is given, then it means continue to '
        'edit the given model weight, otherwise edit the pre-trained model '
        'weight. ')
    parser.add_argument(
        '--meta-info',
        '-m',
        help='Path to the meta info json file of the editor. Only needed if you '
        'wanna load a previously used editor and continue editing the model.') # Continue the training, should not be used in the first time
    parser.add_argument('--gpu-id', type=int, default=0, help='GPU ID.')
    parser.add_argument(
        '--cfg-options',
        nargs='+',
        action=DictAction,
        help='key value pairs to override the config file entries. The pairs need to '
        'be in format of xxx=yyy')

    args = parser.parse_args()
    return args
# Check this link if you want to know more about argparse
# https://docs.python.org/3/library/argparse.html

def main():
    args = parse_args()
    work_dir = args.work_dir
    mkdir_or_exist(work_dir)
    device = f'cuda:{args.gpu_id}'

    timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
    log_file = osp.join(work_dir, f'{timestamp}.log')
    logger = setup_logger('uce', filepath=log_file)

    cfg = Config.fromfile(args.config)
    cfg.editor.update({'device': device})
    if args.cfg_options is not None:
        cfg.merge_from_dict(args.cfg_options)
    logger.info(f"Using config:\n{'=' * 60}\n{cfg.pretty_text}\n{'=' * 60}\n")

    editor = EDITORS.build(cfg.editor)
    if args.editor_ckpt is not None:
        editor = load_editor(editor, args.editor_ckpt, args.meta_info).to(device)

    edit_concepts, guided_concepts, preserve_concepts = parse_concepts(
        args.edit_concepts,
        guided_concepts=args.guided_concepts,
        preserve_concepts=args.preserve_concepts,
        num_preserve_concepts=args.np,
        with_extra=args.with_extra,
    )
    editor.edit(edit_concepts, guided_concepts, preserve_concepts)
    save_editor(editor, osp.join(work_dir, f'editor_{editor.id_code}.pt'))

if __name__ == '__main__':
    main()

"""
from mmengine.config import Config

cfg = Config.fromfile('learn_read_config.py')
print(cfg)

can be used for python(dict), json and yaml file
"""


def getPermutation(n,k):
    from functools import reduce
    n_list=[str(i) for i in range(1,n+1)]
    n_list="".join(n_list)#如果是n_list=" ".join(n_list)。这里" "里面是有空格的，则生成的字符串之间都是有空格的
    #permutations=reduce([lambda s,c:p[:i]+c+p[i:] for i in range(len(p)) for p in s],n_list,[])
    #生成全排列注意点
    permutations = reduce(lambda s, c: [p[:i] + c + p[i:] for p in s for i in range(len(p)+1)], n_list, [""])
    """1、n_list要先转换成字符串
       2、lambda函数的函数体用[]扩住，而不是整个lambda用[]扩住
       3、for i in range(len(p)+1),这里是最重要的。因为必须要len(p)+1，如果不+1，则最后只会生成[],因为刚开始跳不出""
       4、然后n_list, [""]，也重要的[""]里面必须有一个初始化的“”，要不然进不去for p in s
       """
    permutations.sort(key=lambda x:x)
    return permutations[k-1]
"""这样虽然正确但是时间是远远超出的"""

def test_2(n,k):
    """这里的思想是，先生成一个n_list，有序，然后用k整除n-1的阶乘，这样就知道了
    k应该掉落在那个字符开头的permutations，然后%n-1的阶乘，表示的在这个permutations中
    的位置，如果j==0，这就意味着到了这个permutations集合的最后一个了，在当前n_list[n-1]之后的
    都已经排好序了，是逆序的
    """
    from functools import reduce
    n_list = [str(i) for i in range(1, n + 1)]
    result=""
    while(n_list):
        num=reduce(lambda a,b:a*b,[x for x in range(1,len(n_list))],1)
        i=k//num
        j=k%num
        if j == 0:
            result = result + n_list[i-1]
            n_list.pop(i-1)
            result=result+"".join(n_list[::-1])
            return result
        result=result+n_list[i]
        n_list.pop(i)
        k=j
import math
def permutation_k(n,k):
    #这种是19年4月10号做的，很明显这是一个递归思想啊
    ans=[str(i) for i in range(1,n+1)]
    def f(m,temp):#这个函数的含义是在temp中的从小到大排列的所有组合中，找到第k个
        if m==0:
            return "".join(temp)
        else:
            number=math.factorial(len(temp)-1)
            return temp[m//number]+f(m%number,temp[0:m//number]+temp[m//number+1:])
    return f(k,ans)
print(permutation_k(8,7))
n=2
k=2
#getPermutation(n,k)
print(test_2(n,k))


from rest_framework.schemas import AutoSchema

from Apps.common.services import Params, BaseService

class GoogleMobility_Service(BaseService):
    def __init__(self):
        self.dropped_keys = []
        self.single_keys = ['CountryName', 'CountryCode']

        self.params = [
            Params(name='regionCode', dtype=str, required=True,
                   location='query', description="Country code (ISO3)"),
            Params(name='startDate', dtype=str, required=True,
                   location='query', description="Query start date (format: %Y-%m-%d)"),
            Params(name='offset', dtype=int, required=True,
                   location='query', description="The number of dates from startDate."),

            # Params(name='retail_and_recreation', dtype=bool, required=True,
            #        location='header', description="requesting retail and recreation data"),
            # Params(name='grocery_and_pharmacy', dtype=bool, required=True,
            #        location='header', description="requesting grocery and pharmacy data"),
            # Params(name='parks', dtype=bool, required=True,
            #        location='header', description="requesting parks data"),
            # Params(name='transit_stations', dtype=bool, required=True,
            #        location='header', description="requesting transit stations data"),
            # Params(name='workplaces', dtype=bool, required=True,
            #        location='header', description="requesting workplaces data"),
            # Params(name='residential', dtype=bool, required=True,
            #        location='header', description="requesting residential data"),
        ]
        self.methods = ['get']

        super(GoogleMobility_Service, self).__init__(params=self.params, methods=self.methods,
                                                     dropped_keys=self.dropped_keys, single_keys=self.single_keys)
        self.schema = GoogleMobility_Schema(self.fields)

class GoogleMobility_Schema(AutoSchema):
    manual_fields = []  # common fields

    def __init__(self, fields):
        super().__init__()
        self.manual_fields = fields

    def get_manual_fields(self, path, method):
        super().get_manual_fields(path, method)
        custom_fields = []

        return self.manual_fields + custom_fields


__author__ = 'zhamilto'

from tests_framework.ui_building_blocks.screen import Screen, ScreenActions
from tests_framework.ve_tests.tests_conf import DeviceType
import logging

MAX_FOR_YOU_ASSETS = 10
MAX_ON_AIR_ASSETS = 10
MAX_FEATURE_POSTER_ASSETS = 4
OPEN_VOD_ACTION_MENU_TIME_OUT = 2.5

class TvFilter(Screen):
    def __init__(self, test):
        Screen.__init__(self, test, "tv_filter")

    def get_events_by_section(self, name):
        elements = self.test.milestones.getElements()
        events = self.test.ui.get_sorted_elements("event_view", 'x_pos', elements, "section", name)
        return events

    def wait_for_events_by_selection(self, name, events_must_exist=True):
        events = None
        for wait in range(0, 30):
            events = self.get_events_by_section(name)
            if events:
                break
            self.test.wait(1)

        if events_must_exist:
            self.test.log_assert(events, "Cannot find events for section " + name)

        return events

    def navigate(self):
        logging.info("Navigate to tv_filter")
        label_found = False
        for retry in range(0, 30):
            if self.test.screens.header.item_exists("DIC_MAIN_HUB_TV"):
                label_found = True
            # self.test.log_assert(not self.is_active(), "Television label not found but in tv-filter screen!")
            elements = self.test.milestones.getElements()
            screen_name = self.test.milestones.get_current_screen(elements)
            self.test.log("Currently in " + screen_name)
            if screen_name == "tv_filter":
                return
            if label_found:
                self.test.screens.header.tap_item("DIC_MAIN_HUB_TV")
            elif screen_name == "guide":
                self.test.ui.tap_element("back")
            elif screen_name == "action_menu" or screen_name == "trick_bar":
                self.test.ui.tap_element("exit")
                # When going back from action menu opened from search back might have "TELEVISION" label
                elements = self.test.milestones.getElements()
                screen_name = self.test.milestones.get_current_screen(elements)
                if screen_name == "tv_search":
                    if self.test.platform == "Android":
                        if self.test.device_type != DeviceType.TABLET:
                            self.test.ui.tap_localized_id("DIC_CANCEL")
                        else:
                            self.test.ui.tap_localized_label("DIC_CANCEL")
                    else:
                        self.test.ui.tap_localized_id("DIC_CANCEL")
                self.navigate()
            elif screen_name == "tv_search":
                if self.test.platform == "Android":
                    if self.test.device_type != DeviceType.TABLET:
                        self.test.ui.tap_localized_id("DIC_CANCEL")
                    else:
                        self.test.ui.tap_localized_label("DIC_CANCEL")
                else:
                    self.test.ui.tap_localized_id("DIC_CANCEL")
            elif screen_name == "full_content_screen":
                self.test.ui.tap_element("back")
            else:
                self.test.screens.infolayer.show()
                if self.test.device_type != DeviceType.TABLET and self.test.project != "KD":
                    self.test.ui.tap_element("exit")
                else:
                    self.test.ui.tap_element("actionmenu")
                    self.test.ui.tap_element("exit")
            self.test.wait(1)
        self.test.log_assert(label_found, "Cannot find television label")
        if not self.is_active():
            self.test.screens.header.tap_item("DIC_MAIN_HUB_TV")
        self.verify_active()

    def dismiss(self):
        self.verify_active()
        #Scroll down to reveal the on air events
        self.scroll_to_selection("DIC_FILTER_TV_ON_AIR")
        #Retrieve the poster events
        onAirTitle = self.test.milestones.get_dic_value_by_key("DIC_FILTER_TV_ON_AIR").upper()
        onAirEvents = self.wait_for_events_by_selection(onAirTitle)
        onAirFound = False
        for onAirEvent in onAirEvents:
            self.test.appium.tap_element(onAirEvent)
            #Wait for spinner to be removed
            self.test.ui.wait_for_element_removed("spinner")
            #Check if error message is not displayed
            elements = self.test.milestones.getElements()
            #Check for error
            if self.test.ui.element_exists("error_msg", elements):
                #Close notification
                self.test.screens.notification.dismiss()
                #Tap exit button
                self.test.ui.tap_element("exit", elements)
                self.verify_active()
            else:
                onAirFound = True
                break
        self.test.log_assert(onAirFound, "Cannot find poster in tv-filter that can be played")
        self.test.screens.infolayer.verify_active(ignoreNotification=True)
        from tests_framework.ui_building_blocks.screen import ScreenDismiss
        self.test.screens.infolayer.dismiss(ScreenDismiss.TAP)
        self.test.screens.fullscreen.verify_active(ignoreNotification=True)

    def count_events_each_sections(self):
        on_air_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_TV_ON_AIR").upper()
        for_you_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_FOR_YOU").upper()
        sections = {"poster": MAX_FEATURE_POSTER_ASSETS, on_air_dic: MAX_ON_AIR_ASSETS, for_you_dic: MAX_FOR_YOU_ASSETS}
        for i in range(0, len(sections)):
            self.test.wait(5)
            if self.get_events_by_section(sections.keys()[i]):
                channelsNumber = len(self.scroll_and_return_events(sections.keys()[i]))
                self.test.log_assert(channelsNumber <= sections.values()[i], "app present wrong number of events in:" + sections.keys()[i])

    def check_button_see_all(self):
        on_air_channels = self.test.ctap_data_provider.send_request("ON_AIR_LIST", None)
        if [on_air_channels["count"]] > 10:
            on_air_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_TV_ON_AIR").upper()
            see_all_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_SEE_ALL").upper()
            #Scroll down to reveal the on air events
            self.scroll_to_selection("DIC_FILTER_TV_ON_AIR")
            #Check elements
            elements = self.test.milestones.getElements()
            title_section = self.test.milestones.getElement(
                [("title_section", on_air_dic, "=="), ("title_text", see_all_dic, "==")], elements)
            self.test.log_assert(title_section, "See all button not found")

    def verify_first_item_after_tuned(self):
        feature_poster_event = self.test.milestones.getElement([("name", "event_view", "=="), ("section", "poster", "==")])
        self.test.appium.swipe_element(feature_poster_event, feature_poster_event["width"]+15, ScreenActions.LEFT, 2500)
        self.test.wait(2)
        tuned_channel = self.wait_for_events_by_selection("poster")[0]
        self.test.appium.tap_element(tuned_channel)
        self.test.screens.linear_action_menu.verify_active()
        self.test.screens.tv_filter.navigate()
        self.test.screens.tv_filter.verify_active()
        feature_poster_event = self.test.milestones.getElement([("name", "event_view", "=="), ("section", "poster", "==")])
        self.test.appium.swipe_element(feature_poster_event, feature_poster_event["width"], ScreenActions.RIGHT, 2500)
        self.test.wait(2)
        poster_first_item = self.wait_for_events_by_selection("poster")[0]
        self.test.log_assert('channel_number' in tuned_channel, "Cannot find channel number in tuned channel, item: [" + str(poster_first_item) + "] tuned channel: [" + str(tuned_channel) + "]")
        self.test.log_assert('channel_number' in poster_first_item, "Cannot find channel number in poster first item, item: [" + str(poster_first_item) + "] tuned channel: [" + str(tuned_channel) + "]")
        self.test.log_assert(poster_first_item['channel_number'] == tuned_channel['channel_number'],
                        "Not present last tuned channel on featured poster first items ")

    def scroll_and_return_events (self, section):
        channelsNumber = []
        new_event = ""
        sectionsEvents = self.wait_for_events_by_selection(section)
        self.test.log_assert('channel_number' in sectionsEvents[0], "Missing channel number in event: " + str(sectionsEvents[0]))
        last_event = sectionsEvents[0]['channel_number']
        while last_event != new_event:
            channelsNumber.append(sectionsEvents[0]['channel_number'])
            last_event = sectionsEvents[0]['channel_number']
            self.test.appium.swipe_element(sectionsEvents[0], sectionsEvents[0]["width"] + 15, ScreenActions.LEFT, 2500)
            self.test.wait(2)

            sectionsEvents = self.wait_for_events_by_selection(section)
            new_event = sectionsEvents[0]['channel_number']
        if len(sectionsEvents) > 1:
            for i in range(1, len(sectionsEvents)):
                channelsNumber.append(sectionsEvents[i]['channel_number'])

        item = len(sectionsEvents) - 1
        self.test.appium.swipe_element(sectionsEvents[item], (sectionsEvents[item]["width"] + 15 ) * len(channelsNumber), ScreenActions.RIGHT, 2500)
        self.test.wait(2)
        return channelsNumber

    def scroll_to_selection(self, dic_title):
        dic_title_text = self.test.milestones.get_dic_value_by_key(dic_title).upper()
        for scroll in range(0, 10):
            selection_label = self.test.ui.get_label_containing(dic_title_text)
            if selection_label:
                break
            self.test.ui.swipe_element("up")
        self.test.log_assert(selection_label, "Cannot find section " + dic_title)

    def verify_navigation_from_sections(self):
        on_air_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_TV_ON_AIR").upper()
        for_you_dic = self.test.milestones.get_dic_value_by_key("DIC_FILTER_FOR_YOU").upper()
        feature_poster = self.wait_for_events_by_selection("poster")
        on_air_events = self.wait_for_events_by_selection(on_air_dic)
        for_you_events = self.wait_for_events_by_selection(for_you_dic, False) # it's OK if there aren't any events

        if feature_poster:
            self.test.log("Tapping event: " + str(feature_poster[0]))
            self.test.appium.tap_center_element(feature_poster[0])
            self.test.screens.linear_action_menu.verify_active()
            self.test.screens.tv_filter.navigate()
            self.test.screens.tv_filter.verify_active()

        if on_air_events:
            for evt in on_air_events:
                self.test.log("Tapping event: " + str(evt))
                self.test.appium.tap_center_element(evt)
                self.test.screens.infolayer.verify_active()
                self.test.screens.tv_filter.navigate()
                self.test.screens.tv_filter.verify_active()

        if for_you_events:
            for evt in for_you_events:
                self.test.log("Tapping event: " + str(evt))
                self.test.appium.tap_center_element(evt)
                self.test.screens.infolayer.verify_active()
                self.test.screens.tv_filter.navigate()
                self.test.screens.tv_filter.verify_active()

    def get_current_channel(self):
        self.navigate()
        #Scroll down to reveal the on air events
        self.scroll_to_selection("DIC_FILTER_TV_ON_AIR")
        onAirTitle = self.test.milestones.get_dic_value_by_key("DIC_FILTER_TV_ON_AIR").upper()
        result = self.wait_for_events_by_selection(onAirTitle)[0]["title_text"]
        self.test.log_assert(result , "No current channel in tv_filter , ON AIR section")
        return result

    def open_vod_action_menu_by_position(self, position):

        self.test.screens.store_filter.navigate()

        device_type = self.test.device_type
        vod_events = self.test.screens.main_hub.get_events_by_source("EVENT_SOURCE_TYPE_VOD")

        self.test.log_assert(position >= 0 and position < len(vod_events), "postion  " + str(position) + " is more than the vod event count " + str(len(vod_events)))
        self.test.appium.tap_element(vod_events[position])
        self.test.wait(OPEN_VOD_ACTION_MENU_TIME_OUT)


# coding: utf-8
"""
Parser/type converter for data in Interactive Brokers' Flex XML format.

https://www.interactivebrokers.com/en/software/reportguide/reportguide.htm#reportguide/activity_flex_query_reference.htm
"""
# stdlib imports
import xml.etree.ElementTree as ET

# local imports
from ibflex import schemata
from ibflex.schemata import elementSchemata

class FlexParserError(Exception):
    """ Base class for errors in this module """
    pass

def parse(source):
    tree = ET.ElementTree()
    tree.parse(source)
    root = tree.getroot()
    return parse_response(root)

def parse_response(elem):
    response = schemata.FlexQueryResponse.convert(elem)
    flexStmts = elem.findall('FlexStatements')

    # Sanity check
    if len(flexStmts) != 1:
        msg = ("FlexQueryResponse must contain exactly 1 FlexStatements, "
               "not {}")
        raise FlexParserError(msg.format(len(flexStmts)))

    response['FlexStatements'] = parse_stmts(flexStmts[0])
    return response

def parse_stmts(elem):
    attrs = schemata.FlexStatements.convert(elem)
    count = attrs['count']
    flexStmt = elem.findall('FlexStatement')

    # Sanity check
    if len(flexStmt) != count:
        msg = ("FlexStatements declares count={} "
               "but contains {} FlexStatement elements")
        raise FlexParserError(msg.format(count, len(flexStmt)))

    return [parse_stmt(stmt) for stmt in flexStmt]

def parse_stmt(elem):
    stmt = schemata.FlexStatement.convert(elem)
    children = dict(parse_stmt_child(child) for child in elem)
    stmt.update(children)
    return stmt

def parse_stmt_child(elem):
    # If the tag isn't one of the special cases defined in stmt_child_parsers,
    # by default treat it as a list container
    parser = stmt_child_parsers.get(elem.tag, parse_list)
    return parser(elem)

def parse_acctinfo(elem):
    return 'AccountInformation', schemata.AccountInformation.convert(elem)

def parse_rates(elem):
    return 'ConversionRates', dict(parse_rate(rate) for rate in elem)

def parse_rate(elem):
    """
    Use input schema to convert element.

    Return duple of ((currency, date), rate) suitable for use
    as a dict item.
    """
    rate = schemata.ConversionRate.convert(elem)
    return (rate['fromCurrency'], rate['reportDate']), rate['rate']

def parse_fxpos(elem):
    if len(elem) == 0:
        items = []
    else:
        # Sanity check
        if len(elem) != 1:
            msg = "<{}> has more than 1 child: {}".format(
                elem.tag,
                ', '.join(["<{}>".format(child.tag) for child in elem])
            )
            raise FlexParserError(msg)
        fxLots = elem[0]
        if fxLots.tag != 'FxLots':
            msg = "<{}> can only contain <FxLots>, not <{}>"
            raise FlexParserError(msg.format(elem.tag, fxLots))

        attrName, items = parse_list(fxLots)

    return 'FxPositions', items

def parse_list(elem):
    """
    Use container tag to look up conversion schema for contained items.

    Return duple of (container tag, list of converted items).
    """
    tag = elem.tag
    try:
        schema = elementSchemata[tag]
    except KeyError:
        msg = "Don't know the schema to parse items in {}"
        raise FlexParserError(msg.format(tag))
    items = [schema.convert(item) for item in elem]
    return tag, items

stmt_child_parsers = {'AccountInformation': parse_acctinfo,
                      'ConversionRates': parse_rates,
                      'FxPositions': parse_fxpos, }

##############################################################################
# CLI SCRIPT
###############################################################################
def main():
    from argparse import ArgumentParser

    argparser = ArgumentParser(
        description='Parse Interactive Brokers Flex XML data')
    argparser.add_argument('file', nargs='+', help='XML data file(s)')
    args = argparser.parse_args()

    for file in args.file:
        print(file)
        response = parse(file)
        # print(response)
        for stmt in response['FlexStatements']:
            for trade in stmt['Trades']:
                print(trade)

if __name__ == '__main__':
    main()


import cv2
import matplotlib.pyplot as plt

def main():
    windowName="Live Webcam Video Feed Capture"
    cv2.namedWindow(windowName)

    cap = cv2.VideoCapture(0)

    filename='C:\\Users\\ASH\\Desktop\\New folder\\456.avi'

    codec= cv2.VideoWriter_fourcc('X','V','I','D')
    framerate=30
    resolution = (640,480)
#codec examples => WMV2,WMV1,MJPG,DIVX,XVID,H264

    VideoFileOutput=cv2.VideoWriter(filename,codec,framerate,resolution)

    if cap.isOpened():          #check if camera is opened or not
        ret,frame=cap.read()
    else:
        ret=False

    while ret:
        ret,frame=cap.read()

        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) #to swap blue green color of video

        VideoFileOutput.write(frame)

        cv2.imshow(windowName,frame)
        if cv2.waitKey(1)==27:
            break

    cap.release()       #turn off webcam

    cv2.destroyAllWindows()

if __name__=="__main__":
    main()


import hashlib
import yaml

import url_utils
import config

def tokenize_string(string):
    tokens = []
    cur_token = ""

    for char in string:
        if char in config.settings["ALLOWED_AN_CHARS"]:
            cur_token += char
        else:
            if cur_token:
                tokens.append(cur_token)
                cur_token = ""
            else:
                pass
    if cur_token:
        tokens.append(cur_token)
    return tokens

def get_base_filename(url):
    tokens = url_utils.tokenize_url(url)
    md5 = hashlib.md5(url.encode("utf-8")).hexdigest()
    tokens.append(md5)
    base_filename = "-".join(tokens)
    return base_filename


# from pudb import set_trace; set_trace()
from typing import List, Tuple
import math

class Solution1:
    def longestPath(self, parent: List[int], s: str) -> int:
        """LeetCode 2246

        I am glad that this solution was almost exactly the same as the updated
        one last time I encountered this problem in April 2022.

        Direct DFS. The return of dfs(idx) is the longest path that satisfies
        the question starting from idx. For each idx, we can also compute a
        potential result, which is the longest path of its child plus the second
        longest path of its child plus one.

        O(NlogN), 1829 ms, faster than 83.81%
        """
        graph = [[] for _ in range(len(s))]
        for i, p in enumerate(parent[1:], 1):
            graph[p].append(i)
        self.res = 0

        def dfs(idx) -> int:
            max_lens = [0, 0]
            for nex in graph[idx]:
                l = dfs(nex)
                if s[nex] != s[idx]:
                    max_lens.append(l)
            max_lens.sort()
            self.res = max(self.res, max_lens[-1] + 1 + max_lens[-2])
            return max_lens[-1] + 1

        dfs(0)
        return self.res

class Solution2:
    def longestPath(self, parent: List[int], s: str) -> int:
        """Remove the sort. Use two variables to keep track the largest and
        second largest.

        O(N), 1589 ms, faster than 95.34%
        """
        graph = [[] for _ in range(len(s))]
        for i, p in enumerate(parent[1:], 1):
            graph[p].append(i)
        self.res = 0

        def dfs(idx) -> int:
            l1, l2 = 0, 0  # max, second max
            for nex in graph[idx]:
                l = dfs(nex)
                if s[nex] != s[idx]:
                    if l > l1:
                        l2, l1 = l1, l
                    elif l > l2:
                        l2 = l
            self.res = max(self.res, l1 + l2 + 1)
            return l1 + 1

        dfs(0)
        return self.res

sol = Solution2()
tests = [
    ([-1,0,0,1,1,2], "abacbe", 3),
    ([-1,0,0,0], "aabc", 3),
    ([-1,0,1], "aab", 2),
]

for i, (parent, s, ans) in enumerate(tests):
    res = sol.longestPath(parent, s)
    if res == ans:
        print(f'Test {i}: PASS')
    else:
        print(f'Test {i}; Fail. Ans: {ans}, Res: {res}')