import datetime
import sqlite3
from os import path

def get_db():
    #conn = sqlite3.connect("pizza.db")

    ROOT = path.dirname(path.realpath(__file__))
    conn = sqlite3.connect(path.join(ROOT, "pizza.db"))

    cur = conn.cursor()
    return conn, cur

def get_products():
    conn, cur = get_db()

    products_rows = cur.execute(
        'SELECT id, name, description, price, image FROM products ORDER BY id').fetchall()

    products = []

    for product_row in products_rows:
        product = {
            "id" : product_row[0],
            "name" : product_row[1],
            "description" : product_row[2],
            "price" : product_row[3],
            "image" : product_row[4]
        }

        products.append(product)
    return products

def add_client(name, surname, adress, phone):
    conn, cur = get_db()

    cur.execute(
        'INSERT INTO client (name, surname, adress, phone) VALUES (?,?,?,?)',
        [name, surname, adress, phone]
    )

    conn.commit()
    return cur.lastrowid

def add_pizza(order_id, name, value):
    conn, cur = get_db()

    cur.execute(
        'INSERT INTO pizza (order_id, name, value) VALUES (?, ?,?)',
        [order_id, name, value]
    )

    conn.commit()
    return cur.lastrowid

def add_order(client_id, status):
    conn, cur = get_db()

    cur.execute(
        'INSERT INTO orders (client_id, status, date) VALUES (?,?,?)',
        [client_id, status, datetime.datetime.now().replace(microsecond=0)]
    )

    conn.commit()
    return cur.lastrowid

def get_client_id(order_id):
    conn, cur = get_db()
    ids = cur.execute('SELECT client_id FROM orders WHERE id =?', [order_id]).fetchone()

    return ids[0]

def del_order(order_id):
    conn, cur = get_db()

    cur.execute(
        'DELETE FROM pizza WHERE order_id = ?',
        [order_id]
    )

    cur.execute(
        'DELETE FROM client WHERE id = ?',
        [get_client_id(order_id)]
    )

    cur.execute(
        'DELETE FROM orders WHERE id = ?',
        [order_id]
    )

    conn.commit()

def get_orders():
    conn, cur = get_db()

    order_rows = cur.execute(
        'SELECT id, client_id, status, date FROM orders ORDER BY id').fetchall()

    orders = {}

    for order_row in order_rows:
        client_id = order_row[1]
        client = get_client(client_id)
        pizza = get_pizza(order_row[0])
        order = {
            'client': {
                'name': client['name'],
                'surname': client['surname'],
                'adress': client['adress'],
                'phone': client['phone']
            },
            'pizza' : pizza,
            'status': { order_row[2]: order_row[3]}
        }
        orders.update({order_row[0]: order})

    return orders

def get_order(order_id):
    conn, cur = get_db()

    order_row = cur.execute(
        'SELECT id, client_id, status, date FROM orders WHERE id =?', [order_id]).fetchone()

    client_id = order_row[1]
    client = get_client(client_id)
    pizza = get_pizza(order_row[0])
    order = {
        'client': {
            'name': client['name'],
            'surname': client['surname'],
            'adress': client['adress'],
            'phone': client['phone']
        },
        'pizza': pizza,
        'status': {order_row[2]: order_row[3]}
    }

    return order

def get_client(client_id):
    conn, cur = get_db()

    client_row = cur.execute('SELECT id, name, surname, adress, phone FROM client WHERE id = ?', [client_id]).fetchone()

    client = {
        "id" : client_row[0],
        "name" : client_row[1],
        "surname" : client_row[2],
        "adress" : client_row[3],
        "phone" : client_row[4]
    }

    return client

def get_pizza(order_id):
    conn, cur = get_db()

    pizza = {}

    pizza_rows = cur.execute('SELECT order_id, name, value FROM pizza WHERE order_id = ?', [order_id]).fetchall()

    for pizza_row in pizza_rows:
        pizza.update({pizza_row[1]: pizza_row[2]})

    return pizza

def update_status(id, status):
    conn, cur = get_db()

    cur.execute('UPDATE orders SET status = ? WHERE id = ?', [status, id])
    conn.commit()


"""Nerdle Game tree builder and analysis of distribution of #guesses over all answers."""
import collections
import numpy as np
import scipy.stats
from typing import Iterable, Dict

from . import solver

class Node:
    def __init__(self, key, guesses, answers, score, children, hint=None, parent=None):
        self.key = key
        self.guesses = guesses
        self.answers = answers
        self.score = score
        self.hint = hint
        self.children = children
        self.parent = parent

    def __repr__(self):
        return "Node[key={}, guesses={} answers={}{}, score={}, children={}]".format(
            self.key, len(self.guesses), len(self.answers),
            " " + str(self.answers) if len(self.answers) <= 10 else "",
            self.score.shape, len(self.children))

    def __str__(self):
        return repr(self)

    def guess_key(self, key):
        """Returns the root-level index of guess key(s) (intt or np.ndarray) of this node."""
        node = self
        while node.parent:
            node = node.parent
            key = node.guesses[key]
        return key

    def answer_key(self, key):
        """Returns the root-level index of answer key(s) (intt or np.ndarray) of this node."""
        node = self
        while node.parent:
            node = node.parent
            key = node.answers[key]
        return key

class GameTreeBuilder:
    def __init__(self, solver_data, max_answers: int = 10000000):
        self._solver_data = solver_data
        self._score_db = solver_data.score_db.copy()[:, :max_answers]
        self._solver = solver.NerdleSolver(solver_data)
        self._all_keys = solver_data.all_keys
        self._n = len(solver_data.all_keys)

    def build(self, debug: bool = False, strategy="minimax",
              min_sample_size: int = 2000, sample_factor: float = 1.7,
              guess_coarsening_factor: float = 4) -> Node:
        if strategy == "minimax":
            bucket_size_functor = max_bucket_sizes
        elif strategy == "multilevel":
            def bucket_size_functor(a):
                if a.shape[1] <= min_sample_size:
                    #print(a.shape, "max_bucket_sizes")
                    return max_bucket_sizes(a)
                else:
                    print(a.shape, "min_biased_multilevel_sampling")
                    return min_biased_multilevel_sampling(
                        a, max_bucket_sizes, min_sample_size=min_sample_size,
                        sample_factor=sample_factor)
        else:
            raise ValueError("Unknown max bucket calculation strategy {}".format(strategy))
        quantity = lambda a: bucket_size_functor(a) / a.shape[1]
        root = Node(None, self._all_keys, self._all_keys, self._score_db, [])
        pre_traversal(root, lambda node: self._process_node(
            node, quantity, guess_coarsening_factor=guess_coarsening_factor), debug=debug)
        return root

    def _process_node(self, node, bucket_size_functor, guess_coarsening_factor: float = 4):
        if len(node.answers) == 1:
            guess_is_answer = np.where(node.guesses == node.answers[0])[0]
            if len(guess_is_answer) != 1 or not self._solver.is_correct(node.score[guess_is_answer[0], 0]):
                raise ValueError("Failed to solve game")
        else:
            # Coarsen in rows (guesses).
            score = node.score
            if guess_coarsening_factor > 1 and len(node.answers) <= 0.1 * self._n:
                # Coarsen in rows.
                guesses = np.sort(
                    np.concatenate(
                    (node.answers,
                     np.random.choice(np.setdiff1d(node.guesses, node.answers),
                                      size=int((self._n - len(node.answers)) / guess_coarsening_factor),
                                      replace=False))))
                score = score[np.where(np.in1d(node.guesses, guesses))[0]]
            else:
                guesses = node.guesses

            # Find best next guess = argmin(max bucket size).
            answer_index = np.arange(len(node.answers), dtype=int)
            bucket_sizes = bucket_size_functor(score)
            feasible = np.logical_not(np.in1d(np.arange(len(bucket_sizes)), answer_index))
            bucket_size, _, guess_index_opt = min((b, k_feasible, k)
                                                  for k, (k_feasible, b) in enumerate(zip(feasible, bucket_sizes)))
            guess_opt = guesses[guess_index_opt]

            # TODO: use depth-first traversal and only keep leaf depth (=#guesses) and perhaps its solution path
            # to reduce memory of storing entire tree.
            info = _bucket_iterable(answer_index, score[guess_index_opt])
            node.key = (guess_opt, self._solver_data.answers[guess_opt], bucket_size)
            node.children = [
                Node(None, guesses, node.answers[bucket], score[:, bucket], [], hint=hint, parent=node)
                for hint, bucket in info.items()
            ]

def max_bucket_sizes(score) -> np.ndarray:
    if score.shape[1] <= 300:
        return np.array([collections.Counter(row).most_common(1)[0][1] for row in score])
    else:
        return scipy.stats.mode(score, axis=1, keepdims=False)[1]

