from domain.domain import Question
from repository.repository import QuestionRepo
from service.service import QuestionService, QuizNotPossibleException

class InvalidInputException(Exception):
    pass

class ConsoleUI:
    def __init__(self):
        self._repo = QuestionRepo()
        self._service = QuestionService(self._repo)

    def invalid_input_message(self):
        print("\nInvalid input!")

    def impossible_quiz_required(self):
        print("\nCould not create the requied quiz!")

    def quiz_not_existent(self):
        print("\nThe required quiz does not exist!")

    def execute_user_command(self):
        user_command = input("\n>> ").strip()

        tokens = user_command.split(' ')

        if tokens[0] not in ['add', 'create', 'start', 'exit']:
            raise InvalidInputException

        if tokens[0] == 'add':
            arguments = tokens[1].split(';')

            if len(arguments) != 7:
                raise InvalidInputException

            if not arguments[0].isnumeric():
                raise InvalidInputException

            if arguments[-1] not in ['easy', 'medium', 'hard']:
                raise InvalidInputException

            if arguments[-2] not in [arguments[-3], arguments[-4], arguments[-5]]:
                raise InvalidInputException

            self._service.add_question(arguments)

        elif tokens[0] == 'create':
            if len(tokens) != 4:
                raise InvalidInputException

            difficulty = tokens[1]
            number_of_questions = tokens[2]
            filename = tokens[3]

            if difficulty not in ['easy', 'medium', 'hard']:
                raise InvalidInputException

            if not number_of_questions.isnumeric():
                raise InvalidInputException

            try:
                self._service.create_quiz(difficulty, int(number_of_questions), filename)
            except QuizNotPossibleException:
                self.impossible_quiz_required()

        elif tokens[0] == 'start':
            # Take the quiz.
            filename = tokens[1]

            score = 0

            try:
                open_file = open(f"src/{filename}", 'r')

                lines = open_file.readlines()

                quiz_list = []

                for line in lines:
                    arguments = line.strip().split(';')
                    if len(arguments) == 7:
                        new_question = Question(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6])
                        quiz_list.append(new_question)

                for question in quiz_list:
                    print(question.format_question())
                    user_choice = input("\nYour answer(the index): ").strip()

                    while user_choice not in ['1', '2', '3']:
                        self.invalid_input_message()
                        user_choice = input("\nYour answer(the index): ").strip()

                    user_answer = question.choice_a
                    if user_choice == '2':
                        user_answer = question.choice_b
                    elif user_choice == '3':
                        user_answer = question.choice_c

                    if user_answer == question.correct_choice:
                        if question.difficulty == 'easy':
                            score += 1
                        elif question.difficulty == 'medium':
                            score += 2
                        elif question.difficulty == 'hard':
                            score += 3

                print(f"\n\tYour score: {score}")

            except OSError:
                self.quiz_not_existent()

        elif tokens[0] == 'exit':
            return not None

    def start(self):
        while True:
            while True:
                try:
                    run = self.execute_user_command()
                    break
                except InvalidInputException:
                    self.invalid_input_message()

            if run is not None:
                break


import os
from flask import (
    Flask,
    render_template,
    request,
    redirect,
    url_for,
    send_from_directory,
)
from werkzeug.utils import secure_filename
from pypdf import PdfReader, PdfWriter

if os.name == "nt":
    UPLOAD_FOLDER = f"{str(os.getcwd())}\\uploads"
    DOWNLOAD_FOLDER = f"{str(os.getcwd())}\\downloads"
elif os.name == "posix":
    UPLOAD_FOLDER = f"{str(os.getcwd())}/uploads"
    DOWNLOAD_FOLDER = f"{str(os.getcwd())}/downloads"

ALLOWED_EXTENSIONS = {"pdf"}

app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
app.config["DOWNLOAD_FOLDER"] = DOWNLOAD_FOLDER
app.config["MAX_CONTENT_LENGTH"] = 64 * 1000 * 1000

def allowed_file(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route("/", methods=["GET"])
def index():
    delete_files()
    return render_template("index.html")

@app.route("/split", methods=["POST"])
def split_pdf():
    if "pdf_file" not in request.files:
        return render_template("index.html", error_message="No file selected.")

    file = request.files["pdf_file"]

    if file.filename == "":
        return render_template("index.html", error_message="No file selected.")

    if not allowed_file(file.filename):
        return render_template(
            "index.html", error_message="Invalid file format. Only PDF files allowed."
        )

    file_path = os.path.join(
        app.config["UPLOAD_FOLDER"], secure_filename(file.filename)
    )
    file.save(file_path)

    try:
        pdf = PdfReader(file_path)

        # Split the PDF into individual pages
        for page_number in range(len(pdf.pages)):
            output = PdfWriter()
            output.insert_page(pdf.pages[page_number], page_number + 1)

            # Save each page as a separate PDF
            output_filename = f"page_{page_number + 1}.pdf"
            output_path = os.path.join(app.config["DOWNLOAD_FOLDER"], output_filename)
            with open(output_path, "wb") as output_file:
                output.write(output_file)
                output_file.close()

        delete_uploads()
        return redirect(url_for("download"))

    except Exception as e:
        return render_template(
            "index.html",
            error_message="An unexpected error occurred.",
        )

@app.route("/merge", methods=["POST"])
def merge_pdf():
    uploaded_files = request.files.getlist("pdf_files[]")

    if len(uploaded_files) < 2:
        return render_template(
            "index.html", error_message="Please select at least two PDF files."
        )

    file_paths = []
    for file in uploaded_files:
        if file.filename == "":
            return render_template("index.html", error_message="No file selected.")

        if not allowed_file(file.filename):
            return render_template(
                "index.html",
                error_message="Invalid file format. Only PDF files are allowed.",
            )

        file_path = os.path.join(
            app.config["UPLOAD_FOLDER"], secure_filename(file.filename)
        )
        file.save(file_path)
        file_paths.append(file_path)

    try:
        output = PdfWriter()
        output_path = os.path.join(app.config["DOWNLOAD_FOLDER"], "merged.pdf")

        # Merge the PDF files
        for file_path in file_paths:
            pdf = PdfReader(file_path)
            for page_number in range(len(pdf.pages)):
                output.add_page(pdf._get_page(page_number))

        with open(output_path, "wb") as output_file:
            output.write(output_file)
            output_file.close()

        delete_uploads()
        return redirect(url_for("download"))

    except Exception as e:
        return render_template(
            "index.html",
            error_message="An unexpected error occurred.",
        )

@app.route("/download", methods=["GET"])
def download():
    files = os.listdir(app.config["DOWNLOAD_FOLDER"])
    return render_template("download.html", files=files)

@app.route("/download/<path:filename>", methods=["GET"])
def download_file(filename):
    return send_from_directory(
        app.config["DOWNLOAD_FOLDER"], filename, as_attachment=True
    )

@app.route("/about")
def about():
    return render_template("about.html")

def delete_uploads():
    directory = app.config["UPLOAD_FOLDER"]
    files = os.listdir(directory)
    for file in files:
        file_path = os.path.join(directory, file)
        if os.path.isfile(file_path):
            os.remove(file_path)

def delete_downloads():
    directory = app.config["DOWNLOAD_FOLDER"]
    files = os.listdir(directory)
    for file in files:
        file_path = os.path.join(directory, file)
        if os.path.isfile(file_path):
            os.remove(file_path)

def delete_files():
    delete_uploads()
    delete_downloads()


import matplotlib.pyplot as plt
import pandas as pd

"""
各登船港口的获救情况
"""
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.serif'] = ['SimHei']

fig = plt.figure()
fig.set(alpha = 0.2)    #设定图表颜色alpha参数

data_train = pd.read_csv("E:/Python/Titanic-data-all/train.csv")

Survived_0 = data_train.Embarked[data_train.Survived == 0].value_counts()
Survived_1 = data_train.Embarked[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'获救': Survived_1, u'未获救': Survived_0})
df.plot(kind='bar', stacked=True)
plt.title(u"各登录港口乘客的获救情况")
plt.xlabel(u"登录港口")
plt.ylabel(u"人数")

plt.show()


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

"""
描述：二叉树的层次遍历，难度（medium）
给定一个二叉树，返回其按层次遍历的节点值。 （即逐层地，从左到右访问所有节点）。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层次遍历结果：
[
  [3],
  [9,20],
  [15,7]
]

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
"""

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

from collections import deque

class Solution:
    def levelOrder(self, root: TreeNode):
        """BFS，O（N）时间复杂度"""
        if not root:
            return []
        result = []
        queue = deque()
        queue.append(root)
        while queue:
            level_size = len(queue)
            current_level = []
            for _ in range(level_size):
                node = queue.popleft()
                current_level.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            result.append(current_level)
        return result


from gpt_index import GPTSimpleVectorIndex, SimpleDirectoryReader, LLMPredictor
from langchain import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import DirectoryLoader
from langchain.chains.summarize import load_summarize_chain
# from generate import agent_executor
from flask import Flask, request
from flask_cors import CORS, cross_origin
from dotenv import load_dotenv
from urllib.parse import urlparse
import requests
import os
import uuid
import openai

load_dotenv()

app = Flask(__name__)
CORS(app,)

@app.route('/')
def home():
    return "Flask up and running!"

# for legal ai upload pdf
@cross_origin('*')
@app.route('/legal-ai-upload', methods=['GET', 'POST'])
def legal_ai_upload():

    if request.method == 'POST':

        url = request.json['pdfurl']
        parsedurl = urlparse(url)

        pdf = os.path.basename(parsedurl.path)
        pdf_ID = str(uuid.uuid4())   # unique identifier for each user
        response = requests.get(url)

        if not os.path.exists(f'static/pdfs/{pdf}'):
            os.makedirs(f'static/pdfs/{pdf_ID}')

        # Check if the request was successful
        if response.status_code == 200:
            with open(f'static/pdfs/{pdf_ID}/{pdf}.pdf', 'wb') as f:
                f.write(response.content)

        # summarize
        loader = DirectoryLoader(f"static/pdfs/{pdf_ID}/")
        docs = loader.load()

        llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
        chain = load_summarize_chain(llm, chain_type="stuff")

        summary = chain.run(docs)

        return {
            "pdf_ID": pdf_ID,
            "summary": summary
        }

