"""Implement Binary Search Tree."""
from collections import deque
import random

class Node(object):
    """Create Node Object. At this point, Node.Value must be a number."""

    def __init__(self, value=None, left_child=None, right_child=None, parent=None):
        """Initialize Node Object."""
        self.value = value
        self.left_child = left_child
        self.right_child = right_child
        self._parent = parent

    @property
    def parent(self):
        """Return Parent Property."""
        return self._parent

    @parent.setter
    def parent(self, node):
        """Set the parent of the node, and set the appropriate child of parent."""
        self._parent = node
        if node is None:
            self._parent = None
        elif isinstance(node, Node):
            if self.value and self.value > node.value:
                node.right_child = self
            else:
                node.left_child = self
        else:
            raise TypeError

    def leftest(self):
        """Get the Leftest Child of this node."""
        return self.left_child.leftest() if self.left_child else self

    def orphan_self(self, child):
        """Connect given child to the parent of this node, on the correct side."""
        if child is None:
            if self.value >= self.parent.value:
                self.parent.right_child = None
            else:
                self.parent.left_child = None
        else:
            child.parent = self.parent

    def _depth(self):
        left_depth = self.left_child._depth() if self.left_child else 0
        right_depth = self.right_child._depth() if self.right_child else 0
        return 1 + max(left_depth, right_depth)

    def balance(self):
        """Check Children and return balance of node."""
        left_weight = self.left_child._depth() if self.left_child else 0
        right_weight = self.right_child._depth() if self.right_child else 0
        return left_weight - right_weight

    def pre_order(self):
        """Create Generator for helping Pre order Traversal."""
        yield self.value
        if self.left_child:
            for item in self.left_child.pre_order():
                yield item
        if self.right_child:
            for item in self.right_child.pre_order():
                yield item

    def in_order(self):
        """Create Generator for helping in order Traversal."""
        if self.left_child:
            for item in self.left_child.in_order():
                yield item
        yield self.value
        if self.right_child:
            for item in self.right_child.in_order():
                yield item

    def post_order(self):
        """Create Generator for helping in post order Traversal."""
        if self.left_child:
            for item in self.left_child.post_order():
                yield item
        if self.right_child:
            for item in self.right_child.post_order():
                yield item
        yield self.value

    def _get_dot(self):
        """Recursively prepare a dot graph entry for this node."""
        if self.left_child is not None:
            yield "\t{} -> {};".format(self.value, self.left_child.value)
            for i in self.left_child._get_dot():
                yield i
        elif self.right_child is not None:
            r = random.randint(0, 1e9)
            yield "\tnull{} [shape=point];".format(r)
            yield "\t{} -> null{};".format(self.value, r)
        if self.right is not None:
            yield "\t{} -> {};".format(self.value, self.right_child.value)
            for i in self.right_child._get_dot():
                yield i
        elif self.left_child is not None:
            r = random.randint(0, 1e9)
            yield "\tnull{} [shape=point];".format(r)
            yield "\t{} -> null{};".format(self.value, r)

class Bst(object):
    """Create a Binary Search Tree Object."""

    def __init__(self, root=None):
        """Initialize Binary Search Tree."""
        self.root = root
        self._size = 0

    def pre_order(self):
        """Create Generator for in pre order Traversal. Calls Helper."""
        if not self.root:
            return
        for item in self.root.pre_order():
            yield item

    def in_order(self):
        """Create Generator for in in order Traversal. Calls Helper."""
        if not self.root:
            return
        for item in self.root.in_order():
            yield item

    def post_order(self):
        """Create Generator for in post order Traversal. Calls Helper."""
        if not self.root:
            return
        for item in self.root.post_order():
            yield item

    def breadth_first(self):
        """Breadth first traversal."""
        if not self.root:
            return
        queue = deque([self.root])
        while queue:
            node = queue.pop()
            yield node.value
            if node.left_child:
                queue.appendleft(node.left_child)
            if node.right_child:
                queue.appendleft(node.right_child)

    def insert(self, value):
        """Make new node and, if node not in tree, insert into tree."""
        if not isinstance(value, (int, float)):
            raise TypeError
        if not self.contains(value):
            new_node = Node(value=value)
            self._size += 1
            if self.root is None:
                self.root = new_node
            else:
                cursor = self.root
                while True:
                    if new_node.value > cursor.value:
                        if cursor.right_child is None:
                            new_node.parent = cursor
                            self.check_balance(cursor)
                            return
                        cursor = cursor.right_child
                    else:
                        if cursor.left_child is None:
                            new_node.parent = cursor
                            self.check_balance(cursor)
                            return
                        cursor = cursor.left_child

    def check_balance(self, node):
        """Check node's balance. Rebalances accordingly and updates parent balance."""
        if node:
            current_balance = node.balance()
            if current_balance > 1 or current_balance < -1:
                self.rebalance(node)
            elif node.parent and node.parent.balance() != 0:
                self.check_balance(node.parent)

    def rotate_left(self, node):
        """Rotate node to the left, make node.right_child new subtree root."""
        swap = node.right_child
        swap.orphan_self(swap.left_child)
        if node == self.root:
            self.root = swap
        swap.parent = node.parent
        node.parent = swap

    def rotate_right(self, node):
        """Rotate node to the right, make node.left_child new subtree root."""
        swap = node.left_child
        swap.orphan_self(swap.right_child)
        if node == self.root:
            self.root = swap
        swap.parent = node.parent
        node.parent = swap

    def rebalance(self, node):
        """Rebalance nodes."""
        if node.balance() < 0:
            if node.right_child.balance() > 0:
                self.rotate_right(node.right_child)
            self.rotate_left(node)
        elif node.balance() > 0:
            if node.left_child.balance() < 0:
                self.rotate_left(node.left_child)
            self.rotate_right(node)

    def _contains(self, value):
        """Helper function: returns node matching value."""
        cursor = self.root
        while cursor:
            if cursor.value == value:
                return cursor
            cursor = cursor.right_child if value > cursor.value else cursor.left_child

    def contains(self, value):
        """Check if node with property equal to value is in tree.

        Calls helper _contains method.
        Return Boolean Value.
        """
        return bool(self._contains(value))

    def size(self):
        """Return _size property of tree."""
        return self._size

    def depth(self):
        """Return integer representing number of levels in tree."""
        return self.root._depth() if self.root else 0

    def balance(self):
        """Return Balance of root node.

        If Right is deeper than left, expect a negative integer.
        Expect a positive integer is left size is deeper than right.
        """
        return self.root.balance() if self.root else 0

    def _get_right_leftest(self, node):
        while True:
            swap_node = node.right_child.leftest()
            if not swap_node.right_child:
                return swap_node

    def _delete_node_with_two_children(self, node):
        swap_node = self._get_right_leftest(node)
        parent = swap_node.parent
        node.value = swap_node.value
        swap_node.orphan_self(None)
        self.check_balance(parent)

    def _delete_node(self, node, child):  # child can be a node or None
        parent = node.parent
        if node.value == self.root.value:
            self.root = child
            self.check_balance(child)
        else:
            node.orphan_self(child)
            self.check_balance(parent)

    def delete(self, value):
        """Delete node with value given, and adjust tree accordingly."""
        node = self._contains(value)
        if node:
            self._size -= 1
            if node.right_child and node.left_child:
                self._delete_node_with_two_children(node)
            else:
                child = node.right_child if node.right_child else node.left_child
                self._delete_node(node, child)

    def draw_graph(self):
        """Draw dot graph."""
        if self.root:
            return "digraph G {{\n{}}} \t{};\n{}\n".format(self.root.value, "".join(self.root._get_dot()))


from src.analyzer.analyzer import Analyzer
from src.body.body import Body, Bulking
from src.food.food import (
    Apple,
    Banana,
    ChickenBreast,
    Courgette,
    Egg,
    Ham,
    OatFlakes,
    Oil,
    Pork,
    Whey,
    WhiteBread,
    WhiteRice,
    Yogurt,
)
from src.meal.meal import Meal, MealPlan

body = Body(weight=55, fat=0.25, cal_neutral=1500)
bulking = Bulking(body=body, calory_intake=2000, features=None)

bread_breakfast = Meal([WhiteBread(g=40), Egg(g=60), Ham(g=40)], name="bread_breakfast")
oat_breakfast = Meal([OatFlakes(g=40)], name="oat_breakfast")

chicken_meal = Meal(
    [
        ChickenBreast(g=200),
        Whey(g=25),
        WhiteRice(g=110),
        Courgette(g=50),
        Banana(g=100),
        Yogurt(g=100),
        Oil(g=15),
    ],
    name="chicken_meal",
)

porc_meal = Meal(
    [
        Pork(g=200),
        Whey(g=25),
        WhiteRice(g=110),
        Courgette(g=50),
        Apple(g=100),
        Yogurt(g=100),
        Oil(g=15),
    ],
    name="porc_meal",
)

meal_plan = MealPlan([bread_breakfast, chicken_meal, porc_meal])
analyzer = Analyzer(meal_plan, bulking)
# print(analyzer.summary())
print(analyzer.details())

#                     kCal  protein        fat    carb  fibers
# bread_breakfast   257.00    19.80  10.280000   20.86    1.08
# chicken_meal      779.85    74.17  25.980000   58.35    3.10
# porc_meal         896.85    65.37  46.680000   49.35    2.90
# body_strategy    2000.00   110.00  44.444444  290.00     NaN
# analyzer          -66.30    49.34  38.495556 -161.44     NaN


import pytest

from six import StringIO

from tests.base import BaseTest

class TestFileApi(BaseTest):

    @pytest.fixture(scope='class')
    def file(self, app):
        file = StringIO(app.session_name('test content'))
        setattr(file, 'name', app.session_name('test_file'))
        yield file

    def test_upload(self, client, file):
        uploaded_file_name = client.file_api.upload(file)
        assert file.name in uploaded_file_name, u'File name is a part of the returned identifier.'


import os
import random

import pandas as pd

import SharedConsts as sc
from Agents.dqn_agent import DqnAgent
from Reinforcement_env.env import PhyloGame

def run_dqn_agent_experiment(**kwargs):
    agent, result_dir = set_up_dqn_agent(kwargs['cpus'], kwargs['experiment_unique_dir_name'])

    all_episode_rewards, all_episode_q, loss = agent.train(episodes=sc.EPISODES, result_dir=result_dir)

    # change to show=False when running jobs (then it saves the plot in the dataset dir)
    agent.env.helper.plot_rl_scores(result_dir, all_episode_rewards, all_episode_q, loss)

    agent.test(result_dir=result_dir, final_test=True, episode=sc.EPISODES)

def set_up_dqn_agent(cpus, experiment_unique_dir_name, buffer_data_dir_lst=None):
    # buffer_data_dir_lst - should only be set if this is a learn from experience scenario
    random.seed(sc.RANDOM_SEED)
    number_of_cpus = int(cpus) if cpus is not None else None

    result_dir = sc.EXPERIMENTS_RESDIR / experiment_unique_dir_name
    if not os.path.exists(result_dir):
        os.mkdir(result_dir)
    train_datasets, test_datasets = choose_rl_datasets(sc.NUMBER_OF_SPECIES, sc.HOW_MANY_DATASETS_TRAIN)
    print(f'train datasets: {train_datasets}')
    print(f'test datasets: {test_datasets}')
    # train_datasets = switch_train_sets(buffer_data_dir_lst, train_datasets)
    env = PhyloGame(datasets=train_datasets, number_of_cpus_to_use=number_of_cpus,
                    use_random_starts=sc.USE_RANDOM_STARTING_TREES, results_dir=result_dir, is_train=True)
    test_env = PhyloGame(datasets=test_datasets, number_of_cpus_to_use=number_of_cpus,
                         use_random_starts=sc.USE_RANDOM_STARTING_TREES, results_dir=result_dir, is_train=False)

    agent = DqnAgent(env=env, test_env=test_env, experiment_unique_dir_name=experiment_unique_dir_name)
    return agent, result_dir

def choose_rl_datasets(number_of_species, how_many_ds_train):
    if sc.FIXED_TEST_DATASETS is None:
        test_df = pd.read_csv(sc.PATH_TO_TESTING_TREES_FILE)
        test_datasets = list(test_df[test_df['ntaxa'].isin(number_of_species)]['data_set_number'].astype(str))
    else:
        test_datasets = sc.FIXED_TEST_DATASETS

    if sc.FIXED_TRAIN_DATASETS is None:
        train_df = pd.read_csv(sc.PATH_TO_TRAINING_TREES_FILE)
        train_datasets = list(train_df[train_df['ntaxa'].isin(number_of_species)]['data_set_number'].astype(str))
        train_datasets = random.sample(train_datasets, how_many_ds_train)
    else:
        train_datasets = sc.FIXED_TRAIN_DATASETS

    return train_datasets, test_datasets