def min_biased_multilevel_sampling(
        score, quantity, min_sample_size: int = 2000, sample_factor: float = 1.7,
        debug: bool = False):
    """Quantity is a functor that depends on the set of values of a row (i.e., its values is independent of column
    ordering."""
    # Ensure linear complexity.
    assert sample_factor < 2
    m, n = score.shape
    if n <= min_sample_size:
        return quantity(score)
    # 'rows' is the active set of rows. As we increase the sample, result[rows] becomes more accurate; we only
    # need a high accuracy in small result values, so we keep halving 'rows' in the loop below while increasing
    # the sample size. [log2(m)] + 1 repeats at most.
    rows, cols, result = np.arange(m, dtype=int), np.arange(n, dtype=int), np.zeros((m, ))
    sample_size = min_sample_size
    while rows.size:
        if debug:
            print("#rows", len(rows), "x sample_size", sample_size, "=", len(rows) * sample_size)
        # Select a random sample of the rows of size 'sample_size'.
        if sample_size > len(cols):
            raise ValueError("sample_size {} > #cols {}".format(sample_size, len(cols)))
        col_sample = np.random.choice(cols, size=sample_size, replace=False)
        # Calculate max bucket sizes for all elements in 'rows' using the current sample (overriding some old values).
        quantities = quantity(score[rows][:, col_sample])
        result[rows] = quantities
        if sample_size == n:
            break
        # Restrict rows to the smaller half of quantity value.
        #  If the quantity distribution is sufficiently spread so that the median is not repeated many times, the
        # loop halves len(rows), so there ~ log2(m) repeats. But what happens when the median is repeated?
        # Truncate the list 'i' to half the size of rows, filling it with values < median and some values = median.
        q_median = np.median(quantities)
        i = np.where(quantities < q_median)[0]
        i = np.concatenate((i, np.where(quantities == q_median)[0][:len(rows) // 2 - len(i)]))
        rows = rows[i]
        sample_size = min(int(sample_factor * sample_size), n)
    return result

class TreeDepthCalculator:
    def __init__(self, node: Node):
        self.depth = {}
        self._current_depth = 0
        self._calculate_tree_depth(node)

    def _calculate_tree_depth(self, node: Node):
        self._process(node)
        self._current_depth += 1
        for child in node.children:
            self._calculate_tree_depth(child)
        self._current_depth -= 1

    def _process(self, node):
        self.depth[node] = self._current_depth

def pre_traversal(
        node: Node,
        process_node,
        depth: int = 0,
        debug: bool = False):
    process_node(node)
    if debug: # and depth <= 1:
        print("\t" * depth, node)
    for child in node.children:
        pre_traversal(child, process_node, depth=depth + 1, debug=debug)

def _bucket_iterable(answers: Iterable, score: Iterable) -> Dict:
    s = collections.defaultdict(list)
    for a, v in zip(answers, score):
        s[v].append(a)
    return s


import pytest
import torch
from datasets import Dataset, load_dataset
from transformers import AutoConfig, AutoModel, AutoTokenizer

from primeqa.mrc.models.heads.extractive import EXTRACTIVE_HEAD
from primeqa.mrc.models.task_model import ModelForDownstreamTasks
from primeqa.mrc.processors.preprocessors.base import BasePreProcessor
from primeqa.mrc.data_models.target_type import TargetType
from tests.primeqa.mrc.common.parameterization import parameterize_fixture_with_model_name

class UnitTest:
    """
    Base class for all unit test classes
    """

    @parameterize_fixture_with_model_name
    def model_name_and_config(self, request):
        model_name = request.param
        _ = AutoModel.from_pretrained(model_name)  # Pre-download LM inside flaky fixture so other tests have it
        return model_name, AutoConfig.from_pretrained(model_name)

    @pytest.mark.flaky(reruns=5, reruns_delay=2)  # Account for intermittent S3 errors downloading HF data
    @pytest.fixture(scope='session')
    def tokenizer(self, model_name_and_config):
        model_name, _ = model_name_and_config
        return AutoTokenizer.from_pretrained(model_name)

    @pytest.fixture(scope='session')
    def config_and_model_with_extractive_head(self, model_name_and_config):
        model_name, config = model_name_and_config
        model = ModelForDownstreamTasks.from_config(config,
                                                    model_name,
                                                    task_heads=EXTRACTIVE_HEAD)
        head_name = next(iter(EXTRACTIVE_HEAD))
        model.set_task_head(head_name)
        return config, model

    @pytest.fixture(scope='session')
    def extractive_training_inputs(self, config_and_model_with_extractive_head):
        _, model = config_and_model_with_extractive_head
        bs, seq_len = model.dummy_inputs['input_ids'].shape
        kwargs = dict(start_positions=torch.randint(0, seq_len, (bs, 1)),
                      end_positions=torch.randint(0, seq_len, (bs, 1)),
                      target_type=torch.randint(0, len(TargetType), (bs, 1)))
        kwargs.update(model.dummy_inputs)
        return kwargs

    @pytest.fixture(scope='session')
    def train_examples(self):
        question = ["Who walked the dog?", "What time is it?"]
        context = [["Alice walks the cat", "Bob walks the dog"],
                   ["The quick brown fox jumps over the lazy dog", "Glenn the otter lives at the aquarium", "Go"]]
        example_id = ["foo-abc", "bar-123"]
        start_positions = [[0], [-1]]
        end_positions = [[2], [-1]]
        passage_indices = [[1], [-1]]
        yes_no_answer = [["NONE"], ["NONE"]]
        examples_dict = dict(question=question, context=context, example_id=example_id,
                             target=[dict(start_positions=s, end_positions=e, passage_indices=p, yes_no_answer=yn)
                                     for s, e, p, yn in
                                     zip(start_positions, end_positions, passage_indices, yes_no_answer)])
        examples_dataset = Dataset.from_dict(examples_dict)
        return examples_dataset

    @pytest.fixture(scope='session')
    def eval_examples(self, train_examples):
        return train_examples.remove_columns('target')

    @pytest.fixture(scope='session')
    def preprocessor(self, tokenizer):
        return BasePreProcessor(
            tokenizer,
            stride=128,
            load_from_cache_file=False,
            negative_sampling_prob_when_has_answer=0.5,
            negative_sampling_prob_when_no_answer=0.5,
        )

    @pytest.fixture(scope='session')
    def train_examples_and_features(self, train_examples, preprocessor):
        return preprocessor.process_train(train_examples)

    @pytest.fixture(scope='session')
    def eval_examples_and_features(self, eval_examples, preprocessor):
        return preprocessor.process_eval(eval_examples)

    @staticmethod
    def _assert_is_floating_point_tensor(tensor):
        assert isinstance(tensor, torch.Tensor)
        assert tensor.dtype.is_floating_point

    @pytest.mark.flaky(reruns=10, reruns_delay=30)  # Account for intermittent S3 errors downloading HF data
    @pytest.fixture(scope='session')
    def tydiqa_train_examples(self):
        raw_dataset = load_dataset("tydiqa", "primary_task", split='train', streaming=True)
        iterable_dataset = raw_dataset.take(100)
        examples = {}
        for e in iterable_dataset:
            for key in e.keys():
                if key not in examples:
                    examples[key] = []
                examples[key].append(e[key])
        return Dataset.from_dict(examples)

    @pytest.mark.flaky(reruns=10, reruns_delay=30)  # Account for intermittent S3 errors downloading HF data
    @pytest.fixture(scope='session')
    def tydiqa_eval_examples(self):
        raw_dataset = load_dataset("tydiqa", "primary_task", split='validation', streaming=True)
        iterable_dataset = raw_dataset.take(100)
        examples = {}
        for e in iterable_dataset:
            for key in e.keys():
                if key not in examples:
                    examples[key] = []
                examples[key].append(e[key])
        return Dataset.from_dict(examples)

    @pytest.mark.flaky(reruns=10, reruns_delay=30)  # Account for intermittent S3 errors downloading HF data
    @pytest.fixture(scope='session')
    def squad_train_examples(self):
        raw_dataset = load_dataset("squad", "plain_text", split='train', streaming=True)
        iterable_dataset = raw_dataset.take(100)
        examples = {}
        for e in iterable_dataset:
            for key in e.keys():
                if key not in examples:
                    examples[key] = []
                examples[key].append(e[key])
        return Dataset.from_dict(examples)

    @pytest.mark.flaky(reruns=10, reruns_delay=30)  # Account for intermittent S3 errors downloading HF data
    @pytest.fixture(scope='session')
    def squad_eval_examples(self):
        raw_dataset = load_dataset("squad", "plain_text", split='validation', streaming=True)
        iterable_dataset = raw_dataset.take(100)
        examples = {}
        for e in iterable_dataset:
            for key in e.keys():
                if key not in examples:
                    examples[key] = []
                examples[key].append(e[key])
        return Dataset.from_dict(examples)


from pyspark import SparkConf
from pyspark.sql import SparkSession

my_conf = SparkConf()
my_conf.set("spark.app.name", "my first application")
my_conf.set("spark.master", "local[*]")
spark = SparkSession.builder.config(conf=my_conf).getOrCreate()
orderDf = spark.read.option("header", True).option("inferSchema", True).csv("/Users/Wolverine/Documents/BigData-Hadoop"
                                                                            "/Week 11/DataSets/orders.csv")
groupedDf = orderDf.repartition(4) \
    .where("order_customer_id > 10000") \
    .select("order_id", "order_customer_id") \
    .groupBy("order_customer_id") \
    .count()
groupedDf.show()


'''
Neste problema prentede-se que implemente uma função que calcula o rectângulo onde se movimenta um robot.

Inicialmente o robot encontra-se na posição (0,0) virado para cima e irá receber uma sequência de comandos numa string.
Existem quatro tipos de comandos que o robot reconhece:
  'A' - avançar na direcção para o qual está virado
  'E' - virar-se 90º para a esquerda
  'D' - virar-se 90º para a direita
  'H' - parar e regressar à posição inicial virado para cima

Quando o robot recebe o comando 'H' devem ser guardadas as 4 coordenadas (minímo no eixo dos X, mínimo no eixo dos Y, máximo no eixo dos X, máximo no eixo dos Y) que definem o rectângulo
onde se movimentou desde o início da sequência de comandos ou desde o último comando 'H'.

A função deve retornar a lista de todas os rectangulos (tuplos com 4 inteiros)
'''

def robot(comandos):
    movs = {
        0: (0,1),   # norte
        1: (1,0),   # este
        2: (0,-1),  # sul
        3: (-1,0)   # oeste
    }
    faced = 0
    mov = [0,0] # x,y
    maxX = 0
    maxY = 0
    minX = 0
    minY = 0
    r = []
    for com in comandos:
        if com == 'A':
            mov[0] += movs[faced][0]
            mov[1] += movs[faced][1]
            if(mov[0] > maxX):
                maxX = mov[0]
            elif(mov[0] < minX):
                minX = mov[0]

            if (mov[1] > maxY):
                maxY = mov[1]
            elif(mov[1] < minY):
                minY = mov[1]
        elif com == 'E':
            faced = (faced-1) % 4
        elif com == 'D':
            faced = (faced+1) % 4
        else:
            r.append((minX,minY,maxX,maxY))
            maxX = 0
            maxY = 0
            minX = 0
            minY = 0
            mov[0] = 0
            mov[1] = 0
            faced = 0

    return r


"""
    给定二叉树的根 root ，返回树中最长连续路径的长度。
    连续路径是路径中相邻节点的值相差 1 的路径。此路径可以是增加或减少。
    例如， [1,2,3,4] 和 [4,3,2,1] 都被认为有效，但路径 [1,2,4,3] 无效。
    另一方面，路径可以是子-父-子顺序，不一定是父子顺序。

    示例 1:
        输入: root = [1,2,3]
        输出: 2
        解释: 最长的连续路径是 [1, 2] 或者 [2, 1]。

    示例 2:
        输入: root = [2,1,3]
        输出: 3
        解释: 最长的连续路径是 [1, 2, 3] 或者 [3, 2, 1]。

"""
from typing import Optional

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:

    def __init__(self):
        self._max_length = 0

    def longestConsecutive(self, root: Optional[TreeNode]) -> int:
        """
        底层到当前节点最长的递增连续路径长度
        底层到当前节点最长的递减连续路径长度

        :param root:
        :return:
        """
        return self.answer_1(root)

    def answer_0(self, root):
        self._dfs_0(root)
        return self._max_length

    def _dfs_0(self, node):
        if not node:
            return 0, 0

        left_up, left_down = self._dfs_0(node.left)
        right_up, right_down = self._dfs_0(node.right)

        new_up = new_down = 1

        if node.left and node.left.val + 1 == node.val:
            new_up = max(new_up, left_up + 1)
        if node.left and node.left.val - 1 == node.val:
            new_down = max(new_down, left_down + 1)

        if node.right and node.right.val + 1 == node.val:
            new_up = max(new_up, right_up + 1)

        if node.right and node.right.val - 1 == node.val:
            new_down = max(new_down, right_down + 1)

        self._max_length = max(self._max_length, new_up + new_down - 1)
        return new_up, new_down

    def answer_1(self, root):
        self._dfs_1(root)
        return self._max_length

    def _dfs_1(self, node):
        if not node:
            return 0, 0
        left = self._dfs_1(node.left)
        right = self._dfs_1(node.right)

        inc = dec = 1
        if node.left:
            if node.left.val == node.val + 1:
                inc += left[0]
            elif node.left.val == node.val - 1:
                dec += left[1]

        if node.right:
            if node.right.val == node.val + 1:
                inc = max(inc, right[0] + 1)
            elif node.right.val == node.val - 1:
                dec = max(dec, right[1] + 1)
        self._max_length = max(self._max_length, dec + inc - 1)
        return inc, dec


import turtle
import pandas

screen = turtle.Screen()
screen.title("U.S. States Game")

img = "blank_states_img.gif"
screen.addshape(img)  # Adds an image as shape. Turtle only accepts gif.
turtle.shape(img)

data = pandas.read_csv("50_states.csv") # Reads the 50_states.csv.
all_states = data.state.to_list() # Converts the data["state"] to a list with only states.
correct_guesses = []  # List that will contain the correct guesses,

while len(correct_guesses) < 50:  # Game continues until you have guessed every state right.
    # Text input that saves the users guess.
    answer_state = screen.textinput(title=f"{len(correct_guesses)}/{len(all_states)} States Correct", prompt="What's another state's name?").title()
    # If the user guess "Exit": Saves the missing states into a new csv and breaks the loop.
    if answer_state == "Exit":
        missing_states = []
        for state in all_states:
            if state not in correct_guesses:
                missing_states.append(state)
        new_data = pandas.DataFrame(missing_states)
        new_data.to_csv("states_to_learn.csv")
        break
    # If the answer is correct, saves the state into correct_guesses and creates turtle that writes
    # the state name on the screen.
    if answer_state in all_states:
        t = turtle.Turtle()
        t.hideturtle()
        t.penup()
        state_data = data[data.state == answer_state]
        t.goto(int(state_data.x), int(state_data.y)) # Gets the x and y attribute from state_data row.
        t.write(arg=answer_state, align="center", font=('Arial', 8, 'normal'))  # Writes the name of the guessed state.
        correct_guesses.append(answer_state)


from typing import List

def part1(values: List[int]):
    total = 0
    for x, y in zip(values[1:], values[:-1]):
        if x > y:
            total += 1

    print(total)

def part2(values: List[int]):
    total = 0
    prev = sum(values[:3])

    for t in zip(values[1:-2], values[2:-1], values[3:]):
        s = sum(t)
        if s > prev:
            total += 1
        prev = s

    print(total)

def main():
    f = open('inputs/day01.txt')
    values = [int(x.strip()) for x in f.readlines()]

    part1(values)
    part2(values)

if __name__ == '__main__':
    main()


from .payment import home
from .. import BaseHandler

def get_plugin_handlers():
    plugin_name = get_plugin_info()["name"]

    return [
        (r'/{}'.format(plugin_name), home),
        (r'/{}/'.format(plugin_name), home),
    ]

def get_plugin_info():
    return {
        "name": "payment",
        "entrypoints": [
            {
                "title": "Platby",
                "url": "/payment",
                "icon": "payment",
            }
        ]
    }


import json

import tabulate
import pandas as pd
import numpy as np
import os
import os.path as osp
import glob
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--dir', type=str, help='the log directory')
    args = parser.parse_args()

    path = args.dir

    files = sorted(glob.glob(osp.join(path, '*.log')))

    def parse_name(s):
        s = s.replace('-snapshot','')
        l = s.split('-')
        ds_name = ''
        for x in l[:-2]:
            if len(ds_name) > 0:
                ds_name = ds_name + '-'
            ds_name = ds_name + x
        return ds_name, l[-2], l[-1]

    def get_diff(x, y):
        if x == 'nan':
            return -1e9
        if y == 'nan':
            return 1e9
        x = x.strip('**')
        y = y.strip('**')
        x_acc, x_std = x.split(' +- ')
        y_acc, y_std = y.split(' +- ')
        return float(x_acc) - float(y_acc)
        if x_acc != y_acc:
            return float(x_acc) - float(y_acc)
        else:
            return float(y_std) - float(x_std)

    acc_map, time_map, diff_map, best_map = {}, {}, {}, {}

    for filename in files:
        with open(filename, 'r') as f:
            filename = filename.replace(path + '/', '')
            filename = filename.strip('.log')

            try:
                json_dict = json.load(f)
            except json.decoder.JSONDecodeError:
                continue
            ds_name, filter_method, snapshot = parse_name(filename)
            for kk, v in json_dict.items():
                k = kk
                if 'WL_' in kk:
                    k = 'WL'
                if 'GL_' in kk:
                    k = 'GL'
                if 'WLOA_' in kk:
                    k = 'WLOA'
                if 'CSM_' in kk:
                    k = 'CSM'
                if 'PM_' in kk:
                    k = 'PM'
                if 'MLG' in kk:
                    k = 'MLG'
                if k not in acc_map:
                    acc_map[k] = {}
                    time_map[k] = {}
                if ds_name not in acc_map[k]:
                    acc_map[k][ds_name] = {}
                    time_map[k][ds_name] = {}

                if filter_method + '-' + snapshot not in acc_map[k][ds_name]:
                    acc_map[k][ds_name][filter_method + '-' + snapshot] = 'nan'
                    time_map[k][ds_name][filter_method + '-' + snapshot] = 'nan'
                if 'acc' in v and get_diff(acc_map[k][ds_name][filter_method + '-' + snapshot], v['acc']) < 0:
                    acc_map[k][ds_name][filter_method + '-' + snapshot] = v['acc']
                    time_map[k][ds_name][filter_method + '-' + snapshot] = v['time']

    for k, ma in acc_map.items():
        print(f'## {k}')
        df = pd.DataFrame(ma)
        print(tabulate.tabulate(
            df,
            tablefmt='github',
            headers='keys'
        ))
        print()

    diff_map = {}
    for kernel_method, ma in acc_map.items():
        diff_map[kernel_method] = {}
        for ds_name, mama in ma.items():
            if 'intact-001' not in mama:
                mama['intact-001'] = 'nan'
            intact_1 = mama['intact-001']
            diff_map[kernel_method][ds_name] = -1e9
            for method, res in mama.items():
                if method == 'intact-001':
                    continue
                diff_map[kernel_method][ds_name] = max(get_diff(res, intact_1), diff_map[kernel_method][ds_name])

    print(f'## improvement')
    df = pd.DataFrame(diff_map)
    print(tabulate.tabulate(
        df,
        tablefmt='github',
        headers='keys',
        floatfmt='+.2f'
    ))
    print()

    best_map = {}
    for kernel_method, ma in acc_map.items():
        for ds_name, mama in ma.items():
            if ds_name not in best_map:
                best_map[ds_name] = {}
                best_map[ds_name]['name'] = 'nan'
                best_map[ds_name]['acc'] = 'nan'
                best_map[ds_name]['improvement'] = -1e9
            for method, res in mama.items():
                if get_diff(best_map[ds_name]['acc'], res) < 0:
                    best_map[ds_name]['name'] = kernel_method + '-' + method
                    best_map[ds_name]['acc'] = res
    ds_names = set()
    for kernel_method, ma in acc_map.items():
        for ds_name, _ in ma.items():
            ds_names.add(ds_name)

    for ds_name in ds_names:
        intact_1 = 'nan'
        for kernel_method, ma in acc_map.items():
            if get_diff(intact_1, ma[ds_name]['intact-001']) < 0:
                intact_1 = ma[ds_name]['intact-001']

        for kernel_method, ma in acc_map.items():
            for d_name, mama in ma.items():
                if ds_name != d_name:
                    continue
                for method, res in mama.items():
                    if method == 'intact-001':
                        continue
                    best_map[ds_name]['improvement'] = max(best_map[ds_name]['improvement'], get_diff(res,intact_1))

    print('## best method')
    df = pd.DataFrame(best_map)
    print(tabulate.tabulate(
        df.transpose(),
        tablefmt='github',
        headers='keys',
        floatfmt='+.2f'
    ))


S = lambda: map(int, input().split())
L = lambda: list(S())

def solve():
    n = int(input())
    if n == 1:
        print(1)
    elif n % 2 == 1:
        print(-1)
    else:
        ans = []
        for i in range(n//2, 0, -1):
            ans.append(i*2-1)
            ans.append(i*2)
        print(*ans)

    return

if __name__ == "__main__":
    for test in range(int(input())):
        solve()


import argparse

parser = argparse.ArgumentParser(description='Header file to use.')

parser.add_argument("-f", "--file", help="Header file to use.", type=str, required=True)
parser.add_argument("-t", "--target", help="Source file to write.", type=str, required=True)

args = parser.parse_args()

header_prelog = "\n#include <ProcessingUnit/A64InstructionSet/A64InstructionSet.h>\n#include <Utility/StreamableEnum.h>\n#include <ostream>\n#include <string_view>\n\nBEGIN_NAMESPACE\n\n"
header_epilog = "END_NAMESPACE\n"
map_prelog = "\nstatic constexpr SmallConstMap< "
map_name_epilog = "StringMap { { {"
map_epilog = "} } };\n"

ToChar_func_prelog = "template <>\nstatic std::string_view Enum::ToChar("
ToChar_func = " elem) { \n return "
ToChar_func_epilog = "StringMap.At(elem);\n}\n"

stream_func_prelog = "template<>\nstd::ostream& operator<<(std::ostream&os, "
stream_func_epilog = " elem) {\nos << Enum::ToChar(elem);\nreturn os;\n}"

enums = dict()
first_enum_name = ""

with open(args.file, "r") as f:
    lines = f.readlines()

    first_enum = True
    enum_found = False
    enum_just_found = False

    current_enum = ""

    for line in lines:
        if(enum_found):
            line = line.replace(" ", "")
            line = line.replace(",", "")
            line = line.replace("\n", "")

            if "//" in line:
                loc = line.find("//")
                line = line[0:loc]

            if line == "ARM_EMU_COUNT":
                enum_found = False
                continue
            else:
                if(len(line) != 0):
                    enums[current_enum].append(line)

        if(enum_just_found):
            enum_found = True
            enum_just_found = False
            continue

        if "enum class" in line and (not enum_found or not enum_just_found):
            enum_just_found = True
            line = line.replace(" ", "")
            line = line.removeprefix("enumclass")
            line = line.replace(":std::uint32_t\n", "")
            enums[line] = list()
            current_enum = line
            if(first_enum):
                first_enum_name = line
                first_enum_name = first_enum_name.replace("A64", "")
                first_enum = False

with open(args.target, "w") as f:
    f.write(header_prelog)
    f.write("namespace {\n\n")
    f.write("using namespace std::literals::string_view_literals;\n")

    for key, values in enums.items():
        f.write(map_prelog)
        tmp_key = key.replace("A64", "")

        if(first_enum_name != tmp_key):
            f.write(first_enum_name)
            f.write("::")
        f.write(key)

        f.write(", std::string_view, enum_size_v< ")
        if(first_enum_name != tmp_key):
            f.write(first_enum_name)
            f.write("::")
        f.write(key)

        f.write(" > >")
        f.write(key)
        f.write(map_name_epilog)
        f.write("\n")
        for value in values:
            f.write("{ ")

            if(first_enum_name != tmp_key):
                f.write(first_enum_name)
                f.write("::")
            f.write(key)
            f.write("::")
            f.write(value)
            f.write(", \"")
            f.write(value)
            f.write("\"sv }, ")
        f.write(map_epilog)
    f.write("\n}\n\n")

    for key, _ in enums.items():
        f.write(ToChar_func_prelog)

        tmp_key = key.replace("A64", "")
        if(first_enum_name != tmp_key):
            f.write(first_enum_name)
            f.write("::")

        f.write(key)
        f.write(ToChar_func)
        f.write(key)
        f.write(ToChar_func_epilog)
        f.write("\n")

        f.write(stream_func_prelog)
        tmp_key = key.replace("A64", "")
        if(first_enum_name != tmp_key):
            f.write(first_enum_name)
            f.write("::")
        f.write(key)
        f.write(stream_func_epilog)
        f.write("\n")
        f.write("\n")

    f.write(header_epilog)


import pandas as pd
from sklearn.cluster import DBSCAN, KMeans
__all__ = [
    'dbscan',
    'kmeans',
]

def dbscan(data, **kwargs):
    eps = float(kwargs.pop('eps'))
    minpts = int(kwargs.pop('minpts'))
    predict_label = kwargs.pop('predict_labels')
    store = kwargs.pop('store_origin')
    clustering = DBSCAN(eps=eps, min_samples=minpts)
    df = pd.DataFrame(clustering.fit_predict(data))
    df.columns = [predict_label]
    if store == 'True':
        df = pd.concat([data, df], axis=1)
    return df

def kmeans(data, **kwargs):
    n_cluster = int(kwargs.pop('n_cluster'))
    max_iter = int(kwargs.pop('max_iter'))
    predict_label = kwargs.pop('predict_labels')
    store = kwargs.pop('store_origin')
    kmeans = KMeans(n_clusters=n_cluster, max_iter=max_iter)
    df = pd.DataFrame(kmeans.fit_predict(data))
    df.columns = [predict_label]
    if store == 'True':
        df = pd.concat([data, df], axis=1)
    return df


import numpy as np

from Common import get_plot_type, get_db_connection, close_db, get_logger, show_information_message, execute_inquiry, \
    get_row_model, init_tableview

from PyQt5.QtWidgets import QMainWindow, QApplication, QGridLayout, QHeaderView

from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar

import seaborn as sns  #https://seaborn.apachecn.org/#/docs/12   seaborn中文文档

import pandas as pd

from PyQt5.QtCore import pyqtSlot, QItemSelectionModel, QModelIndex

from PyQt5.QtGui import QStandardItem, QStandardItemModel

from UI.Ui_PlotSubWindow import Ui_PlotSubWindow

from Util.Plot import Myplot2D

#https://seaborn.apachecn.org/#/docs/12   seaborn中文文档

#这块需要信号的方式传递横纵坐标，还有折线图与饼状图的选择#

class PlotSubWindow(QMainWindow):

    def __init__(self, plot_type=-1, row = None, line = None, data = None, type_label = None, parent=None):
        super(PlotSubWindow, self).__init__(parent)
        self.UI = Ui_PlotSubWindow()
        self.UI.setupUi(self)

        self.row = row  #横轴
        self.line = line  #纵轴
        self.plot_type = plot_type  #画图种类 1：代表折线图 0：代表柱状图
        self.type_label = type_label  #画图标签

        self.fig_line = None
        #self.plot_type = None

        self.init_plot_frame()
        if plot_type == 0:  # 柱状图
            self.plt_multi_colums(row, line, type_label)
        elif plot_type == 1:
            self.plt_multi_line(row, line, type_label)

        #self.plot_line_or_pie(plot_type, row, line, type_label)

        ##################################加tableView功能######################
        if data is not None:
            self.init_model = None
            init_tableview(self.UI.tableView, hor_size=50, ver_size=50)
            self.get_initial_model(data, type_label)
            data_model = self.init_model
            selection_model = QItemSelectionModel(data_model)

            self.UI.tableView.setModel(data_model)
            self.UI.tableView.setSelectionModel(selection_model)
            # 设置表格充满这个布局QHeaderView
            self.UI.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面

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

    # 初始化画图区域

    def init_plot_frame(self):
        self.fig_line = Myplot2D()
        #tool = NavigationToolbar(self.fig_line, self.UI.frame_5)
        layout = QGridLayout()
        layout.addWidget(self.fig_line)
        #layout.addWidget(tool)
        self.UI.frame_5.setLayout(layout)

    #根据横纵列表以及画图种类进行画图
    def plot_line_or_pie(self, plot_type: int, row: list, line: list, type_label: str):

        if plot_type == -1:
            return
        elif plot_type == 0:  #折线图
            if len(line) == 11:
                line = list(['低', '低', '较低', '较高', '高', '较高', '低', '低', '较低', '较高', '较低'])
            else:
                line = list(['较高'])
            #self.plot_line(row, line, type_label)
            self.plot_colums(row, line, type_label, 'red')
            self.plot_colums(row, list(['较低', '较高', '较低','低', '低', '较低', '较高', '高', '较高', '低', '低']), type_label, 'blue')
        else:
            #self.plot_pie(row, line, type_label)
            self.plot_line(row, line, type_label)

    # 绘制折线图，三根线 有最高、平均、最低，折线图 比较简单，容易理解
    def plot_line(self, x: list, values: list, type_label: str, grid=True):
        self.fig_line.axes.plot(x,
                                values[0],
                                '-',
                                color='r',
                                marker='h',
                                label=type_label + "折线图")

        self.fig_line.axes.set_title(type_label + "折线图")
        self.fig_line.axes.set_xticks(x, minor=True)

        if type == '安装时长':
            self.fig_line.axes.set_xlabel(type + '(月)')
        elif type == '环境温度':
            self.fig_line.axes.set_xlabel(type + '(℃)')
        self.fig_line.axes.set_ylabel('风险等级')

        # self.fig_line.axes.set_gcf().autofmt_xdate() # 自动旋转日期标记
        if grid:
            self.fig_line.axes.grid(True, linestyle='-.')

        self.fig_line.axes.legend(loc='best', ncol=1)
        self.fig_line.draw()

    # 绘制柱状图，柱状图该怎么画出那种高、中、低效果，待研究2022/2/22 23:56
    def plot_colums(self, x: list, values: list, type: str, color: str, grid=False):
        self.fig_line.axes.bar(x=x,
                               height=values,
                               align='center',
                               label='asdadssadasd',
                               color=color)
        self.fig_line.axes.set_title(type + "柱状图")
        if grid:
            self.fig_line.axes.grid(True)

        self.fig_line.axes.legend()
        self.fig_line.draw()

    def plt_multi_line(self, row=None, line=None, type_label=None):
        reward = list([])
        reward2 = list([])
        reward3 = list([])

        for i in range(0, len(row)):
            if type_label == '安装时长':
                row[i] = float(row[i])
            reward.append(float(line[0][i]))
            reward2.append(float(line[1][i]))
            reward3.append(float(line[2][i]))
        episode = row
        '''
        episode = [23]
        reward = [35]
        reward2 = [34]
        reward3 = [33]
        '''
        RL1_date = pd.DataFrame({'iteration': episode, 'reward': reward, 'algo': '最高指数', 'style': '*'})
        RL2_data = pd.DataFrame({'iteration': episode, 'reward': reward2, 'algo': '平均指数', 'style': 'h'})
        RL3_data = pd.DataFrame({'iteration': episode, 'reward': reward3, 'algo': '最低指数', 'style': 'v'})

        frames = [RL1_date, RL2_data, RL3_data]
        # pd.concat(frames).plot(kind="bar", x="iteration", y="reward", ax=self.fig_line.axes)
        dataset = pd.concat(frames)
        self.fig_line.axes.grid(True, linestyle='-.')

        sns.set_context("paper", font_scale=1.3, rc={"lines.linewidth": 1.5})

        #  palette：调色板
        ax = sns.relplot(x="iteration", y="reward", ax=self.fig_line.axes, palette=['r', 'b', 'g'], hue="algo", ci="5",
                         kind="line", markers=True, style='style',
                         data=dataset, legend='brief')

        x_ticks = None

        if type_label == '温度':  # 温度规定，温度范围从-20℃~50℃，以2℃间隔段为一个点。
            x_ticks = np.arange(-20, 50, 2.0)
            self.fig_line.axes.set_xticks(x_ticks)
            self.fig_line.axes.set_xlabel("温度（℃）", fontsize=13)
        elif type_label == '安装时长':
            #x_ticks = np.arange(1, 4, 1)
            #self.fig_line.axes.set_xticks(x_ticks)
            self.fig_line.axes.set_xlabel("安装时长（月）", fontsize=13)
        elif type_label == '使用频率':
            self.fig_line.axes.set_xlabel("使用频率", fontsize=13)

        self.fig_line.axes.set_ylabel("风险等级指数", fontsize=13)

        self.fig_line.axes.legend(title='', loc='lower right', labels=["最高指数", "平均指数", "最低指数"])

    # 绘制柱状图，画出那种高、中、低效果 主要
    def plt_multi_colums(self, row=None, line=None, type_label=None):
        '''
        episode = [1, 2, 3]
        reward = [5, 8, 5]
        reward2 = [4, 6, 6]
        reward3 = [6, 4, 7]
        '''
        episode = row
        reward = line[0]
        reward2 = line[1]
        reward3 = line[2]

        RL1_date = pd.DataFrame({'iteration': episode, 'reward': reward, '等级指数': '最高指数', 'palette': 'r'})
        RL2_data = pd.DataFrame({'iteration': episode, 'reward': reward2, '等级指数': '平均指数', 'palette': 'b'})
        RL3_data = pd.DataFrame({'iteration': episode, 'reward': reward3, '等级指数': '最低指数', 'palette': 'g'})

        frames = [RL1_date, RL2_data, RL3_data]
        #pd.concat(frames).plot(kind="bar", x="iteration", y="reward", ax=self.fig_line.axes)
        dataset = pd.concat(frames)

        #  palette：调色板

        ax = sns.catplot(x="iteration", y="reward", ax=self.fig_line.axes, palette=['r', 'b', 'g'], hue="等级指数", ci="sd", kind="bar", data=dataset, legend=True)

        #sns.despine(top=False, right=False, left=False, bottom=False)
        #ax.set(xlabel='Iteration', ylabel='风险等级指数')
        self.fig_line.axes.set_ylabel("风险等级指数", fontsize=13)
        if type_label == '生产厂家':
            self.fig_line.axes.set_xlabel("生产厂家", fontsize=13)
        elif type_label == '运营商':
            self.fig_line.axes.set_xlabel("运营商", fontsize=13)
        elif type_label == '使用频率':
            self.fig_line.axes.set_xlabel("使用频率", fontsize=13)
        #self.fig_line.axes.legend(title='', loc='upper right', labels=["最高指数", "平均指数", "最低指数"])
        #plt.show()
        #self.fig_line.draw_idle()

    # 绘制饼状图
    def plot_pie(self, x: list, values: list, type: str, grid=False):
        self.fig_line.axes.pie(values,
                              labels=x,
                              autopct='%1.1f%%',
                              shadow=True,
                              startangle=150)

        self.fig_line.axes.set_title(type + "饼状图")
        if grid:
            self.fig_line.axes.grid(True)
        self.fig_line.axes.legend()
        self.fig_line.draw()

    # 添加表格到tableView区 2022/2/27

    # 获取最初的数据模型
    def get_initial_model(self, data=None, type_label=None):
        head = None
        if type_label == '安装时长':
            head = list(['安装时长（月）', '最高（风险等级指数）台数', '平均（...）', '最低（...）'])
        elif type_label == '生产厂家':
            head = list(['生产厂家', '最高（风险等级指数）台数', '平均（...）', '最低（...）'])
        elif type_label == '运营商':
            head = list(['运营商', '最高（风险等级指数）台数', '平均（...）', '最低（...）'])
        elif type_label == '使用频率':
            head = list(['使用频率', '最高（风险等级指数）台数', '平均（...）', '最低（...）'])
        elif type_label == '温度':
            head = list(['温度（℃）', '最高（风险等级指数）台数', '平均（...）', '最低（...）'])
        model = get_row_model(2, header=head)
        self.init_model = self.add_data(model, data)

    # 向模型添加数据
    def add_data(self, model: QStandardItemModel, data) -> QStandardItemModel:
        #line1 = list(['', 0, 3, 0])
        for i in data:
            row = []
            for j in range(len(i)):
                item = QStandardItem(str(i[j]))
                row.append(item)
            model.appendRow(row)
        return model

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    win = PlotSubWindow()
    win.show()
    sys.exit(app.exec())


'''
This program allowes the users can extract first order model with input is the rules
Example:
Input:
sống(nam, hà_nội)
học_sinh(nam)
học(nam, lớp_mười_hai)
Bố(đạt, nam)

Output:
D = {d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}
F : {
	F(nam) = d1
	F(hà_nội) = d2
	F(lớp_mười_hai) = d3
	F(đạt) = d4
}
'''

import re
import operator

FPATH = 'rule'

file = open(FPATH)
lines = [re.sub(r'[\.\(,\)]', ' ', line).lower() for line in file if len(line) > 1]

rules = []
vocab = dict()
for line in lines:
	words = line.split()
	outside = words[0]
	inside = words[1:]
	vocab[outside] = len(inside)
	rules.append((outside, inside))
	for word in inside:
		vocab[word] = 0

vocab = [item for item in vocab.items()]
vocab.sort(key=operator.itemgetter(1), reverse=True)

lst = []
for item in vocab:
	lst.append('({0}, {1})'.format(item[0], item[1]))

fact = [w for w in vocab if w[1] == 0]

D = {}
for i in range(1, len(fact) + 1):
	D[fact[i - 1][0]] = 'd' + str(i)
#print(D)

def print_list_tuple(lst):
	string = []
	for item in lst:
		if len(item) == 1:
			string.append(item[0])
		else:
			string.append('(' + ', '.join(item) + ')')
	string = str(', '.join(string)).replace('\'', '')
	return string

vocab.sort(key=operator.itemgetter(1), reverse=False)
vocab = [w[0] for w in vocab]
def show_model(lst, D):
	F = {}
	for item in rules:
		outside, inside = item
		if outside not in F.keys():
			F[outside] = F[outside] = [tuple(inside)]
		else:
			F[outside].append(tuple(inside))
	print("F : {")
	for key in vocab:
		print('\t', end='')
		lst = []
		if key in D:
			F[key] = [tuple([D[key]])]
			print('F({0})'.format(key) + ' = ' + print_list_tuple(F[key]))
		else:
			for items in F[key]:
				sub_lst = []
				for item in items:
					sub_lst.append(D[item])
				lst.append(tuple(sub_lst))
			F[key] = set(lst)
			print('F({0})'.format(key) + ' = {' + print_list_tuple(F[key]) + '}')
	print('}')
	return F

def show_tu_vung(lst):
	for w in lst:
		print('tu_vung{0}.'.format(w))

def show_model_pl(fact, rules):
	for item in fact:
		print('giá_trị({0}).'.format(item[0]))
	for item in rules:
		outside, inside = item
		print('{0}{1}.'.format(outside, str(tuple(inside)).replace('\'', '').replace(',)', ')')))
#show_model(lst, D)
#show_tu_vung(lst)
show_model_pl(fact, rules)


from rest_framework import status
from rest_framework.response import Response

def validate_params(request, params):
    """Validate URL query params. If returns None, params are valid."""
    for param in params:
        res = request.query_params.get(param)
        if res is None:
            return Response(
                data=f"{param} is required", status=status.HTTP_400_BAD_REQUEST
            )
    return None

def validate_body(request, attrs):
    """Validate request body for POST requests. If returns None, params are valid."""
    for attr in attrs:
        res = request.data.get(attr)
        if res is None:
            return Response(
                data=f"{attr} is required", status=status.HTTP_400_BAD_REQUEST
            )
    return None


import datetime as dt
import os

from finances_automation import configuration as conf
from finances_automation.operations import analyses
from finances_automation.repositories import BaseRepository
from finances_automation.validation.analyse import analyser_validator

class Analyser:

    @analyser_validator
    def __init__(self, analysis_type, table_to_analyse, start_date, end_date, table_to_store=None):
        """ Initialise an Analyser.

        :param str analysis_type: name of analysis_result to carry out
        :param finances_automation.entities.table.Table table_to_analyse: table to analyse
        :param finances_automation.entities.table.Table table_to_store: table to store analysis_result in
        :param str start_date: date to start analysis_result at
        :param str end_date: date to end analysis_result at
        """
        self.available_analyses = analyses.get_available_analyses()
        self.chosen_analysis = analyses.get_analysis(analysis_type)

        self.analysis_result = None
        self.categories = conf.categories

        self.table_to_analyse = table_to_analyse
        self.table_to_store = table_to_store

        self.repositories = {'table_to_analyse': BaseRepository(self.table_to_analyse)}

        if self.table_to_store:
            self.repositories['table_to_store'] = BaseRepository(self.table_to_store)

        self.start_date, self.end_date = (
            dt.datetime.strptime(date, self.table_to_analyse.date_format).date()
            for date in (start_date, end_date)
        )

    def analyse(self):
        """Perform an analysis on a table between two dates, storing it in the database.

        :return None:
        """
        self.repositories['table_to_analyse'].load_by_date(self.start_date, self.end_date)

        self.analysis_result = self.chosen_analysis(
            table=self.table_to_analyse,
            categories=self.categories,
            start_date=self.start_date,
            end_date=self.end_date,
            show_plot=True
        )

        self._set_metadata()

        if self.table_to_store is not None:
            self._store()

    def _store(self):
        """ Store the analysis result in the database.

        :return None:
        """
        if self.chosen_analysis.__name__ not in analyses.ANALYSES_EXCLUDED_FROM_STORAGE:
            self.repositories['table_to_store'].insert(self.analysis_result)

    def _set_metadata(self):
        """ Add analysis metadata to the database entry.

        :return None:
        """
        self.analysis_result['tables_analysed'] = self.table_to_analyse.name
        self.analysis_result['start_date'] = self.start_date
        self.analysis_result['end_date'] = self.end_date
        self.analysis_result['analysis_datetime'] = dt.datetime.now()

    def export(self, path):
        """ Export the analysis to a local location.

        :param str path:
        :return None:
        """
        export_type = analyses.ANALYSIS_NAMES_AND_EXPORT_TYPES[self.chosen_analysis.__name__]

        if self.analysis_result is None:
            raise ValueError('No analysis to be exported.')

        if not os.path.exists(path):
            os.makedirs(path)

        filename = self.table_to_analyse.name + '_' + str(self.analysis_result['analysis_datetime'][0]) + export_type

        if export_type == '.csv':
            self.analysis_result.to_csv(os.path.join(path, filename), index=False, encoding='utf-8')
        elif export_type == '.png':
            self.analysis_result.savefig(os.path.join(path, filename), format='png')


'''

Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.

Example 1:

Input: head = [1,2,6,3,4,5,6], val = 6
Output: [1,2,3,4,5]
Example 2:

Input: head = [], val = 1
Output: []
Example 3:

Input: head = [7,7,7,7], val = 7
Output: []

Constraints:

The number of nodes in the list is in the range [0, 104].
1 <= Node.val <= 50
0 <= val <= 50

'''

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:

        if head is None:
            return None

        if head.next is None:
            if head.val == val:
                return None
            else:
                return head

        curr = head
        next = head.next
        while curr is not None or next is not None:
            if curr.val == val:
                curr = curr.next
                if curr is None:
                    next = None
                else:
                    next = curr.next
                head = curr
            elif next is not None and next.val == val:
                next = next.next
                curr.next = next
            else:
                curr = curr.next
                if curr is None:
                    next = None
                else:
                    next = next.next

        return head

a = Solution()
lst = ListNode(1)
lst.next = ListNode(1)
lst.next.next = ListNode(1)
# lst.next.next.next = ListNode(3)
# lst.next.next.next.next = ListNode(4)
# lst.next.next.next.next.next = ListNode(5)
# lst.next.next.next.next.next.next = ListNode(6)

new_l = a.removeElements(None, 4)
while new_l is not None:
    print(new_l.val)
    new_l = new_l.next


from bs4 import BeautifulSoup
import requests
import time
import os
url = 'https://www.azlyrics.com/lyrics/hozier/{}.html'
songs = ["takemetochurch","someonenew", "tobealone", "fromeden", "worksong",
         "likerealpeopledo", "cherrywine", "arsonistslullabye", "shrike",
         "ninacriedpower", "almostsweetmusic", "be", "talk", "wouldthati",
         "sunlight", "firsttime", "francesca", "icarrionicarian", "eatyouryoung",
         "damagegetsdone", "whoweare", "allthingsend", "unknownnth", "firstlight",
         "abstractpsychopomp"]

# create a folder to store the data
folder_name = 'songs'

try:
    if not os.path.exists(folder_name):
        os.mkdir(folder_name)
    else:
        print('Directory already exist')
except Exception as e:
    print(f'Something went wrong with creating the directory: {str(e)}')

# get the html of each song and store inside the folder
with open("song_lyrics.txt", "a") as output_file:
    # get the html of each song and store inside the folder
    for song in songs:
        url_song = url.format(song)
        data = requests.get(url_song)  # request to get the content of the html
        time.sleep(5)  # buffer to avoid time out error

        # store the raw html inside the created folder.
        with open(os.path.join(folder_name, f"{song}.html"), "w+") as f:
            f.write(data.text)

        # clean up the html
        with open(os.path.join(folder_name, f"{song}.html"), "r") as f:
            page = f.read()

            upper_bound = '<!-- Usage of azlyrics.com content by any third-party lyrics provider is prohibited by our licensing agreement. Sorry about that. -->'
            lower_bound = '<!-- MxM banner -->'

            starting_pos = page.find(upper_bound)
            end_pos = page.find(lower_bound)

            if starting_pos != -1 and end_pos != -1:
                extract_content = page[starting_pos + len(upper_bound):end_pos]

                # parse the extracted content
                soup = BeautifulSoup(extract_content, 'html.parser')

                # erase html tags
                for tag in soup.find_all():
                    tag.decompose()

                lyrics_only = soup.get_text().strip()

                # Append lyrics to the output file
                output_file.write(lyrics_only + "\n")


from panda3d.core import *
from direct.showbase import DirectObject
from direct.interval.IntervalGlobal import *
from toontown.toonbase import ToontownGlobals
from . import MovingPlatform
from direct.task.Task import Task
from toontown.suit import Suit
from toontown.suit import SuitDNA

class Ouch(DirectObject.DirectObject):

    def __init__(self, keyEvent, callback):
        DirectObject.DirectObject.__init__(self)
        self.accept(keyEvent, callback)

    def destroy(self):
        self.ignoreAll()

class CyclePlacer(DirectObject.DirectObject):

    def __init__(self, locations, keyEvent, startIndex = 0):
        DirectObject.DirectObject.__init__(self)
        self.locations = locations
        self.index = startIndex
        self.accept(keyEvent, self.gotoNextLocation)

    def destroy(self):
        self.locations = None
        self.ignoreAll()
        return

    def gotoNextLocation(self):
        self.index = (self.index + 1) % len(self.locations)
        self.gotoLocation()

    def gotoLocation(self, index = None):
        if index is None:
            index = self.index
        pos, h = self.locations[index]
        base.localAvatar.reparentTo(render)
        base.localAvatar.setPos(*pos)
        base.localAvatar.setH(h)
        return

class ToonLifter(DirectObject.DirectObject):
    SerialNum = 0

    def __init__(self, keyDownEvent, speed = 2):
        DirectObject.DirectObject.__init__(self)
        self.serialNum = ToonLifter.SerialNum
        ToonLifter.SerialNum += 1
        self.taskName = 'ToonLifter%s' % self.serialNum
        self.keyDownEvent = keyDownEvent
        self.keyUpEvent = self.keyDownEvent + '-up'
        self.speed = speed
        self.accept(self.keyDownEvent, self.startLifting)

    def destroy(self):
        self.ignoreAll()
        taskMgr.remove(self.taskName)

    def startLifting(self):

        def liftTask(task, self = self):
            base.localAvatar.setZ(base.localAvatar.getZ() + self.speed)
            return Task.cont

        def stopLifting(self = self):
            taskMgr.remove(self.taskName)
            self.ignore(self.keyUpEvent)
            self.accept(self.keyDownEvent, self.startLifting)

        self.ignore(self.keyDownEvent)
        self.accept(self.keyUpEvent, stopLifting)
        taskMgr.add(liftTask, self.taskName)


'''get Data for piechart in the form (Name|total Amount)
   python3 piechart_data.py ../visualizations/data/linechart_data.csv'''

import csv
import sys
import os
from pprint import pprint

def create_piechart_data(file):
    '''get off my ass pylint'''

    total_schiller = 0
    total_christiane = 0
    total_frauSchiller = 0
    total_stein = 0

    with open(file, "r") as csvfile:
        myreader = csv.DictReader(csvfile, delimiter = ',')
        for row in myreader:
            total_schiller += int(row['NumberSchiller'])
            total_frauSchiller += int(row['NumberFrauSchiller'])
            total_stein += int(row['NumberStein'])
            total_christiane += int(row['NumberChristiane'])

    pie_data = [tuple(["Name"] + ["TotalAmount"]), tuple(["Schiller"]+[total_schiller]),
                tuple(["FrauSchiller"]+[total_frauSchiller]), tuple(["Stein"]+[total_stein]),
                tuple(["Christiane"]+[total_christiane])]

    pprint(pie_data)

    into_csv(pie_data)

def into_csv(liste):
    """writes csv file of the data"""

    with open("../visualizations/data/piechart_data.csv","w") as csvfile:

        writer = csv.writer(csvfile)

        for x in liste:
            writer.writerow(x)

def main():

    file = sys.argv[1]

    create_piechart_data(file)

if __name__ == '__main__':
    main()


print('program begins')
import numpy as np
import matplotlib.pyplot as plt
import time
from numba import jit

def integrand(a, b, x1, x2, y1, y2, z1, z2):
    '''
    Cartesian integral of the six dimensional case with limits a = -lambda and b = lambda
    '''
    tol = 1e-10
    x1 = (b-a)*x1/2 + (b+a)/2  # change of variables for [-1, 1] to [a, b]
    x2 = (b-a)*x2/2 + (b+a)/2
    y1 = (b-a)*y1/2 + (b+a)/2
    y2 = (b-a)*y2/2 + (b+a)/2
    z1 = (b-a)*z1/2 + (b+a)/2
    z2 = (b-a)*z2/2 + (b+a)/2

    r1 = np.sqrt(x1**2+y1**2+z1**2)
    r2 = np.sqrt(x2**2+y2**2+z2**2)

    distance = np.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2))

    if distance > tol:  # checking for singularities
        I = np.exp(-4*(r1+r2))/distance
    else:
        I = 0
    return I

def polar_integrand(a1, b1, a2, b2, r1, r2, t1, t2, p1, p2):
    """
    The spherical integration function which returns the function value of the six dimensional point
    """
    tol = 1e-10

    t1 = (b1-a1)*t1/2 + (b1+a1)/2
    t2 = (b1-a1)*t2/2 + (b1+a1)/2
    p1 = (b2-a2)*p1/2 + (b2+a2)/2
    p2 = (b2-a2)*p2/2 + (b2+a2)/2

    cosb = np.cos(t1)*np.cos(t2) + np.sin(t1)*np.sin(t2)*np.cos(p1-p2)

    r12 = r1**2+r2**2-2*r1*r2*cosb

    if r12 > tol:
        I = np.exp(-3*(r1+r2))*r1**2*r2**2*np.sin(t1)*np.sin(t2)/np.sqrt(r12)
    else:
        I = 0
    return I

def Gauss_leg(n):
    """
    Function which finds the roots and weights of the n-th legendre polynomial.
    """
    L_N = np.zeros(n+1)
    L_N[-1] = 1
    xi = np.polynomial.legendre.legroots(L_N)

    p1 = 1
    p2 = 0
    for j in range(n):
        p3 = p2
        p2 = p1
        p1 = ((2*j+1)*xi*p2 - j*p3)/(j+1)

    pp = n*(xi*p1-p2)/(xi**2-1)
    w = 2/((1-xi**2)*pp**2)

    return xi, w

def Gauss_lag(n):
    """
    Function which finds the roots and weights of the n-th laguerre polynomial.
    """
    L_N = np.zeros(n+1)
    L_N[-1] = 1
    xi = np.polynomial.laguerre.lagroots(L_N)

    p1 = 1
    p2 = 0
    for j in range(n+1):
        p3 = p2
        p2 = p1
        p1 = ((2*j+1-xi)*p2 - j*p3)/(j+1)

    w = xi/((n+1)**2*p1**2)

    return xi, w

if __name__ == '__main__':
    n = np.linspace(3,25,12)
    Leg_I = np.zeros(len(n))
    lamb = 3
    time_spent_leg = np.zeros(len(n))

    for g in range(len(n)):
        N = int(n[g])
        xi, w = Gauss_leg(N)

        a = -lamb
        b = lamb
        start = time.time()
        for i in range(N):  # the six-doubled for-loop to find the integration value
            for j in range(N):
                for k in range(N):
                    for l in range(N):
                        for m in range(N):
                            for h in range(N):
                                Leg_I[g] += w[i]*w[j]*w[k]*w[l]*w[m]*w[h]*integrand(a, b, xi[i], xi[j], xi[k], xi[l], xi[m], xi[h])
            print((i+1)/N*100)

        Leg_I[g] *= ((b-a)/2)**6
        end = time.time()
        time_spent_leg[g] = end-start

    plt.plot(n, Leg_I, 'bo-', label='Gauss Legendre for Cartesian')

    #  Laguerre part

    Lag_I = np.zeros(len(n))
    at = 0; bt = np.pi
    ap = 0; bp = 2 * np.pi
    time_spent_lag = np.zeros(len(n))

    for g in range(len(n)):
        N = int(n[g])
        ri, w_ri = Gauss_lag(N)
        angle, w_angle = Gauss_leg(N)

        start = time.time()
        for i in range(N):  # the six-doubled for-loop to find the integration value
            for j in range(N):
                for k in range(N):
                    for l in range(N):
                        for m in range(N):
                            for h in range(N):
                                Lag_I[g] += w_ri[i] * w_ri[j] * w_angle[k] * w_angle[l] * w_angle[m] * w_angle[h] \
                                        * polar_integrand(at, bt, ap, bp, ri[i], ri[j], angle[k], angle[l], angle[m], angle[h])
            print((i+1)/N*100)
        Lag_I[g] *= ((bt - at) / 2) ** 2 * ((bp - ap)/2)**2
        end = time.time()
        time_spent_lag[g] = end-start

    plt.plot(n, Lag_I, 'ro-', label='Gauss Laguerre for radial')
    plt.axhline(y=5*np.pi**2/16**2)
    plt.xlabel('mesh points, N')
    plt.ylabel('integration value')
    plt.legend()
    plt.show()

    file = open('solution_GQ.txt', 'w') #  Writing our solutions to a text file

    for i in range(len(n)):
        file.write('N=%g, Gauss_leg = %g, time = %g, Gauss_lag = %g, time = %g \n' % (n[i], Leg_I[i], time_spent_leg[i],
                                                                                Lag_I[i], time_spent_lag[i]))


# -*-coding:utf-8-*-
import tensorflow as tf

sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())

def tensor_expand(tensor_Input, Num):
    '''
    张量自我复制扩展，将Num个tensor_Input串联起来，生成新的张量，
    新的张量的shape=[tensor_Input.shape,Num]
    :param tensor_Input:
    :param Num:
    :return:
    '''
    tensor_Input = tf.expand_dims(tensor_Input, axis=0)
    tensor_Output = tensor_Input
    for i in range(Num - 1):
        tensor_Output = tf.concat([tensor_Output, tensor_Input], axis=0)
    return tensor_Output

def get_one_hot_matrix(height, width, position):
    '''
    生成一个 one_hot矩阵，shape=【height*width】，在position处的元素为1，其余元素为0
    :param height:
    :param width:
    :param position: 格式为【h_Index,w_Index】,h_Index,w_Index为int格式
    :return:
    '''
    col_length = height
    row_length = width
    col_one_position = position[0]
    row_one_position = position[1]
    rows_num = height
    cols_num = width

    single_row_one_hot = tf.one_hot(row_one_position, row_length, dtype=tf.float32)
    single_col_one_hot = tf.one_hot(col_one_position, col_length, dtype=tf.float32)
    print(single_row_one_hot.eval())
    print(single_col_one_hot.eval())
    one_hot_rows = tensor_expand(single_row_one_hot, rows_num)
    one_hot_cols = tensor_expand(single_col_one_hot, cols_num)
    print(one_hot_rows.eval())
    print(one_hot_cols.eval())
    one_hot_cols = tf.transpose(one_hot_cols)
    print('trans:', one_hot_cols.eval())

    one_hot_matrx = one_hot_rows * one_hot_cols
    print(one_hot_matrx.eval())
    return one_hot_matrx

def tensor_assign_2D(tensor_input, position, value):
    '''
    给 2D tensor的特定位置元素赋值
    :param tensor_input: 输入的2D tensor，目前只支持2D
    :param position: 被赋值的张量元素的坐标位置，=【h_index,w_index】
    :param value:
    :return:
    '''
    shape = tensor_input.get_shape().as_list()
    height = shape[0]
    width = shape[1]
    h_index = position[0]
    w_index = position[1]
    one_hot_matrix = get_one_hot_matrix(height, width, position)
    #print(one_hot_matrix.eval())
    #print(tensor_input.eval())
    #print(tensor_input[h_index, w_index].eval())
    #print(value)
    #print((one_hot_matrix * value).eval())
    new_tensor = tensor_input - tensor_input[h_index, w_index] * one_hot_matrix + one_hot_matrix * value

    return new_tensor

import tensorflow as tf
import numpy as np

batch_size = 10
max_len = 2
dim = 3

'''
def integrate(integrate_input):
    Xy = integrate_input[0]
    Yx = integrate_input[1]
    #print(Xy.eval())
    #print(Yx.eval())
    #assert dimensions_equal(Xy.shape, (max_len, dim,))
    #assert dimensions_equal(Xy.shape, (max_len, dim,))
    outputs = tf.concat([Xy, Yx], 1)
    #print(outputs.eval())
    return outputs
'''

def integrate(Xy,Yx):
    #print(Xy.eval())
    #print(Yx.eval())
    #assert dimensions_equal(Xy.shape, (max_len, dim,))
    #assert dimensions_equal(Xy.shape, (max_len, dim,))
    #outputs = tf.concat([Xy, Yx], 1)
    #print(outputs.eval())
    #outputs = Xy * np.transpose(Yx)
    #outputs = Xy * tf.transpose(Yx)
    #outputs = Xy * Yx

    outputs = Xy + Yx
    return outputs

'''
def integrate(integrate_input):
    outputs = integrate_input * 2.0
    return outputs
'''

def my_fn(x, y):
    return x * y

def max_sentence_similarity(sentence_input, similarity_matrix):
    """
    Parameters
    ----------
    sentence_input: Tensor
        Tensor of shape (batch_size, num_sentence_words, rnn_hidden_dim).
    similarity_matrix: Tensor
        Tensor of shape (batch_size, num_sentence_words, num_sentence_words).
    """
    # Shape: (batch_size, passage_len)
    def single_instance(inputs):
        single_sentence = inputs[0]
        argmax_index = inputs[1]
        # Shape: (num_sentence_words, rnn_hidden_dim)
        return tf.gather(single_sentence, argmax_index)

    question_index = tf.arg_max(similarity_matrix, 2)
    elems = (sentence_input, question_index)
    # Shape: (batch_size, num_sentence_words, rnn_hidden_dim)
    return tf.map_fn(single_instance, elems, dtype="float")

if __name__ == "__main__":
    '''
    a = np.array([[1, 2, 3], [2, 4, 1], [5, 1, 7]])
    b = np.array([[1, -1, -1], [1, 1, 1], [-1, 1, -1]])
    #print(a)
    print(a.shape)
    #print(b)
    print(b.shape)
    elems = (a, b)

    B = tf.map_fn(lambda x: my_fn(x[0], x[1]), elems, dtype=tf.int64)
    print(B.eval())
    exit(0)
    '''

    '''
    elems = np.array([1, 2, 3, 4, 5, 6])
    squares = tf.map_fn(lambda x: x * x, elems)
    # squares == [1, 4, 9, 16, 25, 36]

    elems = (np.array([1, 2, 3]), np.array([-1, 1, -1]))
    alternate = tf.map_fn(lambda x: x[0] * x[1], elems, dtype=tf.int64)
    print(alternate)
    print(alternate.eval())
    # alternate == [-1, 2, -3]

    elems = np.array([1, 2, 3])
    alternates = tf.map_fn(lambda x: (x, -x), elems, dtype=(tf.int64, tf.int64))
    print(alternates)
    for alternate in alternates:
        print(alternate.eval())
    # alternates[0] == [1, 2, 3]
    # alternates[1] == [-1, -2, -3]
    exit(0)
    '''
    ##test
    '''
    tensor_input = tf.constant([i for i in range(20)], tf.float32)
    tensor_input = tf.reshape(tensor_input, [4, 5])
    print(tensor_input.eval())

    new_tensor = tensor_assign_2D(tensor_input, [2, 3], 100)
    print(new_tensor.eval())
    '''
    # 若inputs1,inputs2的shape为[batch_size,max_len,dim]
    # map_fn将inputs1、inputs2按第0维展开
    # 每次执行integrate时，Xy的shape为[max_len, dim]
    inputs1 = np.ones((batch_size, max_len, dim), dtype='float32')
    #inputs1 = np.ones((batch_size, max_len), dtype='float32')
    inputs1 = 2.0 * inputs1
    print(inputs1.shape)
    #inputs1 = tf.constant(2.0 * inputs1)
    inputs2 = np.ones((batch_size, max_len, dim), dtype='float32')
    #inputs2 = np.ones((batch_size, max_len), dtype='float32')
    inputs2 = 3.0 * inputs2
    print(inputs2.shape)
    #inputs2 = tf.constant(3.0 * inputs2)
    #print(inputs1.eval())
    #print(inputs2.eval())
    #outputs = tf.map_fn(integrate, (inputs1, inputs2), dtype=(tf.float32, tf.float32))
    '''
    inputs = np.concatenate([inputs1, inputs2], axis=-1)
    inputs = tf.constant(inputs1)
    outputs = tf.map_fn(integrate, inputs, dtype=tf.float32)
    print(outputs.eval())
    '''
    #outputs = tf.map_fn(integrate, (inputs1, inputs2), dtype=(tf.float32, tf.float32))
    outputs = tf.map_fn(lambda x: integrate(x[0], x[1]), (inputs1, inputs2), dtype=(tf.float32, tf.float32))# dtype=tf.float32, dtype=(tf.float32, tf.float32)
    print(outputs.eval())


import discord
from discord.ext import commands
import asyncio
import time
import os
from discord.ext.commands import cooldown, BucketType
from discord.ext import commands
from discord.utils import get
import requests
from discord import CategoryChannel
import json

prefix = '?'
client = commands.Bot(command_prefix=prefix)
TOKEN = ''
SELLIXAPI = ''
MERCHANT = ''

with open('product_config.json', 'r') as f:
    PRODUCTDATA = json.load(f)

@client.event
async def on_ready():
    os.system('cls')
    print('Bot launched as {0.user}'.format(client))
    print('Prefix is {prefix}'.format(prefix))

@client.command()
async def claim(ctx, *, arg):
    if ctx.channel.type == discord.ChannelType.private:

        with open('oldorders.txt', 'r') as f:
            if arg in f.read():

                await ctx.send('Order already claimed!')
                await ctx.send('Verifying order...')

                headers = {
                    'Authorization': 'Bearer ' + SELLIXAPI,
                    'X-Sellix-Merchant': MERCHANT
                }

                r = requests.get('https://dev.sellix.io/v1/orders/' + arg, headers=headers)
                sellix = r.json()

                if sellix['error'] == 'Invoice Not Found':
                    await ctx.send('Order not found.')
                else:
                    if sellix['status'] == 200:

                        order_product = sellix['data']['order']['product_title']

                        for i in PRODUCTDATA:
                            if i['product'] == order_product:
                                await ctx.send('Order found, claiming...')
                                await ctx.send('Order is for {product}'.format(product=order_product))
                                with open('oldorders.txt', 'a') as f:
                                    f.write(arg + '\n')
                                filename = i['file']
                                await ctx.send(file=discord.File(filename))
                                await ctx.send('Enjoy!')

                    else:
                        await ctx.send('Failure while checking order, please contact support. Error code: ' + sellix['status'])
    else:
        await ctx.send('Please DM me to claim!')

client.run(TOKEN)


#creating a thread without using a class
from threading import *

#creating function
def display():
    print('love you')
 #creating a thread and run function for 100 times
for i in range(100):
    t=Thread(target=display)
    t.start()


import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

class Db(object):
    def __init__(self, database, logger):
        self.connection = sqlite3.connect(database)
        self.connection.row_factory = dict_factory
        self.connection.execute('PRAGMA FOREIGN_KEYS=ON')
        self.logger = logger

    def close(self):
        self.connection.close()

    def insert_task(self, directory_key, task_type):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                INSERT INTO task
                (directory_key, type)
                VALUES (?, ?)""", (directory_key, task_type))
                self.logger.info('Insert task success.')
                connection.commit()
                return cursor.lastrowid
            except Exception as e:
                self.logger.error(e)
                connection.rollback()
                return 0
            finally:
                cursor.close()

    def insert_images(self, task_id, image_keys, annotations=None):
        if annotations is None:
            annotations = map(lambda _: None, image_keys)
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.executemany("""
                INSERT INTO image
                (task_id, image_key, annotation)
                VALUES (?, ?, ?)""",
                [(task_id, image_key, annotation) for (image_key, annotation) in zip(image_keys, annotations)])
                connection.commit()
                self.logger.info('Insert images success.')
                return cursor.rowcount
            except Exception as e:
                self.logger.error(e)
                connection.rollback()
                return 0
            finally:
                cursor.close()

    def select_tasks(self):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                SELECT id task_id, directory_key, create_time
                FROM task
                ORDER BY task_id DESC""")
                self.logger.info('Select tasks success.')
                return cursor.fetchall()
            except Exception as e:
                self.logger.error(e)
                return []
            finally:
                cursor.close()

    def select_tasks_with_id(self, task_id):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                SELECT id task_id, directory_key, type, create_time
                FROM task
                WHERE id = ?""", (task_id,))
                self.logger.info('Select tasks success.')
                return cursor.fetchall()
            except Exception as e:
                self.logger.error(e)
                return []
            finally:
                cursor.close()

    def delete_tasks_with_id(self, task_id):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                DELETE FROM image
                WHERE task_id = ?""", (task_id,))
                cursor.execute("""
                DELETE FROM task
                WHERE id = ?""", (task_id,))
                self.logger.info('Delete tasks success.')
                return cursor.rowcount
            except Exception as e:
                self.logger.error(e)
                return None
            finally:
                cursor.close()

    def select_images_with_task(self, task_id, limit=None, offset=0):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cmd = """
                SELECT id image_id, image_key, selected
                FROM image
                WHERE task_id = ?
                ORDER BY image_id ASC
                """
                args = [task_id,]
                if limit:
                    cmd += 'LIMIT ? '
                    args.append(limit)
                    if offset:
                        cmd += 'OFFSET ? '
                        args.append(offset)
                cursor.execute(cmd, args)
                self.logger.info('Select images success.')
                return cursor.fetchall()
            except Exception as e:
                self.logger.error(e)
                return []
            finally:
                cursor.close()

    def select_selected_images_with_task(self, task_id):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                SELECT image_key
                FROM image
                WHERE selected = 1
                AND task_id = ?
                ORDER BY id ASC""", (task_id,))
                return cursor.fetchall()
            except Exception as e:
                self.logger.error(e)
                return []
            finally:
                cursor.close()

    def select_images_with_id(self, image_id):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                SELECT id image_id, image_key, selected, task_id, annotation
                FROM image
                WHERE image_id = ?""", (image_id,))
                self.logger.info('Select images success.')
                return cursor.fetchall()
            except Exception as e:
                self.logger.error(e)
                return []
            finally:
                cursor.close()

    def update_image_selection(self, image_id, selected):
        with self.connection as connection:
            cursor = connection.cursor()
            try:
                cursor.execute("""
                UPDATE image
                SET selected = ?
                WHERE id = ?""", (selected, image_id))
                self.logger.info('Update image success.')
                connection.commit()
                return cursor.rowcount
            except Exception as e:
                self.logger.error(e)
                return 0
            finally:
                cursor.close()