# to chat with the uploaded legal pdf
@cross_origin(supports_credentials=True)
@app.route('/legal-ai-chat', methods=['POST', 'GET'])
def legal_ai_chat():
    pdf_ID = request.json["pdf_ID"] if request.json["pdf_ID"] else ""
    query = request.json["message"] if request.json["message"] else ""

    if os.path.exists(f'static/index/{pdf_ID}.json'):
        print("Loading Index loop")

        # load from disk
        loaded_index = GPTSimpleVectorIndex.load_from_disk(
            f'static/index/{pdf_ID}.json')
        response = loaded_index.query(
            query, verbose=True, response_mode="default")
        final_answer = str(response)
        return {"answer": final_answer}

    else:
        print("Creating Index loop")

        # Set path of Indexed jsons
        index_path = f"static/index/{pdf_ID}.json"

        documents = SimpleDirectoryReader(f'static/pdfs/{pdf_ID}').load_data()

        # builds an index over the documents in the data folder
        index = GPTSimpleVectorIndex(documents)

        # save the Index to disk
        index.save_to_disk(index_path)

        # define the LLM to be used
        llm_predictor = LLMPredictor(llm=OpenAI(
            temperature=0, model_name="text-davinci-003"))

        # Load from Disk
        loaded_index = GPTSimpleVectorIndex.load_from_disk(
            index_path, llm_predictor=llm_predictor)
        response = loaded_index.query(
            query, verbose=True, response_mode="default")

        final_answer = str(response)

        return {"answer": final_answer}

@cross_origin(supports_credentials=True)
@app.route('/constitution', methods=['POST', 'GET'])
def constitution():

    if request.method == 'POST':

        question = request.json['question']
        if os.path.exists('docs/index/constitution.json'):
            # load from disk
            loaded_index = GPTSimpleVectorIndex.load_from_disk(
                'docs/index/constitution.json')
            response = loaded_index.query(
                question, verbose=True, response_mode="default")
            final_answer = str(response)
            return {"answer": final_answer}

        else:
            print("Creating Index loop")

            # Set path of Indexed jsons
            index_path = f"docs/index/constitution.json"

            documents = SimpleDirectoryReader(f'docs/pdf/').load_data()

            # builds an index over the documents in the data folder
            index = GPTSimpleVectorIndex(documents)

            # save the Index to disk
            index.save_to_disk(index_path)

            # define the LLM to be used
            llm_predictor = LLMPredictor(llm=OpenAI(
                temperature=0, model_name="gpt-turbo-3.5"))

            # Load from Disk
            loaded_index = GPTSimpleVectorIndex.load_from_disk(
                index_path, llm_predictor=llm_predictor)
            response = loaded_index.query(
                question, verbose=True, response_mode="default")

            final_answer = str(response)

            return {"answer": final_answer}

# @app.route('/chat', methods=['POST', 'GET'])
# def generate_chat():
#     query = request.json['query'] if request.json['query'] else ''
#     # put the logic here for intermediate code
#     answer = agent_executor.run(query)
#     final_answer = parse_final_answer(answer)
#     print(final_answer)
#     return {"response": final_answer}

if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=5000)


from buildcloth.makefile import MakefileCloth
from buildcloth.ninja import NinjaFileCloth
from buildcloth.err import InvalidRule, InvalidBuilder

class Rule(object):
    """
    :class:`~rules.Rule()` represents a build system rule, and provides an
    interface for constructing a rule.
    """
    def __init__(self, name=None):
        """
        :param string name: Specifies a name of the rule.

        When initializing you can specify a name for a :class:`~rules.Rule()`
        directly, or you can set it later using :meth:`~rules.Rule.name()`.
        """
        self._rule = { 'name': name }
        "The internal representation of the Rule."

    def name(self, name=None):
        """
        :param string name: Optional. Specifies a name of the rule.

        :returns: The name of the :class:`~rules.Rule()` object.

        Sets the name of the :class:`~rules.Rule()` object to ``name``.

        Raises :exc:`~err.InvlaidRule` if you do not specify a name *and* the
        :class:`~rules.Rule()` object doesn't have a name.
        """
        if name is None:
            if 'name' in self._rule:
                if self._rule['name'] is None:
                    raise InvalidRule('Rules must have names.')
                else:
                    return self._rule['name']
            else:
                raise InvalidRule('Rules must have names.')
        else:
            self._rule['name'] = name
            return name

    def command(self, cmd=None):
        """
        :param list,str cmd: Optional. Specifies a command or sequence of
                             commands that implement the build rule.

        :returns: The command list of the :class:`~rules.Rule()` object. If you
                  do not specify a command, and the :class:`~rules.Rule()` does
                  not have a command, :meth:`~rules.Rule.command()` will return
                  ``None``.

        Adds or appends ``cmd`` as a command list to the :class:`~rules.Rule()`
        object.

        Raises :exc:`~err.InvlaidRule` if you do not specify a command list
        *and* the :class:`~rules.Rule()` object doesn't a command list.
        """
        if cmd is None and 'command' in self._rule:
            return self._rule['command']
        if cmd is None and 'command' not in self._rule:
            return None
        elif 'command' not in self._rule:
            if type(cmd) is list:
                self._rule['command'] = cmd
            elif type(cmd) is str:
                self._rule['command'] = [cmd]
            return cmd

    cmd = command
    "An alias for :class:`~rules.Rule.command()`."

    def description(self, des=None):
        """
        :param string des: Optional. The text of the description message that
                           the build job will pass to the user.

        :returns: The current description.

        :raises: :exc:`~err.InvalidRule` if there is no description set for this rule.
        """
        if des is None and self._rule['description'] is None:
            raise InvalidRule('Rules must have descriptions.')
        elif des is None:
            return self._rule['description']
        else:
            self._rule['description'] = des
            return des

    msg = description
    "An alias for :class:`~rules.Rule.description()`."

    def depfile(self, dep=None):
        """
        :param string dep: Optional. The path to a Makefile that contains
                           dependencies

        :returns: The current depfile.

        :raises: :exc:`~err.InvalidRule` if there is no depfile set for this rule.
        """
        if dep is None and self._rule['depfile'] is None:
            raise InvlaidRule('dep file already specified')
        elif  dep is None:
            return self._rule['depfile']
        else:
            self._rule['depfile'] = dep
            return dep

    def restat(self):
        """
        Sets this rule as a restat rule. This only affects ninja output.

        :returns: ``True``.
        """
        self._rule['restat'] = True
        return True

    def rule(self):
        """
        :returns: A dictionary that contains the full build rule.

        :raises: :exc:`err.InvalidRule` if you have not specified a name for the
                 builder.
        """

        if self._rule['name'] is None:
            raise InvalidRule('Must specify name for rule.')
        else:
            return self._rule

class RuleCloth(object):
    """
    :class:`~rules.RuleCloth()` provides an interoperable layer between rule
    objects created as :class:`rules.Rule()` objects and build systems generated
    using :class:`~makefile.MakefileCloth()` and
    :class:`~makefile.NinjaFileCloth`.
    """
    def __init__(self, output=None):
        """
        :param string output: Optional. Specifies the output format for the
                              build system. You can specify the output format to
                              the :meth:`~rules.RuleCloth.fetch()` method
                              directly.
        """
        self.rules = {}
        "The structure that represents build rules."

        self.output = None
        "The default build system output format."

    def add(self, rule):
        """
        :param Rule rule: A :class:`~rules.Rule` object.

        :raises: :exc:`~err.InvalidRule` if the rule doesn't have a name or if
                  the rule already exists in :attr:`~rules.RuleCloth.rules`.

        Adds a :class:`~rules.Rule` object to the :class:`~rules.RuleCloth`
        object. Will not overwrite an existing rule.
        """
        if rule.name() in self.rules:
            raise InvalidRule('Rules must have unique names.')
        else:
            nrule = rule.name()
            drule = rule.rule()
            del drule['name']
            self.rules.update({ nrule : drule })

    def list_rules(self):
        """
        :returns: A list of a the names of all rules that exist in the :class:`~rules.RuleCloth` object.
        """
        return self.rules.keys()

    def fetch(self, name, block='_all'):
        """
        :param string name: The name of the build rule in
                            :attr:`~rules.RuleCloth.rules` to return.

        :param string block: Optional; defaults to ``_all``. Specify the name of
                             the block in :attr:`~cloth.BuildCloth.builder` to
                             create and access.

        :returns: The output of :meth:`~cloth.BuildCloth.get_block()` for
                  either Ninja or Makefiles, depending on ``name``.

        :raises: :exc:`~err.InvalidBuilder` when :attr:`~cloth.RuleCloth.output`
                 is neither ``make`` nor ``ninja``.
        """
        if self.output == 'ninja':
            return self._ninja(name, block=block)
        elif self.output == 'make':
            return self._make(name, block=block)
        else:
            raise InvalidBuilder('Must specify output format.')

    def _make(self, name, block='_all'):
        """
        An internal method used by :`~rules.RuleCloth.fetch()` to process
        content from :attr:`~rules.RuleCloth.rules` and return
        :meth:`~cloth.BuildCloth.get_block()` in Makefile format.
        """
        rule = self.rules[name]

        m = MakefileCloth()

        for cmd in rule['command']:
            m.job(cmd, block=block)

        m.msg(rule['description'], block=block)

        if 'depfile' in rule:
            m.raw(['include ' + rule['depfile']], block=block)

        return m.get_block(block)

    def _ninja(self, name, indent=4, block='_all'):
        """
        An internal method used by :`~rules.RuleCloth.fetch()` to process
        content from :attr:`~rules.RuleCloth.rules` and return
        :meth:`~cloth.BuildCloth.get_block()` in Ninja format.
        """
        n = NinjaFileCloth(indent=indent)

        n.rule(name, self.rules[name])
        return n.get_block(block)


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

import unittest
from math import erf
import numpy as np
from numpy.linalg import norm
from nose.plugins.attrib import attr

@attr(speed='fast')
class GaussianTest( unittest.TestCase ):

    """

    Test so that the finite field gives the identical answer as the equations (1),(2) and (3)
    where analytically derived for two random vectors.

    """

    def setUp(self):

        self._source = np.array( [0.1, -0.2 , 1.0], dtype = float )
        self._dest = np.array( [0.5, 0.5, 1.0], dtype = float )
        #self._source = np.random.random( 3 )
        #self._dest = np.random.random( 3 )
        self._R = 0.5

#Return a scalar potential given a destination vector position 0 < norm(r) <= 1
    def equation_one( self, r ):
        return erf( norm( r - self._source) / self._R ) / norm( r - self._source)