#!/usr/bin/env python3

alphabet = 'abcdefghijklmnopqrstuvwxyz'

list = 'aaaba baabb aabab baaab aaaab babaa ababa aaaaa abbab aaaab aaaaa aabbb aaaaa baaba aaaaa aaaab aaaaa bbaaa abaaa'
encode = list.split(' ')

def tr(list):
	ans = []
	text = ''
	for item in encode:
		temp = ''
		for char in item:
			if char == 'a':
				temp += '0'
			else:
				temp += '1'

		ans.append(alphabet[int(temp, 2)])
	return text.join(ans).upper()

print(tr(list))


# import the necessary packages
import argparse
import os

import cv2

# import local packages
from code.detection.people.yolo_func import yolo_func
from code.detection.painting.painting_detection import run_frame
from code.localization.localization import localization
from code.rectification.rectification import rect
from code.retrieval.retrieval import retrieval, load_json_file_from_path
from code.retrieval.setup_db import create_painting_db
from code.paths import PROJ_ROOT, YOLO_WEIGHTS_PATH, YOLO_CFG_PATH

def yolo_setup(weights_path=YOLO_WEIGHTS_PATH, config_path=YOLO_CFG_PATH):
    """
    Reads the weights and config files and prepares the network for the YOLO to run.

    :param weights_path: The path for the weights file.
    :param config_path: The path for the config file.
    :type weights_path: str
    :type config_path: str
    :return: Network and layer names for yolo
    :rtype: tuple
    """
    if not os.path.exists(YOLO_WEIGHTS_PATH):
        print("YOLO weights not found, you can find the link in the readme")
        exit(-2)
    net = cv2.dnn.readNetFromDarknet(config_path, weights_path)
    ln = net.getLayerNames()
    ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    return net, ln

def show_and_wait(img):
    """
    Debug function. Show an image and waits for a key press

    :param img: Image to be shown
    """
    cv2.imshow("img", img)
    cv2.waitKey()

def get_params():
    """
    Verify presence of required arguments and reads passed arguments into a dictionary

    :return: Dictionary of arguments
    :rtype: dict
    """
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--input", required=True,
                    help="path to input video")
    ap.add_argument("-o", "--output", default=argparse.SUPPRESS,
                    help="path to the output name")
    ap.add_argument("-v", "--verbose", default=argparse.SUPPRESS, action='store_true',
                    help="verbose mode")
    ap.add_argument("-d", "--debug", default=argparse.SUPPRESS, action='store_true',
                    help="slow mode")
    ap.add_argument("-s", "--skip", default=1, type=int,
                    help="slow mode")
    return vars(ap.parse_args())

if __name__ == "__main__":
    args = get_params()

    # define if verbose mode
    verbose = "verbose" in args

    # define if debug mode
    debug = "debug" in args

    # define skip for testing purposes
    skip = args["skip"]
    if verbose: print("Analyzing 1 frame each {}".format(skip)) if skip > 1 else print("Analyzing all frames")

    # YOLO setup
    if verbose: print("Loading Yolo...")
    net, ln = yolo_setup()

    # retrieval setup, load db
    if verbose: print("Loading painting descriptors...")
    if not os.path.exists(os.path.join(PROJ_ROOT, "retrieval", "./paintings_descriptors.json")):
        if verbose: print("Descriptors not found, creating them...")
        create_painting_db()
    query_images = load_json_file_from_path(os.path.join(PROJ_ROOT, "retrieval", "paintings_descriptors.json"))

    # color definition
    painting_bbox_color = [255, 0, 0]
    painting_bbox_width = 7
    painting_descr_color = [255, 255, 255]
    painting_descr_size = .4
    painting_descr_thick = 1

    person_bbox_color = [0, 0, 255]
    person_bbox_width = 5
    person_descr_color = [255, 255, 255]
    person_descr_size = .4
    person_descr_thick = 1

    # open input
    if verbose: print("Opening input video...")
    cap = cv2.VideoCapture(args["input"])
    if not cap.isOpened():
        print('Cannot open camera :(')
        exit(-1)

    # retrieve capture parameters
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = int(cap.get(cv2.CAP_PROP_FPS)) / skip
    length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    if verbose: print(
        "Input details:\n - {}px\n - {}px\n - {}fps\n{} frames\nExpected duration: {}s".format(width, height, fps,
                                                                                length,
                                                                                length * 8 / skip))

    # open output if defined
    if "output" in args:
        if verbose: print("Creating output file {}...".format(args["output"]))
        out = cv2.VideoWriter(args["output"] + ".mp4v",
                              cv2.VideoWriter_fourcc('d', 'i', 'v', 'x'), fps,
                              (width, height))

    frame_cnt = 0
    # loop over the whole video
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        if frame_cnt % skip != 0:
            if verbose: print("Skipping frame #{}".format(frame_cnt))
            frame_cnt += 1
            continue
        else:
            frame_cnt += 1

        print("-------------------------")
        print("Frame #{}".format(frame_cnt))

        # object detection
        if verbose: print("Detecting paintings...")
        painting_bboxs, img_cnts = run_frame(frame)
        if verbose: print("Detected {} paintings".format(len(painting_bboxs)))
        if debug: show_and_wait(img_cnts)

        # rectification
        rect_frame, painting_bboxs = rect(frame, painting_bboxs)
        if verbose: print("Rectified")
        if debug: show_and_wait(rect_frame)

        # retrieval
        if verbose: print("Retrieving paintings from DB...")
        for bbox in painting_bboxs:
            results = retrieval(bbox["rect"], query_images)

            # remove rectification from dictionary
            bbox.pop("rect", None)

            # if there is a result add it to the dictionary
            if results is not None:
                result = results[0]
                bbox["painting"] = {
                    "title": result[0],
                    "author": result[1],
                    "room": result[2]
                }
                bbox["list"] = results

        if verbose: print("Retrieved paintings from DB")

        # people detection
        if verbose: print("Detecting people...")
        people_bboxs = yolo_func(frame.copy(), net, ln)
        if verbose: print("Detected {} people".format(len(people_bboxs)))

        # localization
        if len([bbox for bbox in painting_bboxs if "painting" in bbox]) > 0:
            room = localization(painting_bboxs)
        else:
            room = -1
        if verbose: print("Room computed: {}".format(room))

        # Drawing painting_bboxs
        if verbose: print("Drawing...")
        for bbox in painting_bboxs:
            # draw bbox
            (x, y, w, h) = (bbox["x"], bbox["y"], bbox["width"], bbox["height"])
            cv2.rectangle(rect_frame, (x, y), (x + w, y + h), painting_bbox_color, painting_bbox_width)

            # determine description
            if "painting" in bbox:
                painting = bbox["painting"]
                title = "Title: {}".format(painting["title"])
                author = "Author: {}".format(painting["author"])
            else:
                title = "Title: ?"
                author = "Author: ?"

            # draw description
            cv2.putText(rect_frame, title, (x + 20, y + 20),
                        cv2.FONT_HERSHEY_COMPLEX, painting_descr_size, painting_descr_color, painting_descr_thick)
            cv2.putText(rect_frame, author, (x + 20, y + 40),
                        cv2.FONT_HERSHEY_COMPLEX, painting_descr_size, painting_descr_color, painting_descr_thick)

        # Drawing ppl_bboxs
        for bbox in people_bboxs:
            # draw box
            (x, y, w, h) = (bbox["x"], bbox["y"], bbox["width"], bbox["height"])
            cv2.rectangle(rect_frame, (x, y), (x + w, y + h), person_bbox_color, person_bbox_width)

            # detetrmine description (in this case the identified room)
            descr = "Room: {}".format(room if room > 0 else "?")

            # draw description
            cv2.putText(rect_frame, descr, (x + 20, y + 20),
                        cv2.FONT_HERSHEY_COMPLEX, person_descr_size, person_descr_color, person_descr_thick)

        if verbose: print("Exporting result...")

        # print the results as per the project requirements
        print("\tPaintings:")
        if len(painting_bboxs) > 0:
            for bbox in painting_bboxs:
                (x, y, w, h) = (bbox["x"], bbox["y"], bbox["width"], bbox["height"])
                bbox_dict = {'x': x, 'y': y, 'w': w, 'h': h}
                print("\t\t{}".format(bbox_dict))
                print("\t\t\tRetrieval ranked list:")
                if "list" in bbox:
                    for i, result in enumerate(bbox["list"]):
                        print('\t\t\t\t{}) Title: {}, Author: {}, Room: {}'.format(i + 1, result[0],
                                                                                result[1], result[2], result[3]))
                else:
                    print('\t\t\t\tNone')
        else:
            print("\t\tNone")
        print("\tPeoples:")
        if len(people_bboxs) > 0:
            for bbox in people_bboxs:
                (x, y, w, h) = (bbox["x"], bbox["y"], bbox["width"], bbox["height"])
                bbox_dict = {'x': x, 'y': y, 'w': w, 'h': h}
                print("\t\t{}".format(bbox_dict))
        else:
            print("\t\tNone")
        print("\tRoom: {}".format(room if room > 0 else "?"))

        # write resulting frame
        if "output" in args:
            out.write(rect_frame)
        else:
            cv2.imshow("result", rect_frame)
            cv2.waitKey(10)

    # destroy and release
    if verbose: print("Releasing resources and exiting, this may take a while!")
    cv2.destroyAllWindows()
    cap.release()
    if "output" in args:
        out.release()
    exit(0)


import bpy

from ..gui import return_active_set_automation
from ..addon_prefs import get_addon_preferences
from .automation_set_actions import add_item_to_collection

# enum callback for automation set
def automation_set_callback(scene, context):

    items = []

    a_set, a_automation = return_active_set_automation(context)

    scn = context.scene
    for a_s in scn.pupt_properties.automation_set:
        if a_set is not None and a_set == a_s:
            continue
        items.append((a_s.name, a_s.name, ""))

    items.append(('CREATE_NEW', "Create New", ""))

    return items

# set attributes between 2 dataset
def set_properties_from_dataset(datasetin, datasetout, avoid_list, debug):
    if debug: print("Puppeteer --- Copying from %s to %s" % (str(datasetin), str(datasetout))) #debug

    for prop in datasetin.bl_rna.properties:
        if not prop.is_readonly and not prop.identifier in avoid_list:
            try:
                setattr(datasetout, '%s' % prop.identifier, getattr(datasetin, prop.identifier))
            except (KeyError, AttributeError):
                if debug: print("Puppeteer --- Error copying %s" % prop.identifier) #debug
                pass

class PUPT_OT_Copy_Automation(bpy.types.Operator):
    bl_idname = "pupt.copy_automation"
    bl_label = "Copy Automation"
    bl_options = {"UNDO", "INTERNAL"}
    bl_description = "Copy selected automation"

    automation_set : bpy.props.EnumProperty(
        name = "Automation Set",
        items = automation_set_callback,
        )
    new_automation_set_name : bpy.props.StringProperty(name = "Set name", default = "new set")
    cut : bpy.props.BoolProperty(name = "Cut", description = "Remove original automation")

    @classmethod
    def poll(cls, context):
        a_set, a_automation = return_active_set_automation(context)
        return a_automation is not None

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        layout = self.layout
        layout.prop(self, "cut")

        layout.prop(self, "automation_set", text = "Set")

        if self.automation_set == "CREATE_NEW":
            layout.prop(self, "new_automation_set_name", text = "Set Name")

    def execute(self, context):

        debug = get_addon_preferences().debug

        pupt_props = context.scene.pupt_properties
        sets = pupt_props.automation_set
        a_set, a_automation = return_active_set_automation(context)

        # create new set if needed
        if self.automation_set == "CREATE_NEW":
            target_set = add_item_to_collection(sets, self.new_automation_set_name)
            if debug: print("Puppeteer --- New Set created : %s" % target_set.name)
        else:
            target_set = sets[self.automation_set]

        # create automation
        new_automation = add_item_to_collection(target_set.automation, a_automation.name)
        # copy automation props
        set_properties_from_dataset(a_automation, new_automation, ("name"), debug)
        # keyframes
        for k in a_automation.keyframe:
            new_k = new_automation.keyframe.add()
            set_properties_from_dataset(k, new_k, (), debug)
        if debug: print("Puppeteer --- Automation created : %s" % new_automation.name)

        # if cut, remove old automation
        if self.cut:
            a_set.automation.remove(a_set.automation_index)
            if a_set.automation_index != 0:
                a_set.automation_index -= 1
            if debug: print("Puppeteer --- Old automation removed")

        self.report({'INFO'}, "Automation copied")

        return {'FINISHED'}