# coding: utf8
import pickle
import csv
import random

original_dataset = 'data_good_domain_middle.csv'
output_file = 'dataset_mini_100.csv'

def minidata_pickle():

    f = open('data_good_domain_middle.csv', 'r')
    reader = csv.reader(f)
    listn = []
    listd = []
    with open('good_domain.pickle', mode='rb') as fgd:
        gd = pickle.load(fgd)
    for i, row in enumerate(reader):
        if not ('@' in row[8]):
            continue
        domain = row[8].split('@')
        if '"]' in domain[1]:
            domain1 = domain[1].split('"]')
        if '","' in domain1[0]:
            domain1 = domain1[0].split('","')
        domain = domain1[0]
        domain = '@' + domain
        if not (domain in gd):
            continue
        if row[0] in listn:
            continue
        listn.append(row[0])
        listd.append(row)

    return listd

def minidata100(listd):

    fw = open('data_good_domain_mini_100_3.csv', 'w')
    writer = csv.writer(fw)

    random.shuffle(listd)
    new_list = []
    for i, row in enumerate(listd):
        new_list.append(row)
        if len(new_list) == 100:
            break

    writer.writerows(new_list)

listd = minidata_pickle()
minidata100(listd)


"""Here will hopefully lie the code that takes overall
rocket params and turns them into weights! Currently just copypasted what I have from matlab
and full of errors and over-simplifications
when you rewrite, fill out mass_approx_new and then rename it to mass_approx and
change mass_approx to mass_approx_OLD"""
import sys
sys.path.insert(1,"./")
import math
from Toolbox.Constant import psiToPa, lbToKg
from Components.Component import Component
import os
import Toolbox.Constant as const