#Return vector representing the component-wise derivative of equation 2
#Which also is the electric field vector at position r due to a charge distribution

    def equation_two( self, r ):
        dr = norm( r - self._source )
        R = self._R
        invpi = 1/ np.sqrt( np.pi )
        first = erf( dr / R )
        second = 2 * dr * invpi / R * np.exp( -dr**2/R**2 )
        return -( r - self._source ) / dr**3 * ( first - second )

    def equation_three( self, r ):

        d = r
        s = self._source
        dr = norm( d - s )
        R = self._R

        invpi = 1/ np.sqrt( np.pi )

        first = erf( dr / R)
        second = 2 * dr * invpi / R * np.exp( -dr**2/R**2 )
        third = 4*invpi/R**3*np.outer((d-s),(d-s))/dr**2*np.exp( -dr**2/R**2)
        return (3*np.outer((d-s),(d-s))- dr**2*np.diag((1,1,1)) )/ dr**5 *(first - second) - third

    def test_finite_first(self):

        dx = np.array( [0.001, 0, 0], dtype = float )
        dy = np.array( [0, 0.001, 0], dtype = float )
        dz = np.array( [0, 0, 0.001], dtype = float )

        E_x_fin = (self.equation_one( self._dest +dx ) - self.equation_one(self._dest - dx))/(2*0.001)
        E_y_fin = (self.equation_one( self._dest +dy ) - self.equation_one(self._dest - dy))/(2*0.001)
        E_z_fin = (self.equation_one( self._dest +dz ) - self.equation_one(self._dest - dz))/(2*0.001)

        E_x_ana = self.equation_two( self._dest )[0]
        E_y_ana = self.equation_two( self._dest )[1]
        E_z_ana = self.equation_two( self._dest )[2]

        np.testing.assert_almost_equal( E_x_fin , E_x_ana , 3)
        np.testing.assert_almost_equal( E_y_fin , E_y_ana , 3)
        np.testing.assert_almost_equal( E_z_fin , E_z_ana , 3)

    def test_finite_second(self):

        dx = np.array( [0.001, 0, 0], dtype = float )
        dy = np.array( [0, 0.001, 0], dtype = float )
        dz = np.array( [0, 0, 0.001], dtype = float )

        r = self._dest

        E_xx_fin = (self.equation_two( r + dx )[0]-self.equation_two( r - dx )[0])/(2*0.001)
        E_xy_fin = (self.equation_two( r + dx )[1]-self.equation_two( r - dx )[1])/(2*0.001)
        E_xz_fin = (self.equation_two( r + dx )[2]-self.equation_two( r - dx )[2])/(2*0.001)
        E_yy_fin = (self.equation_two( r + dy )[1]-self.equation_two( r - dy )[1])/(2*0.001)
        E_yz_fin = (self.equation_two( r + dy )[1]-self.equation_two( r - dy )[1])/(2*0.001)
        E_zz_fin = (self.equation_two( r + dz )[2]-self.equation_two( r - dz )[2])/(2*0.001)

        E_xx_ana = self.equation_three(  r  )[0][0]
        E_xy_ana = self.equation_three(  r  )[0][1]
        E_xz_ana = self.equation_three(  r  )[0][2]
        E_yy_ana = self.equation_three(  r  )[1][1]
        E_yz_ana = self.equation_three(  r  )[1][1]
        E_zz_ana = self.equation_three(  r  )[2][2]

        np.testing.assert_almost_equal( E_xx_fin , E_xx_ana , 5)
        np.testing.assert_almost_equal( E_xy_fin , E_xy_ana , 5)
        np.testing.assert_almost_equal( E_xy_fin , E_xy_ana , 5)
        np.testing.assert_almost_equal( E_xz_fin , E_xz_ana , 5)
        np.testing.assert_almost_equal( E_yy_fin , E_yy_ana , 3)
        np.testing.assert_almost_equal( E_yz_fin , E_yz_ana , 3)
        np.testing.assert_almost_equal( E_zz_fin , E_zz_ana , 3)

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


from typing import List, Optional, Type

from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.core.cache import cache
from django.db import transaction
from django.db.models import Q, QuerySet
from django.utils import timezone

from baserow.core.utils import Progress

from .cache import job_progress_key
from .constants import JOB_FAILED, JOB_PENDING
from .exceptions import JobDoesNotExist, MaxJobCountExceeded
from .models import Job
from .registries import job_type_registry
from .tasks import run_async_job
from .types import AnyJob

class JobHandler:
    def run(self, job: AnyJob):
        def progress_updated(percentage, state):
            """
            Every time the progress of the job changes, this callback function is
            called. If the percentage or the state has changed, the job will be updated.
            """

            nonlocal job

            if job.progress_percentage != percentage:
                job.progress_percentage = percentage
                changed = True

            if state is not None and job.state != state:
                job.state = state
                changed = True

            if changed:
                # The progress must also be stored in the Redis cache. Because we're
                # currently in a transaction, other database connections don't know
                # about the progress and this way, we can still communicate it to
                # the user.
                cache.set(
                    job_progress_key(job.id),
                    {
                        "progress_percentage": job.progress_percentage,
                        "state": job.state,
                    },
                    timeout=None,
                )
                job.save()

        progress = Progress(100)
        progress.register_updated_event(progress_updated)

        job_type = job_type_registry.get_by_model(job)

        return job_type.run(job, progress)

    @staticmethod
    def get_job(
        user: AbstractUser,
        job_id: int,
        job_model: Optional[Type[AnyJob]] = None,
        base_queryset: Optional[QuerySet] = None,
    ) -> Job:
        """
        Returns the job corresponding to the given id.

        :param job_id: The job id we want to fetch.
        :param job_model: An optional Job model.
        :param base_queryset: An optional base queryset to use instead of the default
            one.
        :return: the job.
        """

        if not job_model:
            job_model = Job

        if base_queryset is None:
            base_queryset = job_model.objects

        try:
            return base_queryset.select_related("user").get(id=job_id, user_id=user.id)
        except Job.DoesNotExist:
            raise JobDoesNotExist(f"The job with id {job_id} does not exist.")

    def get_jobs_for_user(
        self,
        user: AbstractUser,
        filter_states: Optional[List[str]],
        filter_ids: Optional[List[int]],
    ) -> QuerySet:
        """
        Returns all jobs belonging to the specified user.

        :param user: The user we want the jobs for.
        :param filter_states: A list of states that the jobs should have, or not
            have if prefixed with a !.
        :param filter_ids: A list of specific job ids to return.
        :return: A QuerySet with the filtered jobs for the user.
        """

        def get_job_states_filter(states):
            states_q = Q()
            for state in states:
                if state.startswith("!"):
                    states_q &= ~Q(state=state[1:])
                else:
                    states_q |= Q(state=state)
            return states_q

        queryset = Job.objects.filter(user=user).order_by("-updated_on")

        if filter_states:
            queryset = queryset.filter(get_job_states_filter(filter_states))

        if filter_ids:
            queryset = queryset.filter(id__in=filter_ids)

        return queryset.select_related("content_type")

    def get_pending_or_running_jobs(
        self,
        job_type_name: str,
    ) -> QuerySet:
        """
        Returns a queryset of pending or running jobs of a provided job type
        that can be further filtered.

        :param job_type_name: The job type for which we want the queryset.
        :return: Queryset of all pending or running jobs of the job type.
        """

        job_type = job_type_registry.get(job_type_name)
        model_class = job_type.model_class
        return model_class.objects.filter().is_pending_or_running()

    def create_and_start_job(
        self, user: AbstractUser, job_type_name: str, sync=False, **kwargs
    ) -> Job:
        """
        Creates a new job and schedule the asynchronous task.

        :param user: The user whom launch the task.
        :param job_type_name: The job type we want to launch.
        :param sync: True if you want to execute the job immediately.

        :return: The newly created job.
        """

        job_type = job_type_registry.get(job_type_name)
        model_class = job_type.model_class

        # Check how many job of same type are running simultaneously. If count > max
        # we don't want to create a new one.
        running_jobs = model_class.objects.filter(
            user_id=user.id
        ).is_pending_or_running()
        if len(running_jobs) >= job_type.max_count:
            raise MaxJobCountExceeded(
                f"You can only launch {job_type.max_count} {job_type_name} job(s) at "
                "the same time."
            )

        job_values = job_type.prepare_values(kwargs, user)
        job = model_class.objects.create(user=user, **job_values)
        job_type.after_job_creation(job, kwargs)

        if sync:
            run_async_job(job.id)
            job.refresh_from_db()
        else:
            # This wrapper ensure the job doesn't stay in pending state if something
            # goes wrong during the delay call. This is related to the redis connection
            # failure that triggers a sys.exit(1) to be called in gunicorn.
            def call_async_job_safe():
                try:
                    run_async_job.delay(job.id)
                except BaseException as e:
                    job.refresh_from_db()
                    if job.state == JOB_PENDING:
                        job.state = JOB_FAILED
                        job.error = str(e)
                        job.human_readable_error = (
                            f"Something went wrong during the job({job.id}) execution."
                        )
                        job.save()
                    raise

            transaction.on_commit(call_async_job_safe)

        return job

    def clean_up_jobs(self):
        """
        Terminate running jobs after the soft limit and delete expired jobs.
        """

        # Delete old job
        limit_date = timezone.now() - timezone.timedelta(
            minutes=(settings.BASEROW_JOB_EXPIRATION_TIME_LIMIT)
        )
        for job_to_delete in Job.objects.filter(
            created_on__lte=limit_date
        ).is_finished():
            job_type = job_type_registry.get_by_model(job_to_delete.specific)
            job_type.before_delete(job_to_delete.specific)
            job_to_delete.delete()

        # Expire non expired jobs
        limit_date = timezone.now() - timezone.timedelta(
            seconds=(settings.BASEROW_JOB_SOFT_TIME_LIMIT + 1)
        )

        (
            Job.objects.filter(created_on__lte=limit_date)
            .is_pending_or_running()
            .update(
                state=JOB_FAILED,
                human_readable_error=(
                    "Something went wrong during the file_import job execution."
                ),
                error="Unknown error",
                updated_on=timezone.now(),
            )
        )


from typing import List
def quicksort(arr: List) -> List:
    '''
    this func to sorts it alphabetically withou using sort(), by using recursion
    '''
    if not arr:
        return []
    return (quicksort([x for x in arr[1:] if x <  arr[0]])
            + [arr[0]] +
            quicksort([x for x in arr[1:] if x >= arr[0]]))

print(quicksort(['c','ad','as','y','p'])) #output: ['ad', 'as', 'c', 'p', 'y']


import re

def email_parse(email):
    pattern = re.compile(r'^(?P<username>\w+)@(?P<domain>\w+\.\w+)$')
    result = pattern.match(email)
    print(result)
    if result:
        return result.groups()
    else:
        raise ValueError(f'Введен некорректный адрес электронной почты: {email}')

user_email = input('Введите адрес электронной почты: ')
print(email_parse(user_email))


import json
import os
import tempfile
import unittest
from unittest import mock

import numpy as np
import pandas as pd
import sklearn.preprocessing
import tensorflow as tf
from porter.utils import NumpyEncoder
import joblib

HERE = os.path.dirname(__file__)

def load_example(filename, init_namespace=None):
    if init_namespace is None:
        init_namespace = {}
    with open(filename) as f:
        example = f.read()
    exec(example, init_namespace)
    return init_namespace