### REGISTER ---

def register():
    bpy.utils.register_class(PUPT_OT_Copy_Automation)

def unregister():
    bpy.utils.unregister_class(PUPT_OT_Copy_Automation)


from functools import partial
import numpy as np
from numpy.testing import assert_allclose
from scipy.optimize import check_grad
import pytest

from pyquantification.quantifiers.gsls.fitters import WeightSumFitter

def test_get_seed_hists() -> None:
    seed_hists = WeightSumFitter.get_seed_hists(
        calib_hist=np.array([0.1, 0.5, 0.4]),
        target_hist=np.array([0.4, 0.5, 0.1]),
        random_state=1,
    )
    assert np.array(seed_hists).shape == (10, 3)
    assert_allclose(np.sum(np.array(seed_hists), axis=1), np.ones(shape=10))

def test_target_func() -> None:
    assert WeightSumFitter.target_func(
        remain_hist=np.array([0.2, 0.3, 0.5]),
        calib_hist=np.array([0.2, 0.3, 0.5]),
        target_hist=np.array([0.2, 0.3, 0.5]),
    ) == -2.0
    assert WeightSumFitter.target_func(
        remain_hist=np.array([0.0, 0.4, 0.6]),
        calib_hist=np.array([0.2, 0.3, 0.5]),
        target_hist=np.array([0.2, 0.5, 0.3]),
    ) == -((0.3 / 0.4) + (0.3 / 0.6))

def test_target_jacobian() -> None:
    calib1 = np.array([0.2, 0.3, 0.5])
    target1 = np.array([0.2, 0.3, 0.5])
    fun1 = partial(WeightSumFitter.target_func, calib_hist=calib1, target_hist=target1)
    jac1 = partial(WeightSumFitter.target_jacobian, calib_hist=calib1, target_hist=target1)
    assert check_grad(fun1, jac1, np.array([0.2, 0.3, 0.5])) < 1e-06
    assert check_grad(fun1, jac1, np.array([0.0, 0.4, 0.6])) < 1e-06

    calib2 = np.array([0.2, 0.3, 0.5])
    target2 = np.array([0.2, 0.5, 0.3])
    fun2 = partial(WeightSumFitter.target_func, calib_hist=calib2, target_hist=target2)
    jac2 = partial(WeightSumFitter.target_jacobian, calib_hist=calib2, target_hist=target2)
    assert check_grad(fun2, jac2, np.array([0.2, 0.3, 0.5])) < 1e-06
    assert check_grad(fun2, jac2, np.array([0.0, 0.4, 0.6])) < 1e-06

    calib3 = np.array([0.2, 0.4, 0.4])
    target3 = np.array([0.2, 0.4, 0.4])
    fun3 = partial(WeightSumFitter.target_func, calib_hist=calib3, target_hist=target3)
    jac3 = partial(WeightSumFitter.target_jacobian, calib_hist=calib3, target_hist=target3)
    assert check_grad(fun3, jac3, np.array([0.2, 0.3, 0.5])) < 1e-06
    assert check_grad(fun3, jac3, np.array([0.4, 0.3, 0.3])) < 1e-06
    assert check_grad(fun3, jac3, np.array([0.0, 0.4, 0.6])) < 1e-06

def test_equality_constraint_func() -> None:
    assert WeightSumFitter.equality_constraint_func(np.array([1.0, 0.0, 0.0])) == 0.0
    assert WeightSumFitter.equality_constraint_func(np.array([0.2, 0.3, 0.5])) == 0.0
    assert WeightSumFitter.equality_constraint_func(np.array([0.0, 0.0, 0.0])) == 1.0
    assert WeightSumFitter.equality_constraint_func(np.array([0.1, 0.2, 0.3])) == pytest.approx(0.4, 1e-6)
    assert WeightSumFitter.equality_constraint_func(np.array([0.3, 0.5, 0.8])) == pytest.approx(-0.6, 1e-6)

def test_equality_constraint_jacobian() -> None:
    test_hists = [
        np.array([1.0, 0.0, 0.0]),
        np.array([0.2, 0.3, 0.5]),
        np.array([0.0, 0.0, 0.0]),
        np.array([0.1, 0.2, 0.3]),
        np.array([0.3, 0.5, 0.8]),
    ]
    for test_hist in test_hists:
        assert check_grad(WeightSumFitter.equality_constraint_func,
                          WeightSumFitter.equality_constraint_jacobian,
                          test_hist) < 1e-06

def test_find_remain_hist() -> None:
    assert_allclose(WeightSumFitter.find_remain_hist(
        calib_hist=np.array([0.2, 0.3, 0.5]),
        target_hist=np.array([0.2, 0.3, 0.5]),
        random_state=1,
    ), np.array([0.2, 0.3, 0.5]), atol=1e-06)
    assert_allclose(WeightSumFitter.find_remain_hist(
        calib_hist=np.array([0.2, 0.3, 0.5]),
        target_hist=np.array([0.5, 0.3, 0.2]),
        random_state=1,
    ), np.array([0.285714, 0.428571, 0.285714]), atol=1e-06)
    assert_allclose(WeightSumFitter.find_remain_hist(
        calib_hist=np.array([0.0, 0.3, 0.5]),
        target_hist=np.array([0.5, 0.0, 0.2]),
        random_state=1,
    ), np.array([0.0, 0.0, 1.0]), atol=1e-06)
    assert_allclose(WeightSumFitter.find_remain_hist(
        calib_hist=np.array([0.0, 0.3, 0.0]),
        target_hist=np.array([0.5, 0.0, 0.2]),
        random_state=1,
    ), np.array([0.0, 0.0, 0.0]), atol=1e-06)


#If table doesn't exist create table
import sqlite3
# from studyCoding import topic_id
# from login import login
# user_id = login()

CONN = sqlite3.connect('resources.db')
CURSOR = CONN.cursor()
# Class Variable for the info we want.
class Topics_By_User:

    def __init__ (self, user_id, topic_id, id = None):
        self.user_id = user_id
        self.topic_id = topic_id
        self.id = id

    @classmethod
    def create_table(cls) :
        sql = '''
            CREATE TABLE IF NOT EXISTS topic_by_user (
                id INTEGER PRIMARY KEY,
                user_id INT,
                topic_id INT,
                note TEXT
            )
        '''
        CURSOR.execute(sql)

    @classmethod
    def add_to_table(cls, user_id, topic_id) :
        sql = 'INSERT INTO topic_by_user (user_id, topic_id) VALUES (?, ?)'
        CURSOR.execute(sql, (user_id, topic_id) )
        CONN.commit()

    @classmethod
    def get_number_of_topics_studied(cls, user_id):
        pass

# Self.ID = user id global variable
# self.topic = topic currently being studied
# INSERT INTO using this info


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File              : load_questions.py
# Author            : Chi Han, Jiayuan Mao
# Email             : haanchi@gmail.com, maojiayuan@gmail.com
# Date              : 17.07.2019
# Last Modified Date: 20.11.2019
# Last Modified By  : Chi Han
#
# This file is part of the VCML codebase
# Distributed under MIT license
#
# utility for dynmaic loading questions

import os
import numpy as np
from collections import Counter

from utility.common import\
    load, contains, only_contains, \
    union, difference, random_choice_ratio
from dataset.question_dataset \
    import question_dataset

# for balancing dataset suites

def balance_Ans_dataset(dataset, logger):
    output = dataset.random_choice(
        requirement=None,
        num=-1,
        balance_fn=lambda q: q['answer'],
    )
    logger(Counter([q['answer'] for q in output.question_list]), pretty=True)
    logger(f'After balancing: {len(output)}', resume=True)
    return output

def balance_KwAns_dataset(dataset, logger, balance_fn=None):
    if balance_fn is None:
        def balance_fn(q):
            return (q['keywords'][0], q['answer'])
    output = dataset.random_choice(
        requirement=None,
        num=-1,
        balance_fn=balance_fn,
    )
    logger(Counter([q['answer'] for q in output.question_list]), pretty=True)
    logger(f'After balancing: {len(output)}', resume=True)
    return output

def filter_kw_dataset(dataset, kw_concepts, logger, reverse=False):
    middle = 'outside' if reverse else 'in'
    logger(f'Filtering a dataset with keywords {middle} {kw_concepts}')
    logger(f'before filtering: size={len(dataset)}', resume=True)
    output = dataset.filter(
        lambda q: contains(q['keywords'], kw_concepts) != reverse
    )
    logger(f'after filtering: size={len(output)}', resume=True)
    return output

def balance_Ans_suite(suite, logger):
    logger('Balancing questions according to answers')
    with logger.levelup():
        output = {
            split: balance_Ans_dataset(
                dataset, logger
            )
            for split, dataset in suite.items()
        }
    return output

def balance_KwAns_suite(suite, logger, balance_fn=None):
    logger('Balancing questions according to keywords and answers')
    with logger.levelup():
        output = {
            split: balance_KwAns_dataset(
                dataset, logger, balance_fn
            )
            for split, dataset in suite.items()
        }
    return output

def fewer_bias(questions, test_concepts, ratio, logger):
    logger('Biasing a set of questions')
    with logger.levelup():
        logger(f'Original size: {len(questions)}')
        involved_indexes = {
            concept: [ind for ind, qst in questions.questions.items()
                      if concept in qst['keywords']]
            for concept in test_concepts
        }
        remove = union(
            *tuple(random_choice_ratio(indexes, 1 - ratio)
                   for indexes in involved_indexes.values()),
            as_set=True,
        )
        full = union(
            *tuple(involved_indexes.values()),
            as_set=True,
        )
        logger(f'Removed: {len(remove)} out of {len(full)}', resume=True)
        output = questions.copy()
        output.set_indexes(difference(output.indexes, remove))
    return output

def fewer_bias_clsf(questions, test_concepts, ratio, logger,
                    reverse=False):
    logger('Biasing a set of classify questions')
    with logger.levelup():
        logger('Copying the original dataset')
        output = questions.copy(deep=True)
        logger('Biasing')
        for q in logger.tqdm(output.question_list):
            classify_concepts = [
                op['argument'] for op in q['semantic']
            ]
            test_indexes = [
                i for i, concept in enumerate(classify_concepts)
                if (concept in test_concepts) != reverse
            ]
            shape = (q['answer'].shape[0], len(test_indexes))
            mask = np.random.rand(*shape) < ratio
            q['confidence'][:, test_indexes] = \
                q['confidence'][:, test_indexes] * mask
    return output

def get_size(suite, logger, print_it=False):
    size = {split: len(dataset) for split, dataset in suite.items()}
    if print_it:
        logger(f'Size of the dataset: {size}')
    return size

# for manipulating dataset suites
def apply_ratio(suite, ratio, args, logger):
    logger('applying ratio: train={0:0.3f}, val={1:0.3f}, test={2:0.3f}'
           .format(ratio['train'], ratio['val'], ratio['test']))
    return {
        split: dataset.random_choice(
            None,
            args.size * ratio[split],
            None
        )
        for split, dataset in suite.items()
    }

def split_testConcepts(suite, test_concepts, logger):
    logger('Splitting questions according to test_concepts')
    output = {
        'train': suite['train'].filter(
            lambda q: not contains(q.get('keywords', ()), test_concepts)
        ),
        'val': suite['val'].filter(
            lambda q: not contains(q.get('keywords', ()), test_concepts)
        ),
        'test': suite['test'].filter(
            lambda q: only_contains(q.get('keywords', ()), test_concepts)
        )
    }
    logger(suite_length_string(output), resume=True)
    return output

def identical_suite(dataset, logger):
    logger('Getting an identical suite')
    suite = {
        'train': dataset,
        'val': dataset,
        'test': dataset,
    }
    return suite

def filter_suite(suite, requirement, logger):
    logger('Filtering suite according to requirement')
    output = {
        split: dataset.filter(requirement)
        for split, dataset in suite.items()
    }
    return output

def union_suites(suites):
    output = {}
    for split, dataset in suites[0].items():
        output[split] = dataset
        for another in suites[1:]:
            output[split] = output[split].union(another[split])
    return output