class StructuralApproximation(Component):

    def __init__(self,params, OD): #od of rocket in inches (legacy)
        self.mis, self.lambdas, self.totalmasses, self.wstruct,\
        self.newheight, self.heightox, self.heightfuel, \
        self.vol_ox, self.vol_fuel, self.PTanks = mass_approx(params['pc'],
        params['dp'], OD, params['rho_fuel'],params['rho_ox'], params['thrust'], params['isp'], params['time'], params['rm'])
        self.oxpd, self.fuelpd, self.dparray = pressureDrop(OxDensityMetric = params['rho_ox'],     # kg/m^3
                                        OxMassFlowMetric = params['mdot_ox'], # kg/s
                                        OxTubeDiam = 3/4, #in
                                        FuelDensityMetric = params['rho_fuel'],       # kg/m^3
                                        FuelMassFlowMetric = params['mdot_fuel'],# kg/s
                                        FuelTubeDiam = 3/4 ,
                                        params = params               )

    def Equilibrium(self,params, OD):
        self.mis, self.lambdas, self.totalmasses, self.wstruct,\
        self.newheight, self.heightox, self.heightfuel, \
        self.vol_ox, self.vol_fuel, self.PTanks = mass_approx(params['pc'],
        params['dp'], OD, params['rho_fuel'],params['rho_ox'], params['thrust'], params['isp'], params['time'], params['rm'])
        self.oxpd, self.fuelpd, self.dparray = pressureDrop(OxDensityMetric = params['rho_ox'],     # kg/m^3
                                        OxMassFlowMetric = params['mdot_ox'], # kg/s
                                        OxTubeDiam = 3/4, #in
                                        FuelDensityMetric = params['rho_fuel'],       # kg/m^3
                                        FuelMassFlowMetric = params['mdot_fuel'],# kg/s
                                        FuelTubeDiam = 3/4 ,
                                        params = params               )
