# -*- coding: utf-8 -*-
"""
@author: Abhijit
"""

import numpy as np
import cv2
import glob
import os
from keras.preprocessing.image import ImageDataGenerator

class doublet_data(ImageDataGenerator):
    """A basic keras generator for generating pair of images for siamese networks
    input_dir = path to top level directory containing data folders (similar to flow_from_directory)
    """

    def __init__(self,
                 input_dir,
                 rotation_range=0.,
                 width_shift_range=0.,
                 height_shift_range=0.,
                 shear_range=0.,
                 zoom_range=0.,
                 cval=0.,
                 horizontal_flip=False,
                 vertical_flip=False,
                 rescale=None,
                 preprocessing_function=None,
                 batch_size=32,
                 input_shape=(),
                 flatten=False,
                 num_channels=3,
                 seed=5000,
                 dtype=np.float32):

        np.random.seed(seed)
        assert len(input_shape) == 0 or len(input_shape) == 2, "The input shape must be a tuple of length 2"
        self.flatten = flatten
        self.input_dir = input_dir
        self.input_shape = input_shape
        self.num_channels = num_channels
        assert num_channels == 3 or num_channels == 1, "The number of channels must be either 1 or 3"
        assert batch_size > 1, "batch size must be greater than 1"
        self.sub_dirs = [os.path.join(input_dir, x) for x in os.listdir(input_dir)]
        self.batch_size = batch_size
        self.dtype = dtype
        for sub_dir in self.sub_dirs:
            print("number of images in {} is {}".format(os.path.basename(sub_dir), len(os.listdir(sub_dir))))

        super().__init__(
            rotation_range=rotation_range,
            width_shift_range=width_shift_range,
            height_shift_range=height_shift_range,
            shear_range=shear_range,
            zoom_range=zoom_range,
            horizontal_flip=horizontal_flip,
            vertical_flip=vertical_flip,
            rescale=rescale,
            preprocessing_function=preprocessing_function
        )

    def generate_data(self):
        while True:
            all_images_path = []
            for sub_dir in self.sub_dirs:
                all_images_path.append(glob.glob(os.path.join(sub_dir, '*')))
            all_images_path = np.array(all_images_path)
            X1 = []
            X2 = []
            Y = []
            available_choices = [i for i in range(len(all_images_path))]
            for i in range(self.batch_size):
                choice_index = np.random.choice(available_choices)
                if i % 2 == 0:  # take genuine pair
                    img1 = cv2.imread(np.random.choice(all_images_path[choice_index]))
                    img2 = cv2.imread(np.random.choice(all_images_path[choice_index]))
                    Y.append(1)
                else:
                    other_choices = list(set(available_choices)-set([choice_index]))
                    other_choice_index = np.random.choice(other_choices)
                    img1 = cv2.imread(np.random.choice(all_images_path[choice_index]))
                    img2 = cv2.imread(np.random.choice(all_images_path[other_choice_index]))
                    Y.append(0)
                img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
                img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)

                # convert to float before preprocessing
                img1 = img1.astype(self.dtype)
                img2 = img2.astype(self.dtype)

                if self.preprocessing_function:
                    img1 = self.preprocessing_function(img1)
                    img2 = self.preprocessing_function(img2)

                # apply image augmentations if any
                img1 = self.random_transform(img1)
                img2 = self.random_transform(img2)

                if len(self.input_shape) == 2:
                    img1 = cv2.resize(img1, self.input_shape)
                    img2 = cv2.resize(img2, self.input_shape)

                if self.num_channels == 1:
                    img1 = img1[:, :, 0].reshape(img1.shape[0], img1.shape[1], 1)
                    img2 = img2[:, :, 0].reshape(img2.shape[0], img2.shape[1], 1)
                if self.flatten:
                    img1 = np.reshape(img1, -1)
                    img2 = np.reshape(img2, -1)

                X1.append(img1)
                X2.append(img2)

            yield ([np.array(X1), np.array(X2)], np.array(Y))

###############################################################################

class triplet_data(ImageDataGenerator):
    """A basic keras triplet generator
    NOTE: The generation is random, It does not implement hard triplets as given in the Facenet paper
    input_dir = path to top level directory containing data folders (similar to flow_from_directory)
    The returned Y is all 0 because y_true is not used in triplet loss
    """

    def __init__(self,
                 input_dir,
                 rotation_range=0.,
                 width_shift_range=0.,
                 height_shift_range=0.,
                 shear_range=0.,
                 zoom_range=0.,
                 cval=0.,
                 horizontal_flip=False,
                 vertical_flip=False,
                 rescale=None,
                 preprocessing_function=None,
                 batch_size=32,
                 input_shape=(),
                 flatten=False,
                 num_channels=3,
                 seed=5000,
                 dtype=np.float32):
        np.random.seed(seed)
        assert len(input_shape) == 0 or len(input_shape) == 2, "The input shape must be a tuple of length 2"
        self.flatten = flatten
        self.input_dir = input_dir
        self.input_shape = input_shape
        self.num_channels = num_channels
        assert num_channels == 3 or num_channels == 1, "The number of channels must be either 1 or 3"
        assert batch_size > 1, "batch size must be greater than 1"
        self.sub_dirs = [os.path.join(input_dir, x) for x in os.listdir(input_dir)]
        self.batch_size = batch_size
        self.dtype = dtype
        for sub_dir in self.sub_dirs:
            print("number of images in {} is {}".format(os.path.basename(sub_dir), len(os.listdir(sub_dir))))

        super().__init__(
            rotation_range=rotation_range,
            width_shift_range=width_shift_range,
            height_shift_range=height_shift_range,
            shear_range=shear_range,
            zoom_range=zoom_range,
            horizontal_flip=horizontal_flip,
            vertical_flip=vertical_flip,
            rescale=rescale,
            preprocessing_function=preprocessing_function
        )

    def generate_data(self):
        while True:
            all_images_path = []
            for sub_dir in self.sub_dirs:
                all_images_path.append(glob.glob(os.path.join(sub_dir, '*')))
            all_images_path = np.array(all_images_path)
            anchor_list = []
            positive_list = []
            negative_list = []
            Y = []

            available_choices = [i for i in range(len(all_images_path))]
            for i in range(self.batch_size):
                choice_index = np.random.choice(available_choices)
                anchor = cv2.imread(np.random.choice(all_images_path[choice_index]))
                positive = cv2.imread(np.random.choice(all_images_path[choice_index]))

                other_choices = list(set(available_choices)-set([choice_index]))
                other_choice_index = np.random.choice(other_choices)

                negative = cv2.imread(np.random.choice(all_images_path[other_choice_index]))
                Y.append(0)  # Y is not important here so append 0
                anchor = cv2.cvtColor(anchor, cv2.COLOR_BGR2RGB)
                positive = cv2.cvtColor(positive, cv2.COLOR_BGR2RGB)
                negative = cv2.cvtColor(negative, cv2.COLOR_BGR2RGB)

                # convert to float before preprocessing
                anchor = anchor.astype(self.dtype)
                positive = positive.astype(self.dtype)
                negative = negative.astype(self.dtype)

                if self.preprocessing_function:
                    anchor = self.preprocessing_function(anchor)
                    positive = self.preprocessing_function(positive)
                    negative = self.preprocessing_function(negative)

                # apply image augmentations if any
                anchor = self.random_transform(anchor)
                positive = self.random_transform(positive)
                negative = self.random_transform(negative)

                if len(self.input_shape) == 2:
                    anchor = cv2.resize(anchor, self.input_shape)
                    positive = cv2.resize(positive, self.input_shape)
                    negative = cv2.resize(negative, self.input_shape)

                if self.num_channels == 1:
                    anchor = anchor[:, :, 0].reshape(anchor.shape[0], anchor.shape[1], 1)
                    positive = positive[:, :, 0].reshape(positive.shape[0], positive.shape[1], 1)
                    negative = negative[:, :, 0].reshape(negative.shape[0], negative.shape[1], 1)

                if self.flatten:
                    anchor = np.reshape(anchor, -1)
                    positive = np.reshape(positive, -1)
                    negative = np.reshape(negative, -1)

                anchor_list.append(anchor)
                positive_list.append(positive)
                negative_list.append(negative)
            yield ([np.array(anchor_list), np.array(positive_list), np.array(negative_list)], np.array(Y))


'''
We are interested in writing a program that helps us understand dating.

We will work with a dictionary that shows us who is dating whom. In this dictionary, a person will be the key, and the value will be a *SET* containing all the people they are dating. For example:

relations = {
    "Sebastian": {"Kevin", "Lewis", "Fernando"},
    "Max": {"Fernando"},
    "Lewis": {"Sebastian"},
    "Yuki": {"Pierre"},
    "Pierre": {"Yuki"},
    "Fernando": {"Sebastian", "Max"},
    "Carlos": {"Charles", "Lando"},
    "Lando": {"Carlos"},
    "Charles": {"Carlos"},
    "Kevin": {"Sebastian"}
}

In this example, we see that Sebastian is dating 3 people: Kevin, Lewis, and Fernando. Conversely, Lewis is only dating a single person: Sebastian.

We are interested in seeing whether two people are 'connected': Whether there exists a chain of partners in between them.

For example, Lewis and Max are connected by the following chain:

- Lewis is dating Sebastian
- Sebastian is dating Fernando
- Fernando is dating Max

Therefore, Lewis and Max are connected.

On the other hand, Lewis and Yuki are NOT connected. There does not exist a chain of partners between them.

Write a function that accepts a dictionary of relationships and two different people. It should return True if the two people are connected and False if they are NOT connected.

Your function should NOT modify the dictionary nor the sets inside it.
'''

def connected(relations, person_a, person_b):
    # People we have visited so far
    visited = set()

    # Recursive helper, starting from a person trying to find a target person
    def find(start, target):
        # If we have already visited the person we don't need to search them again
        if start in visited:
            return False
        # Mark person as visited
        visited.add(start)
        # Returns True if we find the target person
        if start == target:
            return True
        # Recursively search through each of the person's partners
        for partner in relations[start]:
            found = find(partner, target)
            # If the person is found starting from any of their partners,
            # a path must exist
            if found:
                return True
        return False

    # Call the recursive helper
    return find(person_a, person_b)

# All tests use the same dictionary
relations = {
    "Sebastian": {"Kevin", "Lewis", "Fernando"},
    "Max": {"Fernando"},
    "Lewis": {"Sebastian"},
    "Yuki": {"Pierre"},
    "Pierre": {"Yuki"},
    "Fernando": {"Sebastian", "Max"},
    "Carlos": {"Charles", "Lando"},
    "Lando": {"Carlos"},
    "Charles": {"Carlos"},
    "Kevin": {"Sebastian"}
}
assert connected(relations, "Max", "Lewis") == True
assert connected(relations, "Lewis", "Yuki") == False
assert connected(relations, "Yuki", "Pierre") == True
assert connected(relations, "Lando", "Carlos") == True
assert connected(relations, "Kevin", "Carlos") == False
assert connected(relations, "Kevin", "Fernando") == True
print("All tests passed! Discuss time & space complexity if time remains.")