def suite_length_string(suite):
    length_dict = {
        split: len(suite[split])
        for split in suite.keys()
    }
    output = str(length_dict)
    return output

# basic loading functions

def load_question_file(group, name, args, logger):
    logger(f'Loading questions from {group}.{name}')
    filename = os.path.join(args.dataset_dir, 'my_dataset', group, name+'.pkl')
    questions = load(filename)
    questions = dict_questions(questions, name)
    dataset = question_dataset.Dataset(questions, args).get_agent()
    logger(f'size = {len(dataset)}', resume=True)
    return dataset

def dict_questions(questions, category):
    questions = {
        (category, i): q
        for i, q in enumerate(questions)
    }
    return questions

# Below are some ratios for combining two suites
# conceptual generalization ratios
def cg_ratios(args):
    r_con = args.conceptual_question_ratio
    r_vis = 1 - r_con
    visual_ratio = {
        'train': args.split_ratio['train'] * r_vis,
        'val': args.split_ratio['val'] * r_vis,
        'test': 0,
    }
    conceptual_ratio = {
        'train': args.split_ratio['train'] * r_con,
        'val': args.split_ratio['val'] * r_con,
        'test': args.split_ratio['test'],
    }
    return visual_ratio, conceptual_ratio

def two_cg_ratios(args):
    r_con = args.conceptual_question_ratio
    r_vis = 1 - r_con
    visual_ratio = {
        'train': args.split_ratio['train'] * r_vis,
        'val': args.split_ratio['val'] * r_vis,
        'test': 0,
    }
    conceptual_ratio = {
        'train': args.split_ratio['train'] * r_con / 2,
        'val': args.split_ratio['val'] * r_con / 2,
        'test': args.split_ratio['test'] / 2,
    }
    return visual_ratio, conceptual_ratio, conceptual_ratio

# visual generalization ratios
def vg_ratios(args):
    r_con = args.conceptual_question_ratio
    r_vis = 1 - r_con
    visual_ratio = {
        'train': args.split_ratio['train'] * r_vis,
        'val': args.split_ratio['val'] * r_vis,
        'test': args.split_ratio['test'],
    }
    conceptual_ratio = {
        'train': args.split_ratio['train'] * r_con,
        'val': args.split_ratio['val'] * r_con,
        'test': 0,
    }
    return visual_ratio, conceptual_ratio

def vg_vismix_ratios(args, n_conceptual=1):
    r_con = args.conceptual_question_ratio
    r_vis = 1 - r_con
    visual1_ratio = {
        'train': args.split_ratio['train'] * r_vis * 0.99,
        'val': 0,
        'test': 0,
    }
    visual2_ratio = {
        'train': args.split_ratio['train'] * r_vis * 0.01,
        'val': args.split_ratio['val'] * r_vis,
        'test': args.split_ratio['test'],
    }
    conceptual_ratio = {
        'train': args.split_ratio['train'] * r_con / n_conceptual,
        'val': args.split_ratio['val'] * r_con / n_conceptual,
        'test': 0,
    }
    return (visual1_ratio, visual2_ratio) + \
        (conceptual_ratio,) * n_conceptual

def equal_ratios(args):
    ratio = {split: args.split_ratio[split] * 0.5
             for split in args.split_ratio}
    return ratio, ratio

def first_only_ratios(args):
    ratio_first = {split: args.split_ratio[split]
                   for split in args.split_ratio}
    ratio_second = {split: 0
                    for split in args.split_ratio}
    return ratio_first, ratio_second

def combine_with_ratio(suites, ratio, args, logger):
    logger('Combining questions')
    with logger.levelup():
        ratioed = []
        for i in range(len(suites)):
            logger(i)
            with logger.levelup():
                ratioed.append(apply_ratio(suites[i], ratio[i], args, logger))
        united = union_suites(ratioed)
    return united


########Librerias###############
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk

######Funciones#########
def validar(dato):
	while True:
		if dato:
			return dato
		else:
			return messagebox.showinfo(title="Advertencia", message="No ingresaste un nombre.")

def saludar():
		global i
		nombre=saludo.get()
		if nombre=='':
			return messagebox.showinfo(title="Advertencia", message="No ingresaste un nombre.")
		if i==5:
			return messagebox.showinfo(title="Advertencia", message="El campo de texto solo permite hasta 5 saludos.")
		string=f'¡Hola {nombre}!'
		saludo.delete(0,tk.END)
		lista.insert(i,string)
		i+=1

######Main############
i=0

ventana=tk.Tk()
ventana.config(width=300,height=300)
ventana.title('Saludos')

########caja de texto########

saludo=tk.Entry()
saludo.place(x=20,y=10)

####Boton#######

botonSaludo=tk.Button(text='¡Saludar!',command=saludar)
botonSaludo.place(x=150,y=10)

########Lista###########
lista = tk.Listbox()
lista.place(y=60,x=20, width=250)

ventana.mainloop()

Ejercicios Python (EducacionIT)/Laboratorios-Clase 7/ejercicio.py


import numpy as np

def simulate_model(id_model, years, ns, param):
#ns = number of samples
    delta, gamma, psi, mu_c, \
        rho, phi_x, sigma_bar, \
            nu, phi_s, mu_d, phi,\
                phi_dc, phi_d, theta = param.delta,     param.gamma, param.psi,     \
                                       param.mu_c,      param.rho,   param.phi_x,   \
                                       param.sigma_bar, param.nu,    param.phi_s,   \
                                       param.mu_d,      param.phi,   param.phi_dc,  \
                                       param.phi_d,     param.theta

    months = years*12

    # Column vectors of time series
    x, sig, cg, dg = np.zeros((months+1, ns)), np.zeros((months+1, ns)), \
                   np.zeros((months+1, ns)), np.zeros((months+1, ns))

    # Initial values of time series (t = 0)
    x[0,:], cg[0,:], dg[0,:], sig[0,:] = 0, sigma_bar**(2), mu_c, mu_d

    #Compute the shocks
    np.random.seed(6062020)
    shock_x, shock_c, shock_d, shock_sig = \
        np.random.normal(0, 1, (months+1, ns)), np.random.normal(0, 1, (months+1, ns)), \
            np.random.normal(0, 1, (months+1, ns)), np.random.normal(0, 1, (months+1, ns))

    if id_model == 'noSV':
        ''' BY2004 constant volatility '''
        for i in range(ns):
            for t in range(1, months+1):
                x[t, i]   = rho*x[t-1, i] + phi_x*sigma_bar*shock_x[t, i]
                cg[t, i]  = mu_c + x[t, i] + sigma_bar*shock_c[t, i]
                dg[t, i]  = mu_d +  phi*x[t, i] + phi_d*sigma_bar*shock_d[t, i] + phi_dc*sig[t-1, i]**(0.5)*shock_c[t, i]
    elif id_model == 'SV':
        ''' BY2004 stochastic volatility '''
        for i in range(ns):
            for t in range(1, months+1):
                x[t, i]   = rho*x[t-1, i] + phi_x*sig[t-1, i]**(0.5)*shock_x[t, i]
                sig[t, i] = max( sigma_bar**(2)*(1 - nu) + nu*sig[t-1, i] + phi_s*shock_sig[t-1, i], np.spacing(1))
                cg[t, i]  = mu_c + x[t, i] + sig[t, i]**(0.5)*shock_c[t, i]
                dg[t, i]  = mu_d +  phi*x[t, i] + phi_d*sig[t-1, i]**(0.5)*shock_d[t, i] + phi_dc*sig[t-1, i]**(0.5)*shock_c[t, i] # phi_dc = 0 !

    return x, sig, cg, dg


import requests
import redis
import time

from apiKey import api_key
from main import get_user_page, process_user_page

redis_client = redis.Redis()

while True:
    while redis_client.llen('userQueue') > 0:
        # Get first user in list non-destructively.
        current_user = redis_client.lindex('userQueue', 0).decode('utf-8')
        current_page = get_user_page(current_user, 1)

        process_user_page(current_page)

        total_pages = int(current_page['recenttracks']['@attr']['totalPages'])

        time.sleep(1)

        # Need to add graceful shutdown and support for interruptions.
        # I.E. Need to be saving the current page in case of shutdown in Redis.
        for i in range(2, total_pages):
            current_page = get_user_page(current_user, i + 1)
            process_user_page(current_page)
            time.sleep(1)

        # Finally remove the user and add to relevant queues to keep from adding again.
        redis_client.lrem('userQueue', 1, current_user)
        redis_client.srem('inUserQueue', current_user)
        redis_client.sadd('finishedUsers', current_user)

    time.sleep(1)


import setuptools

def get_requires(filename):
    requirements = []
    with open(filename, "rt") as req_file:
        for line in req_file.read().splitlines():
            if not line.strip().startswith("#"):
                requirements.append(line)
    return requirements

project_requirements = get_requires("requirements.txt")
setuptools.setup(
    name="snake",
    version="2.2.2",
    install_requires=project_requirements
)


import functools

import megengine.functional as F

def iou_loss(pred, target, reduction="none", loss_type="iou"):
    assert pred.shape[0] == target.shape[0]

    pred = pred.reshape(-1, 4)
    target = target.reshape(-1, 4)
    tl = F.maximum(
        (pred[:, :2] - pred[:, 2:] / 2), (target[:, :2] - target[:, 2:] / 2)
    )
    br = F.minimum(
        (pred[:, :2] + pred[:, 2:] / 2), (target[:, :2] + target[:, 2:] / 2)
    )

    area_p = pred[:, 2] * pred[:, 3]
    area_g = target[:, 2] * target[:, 3]

    mask = (tl < br).astype("int32")
    mask = mask[..., 0] * mask[..., 1]

    diff = br - tl
    area_i = diff[..., 0] * diff[..., 1] * mask
    iou = (area_i) / (area_p + area_g - area_i + 1e-16)

    if loss_type == "iou":
        loss = 1 - iou ** 2

    if reduction == "mean":
        loss = loss.mean()
    elif reduction == "sum":
        loss = loss.sum()

    return loss

def smooth_l1_loss(pred, target, beta=1.0):
    r"""Smooth L1 Loss.

    .. math::

        loss_{i} =
        \begin{cases}
        0.5 (x_i - y_i)^2 / beta, & \text{if } |x_i - y_i| < beta \\
        |x_i - y_i| - 0.5 * beta, & \text{otherwise }
        \end{cases}

    Args:
        pred (Tensor): the predictions
        target (Tensor): the assigned targets with the same shape as pred
        beta (int): the parameter of smooth l1 loss.

    Returns:
        the calculated smooth l1 loss.
    """
    x = pred - target
    abs_x = F.abs(x)
    if beta < 1e-5:
        loss = abs_x
    else:
        in_loss = 0.5 * x ** 2 / beta
        out_loss = abs_x - 0.5 * beta
        loss = F.where(abs_x < beta, in_loss, out_loss)
    return loss

l1_loss = functools.partial(smooth_l1_loss, beta=0.0)

def binary_cross_entropy(pred, label, with_logits=True):
    r"""
    Computes the binary cross entropy loss (using logits by default).
    By default(``with_logitis`` is True), ``pred`` is assumed to be logits,
    class probabilities are given by sigmoid.

    Args:
        pred (Tensor): `(N, *)`, where `*` means any number of additional dimensions.
        label (Tensor): `(N, *)`, same shape as the input.
        with_logits (bool): whether to apply sigmoid first. Default: True

    Return:
        loss (Tensor): bce loss value.
    """
    if with_logits:
        # logsigmoid(pred) and logsigmoid(-pred) has common sub-expression
        # hopefully the backend would optimize this
        loss = -(label * F.logsigmoid(pred) + (1 - label) * F.logsigmoid(-pred))
    else:
        loss = -(label * F.log(pred) + (1 - label) * F.log(1 - pred))
    return loss


from objetos.SpiderRouter import SpiderRouter

class SpiderRouterArpList:

    @staticmethod
    def main():
        ip = 'http://192.168.1.1/'
        action = 'cgi?5'
        cookie_type = 'Authorization'
        cookie_body = 'Basic YWRtaW46YWRtaW4='
        port = '80'
        arp_entry = b'[ARP_ENTRY#0,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n'
        spider = SpiderRouter(ip, action, cookie_type, cookie_body, port, '/')
        response = spider.connect(arp_entry, 'POST')

        if response is True:
            [print(x) for x in spider.format_data()]

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


import numpy as np
import array
import time
import re
import urllib.request, urllib.error # .request
from bs4 import BeautifulSoup, Comment
import csv
import os
import sqlite3
from itertools import islice
from datetime import datetime
import sys