def mass_approx(Pc,dp, OD, rho_f,rho_ox, thrust, isp, burntime, rm, printoutput=False, outputdir = ""):
    try:
        fueldp = dp[0]
        oxdp = dp[1]
    except:
        fueldp = dp
        oxdp = dp
        print('YOU SHOULD BE PASSING SEPERATE DPS')
    strcutresweight = 50.6*lbToKg;
    propweight =89.72*lbToKg;
    cfuelweight =5.3*lbToKg;
    coxweight=16.7 *lbToKg;
    cpresweight=14.5*lbToKg;
    cpressys= 12.21*lbToKg;
    cfoxhole=7.7*lbToKg;
    cav=15.03*lbToKg;
    cTC=16.66 *lbToKg;
    currentheight = 253.47*.0254;
    fuelheight=8.72*.0254;
    oxheightcurrent=37.824*.0254;
    presheightcurrent=16*.0254;

    diam_tank	= (OD-.1
                    )*.0254;
    ulox	 =0.05;
    ulfuel	=0.05;
    ulpres	=0.1;
    mf = thrust/isp/9.81; #just pass mass flow rate
    mf_ox=(rm*mf/(rm+1));
    mf_fuel = mf/(rm+1);
    vol_ox	= mf_ox*burntime/rho_ox;
    vol_fuel	= mf_fuel*burntime/rho_f;
    P_pres =	4500*psiToPa;
    P_tank_fuel =	Pc+fueldp;
    P_tank_ox = Pc+oxdp
    vol_pres = (P_tank_fuel*vol_fuel)/(P_pres-P_tank_fuel)+(P_tank_ox*vol_ox)/(P_pres-P_tank_ox); #compresasbility

    heightox	=(vol_ox/(1-ulox))/(math.pi*(diam_tank/2)**2);
    heightfuel	=(vol_fuel/(1-ulfuel))/(math.pi*(diam_tank/2)**2);
    heightpres	=(vol_pres/(1-ulpres))/(math.pi*(diam_tank/2)**2);

    Sy = 40000*psiToPa;
    Fs	=2;
    rho_tank =	2710 #kg/m3
    t_prop_fuel	=P_tank_fuel*diam_tank/(2*Sy)*Fs;
    t_prop_ox	=P_tank_ox*diam_tank/(2*Sy)*Fs;
    t_pres	=P_pres*diam_tank/(2*Sy)*Fs;

    weight_f	=((math.pi*diam_tank*heightfuel)+2*math.pi*(diam_tank/2)**2)*t_prop_fuel*rho_tank;
    weight_ox	=((math.pi*diam_tank*heightox)+2*math.pi*(diam_tank/2)**2)*t_prop_ox*rho_tank;
    weight_pres	=((math.pi*diam_tank*heightpres)+2*math.pi*(diam_tank/2)**2)*t_pres*rho_tank;

    massFuelTank = 0
    massOxTank = 0
    while abs(weight_f-massFuelTank)>.01:
        weight_f=massFuelTank
        weight_ox=massOxTank
        newheight=(currentheight-(fuelheight+oxheightcurrent+presheightcurrent))*8/OD+(heightox+heightfuel+heightpres);#(currentheight-(fuelheight+oxheightcurrent+presheightcurrent))*OD/8+(heightox+heightfuel+heightpres);
        Saratio=(newheight*math.pi/4*OD**2)/(currentheight*math.pi/4*8**2); #GET RID OF THIS
        mdotratio=mf/(4.72*0.453592);
        Pratio_prop=P_tank_ox/(950*psiToPa);
        Pratio_pres=P_pres/(4500*psiToPa);

        global wtc, wav, wfox, wpresys, wpres, whelium, wstruct

        wtc= (57+11) * lbToKg# mdotratio*(cTC);
        wav = (47+.5*13)*lbToKg # mdotratio*Pratio_prop*(cav); # FIX ALL THESE
        wfox= 0 #mdotratio*Pratio_prop*(cfoxhole);
        wpresys=0       #mdotratio*Pratio_pres*cpressys;
        wpres=(82+.5*30) * lbToKg #(vol_pres/0.0055217851)*cpresweight; #make sure this is in metric
        whelium=vol_pres*44.472*P_pres/(31.02*10**6); # this is denisty from refprop for 4500 psi

        # # Ideally You would use these not an overall structures weight
        massNoseCone =  15*lbToKg #11.83*lbToKg # THIS IS A GUESS
        massFins = 40*lbToKg # THIS IS ALSO A GUESS
        massRecovery = 41* lbToKg # 10 # THIS IS ALSO A GUESS
        massRecoveryCoupler = 8*lbToKg;
        massPayloadCoupler = 8 * lbToKg #2.49;
        massAirFrames = 35*lbToKg #  19.962*newheight/currentheight #air frames mass scales with height!?
        massPayload = 3
        wstruct=110 #massPayload+massAirFrames+massPayloadCoupler+massRecovery+massRecoveryCoupler+massFins+massNoseCone
        # massAVCoupler = 0;
        # massParachuteShroud = 0;
        # massAvionicsShroud = 0;
        # massAvionicsShroud = 0;
        # massIntertankBay1Shroud = 0;

        #wstruct=Saratio*strcutresweight#1.369*Saratio*strcutresweight; #The factor for structural weight is in the error in newheight estimate lol its like 1.2

        # BREAK DOWN STUCTURES WEIGHT INTO COMPONENTS
        oxTankThickness,fuelTankThickness, heightfuel, heightox, massOxTank, \
        massFuelTank,fuelTankLengthTotal,oxTankLengthTotal = MetalTankMasses((OD)*0.0254, P_tank_fuel, P_tank_ox, weight_ox, vol_ox,vol_fuel, mf_ox*burntime)

    weight_f=massFuelTank + 15 * lbToKg
    weight_ox = massOxTank + 15 * lbToKg
    mass_avionics = 10*lbToKg

    mis=wtc+wav+wfox+wpresys+wpres+wstruct+weight_f+weight_ox+whelium + mass_avionics; #80 + .7*weight_f+.7*weight_ox
    fuelmass=mf_fuel*burntime;
    oxmass=mf_ox*burntime;
    lambdas=(fuelmass+oxmass)/(mis+fuelmass+oxmass);
    totalmasses=fuelmass+oxmass+mis;

    return mis, lambdas, totalmasses, wstruct, newheight, heightox, heightfuel, vol_ox, vol_fuel, [P_tank_fuel, P_tank_ox]