'''
***NOTES TO INTERVIEWER***

---------Answers to clarifying questions----------

Q: Are relationships always bidirectional?
A: Yes. If person A is dating person B, you are guaranteed that person B is also dating person A. It will always go in both directions. No unrequited love here.

Q: What if I am passed a person who is not in the dictionary?
A: You are guaranteed the input person will be a key in the dictionary.

Q: Can someone show up in the values but not in the keys?
A: No. You are guaranteed that if a person shows up in the values then they will have a corresponding key in the dictionary.

Q: What if the start and end person are the same?
A: You are guaranteed that the start and end will be two different people.

Q: What should I do if there's invalid data?
A: You can assume the data will be valid.

Q: Can I mutate the input?
A: No.

--------------------------------------------------

---------Hints for struggling candidates----------

 - If your candidate struggles with an initial algorithm, ask them what type of search algorithm would be helpful here. Either BFS or DFS can work! Have them talk through what needs to happen at each step of the search. Have them talk through an example starting with Max and ending with Lewis (reverse of the example in the prompt), and have them describe which positions would be visited in what order.

 - Encourage your candidate to print the person at each step of the search if they are not passing the test cases and are unsure why. This can help debug the path that the search takes (and can be especially helpful for debugging infinite loops).

 -------------------------------------------------

OPTIONAL BONUS AT-HOME CHALLENGES (after interview):

- What are the time/space complexities of the sample solution?

- If you wrote a solution that used DFS, try writing a solution that uses BFS or vice versa.

- If you wrote a solution that used recursion, try writing a solution that uses iteration or vice versa.

- Write a function that returns the 'distance' (number of relationships) between two people in the graph. If there are multiple paths, the distance should be based on the shortest one. Note: you will need to make a more complicated graph to test on to sufficiently test this.

EXTRA HARD
- Suppose two people are trying to separate from each other. Write a function that returns the minimum number of breakups needed to make it so they are no longer connected. For example, in the below case there needs to be at least two breakups to ensure that 'x' and 'y' are no longer connected through any relationship chain. Note: you will need to make a more complicated graph to test on to sufficiently test this.

relations = {
    'x': {'b', 'c', 'd'},
    'b': {'x', 'y'},
    'c': {'x', 'y'},
    'd': {'x'},
    'y': {'b', 'c'}
}

'''


import functools
import pytest
import numpy as np
import networkx as nx
import vermouth
import vermouth.forcefield
from vermouth import selectors
from vermouth.processors import apply_rubber_band
from vermouth.processors.apply_rubber_band import (same_chain,
                                                   make_same_region_criterion,
                                                   are_connected,
                                                   build_connectivity_matrix)

# pylint: disable=redefined-outer-name

@pytest.fixture
def disconnected_graph():
    """
    A graph with two connected components.
    The node keys are integers from 0 to 15 (included). The name of each node
    is its key as a string. The first component is labelled as chain A while
    the second is labelled as chain B.
    0 - 1 - 2 - 3
                |
    4 - 5 - 6 - 7

     8 -  9 - 10 - 11
     |         |    |
    12 - 13 - 14 - 15
    """
    graph = nx.Graph()
    graph.add_nodes_from(range(16))
    graph.add_edges_from([
        # First connected component
        [0, 1], [1, 2], [2, 3], [3, 7], [4, 5], [5, 6], [6, 7],
        # Second connected component
        [8, 9], [8, 12], [8, 9], [9, 10], [10, 14], [10, 11], [11, 15],
        [12, 13], [13, 14], [14, 15],
    ])
    for key, node in graph.nodes.items():
        node['name'] = str(key)
        if key < 8:
            node['chain'] = 'A'
        else:
            node['chain'] = 'B'
    return graph

@pytest.mark.parametrize('selection', (
    list(range(16)),  # Use all the nodes, explicitly
    list(range(8)),  # Only the first component
    list(range(8, 16)),  # Only the second component
    list(range(0, 16, 2)),  # Every other nodes
))
@pytest.mark.parametrize('extra_edges', ([], [(7, 10)]))
def test_build_pair_matrix(disconnected_graph, selection, extra_edges):
    """
    The creation of a pair matrix works as expected.

    Here, the criterion is ``True`` when nodes belong to the same domain.
    The graph is defined as having two domains: one per chain. The extra edges
    allow to make sure the connectivity does not impact the domain detection.
    """
    def have_same_chain(graph, left, right):
        return graph.nodes[left]['chain'] == graph.nodes[right]['chain']

    expected = np.zeros((16, 16), dtype=bool)
    expected[:8, :8] = True
    expected[8:, 8:] = True
    np.fill_diagonal(expected, False)
    expected = expected[:, selection][selection]

    disconnected_graph.add_edges_from(extra_edges)
    idx_to_node = dict(enumerate(disconnected_graph.nodes))
    domains = apply_rubber_band.build_pair_matrix(
        disconnected_graph, have_same_chain, idx_to_node, selection)
    assert np.all(domains == expected)

@pytest.mark.parametrize('separation, outcome', (
    (1, [[0, 2], [2, 6], [4, 6], [8, 12], [8, 10],
         [10, 14], [12, 14]]),
    (2, [[0, 2], [2, 6], [4, 6], [0, 6], [2, 4],
         [8, 12], [8, 10], [10, 14], [12, 14],
         [8, 14], [10, 12]])
))
# this only tests connectivity matrix in terms of connection
# and separation in residue space. selection is tested at the
# end with a more integral test
def test_build_connectivity_matrix(disconnected_graph, separation, outcome):
    idx_to_node = dict(enumerate(disconnected_graph.nodes))
    selection = list(range(0, 16, 2))
    resid_attr = {0: 1, 1: 1, 2: 2, 3: 2, 4: 3, 5: 3, 6: 4, 7: 4,
                  8: 5, 9: 5, 10: 6, 11: 6, 12: 7, 13: 7, 14: 8, 15: 8}
    nx.set_node_attributes(disconnected_graph, resid_attr, 'resid')
    connected = build_connectivity_matrix(disconnected_graph,
                                          separation,
                                          idx_to_node,
                                          selection)
    pairs = []
    for from_idx, to_idx in zip(*np.triu_indices_from(connected)):
        if connected[from_idx, to_idx]:
            idxs = [selection[from_idx], selection[to_idx]]
            idxs.sort()
            pairs.append(idxs)

    for pair in outcome:
        assert pair in pairs

    assert len(pairs) == len(outcome)

@pytest.mark.parametrize('nodes, edges, outcome', (
    ([1, 2, 3],
     [(1, 2), (2, 3)],
     True),
    ([1, 2, 3],
     [(2, 3)],
     False)
))
def test_are_connected(nodes, edges, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    assert are_connected(graph, 1, 2, 1) == outcome

@pytest.mark.parametrize('nodes, chain, edges, outcome', (
    ([1, 2, 3],
     {1: "A", 2: "A", 3: "C"},
     [(1, 2), (2, 3)],
     True),
    ([1, 2, 3],
     {1: "A", 2: "B", 3: "C"},
     [(1, 2), (2, 3)],
     False)
))
def test_same_chain(nodes, edges, chain, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    nx.set_node_attributes(graph, chain, "chain")
    print (same_chain(graph, 1, 2))
    assert same_chain(graph, 1, 2) == outcome

@pytest.mark.parametrize('regions, left, right, nodes, chain, resid, edges, outcome', (
    ([(2, 3)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     1,
     2,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(3, 2)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "B", 4: "B"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     1,
     2,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "B", 4: "B"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(2, 3)],
     2,
     5,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     5,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     4,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(3, 3)],
     3,
     3,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(3, 3)],
     3,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
))
def test_make_same_region_criterion(regions, left, right, nodes, edges, chain, resid, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    nx.set_node_attributes(graph, chain, "chain")
    nx.set_node_attributes(graph, resid, "resid")
    same_region = make_same_region_criterion(regions)
    assert same_region(graph=graph, left=left, right=right) == outcome

@pytest.fixture
def test_molecule(scope='function'):
    """
    Molecule with the following connectivity and atom-naming:

    SC2:   2           8
           |           |
    SC1:   1   4       7
           |   |       |
    BB:    0 - 3 - 5 - 6
           -------------
    resid: 1   2   3   4  column wise
    """

    force_field = vermouth.forcefield.ForceField("test")
    molecule = vermouth.molecule.Molecule(force_field=force_field)
    molecule.meta['test'] = True
    # The node keys should not be in a sorted order as it would mask any issue
    # due to the keys being accidentally sorted.
    molecule.add_node(2, atomname='SC2',
                      position=np.array([0., 1.0, 0.0]), resid=1)
    molecule.add_node(0, atomname='BB',
                      position=np.array([0., 0., 0.]), resid=1)
    molecule.add_node(1, atomname='SC1',
                      position=np.array([0., 0.5, 0.0]), resid=1)

    molecule.add_node(3, atomname='BB', position=np.array(
        [0.5, 0.0, 0.0]), resid=2)
    molecule.add_node(4, atomname='SC1', position=np.array(
        [0.5, 0.5, 0.0]), resid=2)

    molecule.add_node(5, atomname='BB', position=np.array(
        [1.0, 0.0, 0.0]), resid=3)

    molecule.add_node(6, atomname='BB', position=np.array(
        [1.5, 0.0, 0.0]), resid=4)
    molecule.add_node(7, atomname='SC1', position=np.array(
        [1.5, 0.5, 0.0]), resid=4)
    molecule.add_node(8, atomname='SC2', position=np.array(
        [1.5, 1.0, 0.0]), resid=4)

    molecule.add_edge(0, 1)
    molecule.add_edge(0, 2)
    molecule.add_edge(0, 3)
    molecule.add_edge(3, 4)
    molecule.add_edge(3, 5)
    molecule.add_edge(5, 6)
    molecule.add_edge(6, 7)
    molecule.add_edge(7, 8)

    return molecule

@pytest.mark.parametrize('chain_attribute, atom_names, res_min_dist, outcome',
                         (({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000])]
                           ),
                          # different min_res
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(0, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.5, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(3, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.0, 1000])]
                           ),
                          # select more than only BB atoms
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB', 'SC1'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(0, 7),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.58114, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(1, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.58114, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(1, 7),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.5, 1000])]
                           ),
                          # change chain identifier
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'B', 4: 'B', 5: 'B',
                            6: 'B', 7: 'B', 8: 'B'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(3, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           )))
def test_apply_rubber_bands(test_molecule, chain_attribute, atom_names, res_min_dist, outcome):
    """
    Takes molecule and sets the chain attributes. Based on chain, minimum distance
    between residues, and atom names elagible it is tested if rubber bands are applied
    for the correct atoms in molecule.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=atom_names)

    domain_criterion = vermouth.processors.apply_rubber_band.same_chain
    nx.set_node_attributes(test_molecule, chain_attribute, 'chain')

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=res_min_dist)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == outcome

@pytest.mark.parametrize('regions, chain_attribute, atom_names, res_min_dist, outcome',
                         (([(1, 4)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000])]
                           ),
                          # different min_res and different regions
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           ),
                          # select more than only BB atoms
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB', 'SC1'],
                           2,
                           []
                           ),
                          # change chain identifier
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'B', 4: 'B', 5: 'B',
                            6: 'B', 7: 'B', 8: 'B'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           )))
def test_apply_rubber_bands_same_regions(test_molecule, regions, chain_attribute, atom_names, res_min_dist, outcome):
    """
    Takes molecule and sets the chain attributes. Based on chain, minimum distance
    between residues, and atom names elagible it is tested if rubber bands are applied
    for the correct atoms in molecule.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=atom_names)

    domain_criterion = vermouth.processors.apply_rubber_band.make_same_region_criterion(regions)
    nx.set_node_attributes(test_molecule, chain_attribute, 'chain')

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=res_min_dist)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == outcome