time_var = 0
EMA_var = 0

def Playoffs_Parser(base_url):

	with sqlite3.connect('Games.db') as conn:  # open('Playoffs_list_ByYear.csv', 'w', newline='') as csvfile, sqlite3.connect('Games.db') as conn:
		#  conn.execute("DROP TABLE IF EXISTS games_table")
		# conn.execute('''CREATE TABLE IF NOT EXISTS games_table(
		# GAME_TAG TEXT NOT NULL PRIMARY KEY,
		# SEASON INT,
		# YEAR INT,
		# MONTH INT,
		# DAY INT,
		# HOME_TEAM TEXT NOT NULL,
		# AWAY_TEAM TEXT NOT NULL,
		# HOME_SCORE INT NOT NULL,
		# AWAY_SCORE INT NOT NULL,
		# OT INT,
		# PBP_URL TEXT NOT NULL
		# );
		# ''')
		insert_rows = [(None,)*11] * 2000
		row_num = 0
		row_values = [None] * 11
		# game_tag_regex = re.compile("(?:.*)/([^/]+)\.html")
		# ot_regex = re.compile("(\d*)OT")

		# writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
		# dict_writer = csv.DictWriter(csvfile, ['GAME_TAG', 'Year', 'Month', 'Day', 'Home Name', 'Away Name', 'Home score', 'Away score', 'OT', 'PbP URL'])
		# dict_writer.writeheader()
		global time_var

		for i in range(2018, 2017, -1):
			cur_url = base_url + '/leagues/NBA_' + str(i) + '_games.html'  # https://www.basketball-reference.com/leagues/NBA_2017_games.html
			start_t = time.time()
			r = urllib.request.urlopen(cur_url)
			html = r.read()
			time_var += time.time() - start_t
			soup = BeautifulSoup(html, "html5lib")

			months_list = soup.find("div", id='content').find("div", attrs={'class': 'filter'}).find_all('a', href=re.compile("leagues/NBA_\d+_games-.+\.html"))

			row_values[1] = i
			for month in months_list:
				start_t = time.time()
				soup2 = BeautifulSoup(urllib.request.urlopen(base_url + month.get('href')).read(), "html5lib")
				time_var += time.time() - start_t
				games_table = soup2.find("table", id="schedule").find("tbody").find_all("tr")  # , attrs={"class": re.compile("toggleable.*$")})

				for game_row in games_table:
					cols = game_row.find_all(['th', 'td'])
					if len(cols) < 10:
						continue
					row_values[0] = game_tag_regex.search(base_url + cols[6].a.get('href')).group(1)
					# tmp_date = re.split("(?: |,)+", cols[0].text)
					tmp_date = datetime.strptime(cols[0].text, '%a, %b %d, %Y')
					row_values[2:5] = [tmp_date.year, tmp_date.month, tmp_date.day]
					row_values[5:7] = [cols[4].text, cols[2].text]
					row_values[7:9] = [int(cols[5].text), int(cols[3].text)]
					ot_num = ot_regex.search(cols[7].text)
					if ot_num is not None:
						row_values[9] = int(ot_num.group(1)) if ot_num.group(1) != '' else 1
					else:
						row_values[9] = None
					row_values[10] = 'https://www.basketball-reference.com/boxscores/pbp/' + row_values[0] + '.html'
					insert_rows[row_num] = tuple(row_values)
					row_num += 1
					# insert_rows.append(tuple(row_values))
					# prev_tr = game_row.previous_sibling.previous_sibling
					# prev_td = prev_tr.td.next_sibling.next_sibling
					# team_names = [a_text.text for a_text in game.find_all("a", href=re.compile("teams"), limit=2)]
					# games_links = game_row.find_all("a", href=re.compile("/boxscores/[0-9]+.*$"))
					# games_urls = [base_url + "/boxscores/pbp/" + str.split(a_text['href'], "/")[2] for a_text in games_links]
					# dict_writer.writerow({'Year': i, 'Team1 Name': team_names[0], 'Team2 Name': team_names[1], 'URLs': ' '.join(games_urls)})

				# writer.writerow([])
			conn.executemany("INSERT INTO games_table VALUES (?,?,?,?,?,?,?,?,?,?,?)", insert_rows[0:row_num])
			row_num = 0
			print("finished season {}-{}".format(i-1, i))
		conn.commit()

def playoffs_series_parser(base_url):
	with sqlite3.connect('Games.db') as conn:  # open('Playoffs_list_ByYear.csv', 'w', newline='') as csvfile, sqlite3.connect('Games.db') as conn:
		conn.execute("DROP TABLE IF EXISTS series_table")
		conn.execute("""CREATE TABLE IF NOT EXISTS series_table(
							GAME_TAG TEXT NOT NULL PRIMARY KEY,
							LEAGUE TEXT NOT NULL,
							SEASON INT,
							SERIES_ID INT,
							GAME_NUM INT,
							HOME_TEAM TEXT NOT NULL,
							AWAY_TEAM TEXT NOT NULL,
							HOME_SCORE INT NOT NULL,
							AWAY_SCORE INT NOT NULL
		);
		""")
		insert_rows = [(None,) * 9] * 2000
		row_values = [None] * 9
		row_num = 0
		# game_tag_regex = re.compile("(?:.*)/([^/]+)\.html")
		# ot_regex = re.compile("(\d*)OT")

		# writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
		# dict_writer = csv.DictWriter(csvfile, ['GAME_TAG', 'Year', 'Month', 'Day', 'Home Name', 'Away Name', 'Home score', 'Away score', 'OT', 'PbP URL'])
		# dict_writer.writeheader()

		for i in range(2017, 1946, -1):
			start_t = time.time()
			for league_name in ['NBA', 'ABA', 'BAA']:
				cur_url = base_url + '/playoffs/' + league_name + '_' + str(i) + '.html'  # ex: https://www.basketball-reference.com/playoffs/NBA_1965.html
				try:
					r = urllib.request.urlopen(cur_url)
				except urllib.error.HTTPError as err:
					if err.code == 404:
						continue
				html = r.read()
				soup = BeautifulSoup(html, "html5lib")

				series_table = soup.find("table", id='all_playoffs')  # .find("div", attrs={'class': 'filter'}).find_all('a', href=re.compile("leagues/NBA_\d+_games-.+\.html"))
				if series_table is None:
					print(i, league_name)
					continue

				series_list = series_table.find("tbody").find_all("tr", id=re.compile("s(\d+)"))
				row_values[1] = league_name
				row_values[2] = i
				for series in series_list:
					row_values[3] = int(series.get('id')[1:])
					games_table = series.find("table").find("tbody").find_all("tr")  # , attrs={"class": re.compile("toggleable.*$")})

					for game_row in games_table:
						cols = game_row.find_all(['th', 'td'])
						if len(cols) < 6:
							continue
						row_values[0] = game_tag_regex.search(base_url + cols[0].a.get('href')).group(1)
						row_values[4] = int(cols[0].text[5:])
						row_values[5:7] = [cols[4].text[2:], cols[2].text]
						row_values[7:9] = [int(cols[5].text), int(cols[3].text)]
						insert_rows[row_num] = tuple(row_values)
						row_num += 1
					# insert_rows.append(tuple(row_values))
					# prev_tr = game_row.previous_sibling.previous_sibling
					# prev_td = prev_tr.td.next_sibling.next_sibling
					# team_names = [a_text.text for a_text in game.find_all("a", href=re.compile("teams"), limit=2)]
					# games_links = game_row.find_all("a", href=re.compile("/boxscores/[0-9]+.*$"))
					# games_urls = [base_url + "/boxscores/pbp/" + str.split(a_text['href'], "/")[2] for a_text in games_links]
					# dict_writer.writerow({'Year': i, 'Team1 Name': team_names[0], 'Team2 Name': team_names[1], 'URLs': ' '.join(games_urls)})

					# writer.writerow([])
			conn.executemany("INSERT INTO series_table VALUES (?,?,?,?,?,?,?,?,?)", insert_rows[0:row_num])
			row_num = 0
			print("finished season {} in {} seconds".format(i, time.time() - start_t))
		conn.commit()

def games_quarter_scores(base_url):
	with sqlite3.connect('Games.db') as conn:
		# conn.execute("DROP TABLE IF EXISTS games_scores")
		# conn.execute("""
		# CREATE TABLE IF NOT EXISTS games_scores(
		# 	GAME_TAG TEXT NOT NULL PRIMARY KEY,
		# 	HOME_SCORE INT NOT NULL,
		# 	AWAY_SCORE INT NOT NULL,
		# 	QT1_H_A TEXT,
		# 	QT2_H_A TEXT,
		# 	QT3_H_A TEXT,
		# 	QT4_H_A TEXT,
		# 	OT1_H_A TEXT,
		# 	OT2_H_A TEXT,
		# 	OT3_H_A TEXT,
		# 	OT4_H_A TEXT
		# );
		# """)
		insert_rows = [(None,) * 14] * 2000
		row_values = [None] * 14

		for i in range(2018, 2017, -1):
			result = conn.execute("""
			SELECT COUNT(*)
			FROM games_table
			WHERE SEASON=?
			""", (i,))
			num_of_rows = result.fetchone()[0]
			games_stats = conn.execute("""
			SELECT games_table.GAME_TAG, games_table.OT
			FROM games_table
			WHERE SEASON=?
			""", (i,))

			games_data = games_stats.fetchall()
			row_index = 0

			for k, game in enumerate(games_data):
				start_t = time.time()
				game_tag = game[0]
				ot_count = game[1] if game[1] is not None else 0

				try:
					cur_url = base_url + "/boxscores/" + game_tag + ".html"  # https://www.basketball-reference.com/boxscores/201611230PHI.html
					r = urllib.request.urlopen(cur_url)
				except urllib.error.HTTPError as err:
					if err.code == 404:
						print("Error:\t", game_tag)
						continue
				html = r.read(70000).decode('utf-8')
				table_search = re.search("<table.{0,50}?id=\"line_score\".{0,50}?>.+?</table>", html, flags=re.I | re.DOTALL)
				table_text = html[table_search.start():table_search.end()]
				# soup = BeautifulSoup(html, "html5lib")
				# scores_table2 = BeautifulSoup(str(soup.find(text=lambda text: isinstance(text, Comment) and re.search("<table .+ id=\"line_score\" .+>", text))), "html5lib")
				scores_table2 = BeautifulSoup(table_text, "html5lib")
				# print(scores_table2.find("table", id='line_score'))
				# print(scores_table2.find("table", id='line_score').find("tbody"))
				scores_table = scores_table2.find("table", id='line_score').find("tbody").find_all("tr")
				away_scores = scores_table[2].find_all("td")
				home_scores = scores_table[3].find_all("td")

				if len(away_scores) - 6 != ot_count or len(home_scores) - 6 != ot_count:
					print("OT count error:\t", game_tag, len(away_scores), ot_count)
					continue

				row_values[0] = game_tag
				row_values[1], row_values[2] = int(home_scores[-1].text), int(away_scores[-1].text)

				for j in range(8):
					if j >= 4 + ot_count:
						row_values[j + 3] = None
					else:
						row_values[j + 3] = "{}-{}".format(home_scores[j+1].text, away_scores[j+1].text)

				insert_rows[row_index] = tuple(row_values)
				row_index += 1
				start_t = time.time() - start_t
				if k%100 == 0:
					print("{} - {}".format(k, start_t))

			conn.executemany("INSERT INTO games_scores VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", insert_rows[0:row_index])
			row_index = 0
			print("finished season {} in {} seconds avg".format(i, time.time() - start_t))

		conn.commit()