def mass_approx_NEW():
    """Feel free to use whatever you want as inputs, though try to keep it limited
    and to things that can be calculated from first order calcs
    inputs : chamber pressure, thrust, burntime, propellant props, whatever else
    outputs : dry mass, mass fraction, total mass
    Note that in the matlab version i had this working with matrices to do optimization faster
    Idk if thats something we want to pursue in python so you can hjust reutrn doubles"""

#function [oxTankThickness,fuelTankThickness, fuelLength, oxLength, massOxTank, massFuelTank,fuelTankLengthTotal,oxTankLengthTotal] = MetalTankMasses(OD,tP,massOxTankGuess,oxVol,fuelVol)
def MetalTankMasses(OD,tP_PA_f, tP_PA_o,massOxTankGuess,oxVol,fuelVol, oxWeight):
    """
    Inputs:
    OD = Tank OD [m]
    tP_PA_f = Tank Pressure [pa] for fuel tnak
    tP_PA_o = Tank Pressure [pa] for ox tnak
    oxVol = volume for ox tank
    fuelVol = volume for fuel tank
    """

    # Calculating Load Conditions
    # Pressure
    tankOuterRadius = OD/2; # Tank OR from OD
    YieldStrength_Aluminum6061 = 241*10**6; # PA (different for cryo, just using normal for now)
    FOS = 2;    # Based on IREC Requirnments for COPV's - Subject to change
    maxStress = YieldStrength_Aluminum6061/FOS;
    maxGs = 7;

    # Axial Loading
    # Mass Assumptions (kg)
    massAvBayPlumbing = wav
    massFoxHolePlumbing = wfox
    massPressTank = wpres
    massPressSystem = wpresys
    massHelium = whelium
    massStructures = wstruct # whole rocket - ideally you would only consider structures above each tank

    #fuelWeight = 102;
    #oxWeight = 213.45;

    # # Ideally You would use these not an overall structures weight
    # massNoseCone = 0;
    # massFins = 0;
    # massRecovery = 0;
    # massRecoveryCoupler = 0;
    # massPayloadCoupler = 2.49;
    # massAVCoupler = 0;
    # massParachuteShroud = 0;
    # massAvionicsShroud = 0;
    # massAvionicsShroud = 0;
    # massIntertankBay1Shroud = 0;
    # massOverFuel = massNoseCone + massPayloadCoupler + massParachuteShroud + ...
    # massRecoveryCoupler + massAvBayPlumbing + massAvionicsShroud + massPressTank+ massHelium + massPressSystem;
    # massOverOx = massOverFuel + massFoxHolePlumbing + massIntertankBay1Shroud;

    massOverFuel = massStructures + massAvBayPlumbing + massPressTank+ massHelium + massPressSystem ;
    massOverOx = massOverFuel + massFoxHolePlumbing + oxWeight + massOxTankGuess;

    # Axial Load From mass estimates
    OxAxialLoad = massOverOx*maxGs*9.8; # N
    FuelAxialLoad = massOverFuel*maxGs*9.8; # N

    # Calculate Tank Thickness
    oxTankThickness = thinWallTankThicknessApproximation(maxStress,OxAxialLoad,tP_PA_o,tankOuterRadius);
    fuelTankThickness = thinWallTankThicknessApproximation(maxStress,FuelAxialLoad,tP_PA_f,tankOuterRadius);

    # Find Tank IR
    fuelTankIR = tankOuterRadius-fuelTankThickness;
    oxTankIR = tankOuterRadius-oxTankThickness;

    # Internal Length From Volume
    oxLength = oxVol/(math.pi*(oxTankIR)**2);
    fuelLength = fuelVol/(math.pi*(fuelTankIR)**2);

    # Tank Mass
    massBulkhead = 6.57; # kg, i have to believe this
    massOxTube = massCylinder(oxTankIR,tankOuterRadius,oxLength);
    massFuelTube = massCylinder(fuelTankIR,tankOuterRadius,fuelLength);
    massOxTank = 2*massBulkhead+massOxTube;
    massFuelTank = 2*massBulkhead+massFuelTube;

    # Tank Heights with bulkhead (approximate)
    bulkheadLengthAboveTube = .17;  # m
    oxTankLengthTotal = bulkheadLengthAboveTube*2 + oxLength;
    fuelTankLengthTotal = bulkheadLengthAboveTube*2 + fuelLength;
    return oxTankThickness,fuelTankThickness, fuelLength, oxLength, massOxTank, massFuelTank,fuelTankLengthTotal,oxTankLengthTotal
    # Uniform internal pressure q (ends capped) + Axial Load
    # Inputs: maximum yield strength of material (includes factor of safety),
    # Max Operating pressure, estimated axial load, tank radius
    # Outputs: Approximate tank wall thickness