def test_skip_no_matches(test_molecule):
    """
    Tests that when no node matches the EN selectors, the molecule is simply skipped.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='matches_none',
        values=['BB', 'SC1'])

    domain_criterion = vermouth.processors.apply_rubber_band.always_true

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=3)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == []

def test_bail_out_on_nan(caplog, test_molecule):
    """
    Test the the EN processor bails out when nan coordinate
    is found.
    """
    test_molecule.nodes[0]['position'] = np.array([np.nan, np.nan, np.nan])
    test_molecule.moltype = "testmol"
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=['BB'])

    domain_criterion = vermouth.processors.apply_rubber_band.always_true

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=3)
    process.run_molecule(test_molecule)

    required_warning = ("Found nan coordinates in molecule testmol. "
                        "Will not generate an EN for it. ")
    record = caplog.records[0]
    assert record.getMessage() == required_warning
    assert len(caplog.records) == 1
    assert test_molecule.interactions['bonds'] == []


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        mid = math.ceil((len(nums) + 1 )/ 2) - 1

        root = TreeNode(nums[mid])

        def bst(numms, parent):
            if len(numms) == 0:
                return None

            mid = math.ceil((len(numms) + 1 )/ 2) - 1
            temp = TreeNode(numms[mid])

            temp.left = bst(numms[:mid], temp)
            temp.right = bst(numms[mid+1:], temp)

            return temp

        root.left = bst(nums[:mid], root)
        root.right = bst(nums[mid+1:], root)

        return root


import src.reseau.TypesFactory as pf
from src.reseau.types.AccountTagInformation import AccountTagInformation

class BasicWhoIsMessage:
   def __init__(self,input):
      self.socialGroups = []
      _id10 = 0
      _item10 = None
      self.deserializeByteBoxes(input)
      self._positionFunc(input)
      self.accountTag = AccountTagInformation(input)
      self._accountIdFunc(input)
      self._playerNameFunc(input)
      self._playerIdFunc(input)
      self._areaIdFunc(input)
      self._serverIdFunc(input)
      self._originServerIdFunc(input)
      _socialGroupsLen = input.readUnsignedShort()
      for _i10 in range(0,_socialGroupsLen):
         _id10 = input.readUnsignedShort()
         _item10 = pf.TypesFactory.get_instance_id(_id10,input)
         self.socialGroups.append(_item10)
      self._playerStateFunc(input)

   def deserializeByteBoxes(self,input) :
      _box0 = input.readByte()
      self.self = bool(bin(_box0)[2:].zfill(8)[0])
      self.verbose = bool(bin(_box0)[2:].zfill(8)[1])

   def _positionFunc(self,input) :
      self.position = input.readByte()

   def _accountIdFunc(self,input) :
      self.accountId = input.readInt()
      if(self.accountId < 0) :
         raise RuntimeError("Forbidden value (" + str(self.accountId) + ") on element of BasicWhoIsMessage.accountId.")

   def _playerNameFunc(self,input) :
      self.playerName = input.readUTF()

   def _playerIdFunc(self,input) :
      self.playerId = input.readVarUhLong()
      if(self.playerId < 0 or self.playerId > 9007199254740992) :
         raise RuntimeError("Forbidden value (" + str(self.playerId) + ") on element of BasicWhoIsMessage.playerId.")

   def _areaIdFunc(self,input) :
      self.areaId = input.readShort()

   def _serverIdFunc(self,input) :
      self.serverId = input.readShort()

   def _originServerIdFunc(self,input) :
      self.originServerId = input.readShort()

   def _playerStateFunc(self,input) :
      self.playerState = input.readByte()
      if(self.playerState < 0) :
         raise RuntimeError("Forbidden value (" + str(self.playerState) + ") on element of BasicWhoIsMessage.playerState.")

   def resume(self):
      print("position :",self.position)
      print("accountId :",self.accountId)
      print("playerName :",self.playerName)
      print("playerId :",self.playerId)
      print("areaId :",self.areaId)
      print("serverId :",self.serverId)
      print("originServerId :",self.originServerId)
      print("playerState :",self.playerState)
      self.accountTag.resume()
      for e in self.socialGroups:
         e.resume()


#!/bin/env python
import sys
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from scipy.stats import f_oneway

projects_matricesfn = sys.argv[1]
outdir = sys.argv[2]

def merge_dfs(projects_matrices):
    dfs = []
    for project in projects_matrices:
        df = projects_matrices[project]
        df['project'] = project
        dfs.append(df)
    df = pd.concat(dfs).dropna(axis='columns').reset_index(drop=True)
    return df

def run_pca(projects_matrices,outdir,statsfh,n_components=2):
    df = merge_dfs(projects_matrices)
    cols = list(df.columns)
    cols.remove('project')
    cols.remove('Subject')
    x = df.loc[:, cols].values
    x = StandardScaler().fit_transform(x)
    y = df.loc[:,['project']].values
    pca = PCA(n_components=n_components)
    principalComponents = pca.fit_transform(x)
    principalDf = pd.DataFrame(data = principalComponents[:,:2],columns = ['principal component 1', 'principal component 2'])
    finalDf = pd.concat([principalDf, df[['project']]], axis = 1)
    fig = plt.figure(figsize = (8,8))
    ax = fig.add_subplot(1,1,1)
    ax.set_xlabel('Principal Component 1')
    ax.set_ylabel('Principal Component 2')
    ax.set_title('2 component PCA')
    targets = list(set(list(df['project'])))
    colors = ['r', 'g', 'b'][0:len(targets)]
    for target, color in zip(targets,colors):
        indicesToKeep = finalDf['project'] == target
        ax.scatter(finalDf.loc[indicesToKeep, 'principal component 1'],
                   finalDf.loc[indicesToKeep, 'principal component 2'],
                   c = color,
                   s = 50)
        ax.legend(targets)
        ax.grid()
    fig.savefig("%s/pca.png" % outdir)
    plt.clf()
    for i,val in enumerate(pca.explained_variance_ratio_):
        statsfh.write("component-%s\t%s\tpca\n" % (i,round(val,3)))
    #print(pca.explained_variance_ratio_)

def plot_mean(projects_matrices,outdir):
    df = merge_dfs(projects_matrices)
    df1 = pd.melt(df,id_vars=['Subject','project'])
    g = sns.FacetGrid(df1,col='variable',col_wrap=10,sharey=False)
    g.map_dataframe(sns.boxplot,x='project',y='value')
    g.savefig("%s/genes.png" % outdir)
    plt.clf()

def run_anova_per_gene(projects_matrices,statsfh):
    df = merge_dfs(projects_matrices)
    projects = list(set(df['project']))
    out = []
    for col in df.columns:
        if col in ['Subject','project']:
            continue
        vals = []
        means = []
        for project in projects:
            col_project_vals = df.loc[df['project'] == project,col].values
            means.append(np.mean(col_project_vals))
            vals.append(col_project_vals)
        f,p = f_oneway(*vals)
        out_line = [col,f,p] + means
        out.append(out_line)
    out.sort(key=lambda x: x[2])
    header = ["gene","f-stat","p-val"] + projects
    header.append("mean-anova")
    statsfh.write("%s\n" % "\t".join(header))
    for line in out:
        line.append("mean-anova")
        statsfh.write("%s\n" % "\t".join(map(str,line)))

def load_matrices(projects_matricesfn):
    projects_matrices = {}
    with open(projects_matricesfn,'r') as fh:
        for line in fh:
            line = line.rstrip().split('\t')
            project = line[0]
            matrixfn = line[1]
            df = pd.read_csv(matrixfn,sep="\t")#,index_col=0)
            subjects = df['Subject']
            ighv_cols = df[df.filter(like='IGHV').columns]
            projects_matrices[project] = pd.concat([subjects,ighv_cols],axis=1)
    return projects_matrices

def plot_cols(projects_matrices,outdir):
    for project in projects_matrices:
        df = projects_matrices[project]
        df1 = pd.melt(df,id_vars=['Subject'])
        g = sns.FacetGrid(df1,col='Subject',col_wrap=10,sharey=False)
        g.map_dataframe(sns.barplot,x='variable',y='value')
        g.savefig("%s/%s.png" % (outdir,project))
        plt.clf()

def plot_no_val_counts(projects_matrices,outdir,statsfh):
    for project in projects_matrices:
        df = projects_matrices[project]
        df_vals = df.iloc[:,1:]
        df_counts = pd.concat([df['Subject'],df_vals[df_vals == 0].count(axis=1)],axis=1).sort_values(by=[0]).reset_index(drop=True)
        plot_row_stats(df_counts,"Number of IGHV genes with 0 value","%s/%s_zero_count.png" % (outdir,project))
        df_counts['project'] = project
        df_counts['stat'] = 'zero_count'
        df_counts.to_csv(statsfh,mode='a',sep='\t',index=False)

def plot_max_val(projects_matrices,outdir,statsfh):
    for project in projects_matrices:
        df = projects_matrices[project]
        df_vals = df.iloc[:,1:]
        df_max = pd.concat([df['Subject'],df_vals.max(axis=1)],axis=1).sort_values(by=[0]).reset_index(drop=True)
        plot_row_stats(df_max,"Max value","%s/%s_max_val.png" % (outdir,project))
        df_max['project'] = project
        df_max['stat'] = 'max_value'
        df_max.round(3).to_csv(statsfh,mode='a',sep='\t',index=False)

def plot_row_stats(df_stat,ylabel,fn):
    width = df_stat.shape[0]/3.1
    plt.figure(figsize=(width,4))
    plot = sns.barplot(x = 'Subject',
                       y = 0,
                       data=df_stat,
                       color="salmon",
                       order=df_stat['Subject'])
    plot.set(ylabel=ylabel,xlabel="Subject")
    plot.get_figure().savefig(fn)
    plt.clf()

statsfh = open("%s/stats.txt" % outdir,'w')
projects_matrices = load_matrices(projects_matricesfn)

plot_cols(projects_matrices,outdir)
plot_no_val_counts(projects_matrices,outdir,statsfh)
plot_max_val(projects_matrices,outdir,statsfh)
run_pca(projects_matrices,outdir,statsfh)
run_anova_per_gene(projects_matrices,statsfh)
plot_mean(projects_matrices,outdir)

statsfh.close()


#[ 1+x+x^2/2!+x^3/3!+....]
def factorial(n):
    f=1
    for i in range(1,n+1):
        f=f*i
    return f

x=int(input("enetr number"))
term=int(input("enetr number of terms"))
s=1
f=1
print(f"1",end="")
for i in range(1,term):
    #f=factorial(i)
    f=f*i  #1*2*3*4
    s=s+((x**i)/f)
    print(f"+{x}^{i}/{i}!",end="")
print("=answer: ",s)

#for loop in reverse order
for i in range(5,1,-1):
    print(i)


import datetime
import re

import markdown
from django.views.decorators.csrf import csrf_exempt

from article.models import Article
# Create your views here.
from django import forms
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views import View
from mdeditor.fields import MDTextFormField

from comment.forms import CommentForm
from comment.views import get_article_comment
from common_lib.article_utils import create_article_id

import markdown2

# from comments.forms import CommentForm
# from comments.get_comment_tree import get_comment_tree
from common_lib.tool_utils import get_pagination
from like.models import ArticleLike

from datetime import datetime, timezone

def article_list(request):
    try:
        keyword = request.POST.get('keyword', default='')
        art_type = request.GET.get('type', default='c')
        page = request.GET.get('page', default=1)
        page = int(page)
        order_by = request.GET.get('order_by', default='release_time')
        # if order_by == 'view_count' or order_by == 'like_count' or order_by == 'comment_count' or :
        order_by = '-' + order_by
        articles_list = Article.objects.filter(title__contains=keyword, type=art_type).order_by(order_by)[(page - 1) * 20: page * 20]
        user = request.user
        article_count = Article.objects.count()
        page_count = (article_count + 19) // 20
        pagination = get_pagination(page, page_count)
        data = {
            'articles': articles_list,
            'total': len(articles_list),
            'choice_file_type': Article.ChoiceFileType,
            'file_type': art_type,
            'pagination': pagination,
            'order_by': order_by,
        }
        return render(request, 'article_list.html', data)
    except Exception as e:
        return render(request, '404_page.html', {'error_msg': e,
                                                 'btn_msg': '返回首页'})

def change_formula(matched):
    formula = matched.group(0)
    formula = formula.replace('_', ' _')
    return '\n<p>' + formula + '</p>\n'

def query_is_like(article_id, user):
    if user.is_anonymous:
        return False
    article = Article.objects.filter(id=article_id)[0]
    if ArticleLike.objects.filter(article=article, user=user).exists():
        is_like = ArticleLike.objects.filter(article=article, user=user)[0].status
        return is_like
    else:
        return False

def article_detail(request, article_id):
    try:
        article = Article.objects.all().get(id__exact=article_id)
    except:
        return render(request, 'article_detail.html', {'msg': 'article not found!'})
    if request.user.id != article.author.id:
        article.view_count += 1
    article.save()
    # article.content = markdown2.markdown(re.sub(r'\$\$(.+?)\$\$', change_formula, article.content))
    article.content = markdown.markdown(article.content, extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',
        'markdown.extensions.toc',
    ])
    is_like = query_is_like(article.id, request.user)
    # is_favorite = query_is_favorite(article.id, request.user)
    form = CommentForm()
    comment_list = get_article_comment(article)
    data = {
        'article': article,
        'is_like': is_like,
        # 'is_favorite': is_favorite,
        'author_id': article.author.id,
        'comment_list': comment_list,
        'form': form
    }
    return render(request, 'article_detail.html', data)

class BlogForm(forms.Form):
    content = MDTextFormField(label='')

@method_decorator(login_required(login_url='/account/login'), name='dispatch')
class Edit(View):
    def get(self, request):
        form = BlogForm()
        data = {
            'form': form,
            'choice_file_type': Article.ChoiceFileType,
        }
        return render(request, 'articles_edit.html', data)

    def post(self, request):
        title = request.POST.get('title')
        file_type = request.POST.get('file_type')
        content = request.POST.get('content')
        article_id = create_article_id()
        author = request.user
        Article.objects.create(id=article_id,
                               title=title,
                               type=file_type,
                               author=author,
                               content=content)
        data = {
            'msg': '发布成功！',
            'url': '/article/' + article_id,
            'btn_msg': '前往查看文章'
        }
        return render(request, 'hint.html', data)

def get_hot_num(article):
    num = 0
    day = (datetime.now(timezone.utc) - article.release_time).days + 1
    return (article.view_count + article.like_count * 2 + article.comment_count * 3 +
            article.favorite_count * 4 + 10) / (day * day)

def get_hot_list():
    articles = Article.objects.all()
    nums = []
    for article in articles:
        nums.append((-get_hot_num(article), article.id))
    nums.sort()
    nums = nums[0:10]
    hot_list = []
    for num in nums:
        hot_list.append(Article.objects.all().get(id=num[1]))
    return hot_list

@login_required(login_url='/account/login')
def front_page(request):
    hot_list = get_hot_list()
    latest_list = Article.objects.all().order_by('-release_time')[0:10]
    data = {
        'hot_list': hot_list,
        'latest_list': latest_list,
    }
    return render(request, 'front_page.html', data)


#For reflection calculations, this library may be useful:
#https://github.com/ezag/pyeuclid

import os
import pygame
import random
from gpiozero import LED

class PongEngine:

	windowW=0	#The width and height of the game window
	windowH=0

	keyboard = ""
	keys = ""

	graphicExtension = ".png"
	paddleEnglish = 1
	gameSpeed = 4 #Ball Speed
	stopSpeed = 0
	UP = -1
	DOWN = 1
	backgroundColor = (255,255,255)
	textColor = (128,128,128)
	font = None
	leftScoreText = ""
	rightScoreText = ""
	leftScoreTextPosition = (0,0)
	rightScoreTextPosition = (0,0)
	winText = ""
	winTextPosition = (0,0)

	leftScore  = 0
	rightScore = 0
	maxScore = 5
	isGameOver = False

	backgroundMapImageName = "background_map" + graphicExtension
	backgroundMapSprite = False
	bmX = 0
	bmY = 0
	bmW = 0
	bmH = 0
	bmSpeed = 0
	bmDirection = -1

	leftPaddleImageName = "left_paddle" + graphicExtension
	leftPaddleSprite = False
	lpX = 0
	lpY = 0
	lpW = 0
	lpH = 0
	lpSpeed = 0
	lpDirection = -1

	rightPaddleImageName = "right_paddle" + graphicExtension
	rightPaddleSprite = False
	rpX = 0
	rpY = 0
	rpW = 0
	rpH = 0
	rpSpeed = gameSpeed + 1
	rpDirection = -1

	ballImageName = "ball" + graphicExtension
	ballSprite = False
	bX = 0
	bY = 0
	bW = 0
	bH = 0
	bSpeed = gameSpeed + 1
	bYDirection = -1
	bXDirection = -1
	bSlope = -1
	#bYIntercept = 0

	def __init__(self, w, h, keyboard):
		self.windowW = w
		self.windowH = h
		self.keyboard = keyboard
		#print(pygame.font.get_fonts())
		self.font = pygame.font.SysFont(None, 36)
		textWidth = self.font.size("SCORE: 0")[0]
		self.leftScoreTextPosition = ((self.windowW/2) - ((self.windowW/4) + textWidth/2), 20)
		self.rightScoreTextPosition = ((self.windowW/2) + ((self.windowW/4) - textWidth/2), 20)
		self.leftScoreText = self.font.render("SCORE: 0", True, self.textColor)
		self.rightScoreText = self.font.render("SCORE: 0", True, self.textColor)

		self.lpX = 30
		self.lpY = self.windowH / 2
		self.rpX = self.windowW-30
		self.rpY = self.windowH / 2
		self.bY = self.windowH / 2
		self.bX = self.windowW / 2
		self.bYIntercept = self.windowH / 2
		self.restartRound()

	def setBackgroundColor(self,color):
		self.backgroundColor = color

	def setTextColor( self, c ):
		self.textColor = c
		#Currently not working because of access to screen variable
		#self.printScoreOnScreen()	#Needed so the screen text changes text immediatly

	def setFont( self, f ):
		self.font = pygame.font.SysFont( f, 72)

	def setBackground(self, anActorClass, imageFileName = False ):
		if( imageFileName ):
			self.backgroundMapImageName = imageFileName

		if( os.path.exists("./images/" + self.backgroundMapImageName + self.graphicExtension) ):
			self.backgroundMapSprite = anActorClass(self.backgroundMapImageName)
			self.backgroundMapSprite.topleft = self.bmX,self.bmY
			self.bmH = self.backgroundMapSprite.midtop[1] - self.backgroundMapSprite.midbottom[1]
			self.bmW = self.backgroundMapSprite.midright[0] - self.backgroundMapSprite.midleft[0]

		else:
			print("There is a problem with the name of the image file for your 'Background Map'")

		return( self.backgroundMapSprite )

	def makeLeftPaddle( self, anActorClass, imageFileName = False ):
		if( imageFileName ):
			self.leftPaddleImageName = imageFileName

		if( os.path.exists("./images/" + self.leftPaddleImageName + self.graphicExtension) ):
			self.leftPaddleSprite = anActorClass(self.leftPaddleImageName)
			self.leftPaddleSprite.center = self.lpX,self.rpY
			self.lpH = abs(self.leftPaddleSprite.midtop[1] - self.leftPaddleSprite.midbottom[1])
			self.lpW = abs(self.leftPaddleSprite.midright[0] - self.leftPaddleSprite.midleft[0])

		else:
			print("There is a problem with the name of the image file for your 'Left Paddle'")

		return( self.leftPaddleSprite )

	def makeRightPaddle( self, anActorClass, imageFileName = False ):
		if( imageFileName ):
			self.rightPaddleImageName = imageFileName

		if( os.path.exists("./images/" + self.rightPaddleImageName + self.graphicExtension	) ):
			self.rightPaddleSprite = anActorClass(self.rightPaddleImageName)
			self.rightPaddleSprite.center = self.rpX,self.rpY
			self.rpH = self.rightPaddleSprite.midtop[1] - self.rightPaddleSprite.midbottom[1]
			self.rpW = self.rightPaddleSprite.midright[0] - self.rightPaddleSprite.midleft[0]

		else:
			print("There is a problem with the name of the image file for your 'Right Paddle'")

		return( self.rightPaddleSprite )

	def makeBall( self, anActorClass, imageFileName = False ):
		if( imageFileName ):
			self.ballImageName = imageFileName

		if( os.path.exists("./images/" + self.ballImageName  + self.graphicExtension) ):
			self.ballSprite = anActorClass(self.ballImageName)
			self.ballSprite.center = self.bX,self.bY
			self.bH = self.ballSprite.midtop[1] - self.ballSprite.midbottom[1]
			self.bW = self.ballSprite.midright[0] - self.ballSprite.midleft[0]

		else:
			print("There is a problem with the name of the image file for your 'Ball'")

		return( self.ballSprite )

	def moveLeftPaddleSprite(self):
		self.lpY = self.lpY + (self.lpSpeed * self.lpDirection)

		self.lpY = max(self.lpY, self.lpH / 2)
		self.lpY = min(self.lpY, self.windowH - self.lpH / 2)

		# An uglier way of saying the same thing as the min/max statement above
		#if self.lpY < self.lpH/2:
		#	self.lpY = self.lpH/2
		#elif self.lpY > self.windowH - self.lpH / 2:
		#	self.lpY = self.windowH - self.lpH / 2

		# The original code that doesn't take direction and speed into account
		#if( (self.lpY > 0 - self.lpH/2) and (self.lpY < self.windowH + self.lpH/2) ):
		#	self.lpY = self.lpY + (self.lpSpeed * self.lpDirection)
		#else:
		#	self.lpDirection = self.lpDirection * -1
		#	self.lpY = self.lpY + (self.lpSpeed * self.lpDirection)

		self.leftPaddleSprite.center = self.lpX, self.lpY

	def moveRightPaddleSprite(self):
		if( (self.rpY > 0 - self.rpH/2) and (self.rpY < self.windowH + self.rpH/2) ):
			self.rpY = self.rpY + (self.rpSpeed * self.rpDirection)
		else:
			self.rpDirection = self.rpDirection * -1
			self.rpY = self.rpY + (self.rpSpeed * self.rpDirection)

		self.rightPaddleSprite.center = self.rpX, self.rpY

	def moveBallSprite(self):
		# The ball's Y component - see if it is above the bottom and below the top of the window
		if( (self.bY > 0 - self.bH/2) and (self.bY < self.windowH + self.bH/2) ):
			self.bY = self.bY + self.bSlope  * ( self.bYDirection)
			#self.bY = self.bY + self.bSlope  * (self.bSpeed * self.bYDirection)

		else:
			self.bYDirection = self.bYDirection * -1
			self.bY = self.bY + self.bSlope * (self.bSpeed * self.bYDirection)

		self.ballSprite.center = self.bX, self.bY
		# The ball's X component
		if( (self.bX - self.bW/2 > 0) and (self.bX < self.windowW - self.bW/2) ):
			# Still in play, so keep going
			self.bX = self.bX + (self.bSpeed * self.bXDirection)

		else:
			# A goal has been made, so keep score and restart next round
			if( self.bXDirection < 0 ):
				self.rightScore += 1
				#print("Goal for right!")
				#self.printScoreOnScreen()
				self.restartRound();
			else:
				self.leftScore += 1
				#print("Goal for left!")
				#self.printScoreOnScreen()
				self.restartRound();

			self.bXDirection = self.bXDirection * -1
			self.bX = self.bX + (self.bSpeed * self.bXDirection)

		self.ballSprite.center = self.bX, self.bY

#	def printScoreOnScreen(self, screen):
#		ls = "SCORE: {0}".format(self.leftScore)
#		rs = "SCORE: {0}".format(self.rightScore)
#		self.leftScoreText = self.font.render(ls, True, self.textColor)
#		self.rightScoreText = self.font.render(rs, True, self.textColor)
#		screen.blit(self.leftScoreText, self.leftScoreTextPosition )
#		screen.blit(self.rightScoreText, self.rightScoreTextPosition )

	def restartRound(self):
		#Position Ball
		self.bX = self.windowW / 2
		self.bY = self.windowH / 2
		# Get some random numbers to spice things up a bit
		r1 = random.random()
		#print(r1)
		if( r1 < 0.5 ):
			self.bYDirection = -1
		else:
			self.bYDirection = 1
		r2 = random.random()
		#print(r2)
		if( r2 < 0.5 ):
			self.bXDirection = -1
		else:
			self.bXDirection = 1

		self.bSlope += r2
		#print(self.bSlope)
		#print("---------------")

	def displayWinningScreen(self, screen, winMsg):
		if( self.backgroundMapSprite ):
			self.backgroundMapSprite.draw()

		textWidth = self.font.size( winMsg )[0]
		self.winTextPosition = ( (self.windowW/2-textWidth/2) , self.windowH/2 )
		self.winText = self.font.render(winMsg, True, self.textColor)
		screen.blit(self.winText, self.winTextPosition )
		#print(winMsg)
		#print(self.isGameOver)

	def isBallYandPaddleYInCommon( self, paddle ):
		paddleTopY = paddle.midtop[1]
		paddleBottomY = paddle.midbottom[1]
		ballTopY = self.ballSprite.midtop[1]
		ballBottomY = self.ballSprite.midbottom[1]

		#if( paddleTopY < ballBottomY ):
		#	print("Paddle Top > Ball Bottom");

		if( ( paddleTopY < ballBottomY ) and ( paddleBottomY > ballTopY ) ):
			#print("Y in Common! with left")
			return(True)
		else:
			return( False )

	def ballAndLeftPaddleFaceCollide(self):
		#Only when ball going left (direction < 0) and paddle have Y in common

		if( (self.bXDirection < 0) and ( self.isBallYandPaddleYInCommon( self.leftPaddleSprite ) )):
			#Detect when ball hits inside face of left paddle and introduce a little wobble
			insideFaceOfLeftPaddleX = (self.lpX + self.lpW/2)
			leftSideOfBallX = (self.bX - self.bW/2)
			if( ( insideFaceOfLeftPaddleX > leftSideOfBallX )):
				self.bXDirection = self.bXDirection * -1
				self.bX = self.bX + (self.bSpeed * self.bXDirection)
				self.ballSprite.center = self.bX, self.bY
				# Put a little 'English' on the ball by adjusting slope, only if paddle is moving
				if(self.lpSpeed != self.stopSpeed):
					if( self.lpDirection < 0 ):
						if( self.bSlope < 0 ):
							print("LP English1")
							self.bSlope = self.bSlope + self.paddleEnglish
						else:
							print("LP English2")
							self.bSlope = self.bSlope - self.paddleEnglish
					else:
						if( self.bSlope > 0 ):
							print("LP English3")
							self.bSlope = self.bSlope - self.paddleEnglish
						else:
							print("LP English4")
							self.bSlope = self.bSlope + self.paddleEnglish

	def ballAndRightPaddleFaceCollide(self):
		#Detect when ball hits inside face of right paddle and introduce a little wobble
		if( (self.bXDirection > 0) and ( self.isBallYandPaddleYInCommon( self.rightPaddleSprite ) )):
			insideFaceOfRightPaddleX = (self.rpX - self.rpW/2)
			rightSideOfBallX = (self.bX + self.bW/2)
			# We have a collision
			if( ( rightSideOfBallX > insideFaceOfRightPaddleX )):
				self.bXDirection = self.bXDirection * -1
				self.bX = self.bX + (self.bSpeed * self.bXDirection)
				self.ballSprite.center = self.bX, self.bY
				# Put a little 'English' on the ball by adjusting slope, only if paddle is moving
				if(self.rpSpeed != self.stopSpeed):
					if( self.rpDirection < 0 ):
						if( self.bSlope < 0 ):
							print("RP English1")
							self.bSlope = self.bSlope + self.paddleEnglish
						else:
							print("RP English2")
							self.bSlope = self.bSlope - self.paddleEnglish

					else:
						if( self.bSlope > 0 ):
							print("RP English3")
							self.bSlope = self.bSlope + self.paddleEnglish
						else:
							print("RP English4")
							self.bSlope = self.bSlope + self.paddleEnglish

	def calculateCollisions(self):
		# Simple Math solution - need to implement 2D Vectors and reflection
		#ballPaddleFaceCollide( self.ballSprite, self.rightPaddleSprite, "R" )
		if(self.ballSprite):
			if( self.leftPaddleSprite ):
				self.ballAndLeftPaddleFaceCollide( )
			if( self.rightPaddleSprite ):
				self.ballAndRightPaddleFaceCollide( )

	def is_A_pressed(self):
		if( self.keyboard[self.keys.A] ):
			return(True)
		else:
			return(False)

	def is_Z_pressed(self):
		if( self.keyboard[self.keys.Z] ):
			return(True)
		else:
			return(False)

	def is_UP_ARROW_pressed(self):
		if( self.keyboard[self.keys.UP] ):
			return(True)
		else:
			return(False)

	def is_DOWN_ARROW_pressed(self):
		if( self.keyboard[self.keys.DOWN] ):
			return(True)
		else:
			return(False)

	def getUserInput(self):
		#Left Paddle
		if( self.keyboard[self.keys.A] ):
			self.lpDirection = -1
			self.lpSpeed = self.gameSpeed
		elif( self.keyboard[self.keys.Z] ):
			self.lpDirection = 1
			self.lpSpeed = self.gameSpeed
		else:
			self.lpSpeed = self.stopSpeed
		#Right Paddle two player mode
		if( self.keyboard[self.keys.UP] ):
			self.rpDirection = -1
			self.rpSpeed = self.gameSpeed
		elif( self.keyboard[self.keys.DOWN] ):
			self.rpDirection = 1
			self.rpSpeed = self.gameSpeed
		else:
			self.rpSpeed = self.stopSpeed

	def drawSprite(self, screen, sprite):
		if( not self.isGameOver ):
			if( sprite ):
				sprite.draw()

	def draw(self, screen):
		screen.clear()
		screen.fill(self.backgroundColor)
		if( not self.isGameOver ):
			if( self.backgroundMapSprite ):
				self.backgroundMapSprite.draw()
			#if( self.leftPaddleSprite ):
			#	self.leftPaddleSprite.draw()
			#if( self.rightPaddleSprite ):
			#	self.rightPaddleSprite.draw()
			#if( self.ballSprite ):
			#	self.ballSprite.draw()

			#self.printScoreOnScreen(screen)
		else:
			pass
			#The game has ended, so show a new screen.
			#if( (self.leftScore - self.rightScore) > 0 ):
			#	self.displayWinningScreen(screen, "Left Wins!")
			#else:
			#	self.displayWinningScreen(screen, "Right Wins!")

	def update(self, keys):
		#pass
		self.keys = keys
		#self.getUserInput()
		if( not self.isGameOver ):
			if( self.leftPaddleSprite ):
				self.moveLeftPaddleSprite()
			if(self.rightPaddleSprite):
				self.moveRightPaddleSprite()
			#if(self.ballSprite):
			#	self.moveBallSprite()         # Also calculates score
			#self.calculateCollisions()
			# Check for Winning Condition, and show win screen, if appropriate
			#if( (self.leftScore >= self.maxScore) or (self.rightScore >= self.maxScore) ):
			#	self.isGameOver = True


'''
Created on Apr 12, 2014

@author: linesprower
'''
'''
Created on Apr 12, 2014

@author: linesprower
'''
import io, sys
import datetime

def solve(fin):
    def nums():
        return [int(x) for x in fin.readline().split()]
    def fnums():
        return [float(x) for x in fin.readline().split()]
    def num():
        return int(fin.readline())

    n = num()
    naomi = fnums()
    ken = fnums()
    naomi.sort()
    ken.sort()
    #print(naomi)
    #print(ken)

    war_score = n
    kenp = 0
    for x in naomi:
        while kenp < n and ken[kenp] < x:
            kenp += 1
        if kenp < n:
            war_score -= 1
            kenp += 1

    score = 0
    for x in naomi:
        if x > ken[0]:
            ken = ken[1:]
            score += 1
        else:
            ken = ken[:-1]
    return "%d %d" % (score, war_score)

def main():
    fname = 'd.in'
    if len(sys.argv) > 1:
        fname = sys.argv[1]
    fin = io.open(fname)
    fout = io.open(fname + '.out', 'w')
    t0 = datetime.datetime.now()
    t = int(fin.readline())

    for i in range(t):
        fout.write('Case #%d: ' % (i + 1))
        fout.write('%s\n' % str(solve(fin)))

    print('Time = %s' % str(datetime.datetime.now() - t0))
    fin.close()
    fout.close()

if __name__ == '__main__':
    main()


# Teste de sintonia feito com a arquitetura completa

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

from __future__ import division
import time
import pwmconverter
import Adafruit_PCA9685
import math
import controle
import RPi.GPIO as GPIO
from MPU6050 import MPU6050
import matplotlib.pyplot as plt
import numpy as np

controle = controle.Controle()

""" instanciando as placas IMU e o Gerador PWM"""
pwm = Adafruit_PCA9685.PCA9685()
sensor = MPU6050(0x68)
sensor.set_accel_range(0x00)
sensor.set_gyro_range(0x00)

motor1 = []
motor2 = []
motor3 = []
motor4 = []

StartTime = time.time()

accel_data_filtered = sensor.get_accel_data()
accX_filtered = accel_data_filtered["x"]
accY_filtered = accel_data_filtered["y"]
accZ_filtered = accel_data_filtered["z"]

gyro_data_filtered = sensor.get_gyro_data()
p_atual_filtered = gyro_data_filtered["x"]
q_atual_filtered = gyro_data_filtered["y"]
r_atual_filtered = gyro_data_filtered["z"]

try:
	while True:

		accel_data = sensor.get_accel_data()
		gyro_data = sensor.get_gyro_data()

		accX = accel_data["x"] # ACELERACAO x em m/s2
		accY = accel_data["y"] # ACELERACAO y em m/s2
		accZ = accel_data["z"] # ACELERACAO z em m/s2

		#--------------------FILTRO---------------------------#
		accX_filtered = accX_filtered*0.7 + accX*0.3
		accY_filtered = accY_filtered*0.7 + accY*0.3
		accZ_filtered = accZ_filtered*0.7 + accZ*0.3
		#-----------------------------------------------------#

		p_atual = gyro_data["x"] #velocidades angulares P em graus/s
		q_atual = gyro_data["y"] #velocidades angulares Q em graus/s
		r_atual = gyro_data["z"] #velocidades angulares R em graus/s

		#--------------------FILTRO---------------------------#
		p_atual_filtered = p_atual_filtered*0.7 + p_atual*0.3
		q_atual_filtered = q_atual_filtered*0.7 + q_atual*0.3
		r_atual_filtered = r_atual_filtered*0.7 + r_atual*0.3
		#-----------------------------------------------------#

		theta_atual_rad = math.atan2(accX,math.sqrt(accZ**2+accY**2)) #atan2() da o resultado em radianos
		phi_atual_rad = math.atan2(accY,math.sqrt(accZ**2+accX**2))
		psi_atual_rad = math.atan2(accY, accX) # psi eh o arcotangente entre o vx e vy

		theta_atual = math.degrees(theta_atual_rad) #conversao de rad pra graus
		phi_atual = math.degrees(phi_atual_rad)
		psi_atual = math.degrees(psi_atual_rad)

		controlealtitude = controle.controle_alt(0, phi_atual, 0, theta_atual, 0, psi_atual, 0, 0, p_atual, q_atual, r_atual)
		controlemotores = controle.motores_control(controlealtitude[0], controlealtitude[1], controlealtitude[2], controlealtitude[3])

		print(controlemotores[0], controlemotores[1], controlemotores[2], controlemotores[3])

		controlemotorespwm = pwmconverter.pwmconverter_all(controlemotores[0], controlemotores[1], controlemotores[2], controlemotores[3])

		motor1.append(controlemotorespwm[0]) #guardando valores dos comandos enviados aos motores, para plotar
		motor2.append(controlemotorespwm[1])
		motor3.append(controlemotorespwm[2])
		motor4.append(controlemotorespwm[3])

		print(controlemotorespwm[0], controlemotorespwm[1], controlemotorespwm[2], controlemotorespwm[3])
		print("--------------------------------------------------")
		pwmconverter.pcamotores(controlemotorespwm[0], controlemotorespwm[1], controlemotorespwm[2], controlemotorespwm[3])

except KeyboardInterrupt: #CTRL + C
	controlemotorespwm = pwmconverter.pwmconverter_all(0, 0, 0, 0)
	pwmconverter.pcamotores(controlemotorespwm[0], controlemotorespwm[1], controlemotorespwm[2], controlemotorespwm[3])

	StopTime = time.time()
	RunTime = StopTime - StartTime
	PassoAmostragem = RunTime / len(motor1)
	t = np.arange(0, RunTime, PassoAmostragem) #evenly sampled time at PassoAmostragem s intervals

	print("\n Abortar missao")
	print("motores para ZERO")
	print("limpa o GPIO")
	GPIO.cleanup()

	motor1 = np.array(motor1)
	motor2 = np.array(motor2)
	motor3 = np.array(motor3)
	motor4 = np.array(motor4)

	plt.figure(1)

	plt.subplot(411)
	plt.plot(motor1)
	plt.ylabel(u'Cmd M1')

	plt.subplot(412)
	plt.plot(motor2)
	plt.ylabel(u'Cmd M2')

	plt.subplot(421)
	plt.plot(motor3)
	plt.ylabel(u'Cmd M3')

	plt.subplot(422)
	plt.plot(motor4)
	plt.ylabel(u'Cmd M4')

	plt.savefig('teste_sintonia.png')

	print("Tempo de amostragem em segundos: ", PassoAmostragem)


t = int(input())
for i in range(t):
	inp = input().split()
	n = int(inp[0])
	a = int(inp[1])
	b = int(inp[2])
	ar = input().split()
	ar[:] = [int(x) for x in ar]
	while True:
		f = 0
		for i in ar:
			if a%i == 0 and f == 1:
				ar.remove(i)
				f = 0
				continue
			if b%i == 0 and f == 0:
				ar.remove(i)
				f = 1
				continue
			if a%i != 0 and f == 1:
				f = 2
			if b%i != 0 and f == 0:
				f = 3
		if f == 2:
			print("BOB")
			break
		if f == 3:
			print("ALICE")
			break


from PySide2.QtWidgets import QWidget, QPushButton, QMessageBox

from .comparison_two_ships import ComparisonTwoShips
from .comparison_multiple_ships import ComparisonMultipleShips
from .checkbox_delegate import CheckBoxDelegate
from .pixmap_delegate import PixmapDelegate
from .shipfu_basic_filter import ShipfuBasicFilter
from comparison_shipfu_table_model import ComparisonShipfuTableModel
from generic_proxy_shipfu_table_model import GenericProxyShipfuTableModel

from .ui.module_comparison import Ui_ModuleComparison
from data import Data

class ModuleComparison(QWidget, Ui_ModuleComparison):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.model = ComparisonShipfuTableModel()
        self.model.dataChanged.connect(self.displaySelectedShipfus)
        self.proxyModel = GenericProxyShipfuTableModel()
        self.proxyModel.setSourceModel(self.model)
        self.shipTableView.setModel(self.proxyModel)

        self.shipTableView.setItemDelegateForColumn(
            1, CheckBoxDelegate(self.shipTableView))
        self.shipTableView.setItemDelegateForColumn(
            2, PixmapDelegate(self.shipTableView))

        self.filters = ShipfuBasicFilter()
        for filterComboBox in (self.filters.rarityComboBox,
                               self.filters.nationComboBox,
                               self.filters.shipTypeComboBox,
                               self.filters.positionComboBox):
            filterComboBox.currentIndexChanged.connect(self.onFilterChanged)
        self.filters.nameLineEdit.textChanged.connect(self.onFilterChanged)
        self.comparisonGridLayout.addWidget(self.filters, 0, 0)

        self.compareButton = QPushButton("Compare selected ships")
        self.compareButton.clicked.connect(self.compareShipfus)
        self.comparisonGridLayout.addWidget(self.compareButton, 6, 0)
        self.resetSelectedShipsPushButton.clicked.connect(
            self.resetSelectedShips)

    def displaySelectedShipfus(self, *_):
        shipfus_to_compare = self.model.getSelectedShipfus()
        if not shipfus_to_compare:
            self.selectedLabel.setText("None")
        else:
            self.selectedLabel.setText(
                ", ".join([x.Shipfu.name for x in shipfus_to_compare]))

    def onFilterChanged(self, new_index):
        self.proxyModel.rarity_filter = self.filters.rarityComboBox.itemData(
            self.filters.rarityComboBox.currentIndex())
        self.proxyModel.nation_filter = self.filters.nationComboBox.itemData(
            self.filters.nationComboBox.currentIndex())
        self.proxyModel.shiptype_filter = \
            self.filters.shipTypeComboBox.itemData(
                self.filters.shipTypeComboBox.currentIndex())
        self.proxyModel.position_filter = \
            self.filters.positionComboBox.currentIndex()

        self.proxyModel.setFilterRegExp(self.filters.nameLineEdit.text())
        self.proxyModel.invalidateFilter()

    def resetSelectedShips(self):
        self.model.reset()
        self.selectedLabel.setText("None")
        self.shipTableView.viewport().repaint()

    def compareShipfus(self):
        if len(self.model.id_shipfus_to_compare) < 2:
            messageBox = QMessageBox()
            messageBox.warning(None, "Error",
                               "Please select at least 2 ships to compare")
            messageBox.setFixedSize(500, 200)
            messageBox.show()
            return

        shipfus_to_compare = self.model.getSelectedShipfus()

        if len(shipfus_to_compare) == 2:
            widget = ComparisonTwoShips(*shipfus_to_compare)
        else:
            widget = ComparisonMultipleShips(shipfus_to_compare,
                                             Data.getRarities())

        prev_widget = self.tabWidget.widget(1)
        if prev_widget:
            del prev_widget
            self.tabWidget.removeTab(1)

        idx = self.tabWidget.addTab(widget, "Results")
        self.tabWidget.setCurrentIndex(idx)


from pyodide.http import pyfetch, FetchResponse
from typing import Optional, Any

async def request(url: str, method: str = "GET", body: Optional[str] = None,
                  headers: Optional[dict[str, str]] = None, **fetch_kwargs: Any) -> FetchResponse:
    """
    Async request function. Pass in Method and make sure to await!
    Parameters:
        url: str = URL to make request to
        method: str = {"GET", "POST", "PUT", "DELETE"} from `JavaScript` global fetch())
        body: str = body as json string. Example, body=json.dumps(my_dict)
        headers: dict[str, str] = header as dict, will be converted to string...
            Example, headers=json.dumps({"Content-Type": "application/json"})
        fetch_kwargs: Any = any other keyword arguments to pass to `pyfetch` (will be passed to `fetch`)
    Return:
        response: pyodide.http.FetchResponse = use with .status or await.json(), etc.
    """
    kwargs = {"method": method, "mode": "cors"}  # CORS: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
    if body and method not in ["GET", "HEAD"]:
        kwargs["body"] = body
    if headers:
        kwargs["headers"] = headers
    kwargs.update(fetch_kwargs)

    response = await pyfetch(url, **kwargs)
    return response


max_gdv=0
for each in ["AT","CE","DM","HS","MM","RN","SC","SP"]:
    f=open(f"{each}.sigs","r")
    for line in f:
        p_name,*values=line.rstrip().split("\t")
        for v in values:
            max_gdv=max(max_gdv,int(v))

    f.close()
print(f"Largest Value is {max_gdv}")


from db_manager import DBManager
from user_manager import UserManager, LoginManager
from transactions_manager import TransactionsManager
from designs import BANK_NAME, colors
from datetime import datetime
import getpass

conn, cursor = DBManager('sample_bank.db').connect()
user_manager = UserManager(conn)
login_manager = LoginManager(conn)
transactions_manager = TransactionsManager(conn)

bank_name_normal = "QuantumBankX"

default_options = [
    "1. Create Account",
    "2. Create Login",
    "3. Login",
    "4. Exit"
]

account_options = [
    "1. Deposit",
    "2. Withdraw",
    "3. Transfer",
    "4. Mini Recipt",
    "5. Logout"
]

login_requirements = [
    "1. CustomerID",
    "2. Password",
]

create_account_requirements = [
    "1. First Name",
    "2. Last Name",
    "3. Date of Birth(YYYY-MM-DD)",
    "4. Gender(M/F)",
    "5. Address",
    "6. Phone Number",
    "7. Email",
    "8. Account Type(Savings/Current)"
]

create_login_requirements = [
    "1. CustomerID",
    "2. Password",
    "3. Confirm Password"
]

if __name__ == '__main__':
    print(BANK_NAME)
    print(colors.bold, colors.fg.cyan, "Welcome to QuantumBankX", colors.reset)
    while True:
        current_user = None
        print("Please select an option:")
        for option in default_options:
            print(option)
        option = input("Enter option: ")
        if option == "1":
            data = []
            for requirement in create_account_requirements:
                data.append(input(requirement + ": "))
            status = user_manager.createUser(data[0], data[1], data[2], data[3], data[4],
                                             data[5], data[6], data[7])
            if status[0]:
                print(colors.fg.green, "Account created successfully.", colors.reset)
                print("CustomerID: " + str(status[2]))
                print("Account Number: " + str(status[3]))
                print()
            else:
                print(colors.fg.red, status[1], colors.reset)
        elif option == "2":
            data = []
            for requirement in create_login_requirements:
                data.append(input(requirement + ": "))
            if data[1] != data[2]:
                print(colors.fg.red, "Passwords do not match.", colors.reset)
                continue
            login_manager.createLogin(data[0], data[1])
            print(colors.fg.green, "Login created successfully.", colors.reset)
            print()
        elif option == "3":
            data = []
            for requirement in login_requirements:
                data.append(input(requirement + ": "))
            login_result = login_manager.login(data[0], data[1])
            if login_result[0]:
                print(colors.fg.green, "Login successful.", colors.reset)
                current_user = user_manager.getUserByCustomerID(data[0])
                print("Welcome, " + current_user[1] + " " + current_user[2])
            else:
                print(colors.fg.red, login_result[1], colors.reset)
        elif option == "4":
            exit()
        else:
            print(colors.fg.red, "Invalid option.", colors.reset)
            continue
        while current_user:
            print("Please select an option:")
            for option in account_options:
                print(option)
            option = input("Enter option: ")
            if option == "1":
                amount = input("Enter amount to deposit: ")
                user_manager.updateBalance(current_user[0], amount)
                transactions_manager.addTransaction(
                    current_user[0], current_user[0], "Deposit", datetime.now(), amount, "Deposit")
                print(colors.fg.green, "Deposit successful.", colors.reset)
                print()
            elif option == "2":
                amount = input("Enter amount to withdraw: ")
                status = user_manager.updateBalance(
                    current_user[0], -int(amount))
                if not status[0]:
                    print(colors.fg.red, status[1], colors.reset)
                    print()
                    continue
                transactions_manager.addTransaction(
                    current_user[0], current_user[0], "Withdraw", datetime.now(), amount, "Withdraw")
                print("Withdrawal successful.")
            elif option == "3":
                amount = input("Enter amount to transfer: ")
                to_account_number = input(
                    "Enter account number to transfer to: ")
                status = user_manager.updateBalance(
                    current_user[0], -int(amount))
                if status[0]:
                    transactions_manager.addTransaction(
                        current_user[8], to_account_number, "Transfer", datetime.now(), amount, "Transfer")
                    to_user = user_manager.getUser(to_account_number)
                    user_manager.updateBalance(to_user[0], amount)
                    print(colors.fg.green, "Transfer successful.", colors.reset)
                else:
                    print(colors.fg.red, status[1], colors.reset)
            elif option == "4":
                print()
                balance = user_manager.getCurrentBalance(current_user[8])
                print("Current Balance: " + str(balance))
                print("Transactions:")
                transactions = transactions_manager.getTransactions(
                    current_user[8])
                for transaction in transactions:
                    print(transaction)
                print("ATM Transactions:")
                atm_transactions = transactions_manager.getATMTransactions(
                    current_user[8])
                for atm_transaction in atm_transactions:
                    print(atm_transaction)
                print()
            elif option == "5":
                print("Logging out.")
                current_user = None
            else:
                print("Invalid option.")
                continue


def mult(a, b):
    neg = False
    if a[0] == "-":
        neg = not neg
        a = a[1]

    if b[0] == "-":
        neg = not neg
        b = b[1]

    if a == "1":
        res = b
    elif b == "1":
        res = a
    elif a == b:
        res = "1"
        neg = not neg
    else:
        s = "ijkij"
        ind = s.find(a + b)
        if ind == -1:
            neg = not neg
            ind = s.find(b + a)
        res = s[ind + 2]

    if neg:
        return "-" + res
    return res

def get_mod(full_mult):
    if full_mult == "1":
        return 1
    if full_mult == "-1":
        return 2
    return 4

def find_prefix(s, mults_mod):

    cur_mult = mults_mod
    for l in range(0, len(s)):
        if cur_mult == "i":
            return l
        cur_mult = mult(cur_mult, s[l])

    return -1

def find_suffix(s, mults_mod):

    cur_mult = mults_mod
    for start in range(len(s), 0, -1):
        if cur_mult == "k":
            return start
        cur_mult = mult(s[start - 1], cur_mult)

    return -1

def mult_all(s):

    cur_mult = "1"
    for c in s:
        cur_mult = mult(cur_mult, c)

    return cur_mult

def has_no_straddle_solution(L, X, s, full_mult, mults_mod):

    mod = get_mod(full_mult)

    for x in range(4):
        prelen = find_prefix(s, mults_mod[x])
        if prelen == -1:
            continue

        for y in range(4):
            sufstart = find_suffix(s, mults_mod[y])
            if sufstart == -1:
                continue

            if prelen >= sufstart:
                continue

            if mult_all(s[prelen:sufstart]) != "j":
                continue

            trial = X - 1 - x - y
            if trial < 0:
                continue

            if (trial % mod) != 0:
                continue

            return True

    return False

def has_straddle_solution(L, X, s, full_mult, mults_mod):

    mod = get_mod(full_mult)

    for x in range(4):
        prelen = find_prefix(s, mults_mod[x])
        if prelen == -1:
            continue

        for y in range(4):
            sufstart = find_suffix(s, mults_mod[y])
            if sufstart == -1:
                continue

            for z in range(4):

                beg = mult_all(s[prelen:])
                end = mult_all(s[:sufstart])
                mid = mult(beg, mults_mod[z])
                mid = mult(mid, end)

                if mid != "j":
                    continue

                trial = X - 2 - x - y - z
                if trial < 0:
                    continue

                if (trial % mod) != 0:
                    continue

                return True

    return False

T = int(input())

for c in range(1, T + 1):
    L, X = (int(i) for i in input().split())
    s = input()

    full_mult = mult_all(s)

    mults_mod = [None] * 4
    mults_mod[0] = "1"
    for i in range(1, 4):
        mults_mod[i] = mult(mults_mod[i - 1], full_mult)

    if has_no_straddle_solution(L, X, s, full_mult, mults_mod):
        print("Case #{}: YES".format(c))
    elif has_straddle_solution(L, X, s, full_mult, mults_mod):
        print("Case #{}: YES".format(c))
    else:
        print("Case #{}: NO".format(c))


import cv2
import time
import random

cap  = cv2.VideoCapture(0)

if not cap.isOpened():
	cap.open(0)

num = random.randint(1,3)

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

	font = cv2.FONT_HERSHEY_SIMPLEX

	for i in range(1,num+1) :
		sr= "Object "+str(i)+" Distance: "+str(random.randint(10,100))+" cm"

		cv2.putText(frame,str(sr),(115,445+(1-i)*45),font,1,(255,255,255),2)
		cv2.imshow('image',frame)

	if cv2.waitKey(1) & 0xFF == ord('q'):
		break

cap.release()
cv2.destroyAllWindows()


from sys import stdin
input = stdin.readline

MAX_N = 2000

def solve(N):
    dp = [[0]*(N+1) for _ in range(N+1)]
    dp[0][0] = 1

    for i in range(1, N+1):
        for j in range(N+1):
            dp[i][j] = dp[i-1][j]
            if j >= i:
                dp[i][j] = (dp[i][j] + dp[i-1][j-i]) % 100999
    return dp[N][N]

T = int(input())
result = []
for _ in range(T):
    N = int(input())
    result.append(solve(N))

print(*result, sep='\n')

백준/Silver/9764. 서로 다른 자연수의 합/서로 다른 자연수의 합.py

서로 다른 자연수의 합.py


"""
Author: Mohammad Ramezani
Created: July 31, 2022
"""

import glob
import os
import winsound
from os import path
import numpy as np
import pretty_midi
import matplotlib.pyplot as plt
from scipy import sparse
from colorama import Fore, Back, Style
from datetime import datetime

# For Music File Transcription
from piano_transcription_inference import PianoTranscription, sample_rate, load_audio

DIRECTORY = 'D:/Business/Idea_Music/Data/Original_Data/IMSLP/'
global COMPLEXITY_LEVEL_NUMBER
WINDOWS_WIDTH = 500

def complexity_class_number_computation(desired_path):
    os.walk(desired_path)
    cnt = 0
    for x in os.walk(desired_path):
        cnt += 1

    print(f'\nNumber of complexity levels =', cnt - 1)
    return cnt - 1

def each_level_track_number(folder_path, complex_level):
    sample_complex = []
    for level in range(1, complex_level + 1):
        pth = folder_path + "{:02d}".format(level) + '/'
        initial_count = 0
        for p in os.listdir(pth):
            if os.path.isfile(os.path.join(pth, p)) and p[-3:] == 'mp3':
                initial_count += 1
        sample_complex.append(initial_count)

    print('Number of samples in each complexity level =', sample_complex)
    return sample_complex

def mp3_to_midi(mp3_name, mid_name):
    (audio, _) = load_audio(mp3_name, sr=sample_rate, mono=True)
    transcriptor = PianoTranscription(device='cpu')  # 'cuda' | 'cpu'
    transcribed_dict = transcriptor.transcribe(audio, mid_name)

def convert_mp3_to_midi(directory):
    # Mp3 files searching and converting them to MIDI
    print(f"\nPlease wait! \nIt is checking for Mp3 to MIDI file conversion...")
    all_mp3_number = 0
    directory_mp3 = directory + '**/*'
    for file in glob.glob(directory_mp3):
        mid_filename = file[:-3] + 'mid'
        if not path.exists(mid_filename) and file[-3:] == 'mp3':
            print(file)
            all_mp3_number += 1
            mp3_filename = file
            mp3_to_midi(mp3_filename, mid_filename)
    print('Total MP3 to MIDI transcription =', all_mp3_number)

def midi_to_pianoroll():

    print(f"\nPlease wait! \nThe pianorolls are being created...\n ")

    database_piano_roll = []
    for i in range(1, COMPLEXITY_LEVEL_NUMBER + 1):
        print(i)
        temp_dir = DIRECTORY + "{:02d}".format(i)
        dir_list = os.listdir(temp_dir)
        # dir_list = [dir_list[0]]  # to choose a desired sample
        j = 0
        for filename in dir_list:
            if filename[-3:] == 'mid':
                j += 1
                midi_filename = temp_dir + '/' + filename
                raw_midi_data = pretty_midi.PrettyMIDI(midi_filename)
                piano_roll = raw_midi_data.get_piano_roll(fs=100)
                piano_roll = piano_roll.astype(np.float16)
                sparse_piano_roll = sparse.csr_matrix(piano_roll)
                database_piano_roll.append([i, j, sparse_piano_roll])

    np.save('database_pianoroll.npy', database_piano_roll, allow_pickle=True)
    print('The piano roll for all samples were created and stored in the directory!')

def sampling_pianoroll(piano_rolls):

    print(f"\nPlease wait! \nThe piano-rolls are being sampled...\n ")

    global group
    for track in range(len(piano_rolls)):

        class_num = piano_rolls[track][0]
        track_num = piano_rolls[track][1]
        piano_roll = piano_rolls[track][2].toarray()

        height, width = piano_roll.shape
        shift_step = 0

        if class_num in [1]:
            group = 0
            if width <= 1500:
                shift_step = 100
            if 1500 < width <= 3000:
                shift_step = 200
            if 3000 < width <= 4500:
                shift_step = 300
            if 4500 < width <= 6000:
                shift_step = 400
            if 6000 < width <= 7500:
                shift_step = 500
            if 7500 < width <= 10000:
                shift_step = 600
            if 10000 < width <= 12000:
                shift_step = 700
            if 12000 < width <= 13000:
                shift_step = 800
            if 13000 < width <= 15000:
                shift_step = 1000
            if 15000 < width:
                shift_step = 2000

        if class_num in [2, 3]:
            group = 0
            if width <= 1500:
                shift_step = 600
            if 1500 < width <= 3000:
                shift_step = 1200
            if 3000 < width <= 4500:
                shift_step = 1800
            if 4500 < width <= 6000:
                shift_step = 2400
            if 6000 < width <= 7500:
                shift_step = 3000
            if 7500 < width <= 10000:
                shift_step = 3600
            if 10000 < width <= 12000:
                shift_step = 4000
            if 12000 < width <= 13000:
                shift_step = 5000
            if 13000 < width <= 15000:
                shift_step = 5500
            if 15000 < width:
                shift_step = 6000

        if class_num in [4]:
            group = 1
            if width <= 1500:
                shift_step = 400
            if 1500 < width <= 3000:
                shift_step = 600
            if 3000 < width <= 4500:
                shift_step = 800
            if 4500 < width <= 6000:
                shift_step = 1200
            if 6000 < width <= 7500:
                shift_step = 1600
            if 7500 < width <= 10000:
                shift_step = 2000
            if 10000 < width <= 12000:
                shift_step = 2800
            if 12000 < width <= 13000:
                shift_step = 4000
            if 13000 < width <= 15000:
                shift_step = 5000
            if 15000 < width:
                shift_step = 6000

        if class_num in [5, 6]:
            group = 1
            if width <= 1500:
                shift_step = 800
            if 1500 < width <= 3000:
                shift_step = 1000
            if 3000 < width <= 4500:
                shift_step = 1200
            if 4500 < width <= 6000:
                shift_step = 1600
            if 6000 < width <= 7500:
                shift_step = 2000
            if 7500 < width <= 10000:
                shift_step = 3000
            if 10000 < width <= 12000:
                shift_step = 5000
            if 12000 < width <= 13000:
                shift_step = 6000
            if 13000 < width <= 15000:
                shift_step = 10000
            if 15000 < width:
                shift_step = 14000

        if class_num in [7, 8, 9]:
            group = 2
            if width <= 1500:
                shift_step = 800
            if 1500 < width <= 3000:
                shift_step = 1200
            if 3000 < width <= 4500:
                shift_step = 1800
            if 4500 < width <= 6000:
                shift_step = 3000
            if 6000 < width <= 7500:
                shift_step = 3600
            if 7500 < width <= 10000:
                shift_step = 5000
            if 10000 < width <= 12000:
                shift_step = 8000
            if 12000 < width <= 13000:
                shift_step = 12000
            if 13000 < width <= 15000:
                shift_step = 15000
            if 15000 < width:
                shift_step = 18000

        if class_num in [10, 11]:
            group = 3
            if width <= 1500:
                shift_step = 3000
            if 1500 < width <= 3000:
                shift_step = 4000
            if 3000 < width <= 4500:
                shift_step = 5000
            if 4500 < width <= 6000:
                shift_step = 6000
            if 6000 < width <= 7500:
                shift_step = 8000
            if 7500 < width <= 10000:
                shift_step = 10000
            if 10000 < width <= 12000:
                shift_step = 12000
            if 12000 < width <= 13000:
                shift_step = 20000
            if 13000 < width <= 15000:
                shift_step = 28000
            if 15000 < width:
                shift_step = 35000

        if class_num in [12]:
            group = 3
            if width <= 1500:
                shift_step = 10500
            if 1500 < width <= 3000:
                shift_step = 18000
            if 3000 < width <= 4500:
                shift_step = 22500
            if 4500 < width <= 6000:
                shift_step = 28000
            if 6000 < width <= 7500:
                shift_step = 34500
            if 7500 < width <= 10000:
                shift_step = 40500
            if 10000 < width <= 12000:
                shift_step = 45500
            if 12000 < width <= 13000:
                shift_step = 55000
            if 13000 < width <= 15000:
                shift_step = 60500
            if 15000 < width:
                shift_step = 70000

        start_point = 0
        sample_num = 0
        # print(Fore.GREEN + 'Pianoroll shape:', piano_roll.shape)
        # print(Fore.GREEN + 'Class: {}, Track: {}, Shift-Step-Size: {}'.format(class_num, track_num, shift_step))
        # print(Style.RESET_ALL)
        while (start_point + WINDOWS_WIDTH) < piano_roll.shape[1]:
            sample_num += 1
            png_directory = 'D:/Business/Idea_Music/Data/Original_Data/ISMLP_PngPhotos/' \
                            'pianoroll_Class{:02d}_Track{:03d}_Sample{:03d}.png'.format(group,  # [class_num -1]
                                                                                track_num,
                                                                                sample_num)
            # print(png_directory)
            plt.imsave(png_directory,
                       piano_roll[:, start_point: start_point + WINDOWS_WIDTH],
                       format='png')
            start_point = start_point + shift_step

        # print(Fore.BLUE + 'Number of samples:', sample_num)
        # print(Style.RESET_ALL)

if __name__ == "__main__":

    # General information of the database
    COMPLEXITY_LEVEL_NUMBER = complexity_class_number_computation(DIRECTORY)
    tracks = each_level_track_number(DIRECTORY, COMPLEXITY_LEVEL_NUMBER)

    # Converting MP3 to MIDI
    convert_mp3_to_midi(DIRECTORY)

    # Converting MIDI to PIANOROLLs
    midi_to_pianoroll()

    # Sampling the piano-roll
    database_pianoroll = np.load('database_pianoroll.npy', allow_pickle=True)
    print(database_pianoroll.shape)
    sampling_pianoroll(database_pianoroll)

    duration = 2000  # milliseconds
    freq = 440  # Hz
    winsound.Beep(freq, duration)
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    print("\nCurrent Time =", current_time)


from __future__ import annotations

import json
import math
import os
import sys
from urllib.parse import urlparse

import libtbx

class AutoEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, libtbx.AutoType):
            return "Auto"
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)

def encode_output_as_utf8() -> None:
    """
    Ensures stdout and stderr are UTF-8 encoded.
    This avoids crashes on Windows when printing unicode where the output is
    redirected away from the console into a pipe or file
    """
    if hasattr(encode_output_as_utf8, "done"):
        return

    if sys.stdout.encoding.lower() != "utf-8":
        sys.stdout.reconfigure(encoding="utf-8")  # type: ignore
        sys.stderr.reconfigure(encoding="utf-8")  # type: ignore
    encode_output_as_utf8.done = True  # type: ignore

def format_float_with_standard_uncertainty(value, standard_uncertainty, minimum=1e-12):
    """
    Formats a float, including the uncertainty in its value.

    Parameters
    ----------
    value : float
    standard_uncertainty : float
    minimum : float

    Returns
    -------
    str

    Examples
    --------
    >>> format_float_with_standard_uncertainty(5e-3, 1e-3)
    '0.0050(10)'
    >>> format_float_with_standard_uncertainty(5e-3, 1e-6)
    '0.0050000(10)'
    """
    if standard_uncertainty <= minimum:
        dp = -int(math.log10(minimum))
        return str(round(value, dp))
    precision = -int(round(math.log10(standard_uncertainty)))
    if precision > -1:
        su = standard_uncertainty * math.pow(10, precision)
        if round(su, 1) < 2:
            su *= 10
            precision += 1
        return "{value:.{precision}f}({irsu})".format(
            value=value, precision=precision, irsu=int(round(su))
        )
    else:
        precision += 1
        su = int(round(standard_uncertainty, precision))
        fmt_str = "%.0f(%i)"
        return fmt_str % (round(value, precision), su)

def show_mask_info(expt_list):
    """Print the number of masked pixels for each module in the detector,
    for each experiment in the input list."""
    for i in expt_list.imagesets():
        d = i.get_detector()
        m = i.get_mask(0)
        print("---- ----")
        print(d)
        for j, _m in enumerate(m):
            print(
                "Module {} has {} masked pixels of {}".format(
                    j, _m.count(False), _m.size()
                )
            )

def get_url_scheme(url) -> str:
    """Extract the URL scheme from the string url, respecting Windows file paths"""

    return urlparse(str(url)).scheme if "://" in str(url) else ""

def ersatz_uuid4() -> str:
    """Generate an ersatz UUID4 i.e. random 128 bit UUID."""

    h = "%032x" % int.from_bytes(os.urandom(16), byteorder="little")
    return "%s-%s-%s-%s-%s" % (h[:8], h[8:12], h[12:16], h[16:20], h[20:])