def Game_Parser(game_id, game_season, game_url):

	dir_name = "Games/{}-{}/".format(game_season-1, game_season)
	if not os.path.exists(dir_name):
		os.makedirs(dir_name)

	#  game_id = str.split(game_url, '/')[5].split('.')[0]
	#  game_id = game_tag_regex.search(game_url).group(1)

	start_t = time.time()
	for k in range(5):
		try:
			r = urllib.request.urlopen(game_url)
			html = r.read()
		except:
			print("\rfailed urlopen {} out of 5".format(k))
			if k == 4:
				raise
			time.sleep(10)
		else:
			break
	global time_var
	global EMA_var
	EMA_var = time.time() - start_t
	time_var += EMA_var
	soup = BeautifulSoup(html, "html5lib")

	title = names_regex.search(soup.find("div", id="content").find("h1").string)
	home_name = title.group(2)
	away_name = title.group(1)

	pbp_table = soup.find("table", id="pbp").find("tbody").find_all("tr")

	with open(dir_name + game_id + ".csv", 'w', newline='') as csvfile:
		writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_ALL)
		writer.writerow([title.group(1), title.group(2), title.group(3), title.group(4)])
		writer.writerow('')
		writer.writerow(['Time', 'H/A action', 'Home: ' + home_name, 'Away: ' + away_name, 'score change', 'description'])
		arr2csv = [''] * 6

		for table_row in pbp_table:
			row_cells = table_row.find_all("td")

			if len(row_cells) == 2:
				arr2csv[0] = row_cells[0].get_text()
				arr2csv[1] = row_cells[1].get_text()
				writer.writerow([arr2csv[0], '-', arr2csv[1]])

			elif len(row_cells) == 6:
				arr2csv[0] = row_cells[0].get_text()
				is_home_action = (row_cells[1].get_text() == '\xa0')
				cur_score = row_cells[3].get_text().split('-')
				arr2csv[1] = 'H' if is_home_action else 'A'
				arr2csv[2] = cur_score[1]
				arr2csv[3] = cur_score[0]
				arr2csv[4] = row_cells[4 if is_home_action else 2].get_text()
				arr2csv[5] = row_cells[5 if is_home_action else 1].get_text()
				writer.writerow(arr2csv)

def Games_Parser():

	global EMA_var
	EMA_time = 0

	with sqlite3.connect('Games.db') as conn:

		for i in range(2018, 2017, -1):
			result = conn.execute("SELECT COUNT(*) FROM games_table WHERE SEASON=?", (i,))
			num_of_rows = result.fetchone()[0]
			games_list = conn.execute("SELECT GAME_TAG, PBP_URL FROM games_table WHERE SEASON=?", (i,))

			for index, game in enumerate(games_list, start=1):
				Game_Parser(game[0], i, game[1])
				EMA_time = (1/6)*EMA_time + (5/6)*EMA_var
				sys.stdout.write('\r')
				if (index % (num_of_rows//10)) == 0:
					sys.stdout.write("sleep.\tindex={},\tnum_of_rows={}".format(index, num_of_rows))
					time.sleep(10)  # sleep for 10 seconds
				else:
					sys.stdout.write("{}% finished ({} avg sec for game:\t{} min remains)".format(index/num_of_rows*100, EMA_time, EMA_time*(num_of_rows - index)/60))
				sys.stdout.flush()

			print("\nFinished season {}-{}".format(i-1, i))

names_regex = re.compile("(.+) at (.+) Play-By-Play, (.+), (.+)$")
game_tag_regex = re.compile("(?:.*)/([^/]+)\.html")
ot_regex = re.compile("(\d*)OT")
game_tag_from_file_name = re.compile("/?(?:.*/)?(.+)\.csv")
start_of_nth_q_regex = re.compile("Start of (\d+)(\S+) (quarter|overtime)", flags=re.I)
jump_ball_regex = re.compile("Jump ball: (.+) vs\. (.+)(?: \((.+)\))?", flags=re.I)
game_pt_regex = re.compile("(.+) (makes|misses) .*(\d)-pt shot (.+)(?:\( assist by (.+)\))?", flags=re.I)
free_throw_regex = re.compile("(.+) (makes|misses) .*free throw(?: (.*)(?:(\d) of (\d))?)?", flags=re.I)
rebound_regex = re.compile("(Defensive|Offensive) rebound by (.+)", flags=re.I)
foul_regex = re.compile("(.*) ?foul by (.+)(?: \(drawn by (.+)\))?", flags=re.I)
turnover_regex = re.compile("Turnover by (.+)(?: \((.+)\))", flags=re.I)
timeout_regex = re.compile("(.+) timeout.*", flags=re.I)
player_substitution_regex = re.compile("(.+) enters the game for (.+)", flags=re.I)

def pbp_to_possessions(game_file):

	with open(game_file, "r", newline='') as csvfile:  # , sqlite3.connect('Games.db') as conn:
		reader = csv.reader(csvfile)
		# conn.execute("DROP TABLE IF EXISTS pbp_table")
		# db_cursor = conn.cursor()
		# db_cursor.execute('''
		# CREATE TABLE IF NOT EXISTS pbp_table(
		# GAME_TAG TEXT NOT NULL,
		# HOME_SCORE INT,
		# AWAY_SCORE INT,
		# TIME_MIN INT,
		# TIME_SEC INT,
		# TIME_MILLI INT,
		# QUARTER TEXT,
		# HorA_ACTION TEXT NOT NULL,
		# SCORE_CHANGE INT,
		# DESCRIPTION TEXT
		# );
		# ''')

		# insert_arr = [(None, ) * 10] * 1000  # max number of rows to insert
		possessions_arr = ["-"] + [0] * 1000  # max number of possessions
		row_values = [None] * 10  # [None] * 10
		row_num = 0

		possessions_index = 1
		cur_time = 0
		cur_quarter = '1'
		last_writen_possession = ''
		score_A, score_H = 0, 0
		team_complement = {'H': 'A', 'A': 'H'}  # used to turn possession

		row_values[0] = game_tag_from_file_name.search(game_file).group(1)  # GAME TAG

		for row in islice(reader, 3, None):
			cur_time = re.split("\D+", row[0])
			row_values[3:6] = map(int, cur_time)  # TIME
			row_values[6] = cur_quarter  # QUARTER
			row_values[8] = None

			if row[1] != '-':  # team action
				row_values[7] = row[1]  # HorA_ACTION
				row_values[9] = row[5]  # DESCRIPTION
				score_A, score_B = int(row[2]), int(row[3])
				row_values[1], row_values[2] = row[2], row[3]  # TEAM SCORES

				res = game_pt_regex.search(row[5])
				if res is not None:  # game point
					if last_writen_possession == row[1]:
						possessions_index -= 1
					elif last_writen_possession == row[1] + ' ':
						possessions_arr[possessions_index] = '0'  # place holder
						possessions_index += 1

					if res.group(2) == 'makes':
						possessions_arr[possessions_index] += int(row[4])  # append new team possession's score
						possessions_index += 1
						last_writen_possession = row[1]
						row_values[8] = int(row[4])  # SCORE CHANGE
					else:  # misses
						# possessions_arr[possessions_index] += 0  # append new team possession
						possessions_index += 1
						last_writen_possession = row[1]

				else:
					res = free_throw_regex.search(row[5])
					if res is not None:  # free throw
						# if res.group(3) is not None and res.group(4) is not None:
						# 	free_throws_count = int(res.group(4))
						# 	cur_free_throw = int(res.group(3))
						#
						# 	if last_writen_possession != row[1] and cur_free_throw > 1:
						# 		print(" {}: Error in game possessions (free throw)".format(row_values[0]))
						# 		raise Exception('Error in possessions')

						if last_writen_possession == row[1]:
							possessions_index -= 1
						elif last_writen_possession == row[1] + ' ':
							possessions_arr[possessions_index] = '0'  # place holder
							possessions_index += 1

						if res.group(2) == 'makes':
							possessions_arr[possessions_index] += int(row[4])  # append new team possession's score
							possessions_index += 1
							last_writen_possession = row[1]
							row_values[8] = int(row[4])  # SCORE CHANGE
						else:  # misses
							# possessions_arr[possessions_index] += 0  # append new team possession
							possessions_index += 1
							last_writen_possession = row[1]

					else:
						res = rebound_regex.search(row[5])
						if res is not None:
							continue
						else:
							res = foul_regex.search(row[5])
							if res is not None: # foul
								continue
							else:
								res = turnover_regex.search(row[5])
								if res is not None:  # turnover
									if last_writen_possession == row[1]:
										possessions_index -= 1
									elif last_writen_possession == row[1] + ' ':
										possessions_arr[possessions_index] = '0'  # place holder
										possessions_index += 1

									# possessions_arr[possessions_index] += 0
									possessions_index += 1
									last_writen_possession = row[1]
								else:
									res = timeout_regex.search(row[5])
									if res is not None:
										continue
									else:
										res = player_substitution_regex.search(row[5])
										if res is not None:
											continue
				if possessions_arr[0] == '-' and possessions_index == 3:  # who starts the
					possessions_arr[0] = row[1]

			else:  # game comment
				row_values[1:3] = [None]*2
				row_values[7] = '-'  # HorA_ACTION
				row_values[9] = row[2]  # DESCRIPTION
				res = start_of_nth_q_regex.search(row[2])

				if res is not None:  # start of a quarter
					cur_quarter = res.group(1)
					last_writen_possession = last_writen_possession + ' '
					if res.group(3) == 'overtime':
						cur_quarter += 'OT'
					possessions_arr[possessions_index] = cur_quarter
					possessions_index += 1
				else:
					res = jump_ball_regex.search(row[2])
					if res is not None:  # jump ball
						continue

			# insert_arr[row_num] = tuple(row_values)  # "('{0[0]}', {0[1]}, {0[2]}, {0[3]}, {0[4]}, {0[5]}, '{0[6]}', '{0[7]}', {0[8]},
			# '{0[9]}')".format(row_values)
			row_num += 1

		#  print(sum(possessions_arr[0:possessions_index:2]), sum(possessions_arr[1:possessions_index:2]))
		# conn.executemany("INSERT INTO pbp_table VALUES (?,?,?,?,?,?,?,?,?,?)", insert_arr[0:row_num])
		# conn.commit()
		# db_cursor.close()
		# conn.close()
	return possessions_arr[0:possessions_index]

def check_pbp(game_tag, season):
	game_possessions = pbp_to_possessions("Games/{}-{}/{}.csv".format(season-1, season, game_tag))
	a_poss = [i for i in game_possessions[0::2] if type(i) == int]
	b_poss = [i for i in game_possessions[1::2] if type(i) == int]
	print(sum(a_poss), sum(b_poss))

# if __name__ == '__main__':

	# check_pbp('200710310DEN', 2008)

	# start_time = time.time()
	# Playoffs_Parser('https://www.basketball-reference.com')
	# playoffs_series_parser('https://www.basketball-reference.com')
	# games_quarter_scores('https://www.basketball-reference.com')
	# print(time.time() - start_time, time_var)

	# start_time = time.time()
	# Games_Parser()
	# print(time.time() - start_time, time_var)

	# Game_Parser('https://www.basketball-reference.com/boxscores/pbp/201706010GSW.html')
	# print(pbp_to_possessions('Games/201706010GSW.csv'))
	# Game_Parser('https://www.basketball-reference.com/boxscores/pbp/201210310DET.html')
	# start_time = time.time()
	# print(pbp_to_possessions('Games/201210310DET.csv'))
	# print(time.time() - start_time)
	# Games_Parser()


# https://stepik.org/lesson/3380/step/4?unit=963
# Sample Input:
# 4
# север 10
# запад 20
# юг 30
# восток 40
# Sample Output:
# 20 -20

napr = {'север': (0, 1), 'запад': (-1, 0), 'юг': (0, -1), 'восток': (1, 0)}
n = int(input())
x_list = [(input()).split(' ') for x in range(n)]
dvizh = [(napr[x][0]*int(y), napr[x][1]*int(y)) for x, y  in x_list]
res = (sum([x for x, y in dvizh]), sum([y for x, y in dvizh]))
print(' '.join(map(str, res)))


import os
import threading
import time
import tkinter as tk
import webbrowser
from tkinter import *

from PIL import ImageTk

root = Tk()

class buttons:
    def run_server(self):
        os.chdir("../SoccerPlayers/")
        os.system("py .\manage.py makemigrations")
        time.sleep(2)
        os.system("py .\manage.py migrate --run-syncdb")
        time.sleep(2)
        os.system("py .\manage.py runserver")

    def __init__(self, master):
        self.canvas = tk.Canvas(root, height=700, width=100, bg="#202020")
        frame = Frame(master)

        # Define buttons
        self.startAppButton = Button(frame, text="Run Website", fg="blue",
                                     command=threading.Thread(target=self.run_server).start)
        self.startAppButton.grid(column=1, row=1)

        self.loadDataButton = Button(frame, text="Load Data", fg="blue",
                                     command=self.load_data)
        self.loadDataButton.grid(column=2, row=1)

        self.startOpenBrowser = Button(frame, text="Open Browser", fg="blue",
                                       command=self.open_broswer)
        self.startOpenBrowser.grid(column=3, row=1)

        self.startExAppButton = Button(frame, text="Run External Application", fg="blue", command=self.runExtrApp)
        self.startExAppButton.grid(column=4, row=1)

        self.quitApp = Button(frame, text="Quit", fg="blue", command=root.destroy)
        self.quitApp.grid(column=10, row=1)

        label = tk.Label(root, text="Soccer Teams GUI", font="Helvetica 18 bold", fg="blue")
        label.pack(padx=80, pady=80)

        frame.pack()

    def load_data(self):
        os.chdir("../SoccerPlayers/")
        os.system(" .\MySQL_data_insert.py")

    # def kill_process(self):
    #     for proc in process_iter():
    #         for conns in proc.connections(kind='inet'):
    #             if conns.laddr.port == 8080:
    #                 proc.send_signal(SIGTERM)

    def open_broswer(self):
        url = 'http://localhost:8080'
        webbrowser.open_new(url)

    def runExtrApp(self):
        os.chdir("../external_application/")
        os.system("py  .\data_manipulation.py")
        file = ""
        with open("../external_application/external_app_results.txt", "r") as output:
            data = output.readlines()
            for x in data:
                file = file + x
            self.canvas = Canvas(root, width=600, height=200, bg="White", bd=0, highlightthickness=0)
            self.canvas.create_text(0, 0, text=file, fill="black", font=("Purisa", 8), anchor="nw")
            self.canvas.pack()

root.geometry("800x600")
root.tk.call('tk', 'scaling', 2.0)

photo = ImageTk.PhotoImage(file="./assets/GuiMain.jpg")
img_label = tk.Label(root, image=photo)
img_label.image = photo
img_label.place(x=0, y=0, relwidth=1, relheight=1)

my_gui = buttons(root)

root.mainloop()


from flask import Flask
from flask_restful import Resource, Api, request, reqparse
from flask_cors import CORS
from flask_socketio import SocketIO
from bson import json_util
from redis import Redis
from database_connection import get_database
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode='threading', cors_allowed_origins='*')
api = Api(app)
CORS(app, allow_headers=['Content-Type', 'Access-Control-Allow-Origin',
                         'Access-Control-Allow-Headers', 'Access-Control-Allow-Methods'])
clients = []
host = os.environ["redis-host"]
hostPort = os.environ["host-port"]
Redis_Client = Redis(host, 6379)
usersLoggedInHashTableName = 'usersLoggedInHashTableName'

class Broker(Resource):

    # Called by the publishers to add data to the db and push data to the subscribers
    @app.route('/publish', methods=['POST'])
    def publish():
        # Read parameter data
        vehicles = request.get_json()
        publishedVehicleIds = []

        # Add published data to the respective tables in the DB
        for vehicle in vehicles:
            vehiclesDb = get_database('vehicles')
            vehicleId = vehicle['vehicleId']
            publishedVehicleIds.append(vehicleId)
            collection_vehicleId = vehiclesDb[vehicleId]
            collection_vehicleId.insert_one(vehicle)

        # Loop through hash table to check all users logged in
        for key, value in Redis_Client.hgetall(usersLoggedInHashTableName).items():
            # Hash table saves data in bytecode hence need to decode
            userName = key.decode("utf-8")
            subscribedBuses = value.decode("utf-8")

            allBusIds = subscribedBuses.split(',')
            subscribedBusesOfUser = list(
                set(publishedVehicleIds) & set(allBusIds))

            # Only if the user has subscribed to any of the buses push it to the user Queue
            if len(subscribedBusesOfUser) > 0:

                busResponse = [
                    x for x in vehicles if x['vehicleId'] in subscribedBusesOfUser]

                publishNameSpace = userName + '-mod-publised'

                # Add the latest user subscriptions to the respective user queue lists
                Redis_Client.rpush(
                    publishNameSpace, json_util.dumps(busResponse))

        return 'published', 200

    # Adds the subscriptions added by the user to the Db
    @app.route('/add-user-subscription', methods=['POST'])
    def addUserSubscriptions():
        userRequest = request.get_json()
        userName = userRequest['userName']
        newUserSubscribedBuses = userRequest['subscribedBuses'].split(',')

        userDb = get_database('user')
        collection_subscriptions = userDb['subscriptions']

        userData = collection_subscriptions.find_one({"userName": userName})

        subscribedBuses = userData['subscribedBuses']
        currentSubscribedBuses = subscribedBuses.split(',')

        newSubscriptionList = list(set().union(
            currentSubscribedBuses, newUserSubscribedBuses))

        newSubscriptionList = filter(None, newSubscriptionList)

        new = ','.join(newSubscriptionList)

        collection_subscriptions.update_one({"_id": userData['_id']}, {
                                            "$set": {"subscribedBuses": new}})

        return 'updated', 200

    # Removes the subscriptions removed by the user from the DB and then from the Hash Table
    @app.route('/remove-user-subscription', methods=['POST'])
    def removeUserSubscriptions():
        userRequest = request.get_json()
        userName = userRequest['userName']
        unSubscribedBuses = userRequest['subscribedBuses'].split(',')

        userDb = get_database('user')
        collection_subscriptions = userDb['subscriptions']

        userData = collection_subscriptions.find_one({"userName": userName})

        subscribedBuses = userData['subscribedBuses']
        currentSubscribedBuses = subscribedBuses.split(',')

        latestSubscribedBuses = [
            x for x in currentSubscribedBuses if x not in unSubscribedBuses]

        new = ','.join(latestSubscribedBuses)

        new = ','.join(latestSubscribedBuses)

        collection_subscriptions.update_one({"_id": userData['_id']}, {
                                            "$set": {"subscribedBuses": new}})

        Broker.updateHashTableOfUserSubscription(userName, new)

        return 'updated', 200

    # Add logged in user to the Hashtable
    @app.route('/add-user-to-hash', methods=['GET'])
    def addUserLoggedIntoHashTable():
        parser = reqparse.RequestParser()
        parser.add_argument('userName', required=True)
        args = parser.parse_args()

        userName = args['userName']

        userDb = get_database('user')
        collection_subscriptions = userDb['subscriptions']

        userData = collection_subscriptions.find_one({"userName": userName})
        subscribedBuses = userData['subscribedBuses']

        Redis_Client.hset(
            usersLoggedInHashTableName, userName, subscribedBuses)

        return 'added', 200

    # Remove logged out user from the Hash table
    @app.route('/remove-user-from-hash', methods=['GET'])
    def removeUserFromHashTable():
        parser = reqparse.RequestParser()
        parser.add_argument('userName', required=True)
        args = parser.parse_args()

        userName = args['userName']

        Redis_Client.hdel(
            usersLoggedInHashTableName, userName)

        return 'removed', 200

    # Used to update the user subscribed buses in the hash table
    def updateHashTableOfUserSubscription(userName, busList):
        publishNameSpace = userName + '-mod-publised'
        Redis_Client.ltrim(publishNameSpace, 999, 0)

        Redis_Client.hset(
            usersLoggedInHashTableName, userName, busList)

api.add_resource(Broker, '/')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=hostPort)