@mock.patch('porter.services.BaseService._ids', set())
class TestExample(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        X = np.random.rand(10, 3)
        cls.X = pd.DataFrame(
            data=X,
            columns=['feature1', 'feature2', 'column3'])
        cls.X['id'] = range(len(X))
        cls.y = np.random.randint(1, 10, size=10)
        cls.preprocessor = sklearn.preprocessing.StandardScaler().fit(cls.X.drop('id', axis=1))
        cls.model = tf.keras.models.Sequential([
            tf.keras.layers.Dense(20, activation='relu', input_shape=(3,)),
            tf.keras.layers.Dense(1, activation='relu')
        ])
        cls.model.compile(loss='mean_squared_error', optimizer='sgd')
        cls.model.fit(cls.preprocessor.transform(cls.X.drop('id', axis=1)), cls.y, verbose=0)
        cls.predictions = cls.model.predict(cls.preprocessor.transform(cls.X.drop('id', axis=1))).reshape(-1)

    def test(self):
        with tempfile.TemporaryDirectory() as tmpdirname:
            joblib.dump(self.preprocessor, os.path.join(tmpdirname, 'preprocessor.pkl'))
            tf.keras.models.save_model(self.model, os.path.join(tmpdirname, 'model.h5'))
            init_namespace = {'model_directory': tmpdirname}
            namespace = load_example(os.path.join(HERE, '../examples/example.py'), init_namespace)
        test_client = namespace['model_app'].app.test_client()
        app_input = self.X.to_dict('records')
        response = test_client.post('/supa-dupa-model/v1/prediction', data=json.dumps(app_input, cls=NumpyEncoder))
        actual_response_data = json.loads(response.data)
        expected_model_name = 'supa-dupa-model'
        expected_api_version = 'v1'
        expected_predictions = {
            id_: pred for id_, pred in zip(self.X['id'], self.predictions)
        }
        self.assertEqual(actual_response_data['model_context']['model_name'], expected_model_name)
        self.assertEqual(actual_response_data['model_context']['api_version'], expected_api_version)
        for rec in actual_response_data['predictions']:
            actual_id, actual_pred = rec['id'], rec['prediction']
            expected_pred = expected_predictions[actual_id]
            self.assertTrue(np.allclose(actual_pred, expected_pred))

@mock.patch('porter.services.BaseService._ids', set())
class TestExampleHealthCheckEndponts(unittest.TestCase):
    def test(self):
        # just testing that the example can be executed
        namespace = load_example(os.path.join(HERE, '../examples/health_check_endpoints.py'))

@mock.patch('porter.services.BaseService._ids', set())
class TestAPILogging(unittest.TestCase):
    def test(self):
        # just testing that the example can be executed
        namespace = load_example(os.path.join(HERE, '../examples/api_logging.py'))

@mock.patch('porter.services.BaseService._ids', set())
class TestGettingStarted(unittest.TestCase):
    def test(self):
        # just testing that the example can be executed
        namespace = load_example(os.path.join(HERE, '../examples/getting_started.py'))

@mock.patch('porter.services.BaseService._ids', set())
class TestFunctionService(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.ns = load_example(os.path.join(HERE, '../examples/function_service.py'))
        cls.test_app = cls.ns['app'].app.test_client()

    def test_get(self):
        r = self.test_app.get('/math/v1/sum')
        self.assertEqual(r.status_code, 200)
        r = self.test_app.get('/math/v1/prod')
        self.assertEqual(r.status_code, 200)

    def test_post_sum(self):
        endpoint = '/math/v1/sum'
        a = list(range(1, 11))
        r = self.test_app.post(endpoint, data=json.dumps(a))
        self.assertEqual(r.status_code, 200)
        self.assertEqual(sum(a), int(r.data))

    def test_post_prod(self):
        endpoint = '/math/v1/prod'
        a = list(range(1, 11))
        r = self.test_app.post(endpoint, data=json.dumps(a))
        self.assertEqual(r.status_code, 200)
        self.assertEqual(np.prod(a), int(r.data))

        # test additional_checks: zero not allowed
        a = list(range(0, 11))
        r = self.test_app.post(endpoint, data=json.dumps(a))
        self.assertEqual(r.status_code, 422)

@mock.patch('porter.services.BaseService._ids', set())
class TestContracts(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.ns = load_example(os.path.join(HERE, '../examples/contracts.py'))
        cls.test_app = cls.ns['model_app'].app.test_client()

    def test_instance_prediction_service(self):
        """Configurations for this service are:

        endpoint = /datascience/user-ratings/v2/instancePrediction
        validate_request_data = True
        batch_prediction = False

        The description of the input schema is

        {
            "id": Integer(),
            "user_id": Integer(),
            "title_id": Integer(),
            "genre": String(['comedy', 'action', 'drama']),
            "average_rating": Number(min=0, max=10)
        }

        """
        valid_data = {
            "id": 0,
            "user_id": 1,
            "title_id": 19302943284,
            "genre": "action",
            "average_rating": 7.9
        }

        invalid_data_missing_key = {
            "user_id": 1,
            "title_id": 19302943284,
            "genre": "action",
            "average_rating": 7.9
        }

        invalid_data_invalid_genre = {
            "user_id": 1,
            "title_id": 19302943284,
            "genre": "isnotvalid",
            "average_rating": 7.9
        }

        invalid_data_invalid_average_rating = {
            "user_id": 1,
            "title_id": 19302943284,
            "genre": "action",
            "average_rating": -1
        }

        endpoint = '/datascience/user-ratings/v2/instancePrediction'
        r = self.test_app.post(endpoint, data=json.dumps(valid_data))
        self.assertEqual(r.status_code, 200)

        r = self.test_app.post(endpoint, data=json.dumps(invalid_data_missing_key))
        self.assertEqual(r.status_code, 422)
        self.assertIn("data must contain ('average_rating', 'genre', 'id', 'title_id', 'user_id')", r.json['error']['messages'][0])

        r = self.test_app.post(endpoint, data=json.dumps(invalid_data_invalid_genre))
        self.assertEqual(r.status_code, 422)
        self.assertIn('genre', r.json['error']['messages'][0])

        r = self.test_app.post(endpoint, data=json.dumps(invalid_data_invalid_average_rating))
        self.assertEqual(r.status_code, 422)
        self.assertIn('average_rating', r.json['error']['messages'][0])

    def test_batch_prediction_service(self):
        """Configurations for this service are:

        endpoint = /datascience/user-ratings/v2/prediction
        validate_request_data = True
        batch_prediction = True

        The description of the input schema is

        [
            {
                "id": Integer(),
                "user_id": Integer(),
                "title_id": Integer(),
                "genre": String(['comedy', 'action', 'drama']),
                "average_rating": Number(min=0, max=10)
            },
            ...
        ]

        """
        valid_data = [
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
        ]

        invalid_data_title_id_is_str = [
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 'a',
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
        ]

        invalid_data_not_an_array = {
            "id": 0,
            "user_id": 1,
            "title_id": 19302943284,
            "genre": "action",
            "average_rating": 7.9
        }

        endpoint = '/datascience/user-ratings/v2/prediction'
        r = self.test_app.post(endpoint, data=json.dumps(valid_data))
        self.assertEqual(r.status_code, 200)

        r = self.test_app.post(endpoint, data=json.dumps(invalid_data_title_id_is_str))
        self.assertEqual(r.status_code, 422)
        self.assertIn('data[1].title_id', r.json['error']['messages'][0])

        r = self.test_app.post(endpoint, data=json.dumps(invalid_data_not_an_array))
        self.assertEqual(r.status_code, 422)
        self.assertIn('data must be array', r.json['error']['messages'][0])

    def test_probabilistic_service(self):
        """Configurations for this service are:

        endpoint = /datascience/proba-model/v3/prediction
        validate_request_data = False
        batch_prediction = True

        The description of the input schema is

        [
            {
                "id": Integer(),
                "user_id": Integer(),
                "title_id": Integer(),
                "genre": String(['comedy', 'action', 'drama']),
                "average_rating": Number(min=0, max=10)
            },
            ...
        ]
        """

        # this endpoint doesn't do data validations so we should get a 500 by sending
        # bad data instead of a 422
        invalid_data = {
            'not the data': 'you were looking for'
        }
        r = self.test_app.post('/datascience/proba-model/v3/prediction', data=json.dumps(invalid_data))
        self.assertEqual(r.status_code, 500)

    def test_spark_interface_service(self):
        """Configurations for this service are:

        endpoint = /datascience/batch-ratings-model/v1/prediction
        validate_request_data = False
        batch_prediction = True

        The description of the input schema is

        [
            {
                "id": Integer(),
                "user_id": Integer(),
                "title_id": Integer(),
                "genre": String(['comedy', 'action', 'drama']),
                "average_rating": Number(min=0, max=10)
            },
            ...
        ]
        """
        valid_data = [
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
            {
                "id": 0,
                "user_id": 1,
                "title_id": 19302943284,
                "genre": "action",
                "average_rating": 7.9
            },
        ]
        r = self.test_app.post('/datascience/batch-ratings-model/v1/prediction', data=json.dumps(valid_data))
        self.assertEqual(r.status_code, 202)
        self.ns['spark_interface_response_schema'].validate(json.loads(r.data))

    def test_custom_service_validations_fail(self):
        """Configurations for this service are:

        endpoint = /custom-service/v1/foo
        validate_request_data = True
        batch_prediction = N/A
        """
        invalid_data1 = 'this string is definitely not an object'
        invalid_data2 = {'this object': 'is an object', 'but not a': 'correct schema'}
        invalid_data_checking_nested_validations1 = {
            'string_with_enum_prop': 'a',
            'an_array': [1, 2],
            'another_property': {'a': 'a', 'b': 1},
            'yet_another_property': [
                {'foo': 'a'},
                {'foo': 'a', 'bar': 1}  # all props should be str
            ]
        }
        invalid_data_checking_nested_validations2 = {
            'string_with_enum_prop': 'a',
            'an_array': [1, 2],
            'another_property': {'a': 'a', 'b': 'not an int'},
            'yet_another_property': [
                {'foo': 'a'},
                {'foo': 'a', 'bar': '1'}
            ]
        }

        r = self.test_app.post('/custom-service/v1/foo', data=json.dumps(invalid_data1))
        self.assertEqual(r.status_code, 422)
        self.assertIn('data must be object', r.json['error']['messages'][0])

        r = self.test_app.post('/custom-service/v1/foo', data=json.dumps(invalid_data2))
        self.assertEqual(r.status_code, 422)
        self.assertIn("data must contain ('an_array', 'another_property', 'string_with_enum_prop', 'yet_another_property')", r.json['error']['messages'][0])

        r = self.test_app.post('/custom-service/v1/foo', data=json.dumps(invalid_data_checking_nested_validations1))
        self.assertEqual(r.status_code, 422)
        self.assertIn("yet_another_property[1].bar", r.json['error']['messages'][0])

        r = self.test_app.post('/custom-service/v1/foo', data=json.dumps(invalid_data_checking_nested_validations2))
        self.assertEqual(r.status_code, 422)
        self.assertIn("another_property.b", r.json['error']['messages'][0])

    def test_custom_service_validations_succeed(self):
        """Configurations for this service are:

        endpoint = /custom-service/v1/foo
        validate_request_data = True
        batch_prediction = N/A
        """
        valid_data = {
            'string_with_enum_prop': 'a',
            'an_array': [1, 2],
            'another_property': {'a': 'a', 'b': 1},
            'yet_another_property': [
                {'foo': 'a'},
                {'foo': 'a', 'bar': 'b'}
            ]
        }
        r = self.test_app.post('/custom-service/v1/foo', data=json.dumps(valid_data))
        self.assertEqual(r.status_code, 200)

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


# coding: utf-8

"""
    Selling Partner API for Finances

    The Selling Partner API for Finances helps you obtain financial information relevant to a seller's business. You can obtain financial events for a given order, financial event group, or date range without having to wait until a statement period closes. You can also obtain financial event groups for a given date range.  # noqa: E501

    OpenAPI spec version: v0

    Generated by: https://github.com/swagger-api/swagger-codegen.git
"""

import pprint
import re  # noqa: F401

import six

class TrialShipmentEvent(object):
    """NOTE: This class is auto generated by the swagger code generator program.

    Do not edit the class manually.
    """
    """
    Attributes:
      swagger_types (dict): The key is attribute name
                            and the value is attribute type.
      attribute_map (dict): The key is attribute name
                            and the value is json key in definition.
    """
    swagger_types = {
        'amazon_order_id': 'str',
        'financial_event_group_id': 'str',
        'posted_date': 'ModelDate',
        'sku': 'str',
        'fee_list': 'FeeComponentList'
    }

    attribute_map = {
        'amazon_order_id': 'AmazonOrderId',
        'financial_event_group_id': 'FinancialEventGroupId',
        'posted_date': 'PostedDate',
        'sku': 'SKU',
        'fee_list': 'FeeList'
    }

    def __init__(self, amazon_order_id=None, financial_event_group_id=None, posted_date=None, sku=None, fee_list=None):  # noqa: E501
        """TrialShipmentEvent - a model defined in Swagger"""  # noqa: E501
        self._amazon_order_id = None
        self._financial_event_group_id = None
        self._posted_date = None
        self._sku = None
        self._fee_list = None
        self.discriminator = None
        if amazon_order_id is not None:
            self.amazon_order_id = amazon_order_id
        if financial_event_group_id is not None:
            self.financial_event_group_id = financial_event_group_id
        if posted_date is not None:
            self.posted_date = posted_date
        if sku is not None:
            self.sku = sku
        if fee_list is not None:
            self.fee_list = fee_list

    @property
    def amazon_order_id(self):
        """Gets the amazon_order_id of this TrialShipmentEvent.  # noqa: E501

        An Amazon-defined identifier for an order.  # noqa: E501

        :return: The amazon_order_id of this TrialShipmentEvent.  # noqa: E501
        :rtype: str
        """
        return self._amazon_order_id

    @amazon_order_id.setter
    def amazon_order_id(self, amazon_order_id):
        """Sets the amazon_order_id of this TrialShipmentEvent.

        An Amazon-defined identifier for an order.  # noqa: E501

        :param amazon_order_id: The amazon_order_id of this TrialShipmentEvent.  # noqa: E501
        :type: str
        """

        self._amazon_order_id = amazon_order_id

    @property
    def financial_event_group_id(self):
        """Gets the financial_event_group_id of this TrialShipmentEvent.  # noqa: E501

        The identifier of the financial event group.  # noqa: E501

        :return: The financial_event_group_id of this TrialShipmentEvent.  # noqa: E501
        :rtype: str
        """
        return self._financial_event_group_id

    @financial_event_group_id.setter
    def financial_event_group_id(self, financial_event_group_id):
        """Sets the financial_event_group_id of this TrialShipmentEvent.

        The identifier of the financial event group.  # noqa: E501

        :param financial_event_group_id: The financial_event_group_id of this TrialShipmentEvent.  # noqa: E501
        :type: str
        """

        self._financial_event_group_id = financial_event_group_id

    @property
    def posted_date(self):
        """Gets the posted_date of this TrialShipmentEvent.  # noqa: E501

        :return: The posted_date of this TrialShipmentEvent.  # noqa: E501
        :rtype: ModelDate
        """
        return self._posted_date

    @posted_date.setter
    def posted_date(self, posted_date):
        """Sets the posted_date of this TrialShipmentEvent.

        :param posted_date: The posted_date of this TrialShipmentEvent.  # noqa: E501
        :type: ModelDate
        """

        self._posted_date = posted_date

    @property
    def sku(self):
        """Gets the sku of this TrialShipmentEvent.  # noqa: E501

        The seller SKU of the item. The seller SKU is qualified by the seller's seller ID, which is included with every call to the Selling Partner API.  # noqa: E501

        :return: The sku of this TrialShipmentEvent.  # noqa: E501
        :rtype: str
        """
        return self._sku

    @sku.setter
    def sku(self, sku):
        """Sets the sku of this TrialShipmentEvent.

        The seller SKU of the item. The seller SKU is qualified by the seller's seller ID, which is included with every call to the Selling Partner API.  # noqa: E501

        :param sku: The sku of this TrialShipmentEvent.  # noqa: E501
        :type: str
        """

        self._sku = sku

    @property
    def fee_list(self):
        """Gets the fee_list of this TrialShipmentEvent.  # noqa: E501

        :return: The fee_list of this TrialShipmentEvent.  # noqa: E501
        :rtype: FeeComponentList
        """
        return self._fee_list

    @fee_list.setter
    def fee_list(self, fee_list):
        """Sets the fee_list of this TrialShipmentEvent.

        :param fee_list: The fee_list of this TrialShipmentEvent.  # noqa: E501
        :type: FeeComponentList
        """

        self._fee_list = fee_list

    def to_dict(self):
        """Returns the model properties as a dict"""
        result = {}

        for attr, _ in six.iteritems(self.swagger_types):
            value = getattr(self, attr)
            if isinstance(value, list):
                result[attr] = list(map(
                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
                    value
                ))
            elif hasattr(value, "to_dict"):
                result[attr] = value.to_dict()
            elif isinstance(value, dict):
                result[attr] = dict(map(
                    lambda item: (item[0], item[1].to_dict())
                    if hasattr(item[1], "to_dict") else item,
                    value.items()
                ))
            else:
                result[attr] = value
        if issubclass(TrialShipmentEvent, dict):
            for key, value in self.items():
                result[key] = value

        return result

    def to_str(self):
        """Returns the string representation of the model"""
        return pprint.pformat(self.to_dict())

    def __repr__(self):
        """For `print` and `pprint`"""
        return self.to_str()

    def __eq__(self, other):
        """Returns true if both objects are equal"""
        if not isinstance(other, TrialShipmentEvent):
            return False

        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        """Returns true if both objects are not equal"""
        return not self == other


import numpy as np

np.random.seed(1)

# create the students data
numStudents = 100
outfile = open("data_students.txt","w")
for i in range(1,numStudents+1):
	outString = ''
	outString += str(i)   # id
	outString += ','
	grade = str(np.random.randint(4)+9)
	outString += grade
	outString += ','
	outString += 'student'
	outString += str(i)   # name
	outString += ','
	email = 'student'+str(i)+'@medford.student.edu'
	outString += email
	outString += ','
	house_num = ( np.random.randint(999) + 1 )
	outString += str(house_num)+" Stuyvestant Avenue"  #address
	outString += "\n"
	outfile.write(outString)
outfile.close()

# create the course data
numCourses = 100
outfile = open("data_courses.txt","w")
for i in range(101,numCourses+101):
	outString = ''
	outString += str(i)   # course_Id
	outString += ','
	outString += 'course'
	outString += str(i)   #course_name
	outString += ','
	credits= str( np.random.randint(2) + 3)
	outString += credits
	outString += "\n"
	outfile.write(outString)
outfile.close()

# create the enrolled data
numEnrolled = 1000
outfile = open("data_enrolled_in.txt","w")
for i in range(1,numEnrolled+1):
	outString = ''
	sid = str( np.random.randint(numStudents) + 1)
	outString += str(sid)   # sid
	outString += ','
	cid = str( np.random.randint(numCourses) + 101)
	outString += cid   # cid
	outString += ','
	termSeason=np.random.randint(2)
	if termSeason == 0:
		term = "Fall"+str(np.random.randint(4)+2020)
	else:
		term = "Spring"+str(np.random.randint(4)+2020)

	outString += term
	outString += "\n"
	outfile.write(outString)
outfile.close()


import uuid

from rest_framework.exceptions import ValidationError
from rest_framework.test import APIRequestFactory, APITestCase
from django.urls import reverse

from comment import views as comment_views
from comment.models import Comment

from tests.confess.confession.tests import CreateConfessionTest

class ReversedUrls:

    @classmethod
    def get_comments_url(cls):
        return reverse('comments', kwargs={'id': 1})

    @classmethod
    def get_reply_url(cls):
        return reverse('comment-replies', kwargs={'id': 1, 'comment_id': 1})

class CommentTest(CreateConfessionTest, APITestCase):
    def setUp(self) -> None:
        self.username = 'John'
        self.body = 'Hello'
        self.related = self.create_confession()
        self.comment_url = ReversedUrls.get_comments_url()
        self.factory = APIRequestFactory()
        self.is_parent = True

    def create_comment(self):
        comment = Comment.objects.create(
            username='Alex',
            body='Comment',
            is_parent=True,
            related_id=self.related.id
        )
        return comment

    def test__create_comment(self):
        req = self.factory.post(
            self.comment_url,
            {'username': 'Alex', 'body': 'Comment', 'is_parent': self.is_parent},
        )
        req.COOKIES.setdefault('session_token', str(uuid.uuid4()))

        resp = comment_views.CommentApiMixin.as_view({'post': 'create'})(req, id=self.related.id)

        comment_count = Comment.objects.all().count()

        self.assertTrue(
            resp.data['id']
        )
        self.assertTrue(
            resp.data['is_parent']
        )
        self.assertTrue(
            comment_count, 1
        )

    def test__list_comments(self):
        self.comment = self.create_comment()
        req = self.factory.get(
            self.comment_url
        )
        req.COOKIES.setdefault('session_token', str(uuid.uuid4()))

        resp = comment_views.CommentApiMixin.as_view({'get': 'list'})(req, id=self.related.id)

        comment_count = Comment.objects.all().count()

        self.assertTrue(
            resp.data[0]['id']
        )
        self.assertTrue(
            resp.data[0]['is_parent']
        )
        self.assertTrue(
            comment_count, 1
        )

class CommentReply(CreateConfessionTest, APITestCase):

    def setUp(self) -> None:
        self.related = self.create_confession()
        self.is_parent = False
        self.parent = self.create_comment()
        self.factory = APIRequestFactory()
        self.reply_url = ReversedUrls.get_reply_url()

    def create_comment(self):
        comment = Comment.objects.create(
            username='Alex',
            body='Comment',
            is_parent=True,
            related_id=self.related.id
        )
        return comment

    def create_reply(self):
        reply = Comment.objects.create(
            username='Bob',
            body='Hello Alex',
            is_parent=False,
            related_id=self.related.id,
            parent_id=self.comment.id
        )
        return reply

    def test__create_reply(self):
        req = self.factory.post(
            self.reply_url,
            {'username': 'Bob', 'body': 'Hi Alex'}
        )
        req.COOKIES.setdefault('session_token', str(uuid.uuid4()))

        resp = comment_views.CommentDetailsApiMixin.as_view({
            'post': 'create'
        })(
            req,
            id=self.related.id,
            comment_id=self.parent.id
        )

        comment_count = Comment.objects.all().count()

        self.assertIsNotNone(
            resp.data['parent']
        )
        self.assertFalse(
            resp.data['is_parent']
        )
        self.assertTrue(
            comment_count, 2
        )

    def test__list_replies(self):
        self.comment = self.create_comment()
        self.reply = self.create_reply()

        req = self.factory.get(
            self.reply_url
        )
        req.COOKIES.setdefault('session_token', str(uuid.uuid4()))

        resp = comment_views.CommentDetailsApiMixin.as_view({'get': 'list'})(req, id=self.related.id,
                                                                             comment_id=self.comment.id)

        comment_count = Comment.objects.all().count()

        self.assertIsNotNone(
            resp.data[0]['parent']
        )
        self.assertFalse(
            resp.data[0]['is_parent']
        )
        self.assertTrue(
            comment_count, 2
        )

    def test__list_replies_wrong_releated(self):
        self.comment = self.create_comment()
        self.reply = self.create_reply()

        req = self.factory.get(
            self.reply_url
        )
        req.COOKIES.setdefault('session_token', str(uuid.uuid4()))

        resp = comment_views.CommentDetailsApiMixin.as_view({'get': 'list'})(req, id=(self.related.id + 10),
                                                                             comment_id=self.comment.id)

        self.assertEqual(200, resp.status_code)
        self.assertRaises(ValidationError)


# Similar to drawPostPan.C, but works directly from the rootLogon.C
import os
import sys
import csv
import subprocess
from argparse import ArgumentParser

parser     = ArgumentParser()
parser.add_argument("-f", "--conf", dest="devicelist", help="Device List and Analyses for camguin", required=True, metavar="DEVICELIST", default="input.txt")
parser.add_argument("-s", "--outfileName", dest="outfileName", help="Run List text file for camguin wrapper", required=True, metavar="SLUG", default="test")

args       = vars(parser.parse_args())
outfileName= args['outfileName']
devicelist = args['devicelist']

lines = []

try:
  with open(devicelist) as devicelistFile:
    for line in csv.reader(devicelistFile, delimiter=','):
      lines.append(line[0])
except:
  print("ERROR: You forgot to have a devicelist \"devicelist.txt\"\n")
  sys.exit()

print("Extracting from run " + lines[0])
os.system("root -l -b -q -x showThing.C'(\"rootfiles/prexPrompt_"+outfileName+".root\",\""+lines[0]+"\",\""+outfileName+"\")'")
os.system("mv showPrint_"+outfileName+".pdf output_"+outfileName+".pdf")
for i in range(1,len(lines)):
  print("Extracting from run " + lines[i])
  os.system("ls showPrint_"+outfileName+".pdf")
  os.system("root -l -b -q -x showThing.C'(\"rootfiles/prexPrompt_"+outfileName+".root\",\""+lines[i]+"\",\""+outfileName+"\")'")
  os.system("ls showPrint_"+outfileName+".pdf")
  os.system("mv output_"+outfileName+".pdf tmp_output_"+outfileName+".pdf")
  os.system("pdfunite tmp_output_"+outfileName+".pdf showPrint_"+outfileName+".pdf output_"+outfileName+".pdf")
  os.system("rm -f tmp_output_"+outfileName+".pdf")

os.system("mv output_"+outfileName+".pdf plots/")


import tensorflow as tf
import numpy
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from tensorflow.contrib.layers import flatten
from sklearn.utils import shuffle
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
from sklearn.model_selection import train_test_split

import IPython
# tf.set_random_seed(0)
df_train = pd.read_csv('dataset/train.csv')
df_test = pd.read_csv('dataset/test.csv')
df_train.head()

df_train = pd.get_dummies(df_train,columns=['label'])
df_features = df_train.iloc[:, :-10].values
df_label = df_train.iloc[:, -10:].values
print(df_features.shape)

X_train, X_test, y_train, y_test = train_test_split(df_features, df_label, test_size = 0.2, random_state = 1212)
#X_test, X_validation, y_test,y_validation = train_test_split(X_test,  y_test, test_size=0.5, random_state=0)
image_size = 28
num_labels = 10
num_channels = 1 # grayscale
def reformat(dataset, labels):
    dataset = dataset.reshape((-1, image_size, image_size, num_channels)).astype(np.float32)
    labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)
    return dataset, labels

train_dataset, train_labels = reformat(X_train, y_train)

#valid_dataset, valid_labels = reformat(X_validation, y_validation)
test_dataset , test_labels = reformat(X_test, y_test)
df_test = df_test.to_numpy().reshape((-1, image_size, image_size, num_channels)).astype(np.float32)
print ('Training set :', train_dataset.shape, train_labels.shape)
#print ('Validation set :', valid_dataset.shape, valid_labels.shape)
print ('Test set :', test_dataset.shape, test_labels.shape)

# Pad images with 0s
X_train      = np.pad(train_dataset, ((0,0),(2,2),(2,2),(0,0)), 'constant')
#X_validation = np.pad(valid_dataset, ((0,0),(2,2),(2,2),(0,0)), 'constant')
X_test       = np.pad(test_dataset, ((0,0),(2,2),(2,2),(0,0)), 'constant')

print ('Training set after padding 2x2    :', X_train.shape, train_labels.shape)
#print ('Validation set after padding 2x2  :', X_validation.shape, valid_labels.shape)
print ('Test set after padding 2x2        :', X_test.shape, test_labels.shape)
print ('Submission data after padding 2x2 :', X_test.shape)

x = tf.placeholder(tf.float32, shape=[None,32,32,1])
y_ = tf.placeholder(tf.int32, (None))
# LeNet-5 architecture implementation using TensorFlow
# def LeNet_5(x):
#IPython.embed()
# Layer 1 : Convolutional Layer. Input = 32x32x1, Output = 28x28x1.
conv1_w = tf.Variable(tf.truncated_normal(shape = [5,5,1,6],mean = 0, stddev = 0.1))
conv1_b = tf.Variable(tf.zeros(6))
conv1 = tf.nn.conv2d(x,conv1_w, strides = [1,1,1,1], padding = 'VALID') + conv1_b
# TODO: Activation.
conv1 = tf.nn.relu(conv1)

# Pooling Layer. Input = 28x28x1. Output = 14x14x6.
pool_1 = tf.nn.max_pool(conv1, ksize = [1,2,2,1], strides = [1,2,2,1], padding = 'VALID')

# TODO: Layer 2: Convolutional. Output = 10x10x16.
conv2_w = tf.Variable(tf.truncated_normal(shape = [5,5,6,16], mean = 0, stddev = 0.1))
conv2_b = tf.Variable(tf.zeros(16))
conv2 = tf.nn.conv2d(pool_1, conv2_w, strides = [1,1,1,1], padding = 'VALID') + conv2_b
# TODO: Activation.
conv2 = tf.nn.relu(conv2)# TODO: Pooling. Input = 10x10x16. Output = 5x5x16.
pool_2 = tf.nn.max_pool(conv2, ksize = [1,2,2,1], strides = [1,2,2,1], padding = 'VALID')

# TODO: Flatten. Input = 5x5x16. Output = 400.
fc1 = flatten(pool_2)

# TODO: Layer 3: Fully Connected. Input = 400. Output = 120.
fc1_w = tf.Variable(tf.truncated_normal(shape = (400,120), mean = 0, stddev = 0.1))
fc1_b = tf.Variable(tf.zeros(120))
fc1 = tf.matmul(fc1,fc1_w) + fc1_b

# TODO: Activation.
fc1 = tf.nn.relu(fc1)

# TODO: Layer 4: Fully Connected. Input = 120. Output = 84.
fc2_w = tf.Variable(tf.truncated_normal(shape = (120,84), mean = 0, stddev = 0.1))
fc2_b = tf.Variable(tf.zeros(84))
fc2 = tf.matmul(fc1,fc2_w) + fc2_b
# TODO: Activation.
fc2 = tf.nn.relu(fc2)

# TODO: Layer 5: Fully Connected. Input = 84. Output = 10.
fc3_w = tf.Variable(tf.truncated_normal(shape = (84,10), mean = 0 , stddev = 0.1))
fc3_b = tf.Variable(tf.zeros(10))
logits = tf.matmul(fc2, fc3_w) + fc3_b

#Invoke LeNet function by passing features
#logits,   conv1_w, conv1_b, conv2_w, conv2_b, fc1_w, fc1_b, fc2_w, fc2_b, fc3_w, fc3_b, fc1, fc2 = LeNet_5(x)#Softmax with cost function implementation
cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_, logits = logits)
loss_operation = tf.reduce_mean(cross_entropy)
optimizer = tf.train.AdamOptimizer(learning_rate = 0.001)
training_operation = optimizer.minimize(loss_operation)

correct_prediction = tf.equal(tf.argmax(logits,1), tf.argmax(y_,1))
accuracy_operation = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# Evaluate function
def evaluate(X_data, y_data):
     num_examples = len(X_data)
     total_accuracy = 0
     sess = tf.get_default_session()
     for offset in range(0, num_examples, BATCH_SIZE):
         batch_x, batch_y = X_data[offset:offset+BATCH_SIZE], y_data[offset:offset+BATCH_SIZE]
         accuracy = sess.run(accuracy_operation, feed_dict={x: batch_x, y_: batch_y})
         total_accuracy += (accuracy * len(batch_x))
     return total_accuracy / num_examples

#To initialise session and run
EPOCHS = 40
BATCH_SIZE = 128
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    num_examples = len(X_train)

    print("Training... with dataset - ", num_examples)
    print()
    for i in range(EPOCHS):
        X_train, y_train = shuffle(X_train, y_train)
        for offset in range(0, num_examples, BATCH_SIZE):
            end = offset + BATCH_SIZE
            batch_x, batch_y = X_train[offset:end], y_train[offset:end]
            sess.run(training_operation, feed_dict={x: batch_x, y_: batch_y})

        #validation_accuracy = evaluate(X_validation, y_validation)
        print("EPOCH {} ...".format(i+1))
        train_accuracy = evaluate(X_train, y_train)
        print("Train Accuracy = {:.3f}".format(train_accuracy))
        #print()

        test_accuracy = evaluate(X_test, y_test)
        print("Test Accuracy = {:.3f}".format(test_accuracy))
    # save
    saver = tf.train.Saver()
    save_path = saver.save(sess, 'lenet.ckpt')
    print("Model saved %s "%save_path)
    np.savetxt('data/conv1_w', sess.run(conv1_w, feed_dict={x: X_train, y_: y_train}).flatten(),  delimiter=',')
    np.savetxt('data/conv1_b', sess.run(conv1_b, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/conv2_w', sess.run(conv2_w, feed_dict={x: X_train, y_: y_train}).flatten(),  delimiter=',')
    np.savetxt('data/conv2_b', sess.run(conv2_b, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc1_w', sess.run(fc1_w, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc1_b', sess.run(fc1_b, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc2_w', sess.run(fc2_w, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc2_b', sess.run(fc2_b, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc3_w', sess.run(fc3_w, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/fc3_b', sess.run(fc3_b, feed_dict={x: X_train, y_: y_train}),  delimiter=',')
    np.savetxt('data/Y_in', sess.run(fc1, feed_dict={x: X_train, y_: y_train}), delimiter=',')
    np.savetxt('data/Y_out', sess.run(fc2, feed_dict={x: X_train, y_: y_train}), delimiter=',')
    # X_train = X_train[0:100,:,:,:]
    # X_test = X_test[0:100,:,:,:]
    n1, n2, n3, n4 = X_train.shape
    n5, n6, n7, n8 = X_test.shape

    np.savetxt('data/train_x', X_train.reshape(n1, n2*n3),  delimiter=',')
    np.savetxt('data/test_x', X_test.reshape(n5, n6*n7),  delimiter=',')
    train_labels = y_train
    test_labels = y_test
    # m1, m2, m3 = train_labels.shape
    # m4, m5, m6 = test_labels.shape
    np.savetxt('data/train_labels', train_labels,  delimiter=',')
    np.savetxt('data/test_labels', test_labels,  delimiter=',')


from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError, OperationFailure
from dotenv import load_dotenv
from pathlib import Path
import os

def mongodb():
    db = connect().get_database(os.getenv('MONGO_CLUSTER'))
    return db

def check_connection():
    try:
        if connect().admin.command('ismaster')['ismaster']:
            print("connected")
    except OperationFailure:
        print("Database not found")
    except ServerSelectionTimeoutError:
        print("MongoDB Server is down.")

def connect():
    dotenv_path = Path('.env')
    load_dotenv(dotenv_path=dotenv_path)
    client = MongoClient(
        'mongodb+srv://' + os.getenv('MONGO_USER') + ':' + os.getenv(
            'MONGO_PASSWORD') + '@' + os.getenv('MONGO_IDENTIFIER') + '.mongodb.net/?retryWrites=true&w=majority')
    return client


import cx_Oracle as db

if __name__ == '__main__':

    # Estabelecendo conexao
    # username/password@host/SID
    conexao_op = db.connect("locadora/locadora@localhost:1521/xe")
    conexao_dw = db.connect("dw_locadora/dw_locadora@localhost:1521/xe")

    cursor_op = conexao_op.cursor()
    cursor_dw = conexao_dw.cursor()

    def dm_socio():
        tb_socio = cursor_op.execute('select cod_soc, nom_soc , dsc_tps from socios join tipos_socios using(cod_tps)')
        tbs_socio = tb_socio.fetchall()

        for l in tbs_socio:
            cursor_dw.execute("insert into dm_socio(id_soc, nom_soc, tipo_socio) values (:1,:2,:3)", l)

    def dm_artista():
        tb_artista = cursor_op.execute('select cod_art, tpo_art, nac_bras, nom_art from artistas')
        tbs_artista = tb_artista.fetchall()

        for l in tbs_artista:
            cursor_dw.execute("insert into dm_artista(id_art, tpo_art, nac_bras, nom_art) values (:1,:2,:3, :4)", l)

    def dm_titulo():
        tb_titulo = cursor_op.execute('select cod_tit, tpo_tit, cla_tit, dsc_tit from titulos')
        tbs_titulo = tb_titulo.fetchall()

        for l in tbs_titulo:
            cursor_dw.execute("insert into dm_titulo(id_titulo, tpo_titulo, cla_titulo, dsc_titulo) values (:1,:2,:3, :4)",
                              l)

    def dm_gravadora():
        tb_gravadora = cursor_op.execute('select cod_grav, uf_grav, nac_bras, nom_grav from gravadoras')
        tbs_gravadora = tb_gravadora.fetchall()

        for l in tbs_gravadora:
            cursor_dw.execute("insert into dm_gravadora(id_grav, uf_grav, nac_bras, nom_grav) values (:1,:2,:3, :4)", l)

    def dm_tempo():
        tb_tempo = cursor_op.execute(
            """SELECT TO_CHAR(dat_loc, 'YY'), TO_CHAR(dat_loc, 'MM'),TO_CHAR(dat_loc, 'YY/MM'), TO_CHAR(dat_loc, 'MON'),
            TO_CHAR(dat_loc, 'MM/YY'),TO_CHAR(dat_loc, 'fmMONTH'), TO_CHAR(dat_loc, 'DD'), TO_CHAR(dat_loc) ,
            TO_CHAR(dat_loc, 'HH24'), TO_CHAR(dat_loc, 'AM') FROM  itens_locacoes""")

        tbs_tempo = tb_tempo.fetchall()
        tabela_result = []
        id_tempo = 1

        for l in tbs_tempo:
            #if(l)
            tabela_result.append([id_tempo, int(l[0]), int(l[1]), l[2].replace('/', ''),l[3],l[4],l[5],l[6],l[7],l[8],l[9]])
            id_tempo += 1

        for l in tabela_result:
            cursor_dw.execute("insert into dm_tempo(id_tempo, nu_ano, nu_mes, nu_anomes, sg_mes, nm_mesano, nm_mes, "
                              "nu_dia, dt_tempo, nu_hora, turno) "
                              "values (:1,:2,:3, :4, :5, :6, :7, :8, :9, :10, :11)", {"1":l[0],"2": l[1],"3":l[2],"4": int(l[3]),"5":l[4],"6":l[5],"7":l[6],"8":int(l[7]),"9":l[8],"10":int(l[9]),"11":l[10]})

    def ft_locacoes():
        ft_locacoes = cursor_dw.execute(
            """select id_soc, id_titulo, id_art, id_grav, id_tempo""")

        tbs_locacoes = ft_locacoes.fetchall()

        for l in tbs_locacoes:
            cursor_dw.execute("insert into ft_locacoes(id_grav, uf_grav, nac_bras, nom_grav) values (:1,:2,:3, :4)", l)

    dm_tempo()
    conexao_dw.commit()
    cursor_dw.close()
    cursor_op.close()
    conexao_dw.close()
    conexao_op.close()


"""An example usage of brailliant to draw a physics simulation with l4z0rs powered by Pymunk.

Mind that this isn't particularly well-organized or optimized code; it was developed with
the library and things were moving around a lot. It's still really cool, though.
"""

from __future__ import annotations

import argparse
import asyncio
import math
import random
import shutil
import signal
import textwrap
from abc import ABC
from collections import deque
from itertools import chain, pairwise, zip_longest
from typing import Iterator

import pymunk
from asynkets import async_getch, PeriodicPulse
from pymunk import Vec2d

from brailliant import BRAILLE_ROWS
from brailliant.canvas import Canvas
from brailliant.cli_utils import setup_terminal
from examples.android_sensors import get_sensor_output

err = deque(maxlen=20)

w, h = shutil.get_terminal_size()

UI_W = 10
UI_W_PADDING = 3
CANVAS_W, CANVAS_H = w * 2, h - h % 8

SIM_SCALE = 1
SHAPE_ELASTICITY = 0.97
MAX_G = 499

class PhysObj(ABC):
    body: pymunk.Body
    shape: pymunk.Shape

class Ball(PhysObj):
    def __init__(
        self,
        x: float,
        y: float,
        vx: float,
        vy: float,
        radius: float,
        mass: float | None = None,
    ) -> None:
        x, y = x, y
        vx, vy = vx, vy

        if mass is None:
            mass = math.pi * radius**2

        self.body = pymunk.Body(
            mass=mass,
            moment=pymunk.moment_for_circle(mass, 0, radius),
        )
        self.body.position = x, y
        self.body.velocity = vx, vy
        self.shape = pymunk.Circle(self.body, radius)
        self.shape.elasticity = SHAPE_ELASTICITY

    def draw(self, canvas: Canvas) -> Canvas:
        # Draw the ball at its current position in the Pymunk space
        return canvas.draw_circle(
            int(self.body.position.x),
            int(self.body.position.y),
            int(self.shape.radius),
            False,
            angle_step=1.5,
        )

class Rectangle(PhysObj):
    def __init__(
        self,
        x: float,
        y: float,
        vx: float,
        vy: float,
        width: float,
        height: float,
        mass: float | None = None,
    ) -> None:
        # Convert input values to Pymunk scale
        x, y = x, y
        vx, vy = vx, vy
        width *= SIM_SCALE
        height *= SIM_SCALE

        # Calculate mass if not provided
        if mass is None:
            mass = width * height

        # Create the body and shape for the rectangle
        self.body = pymunk.Body(mass=mass)
        self.body.position = x, y
        self.body.velocity = vx, vy
        self.body.center_of_gravity = (width / 2, height / 2)
        self.body.angular_velocity = 4
        self.shape = pymunk.Poly(self.body, [(0, 0), (width, 0), (width, height), (0, height)])
        self.body.moment = pymunk.moment_for_poly(mass, self.shape.get_vertices())
        self.shape.elasticity = SHAPE_ELASTICITY

    def draw(self, canvas: Canvas) -> Canvas:
        for s in self.body.shapes:
            first_vertex = s.body.local_to_world(s.get_vertices()[0])
            v1w_x, v1w_y = first_vertex.x, first_vertex.y
            for v0, v1 in pairwise(s.get_vertices()):
                v0w_x, v0w_y = s.body.local_to_world(v0)
                v1w_x, v1w_y = s.body.local_to_world(v1)
                canvas = canvas.draw_line(int(v0w_x), int(v0w_y), int(v1w_x), int(v1w_y))

            canvas = canvas.draw_line(
                int(v1w_x),
                int(v1w_y),
                int(first_vertex.x),
                int(first_vertex.y),
            )
        return canvas

class Triangle(PhysObj):
    def __init__(
        self,
        x: float,
        y: float,
        vx: float,
        vy: float,
        base: float,
        height: float,
        mass: float | None = None,
    ) -> None:
        # Convert input values to Pymunk scale
        x, y = x, y
        vx, vy = vx, vy
        base *= SIM_SCALE
        height *= SIM_SCALE

        # Calculate mass if not provided
        if mass is None:
            mass = 0.5 * base * height

        # Create the body and shape for the triangle
        self.shape = pymunk.Poly(None, [(0, 0), (base, 0), (base / 2, height)])
        self.body = pymunk.Body(
            mass=mass, moment=pymunk.moment_for_poly(mass, self.shape.get_vertices())
        )

        self.body.center_of_gravity = (base / 2, height / 2)
        self.shape.body = self.body
        self.body.position = x, y
        self.body.velocity = vx, vy
        self.shape.elasticity = SHAPE_ELASTICITY

    def draw(self, canvas: Canvas) -> Canvas:
        # Convert the Pymunk coordinates to canvas coordinates
        for s in self.body.shapes:
            first_vertex = s.body.local_to_world(s.get_vertices()[0])

            v1w_x, v1w_y = -1, -1
            for v0, v1 in pairwise(s.get_vertices()):
                v0w_x, v0w_y = s.body.local_to_world(v0)
                v1w_x, v1w_y = s.body.local_to_world(v1)
                canvas = canvas.draw_line(int(v0w_x), int(v0w_y), int(v1w_x), int(v1w_y))

            first_vertex_x, first_vertex_y = first_vertex
            canvas = canvas.draw_line(
                int(v1w_x),
                int(v1w_y),
                int(first_vertex_x),
                int(first_vertex_y),
            )
        return canvas

def get_space():
    """Create a Pymunk space with the default gravity and collision handler."""

    # Initialize Pymunk
    space = pymunk.Space()
    space.damping = 0.999

    wall_radius = 30

    # Set up the walls as Pymunk segments
    right_wall = pymunk.Segment(
        space.static_body,
        (CANVAS_W + wall_radius, 0),
        (CANVAS_W + wall_radius, CANVAS_H),
        wall_radius,
    )
    left_wall = pymunk.Segment(
        space.static_body,
        (-wall_radius, 0),
        (-wall_radius, CANVAS_H),
        wall_radius,
    )
    top_wall = pymunk.Segment(
        space.static_body,
        (0, -wall_radius),
        (CANVAS_W, -wall_radius),
        wall_radius,
    )
    bottom_wall = pymunk.Segment(
        space.static_body,
        (0, CANVAS_H + wall_radius),
        (CANVAS_W, CANVAS_H + wall_radius),
        wall_radius,
    )

    left_wall.elasticity = 1.0  # Set the elasticity (bounciness) of the walls
    right_wall.elasticity = 1.0
    top_wall.elasticity = 1.0
    bottom_wall.elasticity = 1.0
    space.add(left_wall, right_wall, top_wall, bottom_wall)  # Add the walls to the Pymunk space

    # Wall in the middle just for show
    mid_wall = pymunk.Segment(
        space.static_body,
        (round(CANVAS_W / 2), 0),
        (round(CANVAS_W / 2), round(CANVAS_H / 4)),
        1,
    )
    mid_wall.elasticity = 1.0
    space.add(mid_wall)

    return space

def get_objs():
    """Create the objects in the simulation."""

    # Create the objs and add them to the Pymunk space
    return [
        Ball(
            x=CANVAS_W / 4,
            y=CANVAS_H / 4,
            vx=random.uniform(-3, 3),
            vy=random.uniform(-3, 3),
            radius=5,
            mass=2,
        ),
        Ball(
            x=CANVAS_W / 4 * 2,
            y=CANVAS_H / 4,
            vx=random.uniform(-3, 3),
            vy=random.uniform(-3, 3),
            radius=11,
            mass=10,
        ),
        Rectangle(
            x=CANVAS_W / 4 * 3,
            y=CANVAS_H / 4 * 2,
            vx=random.uniform(-3, 3),
            vy=random.uniform(-3, 3),
            width=30,
            height=25,
            mass=10,
        ),
        Triangle(
            x=CANVAS_W / 4,
            y=CANVAS_H / 4 * 2,
            vx=random.uniform(-3, 3),
            vy=random.uniform(-3, 3),
            base=20,
            height=22,
            mass=10,
        ),
        Triangle(
            x=CANVAS_W / 4,
            y=CANVAS_H / 4 * 3,
            vx=random.uniform(-3, 3),
            vy=random.uniform(-3, 3),
            base=10,
            height=6,
            mass=3,
        ),
    ]

def raycast(
    space: pymunk.Space,
    light_start: Vec2d,
    light_end: Vec2d,
    light_length: float,
    max_bounces: int | None = None,
    ignored_shapes: list[pymunk.Shape] | None = None,
) -> Iterator[tuple[Vec2d, Vec2d]]:
    """Return the point where the light ray hits the wall."""
    if ignored_shapes is None:
        ignored_shapes = []

    seg_query = space.segment_query(
        (light_start.x, light_start.y),
        (light_end.x, light_end.y),
        0,
        pymunk.ShapeFilter(),
    )
    seg_query_sorted = list(
        sorted(
            [sq for sq in seg_query if sq.shape not in ignored_shapes],
            key=lambda sq: sq.alpha,
        )
    )

    if not seg_query_sorted:
        yield light_start, light_end
        return

    col_query = seg_query_sorted[0]
    light_end = col_query.point
    yield light_start, light_end

    crt_ray = light_end - light_start

    consumed = crt_ray.length
    light_length -= consumed
    if light_length <= 0:
        return
    col_shape = col_query.shape
    normal = col_query.normal
    if isinstance(col_shape, pymunk.Segment):
        normal = normal.rotated_degrees(crt_ray.get_angle_degrees_between(normal) * 2)
    next_start = light_end
    next_end = next_start + normal * light_length
    if light_length > 1 and (max_bounces is None or max_bounces > 0):
        yield from raycast(
            space,
            next_start,
            next_end,
            light_length,
            max_bounces - 1 if max_bounces is not None else None,
            ignored_shapes=[col_shape] if col_shape is not None else None,
        )

async def show_balls(android_sensors: bool = False) -> None:
    """Create the canvas and show our balls."""

    setup_terminal(CANVAS_H // BRAILLE_ROWS + 8)  # fit the UI and canvas

    canvas = Canvas(CANVAS_W, CANVAS_H)
    canvas.draw_rectangle(0, 0, CANVAS_W - 1, CANVAS_H - 1)
    canvas.draw_line(
        round(CANVAS_W / 2),
        0,
        round(CANVAS_W / 2),
        round(CANVAS_H / 4),
    )

    space = get_space()
    objs = get_objs()
    for obj in objs:
        space.add(obj.body, obj.shape)

    gravy_on = True
    time_on = True
    lasers_bounce_on = False
    lasers_on = False
    gravy = Vec2d(0, -98.1)
    space.gravity = gravy

    async def process_inputs() -> None:
        nonlocal time_on, gravy_on, gravy, lasers_on, lasers_bounce_on

        async for ch in async_getch():
            # Toggle gravity on g
            if ch.lower() == b"g":
                gravy_on = not gravy_on
                if gravy_on:
                    space.gravity = gravy
                else:
                    gravy = space.gravity
                    space.gravity = Vec2d(0, 0)

            # Toggle time on t
            elif ch.lower() == b"t":
                time_on = not time_on

            elif ch.lower() == b"l":
                lasers_on = not lasers_on

            elif ch.lower() == b"b":
                lasers_bounce_on = not lasers_bounce_on

            elif ch == b"\x1b[C":  # Right arrow
                space.gravity = space.gravity.rotated_degrees(6)

            elif ch == b"\x1b[D":  # Left arrow
                space.gravity = space.gravity.rotated_degrees(-6)

            elif ch == b"\x1b[A":  # Up arrow
                space.gravity *= 1.02
                if space.gravity.length > MAX_G:
                    space.gravity = space.gravity.normalized() * MAX_G

            elif ch == b"\x1b[B":  # Down arrow
                space.gravity *= 0.98

    loop = asyncio.get_event_loop()
    t = loop.time()
    time_step = 0.01
    dt = time_step

    def draw_light(copy: Canvas) -> None:
        light_start = Vec2d(2, CANVAS_H / 2)
        rays = chain.from_iterable(
            raycast(
                space,
                light_start,
                light_start + Vec2d(200, 0).rotated_degrees(i / 2),
                CANVAS_W * 0.8,
                max_bounces=8 if lasers_bounce_on else 0,
            )
            for i in range(-30, 31)
        )

        for ray_start, ray_end in rays:
            copy.draw_line(int(ray_start.x), int(ray_start.y), int(ray_end.x), int(ray_end.y))

    def get_ui_str():
        fps = 1 / dt
        stats = [
            f"fps: {fps:03.0f}",
            f"gravity: {space.gravity.length:03.2f} ({space.gravity.angle_degrees:03.2f}°)",
            f"gravity on: {gravy_on}",
            f"time on: {time_on}",
            f"laz0rs on: {lasers_on}",
            f"laz0r bounce: {lasers_bounce_on}",
        ]
        keys = [
            "g: toggle gravity",
            "t: toggle time",
            "up/down: gravity strength",
            "left/right: gravity angle",
            "l: toggle laz0rs",
            "b: toggle laz0r bounce",
        ]

        # Draw the UI (stats and keys). It's joined by newlines and the control
        # characters for clearing a line; this is so that the UI is always
        # redrawn (and e.g. updating FPS from 100 to 99 doesn't leave a ghost 1).
        # The UI is displayed in two columns, with the keys on the left and the
        # stats on the right.

        zipped = zip_longest(stats, keys, fillvalue="")

        ui = f"\n\x1b[2K".join(f"\x1b[2K{stat:<30} {key:<30}" for stat, key in zipped)
        ui = textwrap.indent(ui, " " * UI_W_PADDING)
        return ui

    def draw():
        """Draw the current state of the simulation."""
        copy = canvas.copy()

        for o in objs:
            copy = o.draw(copy)
        if lasers_on:
            draw_light(copy)
        ui = get_ui_str()

        s = "".join(
            (
                "\033[u",  # Restore the cursor position
                copy.get_str(),  # Draw the canvas
                "\n\n",  # Move cursor down
                ui,  # Draw the UI
            )
        )

        print(s, end="", flush=True)

    async def android_sensors_update_gravity() -> None:
        async for x, y, z in get_sensor_output():
            space.gravity = Vec2d(x, y) * -20
            if space.gravity.length > MAX_G:
                space.gravity = space.gravity.normalized() * MAX_G

    asyncio.create_task(process_inputs())

    async def update_physics():
        nonlocal t, dt, gravy
        prev_t = t
        t = loop.time()
        dt = t - prev_t
        if time_on:
            space.step(dt)

    drawer = PeriodicPulse(1 / RATE)

    if android_sensors:
        space.damping = 0.98
        drawer.add_pulse_callback(android_sensors_update_gravity)

    drawer.add_pulse_callback(draw)
    drawer.add_pulse_callback(update_physics)

    exit_fut = loop.create_future()

    # SIGTERM vs SIGINT - SIGTERM is sent by the OS when the process is killed
    # (e.g. with `kill`), while SIGINT is sent by the user (e.g. with Ctrl+C).
    asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, exit_fut.set_result, None)
    asyncio.get_event_loop().add_signal_handler(signal.SIGINT, exit_fut.set_result, None)

    await exit_fut
    drawer.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        "Physics simulator",
        description="Simulate physics with pymunk and brailliant.",
    )
    parser.add_argument(
        "--android",
        action="store_true",
        help="Run in android mode (uses Termux API to get sensor data for gravity)",
    )
    parser.add_argument(
        "--rate",
        type=int,
        default=120,
        help="Physics and screen refresh rate",
    )

    args = parser.parse_args()
    RATE = args.rate

    asyncio.run(show_balls(android_sensors=args.android))