def thinWallTankThicknessApproximation(maxSigma,AxialLoad,MEOP,R):
    q = MEOP;
    p = AxialLoad;
    tAxial = (1/maxSigma) * (q*R/2+p);
    tHoop = q*R/maxSigma;
    thickness = max([tAxial,tHoop]); #Does this make sense? why arent we doing vector sum
    return thickness
# Inputs: Inner Radius and Outer Radius of tank
def massCylinder(IR,OR,length):
    density = 2720; # kg/m**3
    Area = math.pi*(OR**2-IR**2);
    mass = Area*length*density; # kg
    return mass

def pressureDrop(OxDensityMetric = 1090.79390625913,     # kg/m^3
    OxMassFlowMetric = 4.09234712442909, # kg/s
    OxTubeDiam = 3/4, #in
    FuelDensityMetric = 843.4,       # kg/m^3
    FuelMassFlowMetric = 3.28127,# kg/s
    FuelTubeDiam = 3/4     ,
    params = None           ):# in

    if params is None:
        params = {'pc' : 300*const.psiToPa}

    pi = math.pi # lol matlab
    OxLength = 2;                           # length of plumbing line in feet
    OxViscosity = 1015.24 / 1000;           # micropoise to centipoise

               # kg/s

    FuelLength = 10;                        # ft
    FuelViscosity = 1.095;                  # centipoise, approximated as 100% ethanol

    bendRatio = 3;                          # radius of bend / diameter of tube;
                                            # r/d decreases with increased tube size. 3 is an estimate

        # Constants
    g = 32.174; # ft/s^2
    roughness = 0.015 / 304.8; # absolute roughness of stainless steel tubing, input mm, output ft

        # Calculated Variables
    OxDensity = OxDensityMetric/16.018; # lb/ft^3
    OxTubeDiamMetric = OxTubeDiam/39.37; #in to meters
    OxTubeAreaMetric = (pi/4)*(OxTubeDiamMetric**2); #m^2
    OxVelocityFlowMetric = OxMassFlowMetric/(OxDensityMetric * OxTubeAreaMetric); #m/s
    OxVelocityFlow = OxVelocityFlowMetric*3.281;
    OxReynold = 124*OxTubeDiam*OxVelocityFlow*OxDensity/OxViscosity;

    FuelDensity = FuelDensityMetric/16.018; # lb/ft^3
    FuelTubeDiamMetric = FuelTubeDiam/39.37; #in to meters
    FuelTubeAreaMetric = (pi/4)*(FuelTubeDiamMetric**2); #m^2
    FuelVelocityFlowMetric = FuelMassFlowMetric/(FuelDensityMetric * FuelTubeAreaMetric); #m/s
    FuelVelocityFlow = FuelVelocityFlowMetric*3.281;
    FuelReynold = 124*FuelTubeDiam*FuelVelocityFlow*FuelDensity/FuelViscosity;

    # Friction Coefficient f & K(Crane 410 Page X)
    Oxf = 0.25/(math.log(roughness/(3.7*OxTubeDiam/12) + 5.74/(OxReynold**0.9)))**2;
    OxfTurb = 0.25/(math.log(roughness/(3.7*OxTubeDiam/12)))**2;

    KOxElbow = 30*OxfTurb;
    KOxBend = 12*OxfTurb; # Tabularly depends on bend radius (See page
    KOxBallValve = 3*OxfTurb;
    KOxCheckValve = 420*OxfTurb;
    KOxEnter = 0.78;
    KFuelExit = 1.0;

    KOx = KOxEnter + KOxBallValve + KOxCheckValve + KFuelExit;

    Fuelf = 0.25/(math.log(roughness/(3.7*OxTubeDiam/12) + 5.74/(FuelReynold**0.9)))**2;
    FuelfTurb = 0.25/(math.log(roughness/(3.7*FuelTubeDiam/12)))**2;

    KFuelElbow = 30*FuelfTurb;
    KFuelBend = 12*FuelfTurb;
    KFuelBallValve = 3*FuelfTurb;
    KFuelCheckValve = 420*FuelfTurb;
    KFuelEnter = 0.78;
    KFuelExit = 1.0;

    KFuel = KFuelEnter + 2*KFuelBend + KFuelBallValve + KFuelCheckValve + KFuelExit;

    # Pressure Drop (Crane 410 Page 6-4, Equation 6-22)
    OxPressureDropFriction = 0.001295*Oxf*OxLength*OxDensity*(OxVelocityFlow**2)/OxTubeDiam;
    OxPressureDropFittings = (OxDensity/144)*(KOx)*(OxVelocityFlow**2)/(2*g);

    OxPressureDropTotal = OxPressureDropFriction + OxPressureDropFittings

    FuelPressureDropFriction = 0.001295*Fuelf*FuelLength*FuelDensity*(FuelVelocityFlow**2)/FuelTubeDiam;
    FuelPressureDropFittings = (FuelDensity/144)*(KFuel)*(FuelVelocityFlow**2)/(2*g);

    FuelPressureDropTotal = FuelPressureDropFriction + FuelPressureDropFittings

    dparray =  [(params['pc']*.2 + 50*const.psiToPa + FuelPressureDropTotal)*1.5, (params['pc']*.2 + OxPressureDropTotal)*1.5]
    dparray = [150*const.psiToPa, 150*const.psiToPa]
    return OxPressureDropTotal, FuelPressureDropTotal, dparray
        # Note: pressureDropFriction is based on wall friction due to length of
        # straight pipe. pressureDropFittings is due to the turbulence caused
        # by the flow obstruction of internal geometries. It is not clear
        # whether the length of the fittings should be subtracted from
        # pressureDropFriction, or if the double-calculation is necessary.


import time
from turtle import Screen
from paddle import Paddle
from Ball import Ball
from Score import Score

game_is_on = True
screen = Screen()
screen.setup(width=800, height=600)
screen.bgcolor("black")
screen.title("Peddle Game")

paddle1 = Paddle(370, 0)
paddle2 = Paddle(-375, 0)
ball = Ball()
score = Score()

screen.listen()
screen.onkeypress(key="w", fun=paddle2.up)
screen.onkeypress(key="s", fun=paddle2.down)
screen.onkeypress(key="o", fun=paddle1.up)
screen.onkeypress(key="k", fun=paddle1.down)

screen.tracer()

while game_is_on:
    ball.move_ball()

    if ball.ycor() > 280 or ball.ycor() < -280:
        ball.bounce()

    if ball.xcor() > 380:
        score.increase_l_ply_s()
        ball.reset_ball()

    elif ball.xcor() < -380:
        score.increase_r_ply_s()
        ball.reset_ball()

    if (ball.distance(paddle1) < 50 and ball.xcor() > 340) or (ball.distance(paddle2) < 50 and ball.xcor() < -340):
        ball.bounce_from_paddle()

screen.exitonclick()