"""Models for Blogly."""
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
db = SQLAlchemy()

def connect_db(app):

    db.app = app
    db.init_app(app)

# models below
class User(db.Model):
    '''User'''

    __tablename__ = "user"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True,)

    first_name = db.Column(db.String(50), nullable=False, unique=False)

    last_name = db.Column(db.String(50), nullable=False, unique=False)

    image_url = db.Column(db.String(150), nullable=True)

class Post(db.Model):

    __tablename__ = 'post'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True,)

    title = db.Column(db.String(50), nullable=False, unique=False)

    content = db.Column(db.String(), nullable=False, unique=False)

    created_at = db.Column(db.String(), nullable=False, unique=False)

    user_key = db.Column(db.Integer, db.ForeignKey('user.id'))

class Tag(db.Model):

    __tablename__ = 'tag'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True,)

    title = db.Column(db.String(50), nullable=False, unique=False)

class PostTag(db.Model):

    __tablename__ = 'posttag'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True,)

    post_id = db.Column(db.Integer, db.ForeignKey('post.id') )

    tag_id = db.Column(db.Integer, db.ForeignKey('tag.id'))


def first(arr, n, k):
    min = 0
    max = n - 1

    while min <= max:
        mid = (min + max) // 2
        if (mid == 0 or arr[mid-1] < k) and arr[mid] == k:
            return mid
        elif arr[mid] < k:
            min = mid + 1
        else:
            max = mid - 1

    return -1

def last(arr, n, k):
    min = 0
    max = n - 1

    while min <= max:
        mid = (min + max) // 2
        if (mid == n-1 or arr[mid+1] > k) and arr[mid] == k:
            return mid
        elif arr[mid] > k:
            max = mid - 1
        else:
            min = mid + 1

    return -1

# TC : O(log n)
arr = [1, 2, 3, 4, 4, 4, 5, 6]
k = -1
f = first(arr, len(arr), k)
if f == -1:
    print("element does not exist")
else:
    l = last(arr, len(arr), k)
    print(" The occurence of given item is: ", l - f + 1)


import re
import logging

from kuapi.enums import Week

## regex 로 처리해야하는 데이터가 많을 경우, 파일의 효용성을 위해 별도로 분리하였음.
## 또한 regex expression 을 경우에 따라 컴파일하여 쓰는것이 바람직함.

log = logging.getLogger(__name__)

## -----------------------------------------------------------------

RG_DEPARTMENTS = r'el\.style\.color = "black";\s*el.selected = .+?;\s*el\.value ="(.+?)";\s*el.text = "(.+?)";'
RG_GENERAL_TYPES = r'el\.style\.color = "black";\s*el\.value ="(.+?)";\s*el.text = "(.+?)";'
RG_LECTURE_TIME_LOCATION = r"([월화수목금])\((.+?)\)\s(.+?)$"
RG_LECTURE_TIME_LOCATION_2 = r"([월화수목금])\((.+?)\)"

## -----------------------------------------------------------------

rg_lecture_time_location = re.compile(RG_LECTURE_TIME_LOCATION)
rg_lecture_time_location2 = re.compile(RG_LECTURE_TIME_LOCATION_2)
rg_departments = re.compile(RG_DEPARTMENTS)
rg_general_types = re.compile(RG_GENERAL_TYPES)

class SugangRegexr:

    @staticmethod
    def regex_departments(raw: str) -> list:
        assert isinstance(raw, str)
        assert raw != ""

        match = rg_departments.findall(raw)
        if match is None:
            _message = 'regex_departments not match : %s' % raw
            log.warning(_message)
            return []

        return match

    @staticmethod
    def regex_general_types(raw: str) -> list:
        assert isinstance(raw, str)
        assert raw != ""

        match = rg_general_types.findall(raw)
        if match is None:
            _message = 'regex_general_types not match : %s' % raw
            log.warning(_message)
            return []

        return match

    @staticmethod
    def regex_course_timetable(raw: str) -> tuple:
        assert isinstance(raw, str)
        assert raw != ""

        if raw == '미정':
            return tuple()

        def build_time(t: str):
            _t = t.split('-')
            return (int(_t[0]), int(_t[0])) if len(_t) == 1 else (int(_t[0]), int(_t[1]))

        _match_1 = rg_lecture_time_location.match(raw)
        _match_2 = rg_lecture_time_location2.match(raw)

        if not _match_1 and not _match_2:
            log.warning('regex_course_timetable error : %s' % raw)
            return tuple()

        # match 1 "([월화수목금])\((.+?)\)\s(.+?)$ "
        if _match_1:
            groups = _match_1.groups()
            week = Week(groups[0])
            time = build_time(groups[1])
            loc = groups[2]

        # match 2 "([월화수목금])\((.+?)\)"
        else:
            groups = _match_2.groups()
            week = Week(groups[0])
            time = build_time(groups[1])
            loc = None

        return week, time, loc


import sys
import re
import math
import operator
from collections import defaultdict
from functools import reduce

foods = []
with open('input.txt') as f:
    p1, p2 = [[int(num) for num in p.split('\n')[1:]] for p in f.read().strip().split('\n\n')]

def play_combat(p1, p2):
    while len(p1) > 0 and len(p2) > 0:
        if p1[0] > p2[0]:
            p1 = p1[1:] + [p1[0]] + [p2[0]]
            p2 = p2[1:]
        else:
            p2 = p2[1:] + [p2[0]] + [p1[0]]
            p1 = p1[1:]
    return p1 if len(p2) == 0 else p2

winner = play_combat(p1, p2)
winner_score = sum([ix * card for ix, card in enumerate(reversed(winner), 1)])

print(f'Challenge 1: Winner\'s score is {winner_score}')

def play_combat_rec(p1, p2, layer=0):
    seen_deck_configs = set()
    while len(p1) > 0 and len(p2) > 0:
        if (tuple(p1), tuple(p2)) in seen_deck_configs:
            return ('p1', p1)
        seen_deck_configs.add((tuple(p1), tuple(p2)))

        if p1[0] <= len(p1)-1 and p2[0] <= len(p2)-1:  # minus the card we just drew
            winner, _ = play_combat_rec(p1[1:p1[0]+1], p2[1:p2[0]+1])
        else:
            winner = 'p1' if p1[0] > p2[0] else 'p2'

        if winner == 'p1' :
            p1 = p1[1:] + [p1[0]] + [p2[0]]
            p2 = p2[1:]
        else:
            p2 = p2[1:] + [p2[0]] + [p1[0]]
            p1 = p1[1:]

    return ('p1', p1) if len(p2) == 0 else ('p2', p2)

_, winners_stack = play_combat_rec(p1, p2)
winner_score = sum([ix * card for ix, card in enumerate(reversed(winners_stack), 1)])

print(f'Challenge 2: Winner\'s score is {winner_score}')


import network_manager
import ui.button_base
from overlays.overlay import *
from ui.text_box import TextBox

class DisconnectOverlay(Overlay):

    def __init__(self):
        super().__init__()
        yes_button_img = ui.button_base.create_button_surface(160)
        text.draw_centered_text("Oui", yes_button_img.get_width() / 2, yes_button_img.get_height() / 2, yes_button_img, text.get_font(24))
        no_button_img = ui.button_base.create_button_surface(160)
        text.draw_centered_text("Non", no_button_img.get_width() / 2, no_button_img.get_height() / 2, no_button_img, text.get_font(24))

        self.buttons = [
            ButtonIcon(160, 340, 160, 40, yes_button_img, command=lambda: self.disconnect()),
            ButtonIcon(160, 400, 160, 40, no_button_img, command=lambda: self.close())
        ]

    def disconnect(self):
        network_manager.disconnect()
        self.close()

    def get_rendered_surface(self):
        frame = pygame.Surface((OVL_SIZE, OVL_SIZE), pygame.SRCALPHA)
        frame.fill((120, 120, 120))
        text.draw_aligned_text("Confirmer", OVL_SIZE / 2, 32, frame, text.get_font(48), shadow_color=(80, 80, 80), shadow_offset=6)

        message_box = TextBox("Voulez-vous vous déconnecter ?", 80, 200, 320, text.get_font(24))
        message_box.render(frame)

        self._render_buttons(frame)
        return frame


full = {}
while True:
    print(full.keys())
    done = input("Done? ")
    if done in ["done", "y", "yes"]:
        break
    whoDis = input("what channel is this for? ")
    idInput = input(f"[{whoDis}] roleId: ")
    channelidInput = input(f"[{whoDis}] channelId: ")
    imgInput = input(f"[{whoDis}] img: ")

    full[whoDis] = {
        "id":idInput,
        "channelid":channelidInput,
        "img":imgInput
    }

print("\n\n\n\n",full)


import enum

@enum.unique
class GameVersion(enum.Enum):
    """
    An installed version of the original game. Multiple may coexist (e.g. AoK
    and TC). We should usually distinguish versions only as far as we're
    concerned (i.e. assets changed).
    """
    age2_aok = (
        "Age of Empires 2: The Age of Kings",
        False,
        {'empires2.exe', 'data/empires2.dat'},
    )
    age2_tc = (
        "Age of Empires 2: The Conquerors",
        True,
        {'age2_x1/age2_x1.exe', 'data/empires2_x1.dat'},
    )
    age2_tc_10c = (
        "Age of Empires 2: The Conquerors, Patch 1.0c",
        True,
        {'age2_x1/age2_x1.exe', 'data/empires2_x1_p1.dat'},
    )
    age2_hd_3x = (
        "Age of Empires 2: HD Edition (Version 3.x)",
        True,
        {'AoK HD.exe', 'data/empires2_x1_p1.dat'}
    )
    # HD edition version 4.0
    age2_fe = (
        "Forgotten Empires",
        True,
        {'AoK HD.exe', 'resources/_common/dat/empires2_x1_p1.dat'},
    )

    def __init__(self, description, openage_supported, required_files=None):
        self.description = description
        self.openage_supported = openage_supported
        self.required_files = required_files or frozenset()

    def __str__(self):
        return self.description

def get_game_versions(srcdir):
    """
    Determine what versions of the game are installed in srcdir. Yield
    GameVersion values.
    """
    for version in GameVersion:
        if all(srcdir.joinpath(path).is_file()
               for path in version.required_files):
            yield version


def numWays_bf(steps, arrLen):  # DFS. Time: O(3^N) Space: O(1).
    def dfs(steps, arrLen, pos):
        if pos < 0 or pos >= arrLen:
            return 0
        if steps == 0:
            return 1 if pos == 0 else 0
        return dfs(steps - 1, arrLen, pos - 1) + dfs(steps - 1, arrLen, pos) + dfs(steps - 1, arrLen, pos + 1)
    if steps is None or steps < 0 or not arrLen:
        return 0
    return dfs(steps, arrLen, 0)

def numWays_memo(steps, arrLen):  #  O(steps * min(arrLen, steps + 1)), Space: O(steps * min(arrLen, steps + 1))
    def dfs(steps, arrLen, pos, memo):
        if (steps, pos) in memo:
            return memo[(steps, pos)]
        if pos < 0 or pos > arrLen - 1:
            memo[(steps, pos)] = 0
            return 0
        if steps == 0:
            return 1 if pos == 0 else 0
        memo[(steps, pos)] = dfs(steps - 1, arrLen, pos - 1, memo) + dfs(steps - 1, arrLen, pos, memo) \
                            + dfs(steps - 1, arrLen, pos + 1, memo)
        return memo[(steps, pos)] % (10 ** 9 + 7)

    if steps is None or steps < 0 or not arrLen:
        return 0
    memo = {}
    return dfs(steps, arrLen, 0, memo)

def numWays_optimized(steps, arrLen):  #  O(steps * min(arrLen, steps + 1)) Space: O(steps * min(arrLen, steps + 1))
    if steps is None or steps < 0 or not arrLen:
        return 0
    arrLen = min(arrLen, steps + 1)
    prev = [1] + [0] * (arrLen - 1)
    for i in range(1, steps + 1):
        cur = [0] * arrLen
        for j in range(arrLen):
            cur[j] += prev[j]
            if j > 0:
                cur[j] += prev[j - 1]
            if j < arrLen - 1:
                cur[j] += prev[j + 1]
        prev = cur
    return prev[0] % (10 ** 9 + 7)

def numWays_optimized_alt(steps, arrLen):  # O(steps * min(arrLen, steps + 1)) Space: O(min(arrLen, steps + 1))
    if steps is None or steps < 0 or not arrLen:
        return 0
    arrLen = min(arrLen, steps + 1)
    prev = [1] + [0] * (arrLen - 1)
    cur = [0] * arrLen
    for i in range(1, steps + 1):
        for j in range(arrLen):
            cur[j] = 0
            cur[j] += prev[j]
            if j > 0:
                cur[j] += prev[j - 1]
            if j < arrLen - 1:
                cur[j] += prev[j + 1]
        prev, cur = cur, prev
    return prev[0] % (10 ** 9 + 7)

def numWays_minimal(steps, arrLen):  #
    arrLen = min(arrLen, steps + 1)
    f = [1] + [0] * (arrLen - 1) # f[0] = 1

    for i in range(1, steps + 1):
        old = 0
        for j in range(arrLen):
            old_left = old
            old = f[j]
            if j > 0:
                f[j] += old_left
            if j < arrLen - 1:
                f[j] += f[j + 1]
    return f[0] % (10 ** 9 + 7)

def min_ways_dp_2d(steps, arrLen):  # TLE  O(steps*arrLen) both
    dp = [[0] * arrLen for _ in range(steps + 1)]
    dp[0][0] = 1
    for row in range(1, steps + 1):
        for col in range(arrLen):
            if col == 0:
                dp[row][col] = dp[row - 1][col] + dp[row - 1][col + 1]
            elif col == arrLen - 1:
                dp[row][col] = dp[row - 1][col] + dp[row - 1][col - 1]
            else:
                dp[row][col] = dp[row - 1][col] + dp[row - 1][col - 1] + dp[row - 1][col + 1]
    return dp[steps][0] % (10 ** 9 + 7)

if __name__ == '__main__':
    print(min_ways_dp_2d(3, 2))
    print(min_ways_dp_2d(2, 4))
    print(min_ways_dp_2d(4, 2))


"""Module to display test summary on console."""

import os
import sys

from openhtf.core import measurements
from openhtf.core import test_record
import six

class ConsoleSummary():
  """Print test results with failure info on console."""

  # pylint: disable=invalid-name
  def __init__(self, verbose=False, indent=2, output_stream=sys.stdout):
    self.indent = ' ' * indent
    if os.name == 'posix' or True:  # Linux and Mac.
      self.RED = '\033[91m'
      self.GREEN = '\033[92m'
      self.ORANGE = '\033[93m'
      self.RESET = '\033[0m'
      self.BOLD = '\033[1m'
    else:
      self.RED = ''
      self.GREEN = ''
      self.ORANGE = ''
      self.RESET = ''
      self.BOLD = ''

    self.color_table = {
        test_record.Outcome.PASS: self.GREEN,
        test_record.Outcome.FAIL: self.RED,
        test_record.Outcome.ERROR: self.ORANGE,
        test_record.Outcome.TIMEOUT: self.ORANGE,
        test_record.Outcome.ABORTED: self.RED,
    }

    self.verbose = verbose
    self.output_stream = output_stream

  # pylint: enable=invalid-name

  def __call__(self, record):
    output_lines = [
        ''.join((self.color_table[record.outcome], self.BOLD,
                 record.code_info.name, ':', record.outcome.name, self.RESET))
    ]
    if record.outcome != test_record.Outcome.PASS or self.verbose:
      for phase in record.phases:
        new_phase = True
        phase_time_sec = (float(phase.end_time_millis) -
                          float(phase.start_time_millis)) / 1000.0
        for name, measurement in six.iteritems(phase.measurements):
          if measurement.outcome != measurements.Outcome.PASS or self.verbose:
            if new_phase:
              output_lines.append('phase: %s [ran for %.2f sec]' %
                                  (phase.name, phase_time_sec))
              new_phase = False

            output_lines.append('%sitem: %s (%s)' %
                                (self.indent, name, measurement.outcome))
            output_lines.append('%smeasured_value: %s' %
                                (self.indent * 2, measurement.measured_value))
            output_lines.append('%svalidators:' % (self.indent * 2))
            for validator in measurement.validators:
              output_lines.append('%svalidator: %s' %
                                  (self.indent * 3, str(validator)))

        phase_result = phase.result.phase_result
        if not phase_result:  # Timeout.
          output_lines.append('timeout phase: %s [ran for %.2f sec]' %
                              (phase.name, phase_time_sec))
        elif 'CONTINUE' not in str(phase_result):  # Exception.
          output_lines.append('%sexception type: %s' %
                              (self.indent, record.outcome_details[0].code))

    output_lines.append('\n')
    text = '\n'.join(output_lines)
    self.output_stream.write(text)


class Solution:
    """
    @param A: an array
    @return: total of reverse pairs
    """
    def reversePairs(self, A):
        # write your code here
        start = 0
        end = len(A) - 1

        self.quicksort(A,start,end)

        return A

    def quicksort(self,A,start,end):
        if start>=end:
            return
        mid = A[(start+end)//2]
        left = start
        right = end

        while left<=right:
            while A[left] < mid and left <= right:
                left += 1

            while  A[right]>mid and left<=right:
                right-=1

            if left<=right:
                A[left],A[right] = A[right],A[left]
                left += 1
                right -= 1

        self.quicksort(A,start,right)
        self.quicksort(A,left,end)


import functions as fn

users_dict = {"1": "USER_1", "2": "USER_2"}

while True:
    opt = fn.user_menu(users_dict)
    if opt == "exit":
        break
    user = users_dict[opt]
    while True:
        opt = fn.database_menu(user)
        if opt == "exit":
            break
        elif opt == "1":
            fn.show_database(user)
        elif opt == "2":
            fn.add_movie(user)
        elif opt == "3":
            fn.remove_movie(user)
        elif opt == "4":
            fn.select_movie(user)