from typing import Dict, List
import numpy as np
import pandas as pd

class Perimeter:
    REAL_PERIMETER = 518.4

    def __init__(self, point_names, directions: list = None) -> None:
        self.point_names = point_names
        self.initial_coordinates = {}
        self.point_pairs = []
        self.directions = {}

        self.form_point_pairs()
        self.calculate_directions(directions)
        self.compute_initial_coordinates()

    def form_point_pairs(self) -> None:
        for i in range(len(self.point_names)-1):
            self.point_pairs.append((self.point_names[i], self.point_names[i+1]))
        self.point_pairs.append((self.point_names[-1], self.point_names[0]))

    def calculate_directions(self, directions: list = None) -> None:
        # calculating angle for each point considering an evenly space distribution
        # and that East direction is at 0 degrees
        for i, point_name in enumerate(self.point_names):
            self.directions[point_name] = i/len(self.point_names) * 360 if not directions else directions[i]

    def compute_initial_coordinates(self) -> None:
        # defining circunference size
        circum = self.REAL_PERIMETER
        radius = circum / (2*np.pi)
        # calculating initial coordinates for the points in the discrete circle
        # in relation to its center
        for dir in self.directions:
            theta = self.directions[dir] * (np.pi / 180)
            x = radius * np.cos(theta)
            y = radius * np.sin(theta)
            z = 0
            self.initial_coordinates[dir] = (x, y, z)

    @staticmethod
    def print_progress_bar (iteration, total, prefix = 'Progress:', suffix = 'Complete', decimals = 1, length = 50, fill = '█', print_end = "\r"):
        percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
        filled_length = int(length * iteration // total)
        bar = fill * filled_length + '-' * (length - filled_length)
        print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = print_end)
        # Print New Line on Complete
        if iteration == total:
            print()

    @staticmethod
    def calc_2point_dist(pt1: List, pt2: List, mode: str ='2D') -> float:
        if (mode == '2D'):
            dist = ((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2)**0.5
        elif (mode == '3D'):
            dist = ((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2 + (pt1[2] - pt2[2])**2)**0.5
        return dist

    def calc_perimeter(self, points: Dict) -> float:
        """calculates perimeter by iterating over each pair of adjacent points and summing its current distances"""
        perim = 0
        for pairs in self.point_pairs:
            perim += Perimeter.calc_2point_dist(points[pairs[0]], points[pairs[1]], mode='3D')

        return perim

    def calculate_delta_perimeter(self, deformation_type: str, deformation: pd.DataFrame or Dict[pd.DataFrame]) -> np.ndarray:
        # setting first perimeter value as the initial/unaltered one
        perimeter_value = [self.calc_perimeter(self.initial_coordinates)]

        # defining the index to iterate over
        datetime_index = deformation.index if deformation_type == 'temperature' else list(deformation.values())[0].index

        # definining and calling the progress bar
        len_data = len(datetime_index) * len(self.point_names)
        Perimeter.print_progress_bar(0, len_data)

        # starting iteration for perimeter calculation
        for i, timestamp in enumerate(datetime_index):
            curr_pos = {}
            for j, coord in enumerate(self.point_names):
                # setting default coordinates
                x_pos = self.initial_coordinates[coord][0]
                y_pos = self.initial_coordinates[coord][1]
                z_pos = self.initial_coordinates[coord][2]

                # adding tidal effects
                if (deformation_type == 'tides'):
                    if (coord in deformation):
                        x_pos += deformation[coord].loc[timestamp,'East']
                        y_pos += deformation[coord].loc[timestamp,'North']
                        z_pos += deformation[coord].loc[timestamp,'Up']
                # adding thermal effects
                elif (deformation_type == 'temperature'):
                    if (coord in deformation.columns):
                        theta = self.directions[coord] * (np.pi / 180)
                        x_pos += np.cos(theta) * deformation.loc[timestamp, coord]
                        y_pos += np.sin(theta) * deformation.loc[timestamp, coord]

                curr_pos[coord] = (x_pos, y_pos, z_pos)

                # printing progress
                count = i * len(self.point_names) + j
                if (count % int(len_data/10) == 0):
                    Perimeter.print_progress_bar(count, len_data)

            perimeter_value.append(self.calc_perimeter(curr_pos))
        # setting first record as reference
        delta_perimeter = np.array(perimeter_value) - perimeter_value[0]
        return delta_perimeter


# Emily Snodgrass

# find the most frequently occuring number (the mode) in a series of
# numbers entered by the user
freq = []
index = 0
size = 11

# create a list of length 11 filled with zeros
while(index < size):
	freq.append(0)
	index = index + 1

# count how many times each number appears as data is entered
data = int(input("Input some numbers between 0 and 10\n(enter a negative to stop)\n"))
while (data >= 0 and data < size):
	freq[data] = freq[data] + 1
	data = int(input())

#find the largest frequency (mode)
index = 0
mode = 0
while (index < size):
	if (freq[index] > mode):
		mode = freq[index]
	index = index + 1

# print all numbers with the largest frequency
index = 0
print("Mode(s) =", end=" ")
while (index < size and mode > 0):
	if (freq[index] == mode):
		print(index, end=" ")
	index = index + 1

if (mode == 0):
	print("No data")


from Math_Logic.Tree import TreeNode
from Math_Logic.Statement import Statement
from Math_Logic.Property import Property
from Math_Logic.Term import Term
from Math_Logic import ParseStr
import copy

"""
MathTree is the main MathLogic class. Each node consists of either one statement or one property. Also for each node the
contained active adjective etc letters are saved in a sql table.
"""

class MathTree(TreeNode):

    def __init__(self, parent, sentence, position=(0, 0)):
        super().__init__(parent)

        # a sentence is either a property or a statement
        self.sentence = sentence

        self.let_contained = []
        self.let_active = []
        self.let_adjective = []
        self.let_definite = []
        self.equal = []
        self.abbreviations = {}
        self.type = None
        if self.sentence.__class__.__name__ == "str":
            self.sentence = Statement(self.sentence)
        if self.sentence.__class__.__name__ == "Statement":
            self.set_up_statement()
            self.type = "statement"
        elif self.sentence.__class__.__name__=="Property":
            self.set_up_property()
            self.type = "property"

    def set_up_statement(self):
        self.let_contained = self.sentence.get_letters()
        if self.parent is not None:
            self.let_definite = self.parent.let_definite
            self.let_adjective = self.parent.let_adjective
            self.let_active = self.parent.let_active+self.parent.let_contained
            self.equal = self.parent.equal
            self.abbreviations = self.parent.abbreviations
        # definite
        if not self.sentence.presumptions:
            for letter in self.sentence.get_letters():
                if letter not in self.let_adjective:
                    self.let_definite.append(letter)
        # elementary equal
        if self.sentence.is_equality():
            self.equal.append((self.sentence.parameters[0], self.sentence.parameters[1]))

    def set_up_property(self):
        if self.parent is not None:
            self.let_definite = self.parent.let_definite
            self.let_adjective = self.parent.let_adjective
            self.let_active = self.parent.let_active+self.parent.let_contained
            self.equal = self.parent.equal
            self.abbreviations = self.parent.abbreviations
        # adjective
        self.let_adjective.append(self.sentence.contraction.acronym.char)
        if self.sentence.contraction.acronym not in self.abbreviations:
            self.abbreviations[self.sentence.contraction.acronym] = self.sentence
        self.let_adjective = list(set(self.let_adjective))

    # Addition Rule 2.2 and Rule 4.3

    def addition(self, var1, var2, relation):
        check = self.check_addition(var1, var2, relation)
        if check[0]:
            childstatement = Statement(var1 + relation + var2)
            child = MathTree(self, childstatement)
            self.add_child(child)
            return True, "Elementary Addition successful", child
        else:
            return False, check[1]

    def check_addition(self, var1, var2, relation):
        var1, var2 = Term(var1), Term(var2)
        letters1 = var1.get_letters()
        letters2 = var2.get_letters()
        # functional term
        if var1.is_functional() and var2.is_functional():
            return False, "cant add two functional terms"
        if var1.is_functional():
            if var2 not in self.let_active:
                for let in letters1:
                    if let not in self.let_definite:
                        return False, "letter is not definite"
                return True, "possible elementary addition"
        if var2.is_functional():
            if var1 not in self.let_active:
                for let in letters2:
                    if let not in self.let_definite:
                        return False, "letter is not definite"
                return True, "possible elementary addition"
        # elementary Term
        if (var1 not in self.let_active and var2 in self.let_definite) or (
                var2 not in self.let_active and var1 in self.let_definite):
            return True, "possible elementary addition"
        if (var1 not in self.let_active and var2 not in self.let_active) or (
                var1 in self.let_definite and var2 in self.let_definite):
            if var1 == var2 and relation == "=":
                return True, "possible elementary addition"
            return False, "If both letter are of the same flavour, the equality must be reflexive"
        return False, "Both letters have to either be inactive or indefinite"

    # Elementary Substitution Rule 2.3

    def elementary_substitution(self, node, var1, var2):
        if self.type == "statement":
            if self.check_equal(var1, var2):
                var1, var2 = Term(var1), Term(var2)
                modcopy = node.sentence.replace(var1, var2)
                child = MathTree(self, modcopy)
                self.add_child(child)
                return True, "Substitution successful", child
            else:
                return False, "These are not equal"
        return False, "substitution can only be "

    def check_equal(self, var1, var2):
        var1, var2 = Term(var1), Term(var2)
        if (var1, var2) in self.equal or (var2, var1) in self.equal:
            return True
        return False

    # Dual Statements Rule 2.4

    def dual_statement(self, statementstr):
        # add dual statements to a leaf
        statement = Statement(statementstr)
        dual = statement.get_dual()
        if statement.check_admissible(self) and dual.check_admissible(self):
            childa = MathTree(self, statement)
            childb = MathTree(self, dual)
            self.add_child(childa)
            self.add_child(childb)
            return True, "added dual statement", childa, childb
        return False, "dual statement not admissible"

    def contradiction(self, anc1, anc2):
        # if two contradictory statements are found, go back to the last dual split, and add the right statement as
        # middle child
        if anc1.sentence == anc2.sentence.get_dual():
            cur, lastcur = self, self
            while len(cur.children) != 2:
                if cur.has_parent():
                    lastcur = cur
                    cur = cur.parent
                else:
                    return False, "False Tree, mistakes were made"
            child = MathTree(self, lastcur.sentence.get_dual())
            cur.add_child(child, "middle")
            return True, "Contradiction successful"
        return False, "statements not dual"

    def twin_agreement(self, anc1):
        if anc1.sentence == self.sentence:
            cur = self
            while len(cur.children) != 2:
                if cur.has_parent():
                    cur = cur.parent
            if anc1.is_ancestor(cur):
                child = MathTree(self, self.sentence)
                cur.add_child(child, "middle")
                return True, " successful"
            else:
                return False, "These nodes are not twins"
        return False, "statements nto dual"

    # Definition Rule 3.3

    def definition(self, ancestor, var_Str):
        if len(ancestor.sentence.presumptions) > 0:
            hypothesis = ancestor.sentence.presumptions[0][1]
            hyp_quantifier = ancestor.sentence.presumptions[0][0]
            conclusion = ancestor.sentence.copy()
            conclusion.presumptions = conclusion.presumptions[1:]
            if hyp_quantifier == "existential":
                if hypothesis.check_admissible(self):
                    child = MathTree(self, hypothesis)
                    subchild = MathTree(self, conclusion)
                    self.add_child(child)
                    child.add_child(subchild)
                else:
                    var = Term(var_Str)
                    if var not in self.let_active:
                        var_indefinite = Term(repr(hypothesis.get_first_indefinite(self)))
                        child_statement = hypothesis.replace(var_indefinite, var).copy()
                        subchild_statement = conclusion.replace(var_indefinite, var).copy()
                        child = MathTree(self, child_statement)
                        subchild = MathTree(self, subchild_statement)
                        self.add_child(child)
                        child.add_child(subchild)
                    else:
                        return False, "the entered variable is not inactive"
            else:
                return False, "ancestor is not existential"
        else:
            return False, "ancestor is not quantified"
        return True, "successful definition", child, subchild

    # Deduction Rule 3.4

    def Deduction(self, ancestor, hypothesis_ancestor):
        if hypothesis_ancestor.sentence.presumptions > ancestor.sentence.presumptions:
            temp = hypothesis_ancestor
            hypothesis_ancestor = ancestor
            ancestor = temp
        if len(ancestor.sentence.presumptions) > 0:
            hypothesis = ancestor.sentence.presumptions[0][1]
            hyp_quantifier = ancestor.sentence.presumptions[0][0]
            conclusion = ancestor.sentence.copy()
            conclusion.presumptions = conclusion.presumptions[1:]
            if hyp_quantifier == "universal":
                if hypothesis.check_admissible(self):
                    if hypothesis == hypothesis_ancestor.sentence:
                        child = MathTree(self, Statement(hypothesis))
                        subchild = MathTree(self, Statement(conclusion))
                        self.add_child(child)
                        child.add_child(subchild)
                    else:
                        return False, "The hypothesis is not the statement of the third ancestor"
                else:
                    hypanc = hypothesis_ancestor.sentence
                    hyp_lets, hypanc_lets = hypothesis.get_letters(), hypanc.get_letters()
                    if len(hyp_lets) == len(hypanc_lets):
                        index = 0
                        if hypanc == hypothesis:
                            return False, "Third ancestor is not modified copy of hypothesis"
                        while hyp_lets[index] == hypanc_lets[index]:
                            index += 1
                        mod_hypothesis = hypothesis.replace(hyp_lets[index], hypanc_lets[index])
                        if mod_hypothesis == hypanc:
                            child_statement = hypothesis.replace(hyp_lets[index], hypanc_lets[index]).copy()
                            subchild_statement = conclusion.replace(hyp_lets[index], hypanc_lets[index]).copy()
                            if child_statement.check_admissible(self) and subchild_statement.check_admissible(self):
                                subchild = MathTree(self, subchild_statement)
                                self.add_child(subchild)
                            else:
                                return False, "Either the modified hypothesis or modified conclusion are not admissible"
                        else:
                            return False, "hypothesis can not be modified to equal third ancestor"
                    else:
                        return False, "hypothesis can not be modified to equal third ancestor"
            else:
                return False, "ancestor is not universal"
        else:
            return False, "ancestor is not quantified"
        return True, "successful definition", subchild

    # Property addition Rule 4.7

    def property_addition(self, prop_str):
        if ParseStr.check_valid_prop_string(prop_str):
            property = Property(prop_str)
            if property.check_admissible(self):
                if property.contraction.acronym.char in self.let_adjective:
                    if self.abbreviations[property.contraction.acronym].check_modified_copy(property):
                        child = MathTree(self, property)
                        self.add_child(child)
                        return True, "Property Addition successful", child
                    return False, "Property is not proper modified copy"
                child = MathTree(self, property)
                self.add_child(child)
                return True, "Property Addition successful", child
            return False, "The Property was not admissible"
        return False, "Not a valid property string"

    # Apply Property Rule 4.9

    def apply_property(self, property, statement):
        if property.__class__.__name__ == "Property" and statement.__class__.__name__ == "Statement":
            pass
        elif property.__class__.__name__ == "Statement" and statement.__class__.__name__ == "Property":
            temp = property
            property = statement
            statement = temp
        else:
            return False, "One sentence must be a property, while the other is a statement"
        if property.sentence.contraction.acronym == statement.sentence.acronym:
            if len(property.sentence.contraction.parameters) == len(statement.sentence.parameters):
                copy_statement = property.sentence.expansion.copy()
                for index in range(len(property.sentence.contraction.parameters)):
                    copy_statement = copy_statement.replace(property.sentence.contraction.parameters[index],
                                                            statement.sentence.parameters[index])
                    child = MathTree(self, copy_statement)
                    self.add_child(child)
                    return True, "Property application successful", child
            return False, "Something went wrong, different number of parameters"
        return False, "Property must define the acronym of statement"

    # Choice 1 Rule 5.2

    def choice(self, node, variables, additions, secondnode=None):
        # variables is a list of first the two indefinite, then the inactive and finally the 5 definite letters
        # additions is a list of 7 boolean values, describing what nodes to add
        if additions[0] or additions[1]:
            if variables[0] not in self.let_active:
                for i in range(1, 6):
                    if variables[i] not in self.let_definite:
                        return False, "A definite letter is not definite"

                inactive = variables[0]
                def1, def2, def3, def4, def5, def6 = \
                    variables[1], variables[2], variables[3], variables[4], variables[5], variables[6]
                children = []

                if len(node.sentence.parameters) < 2:
                    return False, "Non-valid ancestor"
                sentence1 = node.sentence.presumptions[0]
                sentence2 = node.sentence.presumptions[1]
                for index, hypothesis in enumerate([sentence1, sentence2]):
                    if hypothesis[0] != ["universal", "existential"][index]:
                        return False, "Non-Valid first ancestor"
                    if hypothesis[1].presumptions != []:
                        return False, "Non-Valid first ancestor"
                sentence1, sentence2 = sentence1[1], sentence2[1]
                indef1 = repr(sentence1.get_first_indefinite(self))
                indef2 = repr(sentence2.get_first_indefinite(self))
                if indef1 == None or indef2 == None:
                    return False, "Non-Valid first ancestor"

                cur_node = self

                if additions[0]:
                    statement = Statement(str(inactive + "=" + inactive))
                    child = MathTree(cur_node, statement)
                    cur_node.add_child(child)
                    children.append(child)
                    cur_node = child
                # first statement
                if additions[1]:
                    print(indef2)
                    print(node.sentence)
                    copy = node.sentence.replace(Term(indef2), Term(inactive+"("+indef1+")"))
                    copy.presumptions = copy.presumptions[1:]
                    statement = Statement(str("{"+inactive + "(" + indef1 + ")" + "!=" + inactive + "}" + repr(copy)))
                    child = MathTree(cur_node, statement)
                    cur_node.add_child(child)
                    children.append(child)
                    cur_node = child

                if additions[2]:
                    copy = node.sentence.replace(Term(indef2), Term(inactive+"("+indef1+")"))
                    copy.presumptions = copy.presumptions[2:]
                    statement = Statement(str("{"+inactive + "(" + indef1 + ")" + "!=" + inactive + "}" + repr(copy)))
                    child = MathTree(cur_node, statement)
                    cur_node.add_child(child)
                    children.append(child)
                    cur_node = child
                # second statement
                if additions[3]:
                    statement = Statement(str("{"+inactive+"(" + indef1+")" + "!=" + inactive + "}" + repr(sentence1)))
                    child = MathTree(cur_node, statement)
                    cur_node.add_child(child)
                    children.append(child)
                    cur_node = child

                if sentence1.is_equality() and sentence1.parameters[0] == sentence1.parameters[1]:

                    # third statement
                    if additions[4]:
                        statement = Statement(str(inactive+"(" + def1+")" + "!=" + inactive))
                        child = MathTree(cur_node, statement)
                        cur_node.add_child(child)
                        children.append(child)
                        cur_node = child

                    # fourth statement
                    if additions[5]:
                        statement = Statement(str("{"+def1+"(" + indef1+")" + "!=" + def1+"}"
                                                  +inactive+"(" + indef1+")" + "!=" + inactive))
                        child = MathTree(cur_node, statement)
                        cur_node.add_child(child)
                        children.append(child)
                        cur_node = child

                    # fifth statement
                    if additions[6]:
                        statement = Statement(str("{"+def3+"(" + indef1+")" + "!=" + def3+"}"
                                                  + "{"+indef1+"(" + indef2+")" + "!=" + indef1+"}"
                                                  + inactive+"(" + indef2+")" + "!=" + inactive))
                        child = MathTree(cur_node, statement)
                        cur_node.add_child(child)
                        children.append(child)
                        cur_node = child

                    # sixth statement
                    if additions[7]:
                        statement = Statement(str("{" + inactive + "(" + indef1 + ")" + "!=" + inactive + "}"
                                                  + inactive + "(" + inactive + "(" + indef1 + ")" + ")"
                                                  + "!=" + inactive + "(" + indef1 + ")"))
                        child = MathTree(cur_node, statement)
                        cur_node.add_child(child)
                        children.append(child)
                        cur_node = child

                    # seventh statement
                    if additions[8]:
                        statement = Statement(str("{"+inactive+"("+indef1+")!="+inactive+"}"+"["+indef1+"("+indef2+")!="
                                                  +indef1+"]"+"{"+def4+"("+indef2+")!="+def4+"}"
                                                  +def5+"("+indef1+"("+indef2+")"+")!="+def5))
                        child = MathTree(cur_node, statement)
                        cur_node.add_child(child)
                        children.append(child)
                        cur_node = child

                    if secondnode:
                        anc_sent = secondnode.sentence
                        if len(anc_sent.presumptions) > 1 and anc_sent.presumptions[0][0] == "universal":
                            mod_sentence1 = sentence1.replace()
                            pre1 = anc_sent.presumptions[0][1].replace(def3, indef1)
                            if pre1 == sentence1:
                                pass
                            # eighth statement
                            if additions[9]:
                                statement = Statement(str("{"+sentence1+"}"+inactive+"("+indef1+") != " +inactive))
                                child = MathTree(cur_node, statement)
                                cur_node.add_child(child)
                                children.append(child)
                                cur_node = child

                            # ninth statement
                            if additions[10]:
                                statement = node.sentence.replace(indef2, Term(str(inactive+"("+indef1+")")))
                                child = MathTree(cur_node, statement)
                                cur_node.add_child(child)
                                children.append(child)
                                cur_node = child

                return True, "Choice succesful", children, cur_node

            return False, "The inactive letter is active"
        return False, "one of the first two nodes have to be added first"

    def convert_text(self):
        def childtree(child):
            if len(child.children) == 0:
                return "{[(" + repr(child.sentence) + ")]}"
            else:
                str = "{[( {[(" + repr(child.sentence) + ")]}"
                for subchild in reversed(child.children):
                    str += childtree(subchild)
                str += ")]}"
                return str
        if len(self.children) == 0:
            return str
        return str+childtree(self)

    def tex_compile_tikz(self):
        str = ""
        str += "\\node{"+repr(self.sentence)+"}"
        def childtree(child):
            if len(child.children) == 0:
                return "child { node {" + repr(child.sentence) + "} }"
            else:
                str = "child { node {" + repr(child.sentence) + "}"
                for subchild in reversed(child.children):
                    str += childtree(subchild)
                str += "}"
                return str
        if len(self.children) == 0:
            return str
        return str+childtree(self)

    def tex_compile_forest(self):
        str = ""
        str += "\\begin{forest} squared/.style={rectangle,draw}"

        def childtree(child):
            if len(child.children) == 0:
                return "[" + repr(child.sentence) + ", squared]"
            else:
                str = "[" + repr(child.sentence) + ", squared"
                for subchild in reversed(child.children):
                    str += childtree(subchild)
                str += "]"
                return str

        if len(self.children) == 0:
            return str + "\\end{forest}"
        return str + childtree(self) + "\\end{forest}"

    def tex_compile_qtree(self):
        str = ""
        str += "\\Tree "
        box_width = "3.0"
        def childtree(child):
            if len(child.children) == 0:
                return "[. " + "\\framebox[" + box_width + "\width]{" + repr(child.sentence) + "} " + " ]"
            else:
                str = "[. " + "\\framebox[" + box_width + "\width]{" + repr(child.sentence)+ "} "
                for subchild in reversed(child.children):
                    str += childtree(subchild)
                str += "]"
                return str

        return str + childtree(self)


from mediatr import Mediator

from commands.create_customer import CreateCustomer
from handlers.customer_handlers import (
    CreateCustomerHandler,
    GetCustomersHandler,
)
from queries.get_customers import GetCustomers

if __name__ == "__main__":
    mediator = Mediator()
    mediator.register_handler(CreateCustomerHandler)
    mediator.register_handler(GetCustomersHandler)

    # Command
    command = CreateCustomer(
        first_name="Daniel",
        last_name="Leal",
        tax_id="36974125846",
        email="daniel@email.com",
        phone="91992727481",
    )
    # Handler
    mediator.send(command)

    # Command
    command = CreateCustomer(
        first_name="Yasmin",
        last_name="Leal",
        tax_id="15975324862",
        email="yasmin@email.com",
        phone="91992727481",
    )

    # Handler
    mediator.send(command)

    # Command
    command = CreateCustomer(
        first_name="André",
        last_name="Leal",
        tax_id="84812135482",
        email="andre@email.com",
        phone="91992727481",
    )

    # Handler
    mediator.send(command)

    # query
    query = GetCustomers()

    # Handler
    result = mediator.send(query)
    print(result)


"""
Pyramid backbone.
"""
from dataclasses import dataclass
from typing import List, Optional
from torch.nn import Conv2d, BatchNorm2d, Module, Sequential
from common.gcn_lib.torch_vertex import Grapher, GrapherConfig
from common.train_pipeline.backbone.attention_block import (
    AttentionBlock,
    AttentionBlockConfig,
)
from common.train_pipeline.backbone.ffn import FFN, FFNConfig

from common.train_pipeline.config import BackboneBlockConfig

@dataclass
class PyramidBlockConfig(BackboneBlockConfig):
    """
    Pyramid backbone block config.
    """

    in_channels: int
    out_channels: int
    hidden_dimensions_in_ratio: int
    grapher_config: Optional[GrapherConfig] = None
    attention_config: Optional[AttentionBlockConfig] = None
    ffn_config: Optional[FFNConfig] = None
    number_of_nearest_neighbours: int = 9
    number_of_grapher_ffn_units: int = 2
    shrink_image_conv: bool = True

class PyramidBackbone(Module):
    """
    Pyramid backbone.
    """

    def __init__(self, config: List[PyramidBlockConfig], requires_grad=True) -> None:
        super(PyramidBackbone, self).__init__()
        self.layers: List[Sequential] = []
        for i, block in enumerate(config):
            self.layers.append(self.build_block(block))
            if block.shrink_image_conv:
                self.layers.append(
                    Conv2d(block.in_channels, block.out_channels, 3, 2, 1)
                )
                self.layers.append(BatchNorm2d(block.out_channels))
        self.backbone = Sequential(*self.layers)
        for param in self.backbone.parameters():
            param.requires_grad = requires_grad

    def forward(self, inputs):
        """
        Forward pass.
        """

        return self.backbone(inputs)

    def build_block(self, config: PyramidBlockConfig) -> Sequential:
        """
        Builds a pyramid block.
        """
        layers = []
        for _ in range(config.number_of_grapher_ffn_units):
            if config.grapher_config:
                layers.append(Grapher(config.grapher_config))
            if config.attention_config:
                layers.append(AttentionBlock(config.attention_config))
            if config.ffn_config:
                layers.append(FFN(config.ffn_config))
        return Sequential(*layers)


from datetime import datetime, timezone
import email.utils as eut
import base64

def get_current_time():
    now = datetime.now().strftime("%Y%m%d%H%M%S")
    return now

def get_today_date(split=""):
    now = datetime.now().strftime(f"%Y{split}%m{split}%d")
    return now

def decode_gmo_base64_to_str(s):
    _s = s.split("\"")[1]
    bs = base64.urlsafe_b64decode(_s + '=' * (-len(_s) % 4))
    bl = []
    for b in bs:
        if b > 100:
            bl.append(44)
        else:
            bl.append(b)
    bs2 = bytearray(bl)
    r = bs2.decode("utf-8").split(",")
    return list(filter(lambda x: x != '', r))


matrix_size = [int(num) for num in input().split(", ")]
matrix = []
count_num = 0

for row in range(matrix_size[0]):
    row_input = [int(num) for num in input().split(", ")]
    matrix.append(row_input)
    count_num += sum(row_input)

print(count_num)
print(matrix)

Python_Advanced/Multidimensional Lists - Lab/01. Sum Matrix Elements.py


# -*- coding: utf-8 -*-

import clr
import os.path as Path
import pandas as pd
import numpy as np
import bisect

pathtothisfile = Path.dirname(__file__)

dlls = ['./dlls/ThermoFisher.CommonCore.Data', './dlls/ThermoFisher.CommonCore.RawFileReader',
        'dlls/ThermoFisher.CommonCore.BackgroundSubtraction', 'dlls/ThermoFisher.CommonCore.MassPrecisionEstimator']

for dll in dlls:
    testpath = dll
    print(testpath)
    if Path.isfile(testpath):
        print("founded file")
        clr.AddReference(testpath)
    else:
        try:
            import sys
            sys.path.append(pathtothisfile)
            clr.AddReference(dll)
        except:
            clr.AddReference(dll)

from ThermoFisher.CommonCore.RawFileReader import RawFileReaderAdapter
from ThermoFisher.CommonCore.Data.Business import (ChromatogramSignal, ChromatogramTraceSettings,
                                                   DataUnits, Device, GenericDataTypes, SampleType,
                                                   Scan, TraceType, Range)
from ThermoFisher.CommonCore.Data.FilterEnums import IonizationModeType, MSOrderType
from ThermoFisher.CommonCore.Data.Interfaces import (IChromatogramSettings, IScanEventBase,
                                                     IScanFilter, RawFileClassification,
                                                     IRawDataPlus)
from ThermoFisher.CommonCore.Data import ToleranceUnits
from ThermoFisher.CommonCore.Data import Extensions

class ThermoRawReader():
    """
    This class creates an object which has functions to parse information of
    Thermo RAW files.
    An instance is created by providing the path the Thermo RAW file is saved
    """

    def __init__(self,path,color=None,condition=None):
        self.source=RawFileReaderAdapter.FileFactory(path)
        self.path=path
        self.source.SelectInstrument(Device.MS, 1)
        self.minStartTime=self.source.RunHeaderEx.StartTime
        self.maxStartTime=self.source.RunHeaderEx.EndTime
        self.color=color
        self.condition=condition
        self.baseName=Path.basename(path)
        self.numOfSpectra=self.source.RunHeaderEx.SpectraCount

    def close(self):
        """
        Use this function to close a raw file.
        """
        self.source.Dispose()
        return

    def getMetaData(self):
        """
        This function returns a tuple containing information about:
            Instrument method
            Injection volume
            Date
            Number of scans
            Number of MS1 scans
            Number of MS2 scans
            Number of MS3 scans
        """

        CreationDate=str(self.source.get_CreationDate())
        scanInformation=self.getScanInformation()
        instrumentMethod=self.source.SampleInformation.InstrumentMethodFile
        injectionVolume=self.source.SampleInformation.InjectionVolume
        a=scanInformation.groupby("MassOrder").apply(len)
        numberMS1=0
        numberMS2=0
        numberMS3=0
        for n,item in enumerate(a):
            if a.index[n]==1:
                numberMS1=item
            elif a.index[n]==2:
                numberMS2=item
            elif a.index[n]==3:
                numberMS3=item

        print(self)

        return (instrumentMethod,injectionVolume,CreationDate,
                self.numOfSpectra,numberMS1,numberMS2,numberMS3)

    def getScanInformation(self):
        """
        This function returns a pandas dataframe containing following columns:
            scanNumber
            Massorder (MS1,M2,...)
            Starttime
        """
        rows=list()
        for scan in range(1,self.numOfSpectra+1):
            info=self.source.GetFilterForScanNumber(scan)
            massOrder=info.MSOrder
            StartTime=self.source.RetentionTimeFromScanNumber(scan)
            rows.append([scan,massOrder,StartTime])
        df=pd.DataFrame(rows,columns=['scanNumber','MassOrder','StartTime'])
        df.name="ScanInformation@"+self.baseName
        return df

    def getPrecursorInformation(self):
        """
        This function returns a pandas dataframe containing information about all tandem mass
        spectra in one run. The dataframe includes following columns:
            scanNumber
            PrecursorMass
            StartTime
            TIC
        """
        rows=list()
        for scan in range(1,self.numOfSpectra+1):
            info=self.source.GetFilterForScanNumber(scan)
            massOrder=info.MSOrder
            if massOrder>1:
                scanEvent=self.source.GetScanEventForScanNumber(scan)
                reaction=scanEvent.Reactions[0]
                precursor_mz=reaction.PrecursorMass
                StartTime=self.source.RetentionTimeFromScanNumber(scan)
                trailer=self.source.GetTrailerExtraInformation(scan)
                monoisotopicMass=float(trailer.Values[list(trailer.Labels).index('Monoisotopic M/Z:')])
                chargeState=int(trailer.Values[list(trailer.Labels).index('Charge State:')])

                rows.append([scan,precursor_mz,StartTime,monoisotopicMass,chargeState])
        df=pd.DataFrame(rows,columns=['scanNumber','PrecursorMass','StartTime','monoisotopic m/z','Charge State'])
        return df

    def getXIC(self,massrange,startTime=0,endTime=0,smooth=True,scanFilter="Full ms"):
        """
        Description of the parameters:
               name        type                description
               massrange   string              for example "201.01-203.4" or "201.01-203.4,502.1-503.2"
               startTime   float
               endTime     float               l
               threshould  float               Error in ppm

        This function returns a pandas dataframe containing following columns:
            RT   retention time
            intensity
        """
        if startTime>endTime:
            raise IOError("startTime must be lower than endTime!")

        StartScan=self.source.ScanNumberFromRetentionTime(startTime)
        EndScan=self.source.ScanNumberFromRetentionTime(endTime)

        ls_range=list()

        for item in massrange.split(","):
            startMZ,endMZ=item.split("-")

            ls_range.append(Range.Create(float(startMZ),float(endMZ)))

        settings=ChromatogramTraceSettings(scanFilter,ls_range)

        xic_data = self.source.GetChromatogramData([settings], StartScan, EndScan)
        xic_trace = ChromatogramSignal.FromChromatogramData(xic_data)[0]

        try:
            signal=np.dstack((list(xic_trace.Times),list(xic_trace.Intensities)))[0]
        except:
            df=pd.DataFrame()
            df['RT']=[startTime,endTime]
            df['intensity']=[0,0]
            return(df)

# =============================================================================
#         if smooth:
#             signal=moveAverage(signal,0.1,2)
# =============================================================================

        df=pd.DataFrame()
        df['RT']=signal[:,0]
        df['intensity']=signal[:,1]
        return(df)

    def getTIC(self,startTime=0,endTime=0,scanFilter="Full ms"):
        """
        Description of the parameters:
               name        type                description
               startTime   float
               endTime     float
               smooth      bool

        This function returns a pandas dataframe containing following columns:
            RT          retention time
            intensity

        """
        if startTime>endTime:
            raise IOError("startTime must be lower than endTime!")

        StartScan=-1
        EndScan=-1
        if startTime:
            StartScan=self.source.ScanNumberFromRetentionTime(startTime)

        if endTime:
            EndScan=self.source.ScanNumberFromRetentionTime(endTime)

        settings=ChromatogramTraceSettings(TraceType.TIC)
        settings.set_Filter(scanFilter)

        tic_data = self.source.GetChromatogramData([settings], StartScan, EndScan)
        tic_trace = ChromatogramSignal.FromChromatogramData(tic_data)[0]

        try:
            signal=np.dstack((list(tic_trace.Times),list(tic_trace.Intensities)))[0]
        except:
            df=pd.DataFrame()
            if not startTime:
                startTime=self.minStartTime
            if not endTime:
                endTime=self.maxStartTime
            df['RT']=[startTime,endTime]
            df['intensity']=[0,0]
            return(df)
# =============================================================================
#         if smooth:
#             signal=moveAverage(signal,0.1,2)
# =============================================================================
        df=pd.DataFrame()
        df['RT']=signal[:,0]
        df['intensity']=signal[:,1]
        return(df)

    def getUV(self,startTime=0,endTime=0,smooth=True):
        """
        Description of the parameters:
               name        type                description
               massrange   string              for example "201.01-203.4" or "201.01-203.4,502.1-503.2"
               startTime   float
               endTime     float               l
               threshould  float               Error in ppm

        This function returns a pandas dataframe containing following columns:
            RT          retention time
            intensity

        """
        if startTime>endTime:
            raise IOError("startTime must be lower than endTime!")
        self.source.SelectInstrument(Device.UV, 1)
        StartScan=-1
        EndScan=-1
        if startTime:
            StartScan=self.source.ScanNumberFromRetentionTime(startTime)

        if endTime:
            EndScan=self.source.ScanNumberFromRetentionTime(endTime)

        settings=ChromatogramTraceSettings(TraceType.Analog1)

        UV_data = self.source.GetChromatogramData([settings], StartScan, EndScan)
        UV_trace = ChromatogramSignal.FromChromatogramData(UV_data)[0]

        try:
            signal=np.dstack((list(UV_trace.Times),list(UV_trace.Intensities)))[0]
        except:
            df=pd.DataFrame()
            if not startTime:
                startTime=self.minStartTime
            if not endTime:
                endTime=self.maxStartTime
            df['RT']=[startTime,endTime]
            df['intensity']=[0,0]
            return(df)
# =============================================================================
#         if smooth:
#             signal=moveAverage(signal,0.1,2)
# =============================================================================
        df=pd.DataFrame()
        df['RT']=signal[:,0]
        df['intensity']=signal[:,1]
        self.source.SelectInstrument(Device.MS, 1)
        return(df)

    def getMS1spectraByScanNumber(self,scanNumber):
        """
        Define the scan number of the MS1 spectra
        This function returns a pandas dataframe containing following columns:
            mz
            intensity

        """
        scan_stats = self.source.GetScanStatsForScanNumber(scanNumber)
        if scan_stats.IsCentroidScan: raise IOError("No profile data for scan %s" % scanNumber)

        try:
            scan = self.source.GetSegmentedScanFromScanNumber(scanNumber, scan_stats)
        except:
            df=pd.DataFrame(columns=['mz','intensity'])
            return(df)
        df=pd.DataFrame()
        df['mz']=list(scan.Positions)
        df['intensity']=list(scan.Intensities)
        return(df)

    def getMS1spectraByRT(self,RT):
        """
        Define the retention time in minutes
        This function returns a pandas dataframe containing following columns:
            mz
            intensity

        """
        if RT<self.minStartTime:
            RT=self.minStartTime

        if RT>self.maxStartTime:
            RT=self.maxStartTime

        scanNumber=self.source.ScanNumberFromRetentionTime(RT)
        info=self.source.GetFilterForScanNumber(scanNumber)
        massOrder=info.MSOrder
        while massOrder>1:
            scanNumber=scanNumber-1
            info=self.source.GetFilterForScanNumber(scanNumber)
            massOrder=info.MSOrder

        scan_stats = self.source.GetScanStatsForScanNumber(scanNumber)

        try:
            scan = self.source.GetSegmentedScanFromScanNumber(scanNumber, scan_stats)
        except:
            df=pd.DataFrame(columns=['mz','intensity'])
            return(df,scanNumber)
        df=pd.DataFrame()
        df['mz']=list(scan.Positions)
        df['intensity']=list(scan.Intensities)
        return(df,scanNumber)

    def getMSLabelByScanNumber(self,scanNumber):
        """
        This function returns a pandas DataFrame containing following MS labels:
            mz
            intensity
            resolution
            Base
            noise
            charge

        Define the scanNumber of the spectra

        """
        stream = self.source.GetCentroidStream(scanNumber, False)
        df=pd.DataFrame()
        df['mz']=list(stream.Masses)
        df['intensity']=list(stream.Intensities)
        df['resolution']=list(stream.Resolutions)
        df['Base']=list(stream.Baselines)
        df['noise']=list(stream.Noises)
        df['charge']=list(stream.Charges)

        return(df)

    def getMS2LabelByScanNumber(self,scanNumber):
        return(self.getMSLabelByScanNumber(scanNumber))

    def getFilters(self):
        """
        This function returns a list of filters
        """
        ls_filter=self.source.GetFilters()
        ls_filter=[IScanFilter(item).ToString() for item in ls_filter]
        return(ls_filter)

    def getMS2ScanNumber(self,ls_mz,ls_RT,ls_charge=[],ppm=5e-6):
        """This function returns a list of potential tandem mass spectra for a list
           of mz- and RT-values.
           Input variable:
               name        type                description
               ls_mz       list                list of mz-values
               ls_RT       list                list of retention time values
               ls_charge   list(optional)      list of charge values
               ppm         float               Error in ppm
        """
        df_MS2=self.getPrecursorInformation()
        ls_scanNumber=list()
        for n,mz in enumerate(ls_mz):
            RT=ls_RT[n]
            temp_df=df_MS2[(df_MS2['StartTime']>RT-3)&(df_MS2['StartTime']<RT+3)]
            if ls_charge:
                charge=ls_charge[n]
                result_df=temp_df[df_MS2['precursorCharge']==charge]
            else:
                result_df=temp_df
            result_df=result_df[(result_df['PrecursorMass']>(mz-mz*ppm))&(result_df['PrecursorMass']<(mz+mz*ppm))]
            if len(result_df)==0:
                result_df=temp_df[(result_df['observed_mz']>(mz-mz*ppm))&(temp_df['observed_mz']<(mz+mz*ppm))]
            if len(result_df)==0:
                ls_scanNumber.append(-1)
            elif len(result_df)==1:
                ls_scanNumber.append(int(result_df['scanNumber'].iloc[0]))
            else:
                result_df=result_df[result_df['precursorIntens']==max(result_df['precursorIntens'])]
                ls_scanNumber.append(int(result_df['scanNumber'].iloc[0]))
        return(ls_scanNumber)

    def getDetailedPrecursorInformation(self):
        """
        This function returns a pandas dataframe containing information about all tandem mass
        spectra in one run. The dataframe includes following columns:
            scanNumber
            PrecursorMass
            StartTime
            TIC
            precursorIntensity
            precursorCharge
            observedMZ
        """
        rows=list()
        for scanNumber in range(1,self.numOfSpectra+1):
            info=self.source.GetFilterForScanNumber(scanNumber)
            massOrder=info.MSOrder
            if massOrder==1:
                buff=self.getMSLabelByScanNumber(scanNumber)
                parent_mzValues=np.array(buff['mz'])
                parent_intensValues=np.array(buff['intensity'])
                parent_charge_values=np.array(buff['charge'])
            if massOrder>1:
                scanEvent=self.source.GetScanEventForScanNumber(scanNumber)
                reaction=scanEvent.Reactions[0]
                precursor_mz=reaction.PrecursorMass
                StartTime=self.source.RetentionTimeFromScanNumber(scanNumber)
                scan_stats = self.source.GetScanStatsForScanNumber(1468)
                lower_index=0
                upper_index=0
                n=1
                while lower_index==upper_index:
                    lower_index=bisect.bisect_left(parent_mzValues,precursor_mz-precursor_mz*5e-6*n)
                    upper_index=bisect.bisect_right(parent_mzValues,precursor_mz+precursor_mz*5e-6*n)
                    n+=1
                if upper_index-lower_index>1:
                    buff_mz=np.array(parent_mzValues[lower_index:upper_index])
                    buff_mz_error=abs(buff_mz-precursor_mz)
                    buff_mz=buff_mz[buff_mz_error.argmin()]
                    intens=parent_intensValues[parent_mzValues==buff_mz][0]
                    charge=parent_charge_values[parent_mzValues==buff_mz][0]
                else:
                    buff_mz=parent_mzValues[lower_index:upper_index][0]
                    intens=parent_intensValues[lower_index:upper_index][0]
                    charge=parent_charge_values[lower_index:upper_index][0]
                rows.append([scanNumber,precursor_mz,StartTime,scan_stats.TIC,intens,charge,buff_mz])
        df=pd.DataFrame(rows,columns=['scanNumber','PrecursorMass','StartTime','TIC','precursorIntens','precursorCharge','observed_mz'])
        df.name="PrecursorList@"+self.baseName
        return df

    def getAverageSpectrumByScanNumber(self,firstScanNumber,lastScanNumber):
        options = Extensions.DefaultMassOptions(self.source)
        options.ToleranceUnits = ToleranceUnits.ppm
        options.Tolerance = 5.0
        scanFilter = IScanFilter(self.source.GetFilterForScanNumber(firstScanNumber))
        averageScan = Extensions.AverageScansInScanRange(self.source, firstScanNumber, lastScanNumber, scanFilter, options)

        try:
            scan = averageScan.SegmentedScan
        except:
            df=pd.DataFrame(columns=['mz','intensity'])
            return(df)
        df=pd.DataFrame()
        df['mz']=list(scan.Positions)
        df['intensity']=list(scan.Intensities)
        return(df)

    def getAverageSpectrumByRT(self,firstRT,lastRT):
        options = Extensions.DefaultMassOptions(self.source)
        options.ToleranceUnits = ToleranceUnits.ppm
        options.Tolerance = 5.0
        firstScanNumber=self.source.ScanNumberFromRetentionTime(firstRT)
        lastScanNumber=self.source.ScanNumberFromRetentionTime(lastRT)
        scanFilter = IScanFilter(self.source.GetFilterForScanNumber(firstScanNumber))
        averageScan = Extensions.AverageScansInScanRange(self.source, firstScanNumber, lastScanNumber, scanFilter, options)
        try:
            scan = averageScan.SegmentedScan
        except:
            df=pd.DataFrame(columns=['mz','intensity'])
            return(df)
        df=pd.DataFrame()
        df['mz']=list(scan.Positions)
        df['intensity']=list(scan.Intensities)
        return(df)

if(__name__ == "__main__"):
    rowfile = ThermoRawReader("./D3.raw")
    tic = rowfile.getTIC()
    data = rowfile.getMetaData()
    print(data)

    print(tic.head())


import base64
import io
import zlib
from urllib.parse import parse_qsl, urlencode, urljoin, urlparse

from django.conf import settings
from django.shortcuts import reverse
from django.test.utils import override_settings

import pytest
from defusedxml import ElementTree
from freezegun import freeze_time
from rest_framework.status import (
    HTTP_200_OK,
    HTTP_302_FOUND,
    HTTP_400_BAD_REQUEST,
    HTTP_402_PAYMENT_REQUIRED,
)
from saml2.xml.schema import validate as validate_saml_xml

from baserow.core.handler import CoreHandler
from baserow.core.models import WorkspaceUser
from baserow_enterprise.api.sso.utils import (
    get_frontend_default_redirect_url,
    get_frontend_login_error_url,
)

@pytest.mark.django_db
@override_settings(DEBUG=True)
def test_saml_provider_get_login_url(api_client, data_fixture, enterprise_data_fixture):
    # create a valid SAML provider
    auth_provider_1 = enterprise_data_fixture.create_saml_auth_provider(
        domain="test1.com"
    )
    auth_provider_login = reverse("api:enterprise:sso:saml:login")
    auth_provider_login_url = reverse("api:enterprise:sso:saml:login_url")

    _, unauthorized_token = data_fixture.create_user_and_token()

    response = api_client.get(
        auth_provider_login_url,
        format="json",
        HTTP_AUTHORIZATION=f"JWT {unauthorized_token}",
    )
    assert response.status_code == HTTP_402_PAYMENT_REQUIRED

    _, token = enterprise_data_fixture.create_enterprise_admin_user_and_token()

    # cannot create a SAML provider with an invalid domain or metadata
    response = api_client.get(
        auth_provider_login_url, format="json", HTTP_AUTHORIZATION=f"JWT {token}"
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()
    assert "redirect_url" in response_json
    assert response_json["redirect_url"] == urljoin(
        settings.PUBLIC_BACKEND_URL, auth_provider_login
    )

    # if more than one SAML provider is enabled, this endpoint need a email address
    auth_provider_2 = enterprise_data_fixture.create_saml_auth_provider(
        domain="test2.com"
    )

    # cannot create a SAML provider with an invalid domain or metadata
    response = api_client.get(
        auth_provider_login_url,
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_400_BAD_REQUEST
    response_json = response.json()
    assert response_json["error"] == "ERROR_SAML_INVALID_LOGIN_REQUEST"

    query_params = urlencode(
        {
            "email": f"user@{auth_provider_1.domain}",
            "original": "/database/1/table/1",
        }
    )
    response = api_client.get(
        f"{auth_provider_login_url}?{query_params}",
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()
    assert "redirect_url" in response_json
    assert response_json["redirect_url"] == urljoin(
        settings.PUBLIC_BACKEND_URL, f"{auth_provider_login}?{query_params}"
    )

    query_params = urlencode(
        {
            "email": f"user@{auth_provider_2.domain}",
            "original": "http://external-site.com",
        }
    )
    response = api_client.get(
        f"{auth_provider_login_url}?{query_params}",
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()
    assert "redirect_url" in response_json
    # the original url is not relative so it should be ignored
    response_query_params = urlencode(
        {
            "email": f"user@{auth_provider_2.domain}",
        }
    )
    assert response_json["redirect_url"] == urljoin(
        settings.PUBLIC_BACKEND_URL,
        f"{auth_provider_login}?{response_query_params}",
    )

    query_params = urlencode(
        {
            "email": "user@unregistered-domain.com",
            "original": "http://test.com",
        }
    )
    response = api_client.get(
        f"{auth_provider_login_url}?{query_params}",
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_400_BAD_REQUEST
    response_json = response.json()
    assert response_json["error"] == "ERROR_SAML_INVALID_LOGIN_REQUEST"

    response = api_client.get(
        f"{auth_provider_login_url}?email=invalid_email",
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_400_BAD_REQUEST
    response_json = response.json()
    assert response_json["error"] == "ERROR_QUERY_PARAMETER_VALIDATION"

@pytest.mark.django_db()
@override_settings(DEBUG=True)
def test_user_cannot_initiate_saml_sso_without_enterprise_license(
    api_client, enterprise_data_fixture
):
    enterprise_data_fixture.create_saml_auth_provider(domain="test1.com")
    response = api_client.get(reverse("api:enterprise:sso:saml:login"))
    assert response.status_code == HTTP_302_FOUND
    assert (
        response.headers["Location"]
        == f"{get_frontend_login_error_url()}?error=errorSsoFeatureNotActive"
    )

def decode_saml_request(idp_redirect_url):
    parsed_url = urlparse(idp_redirect_url)
    query_params = parse_qsl(parsed_url.query)
    encoded_saml_request = [v for k, v in query_params if k == "SAMLRequest"][0]
    saml_request_xml = zlib.decompress(
        base64.b64decode(encoded_saml_request), -15
    ).decode("utf-8")
    return ElementTree.parse(io.BytesIO(saml_request_xml.encode("utf-8")))

@pytest.mark.django_db()
@override_settings(DEBUG=True)
def test_user_can_initiate_saml_sso_with_enterprise_license(
    api_client, enterprise_data_fixture
):
    enterprise_data_fixture.create_saml_auth_provider(domain="test1.com")
    enterprise_data_fixture.enable_enterprise()

    sp_sso_saml_login_url = reverse("api:enterprise:sso:saml:login")
    original_relative_url = "database/1/table/1/"
    request_query_string = urlencode({"original": original_relative_url})

    response = api_client.get(f"{sp_sso_saml_login_url}?{request_query_string}")
    assert response.status_code == HTTP_302_FOUND
    idp_sign_in_url = response.headers["Location"]
    idp_url_initial_part = (
        "https://samltest.id/idp/profile/SAML2/Redirect/SSO?SAMLRequest="
    )
    assert idp_sign_in_url.startswith(idp_url_initial_part)
    saml_request = decode_saml_request(idp_sign_in_url)
    assert validate_saml_xml(saml_request) is None
    response_query_params = dict(parse_qsl(urlparse(idp_sign_in_url).query))
    assert response_query_params["RelayState"] == urljoin(
        settings.PUBLIC_WEB_FRONTEND_URL, original_relative_url
    )

    # an invalid email address should result in an error
    response = api_client.get(f"{sp_sso_saml_login_url}?email=john@acme.it")
    assert response.status_code == HTTP_302_FOUND
    assert (
        response.headers["Location"]
        == f"{get_frontend_login_error_url()}?error=errorInvalidSamlRequest"
    )

@pytest.mark.django_db()
@override_settings(DEBUG=True)
def test_saml_assertion_consumer_service(api_client, enterprise_data_fixture):
    user, _ = enterprise_data_fixture.create_enterprise_admin_user_and_token()
    sp_sso_saml_acs_url = reverse("api:enterprise:sso:saml:acs")

    (
        metadata,
        saml_response,
    ) = enterprise_data_fixture.get_valid_saml_idp_metadata_and_response()

    enterprise_data_fixture.create_saml_auth_provider(domain="test1.com")
    with freeze_time("2022-11-23T14:23:25.00Z"):
        response = api_client.post(
            sp_sso_saml_acs_url,
            data={
                "SAMLResponse": saml_response,
                "RelayState": get_frontend_default_redirect_url(),
            },
        )
        assert response.status_code == HTTP_302_FOUND
        assert response.headers["Location"] == (
            f"{get_frontend_login_error_url()}?error=errorInvalidSamlResponse"
        )

    provider = enterprise_data_fixture.create_saml_auth_provider(
        domain="baserow.io", metadata=metadata
    )

    response = api_client.post(
        sp_sso_saml_acs_url,
        data={
            "SAMLResponse": "some invalid SAML response",
            "RelayState": get_frontend_default_redirect_url(),
        },
    )
    assert response.status_code == HTTP_302_FOUND
    assert response.headers["Location"] == (
        f"{get_frontend_login_error_url()}?error=errorInvalidSamlResponse"
    )

    response = api_client.post(
        sp_sso_saml_acs_url,
        data={
            "SAMLResponse": base64.b64encode(
                "some invalid SAML encoded response".encode("utf-8")
            ),
            "RelayState": get_frontend_default_redirect_url(),
        },
    )
    assert response.status_code == HTTP_302_FOUND
    assert response.headers["Location"] == (
        f"{get_frontend_login_error_url()}?error=errorInvalidSamlResponse"
    )

    with freeze_time("2022-11-23T14:23:25.00Z"):
        workspace_user = enterprise_data_fixture.create_user_workspace(user=user)
        invitation = enterprise_data_fixture.create_workspace_invitation(
            workspace=workspace_user.workspace, email="newuser@email.com"
        )
        core_handler = CoreHandler()
        signer = core_handler.get_workspace_invitation_signer()
        workspace_invitation_token = signer.dumps(invitation.id)

        assert not provider.is_verified

        query_string = urlencode(
            {"language": "en", "workspace_invitation_token": workspace_invitation_token}
        )
        response = api_client.post(
            sp_sso_saml_acs_url,
            data={
                "SAMLResponse": saml_response,
                "RelayState": f"{settings.PUBLIC_WEB_FRONTEND_URL}?{query_string}",
            },
        )
        assert response.status_code == HTTP_302_FOUND
        assert response.headers["Location"].startswith(
            (
                f"{get_frontend_login_error_url()}?error=errorWorkspaceInvitationEmailMismatch"
            )
        )

        invitation = enterprise_data_fixture.create_workspace_invitation(
            workspace=workspace_user.workspace, email="davide@baserow.io"
        )
        signer = core_handler.get_workspace_invitation_signer()
        workspace_invitation_token = signer.dumps(invitation.id)

        query_string = urlencode(
            {"language": "en", "workspace_invitation_token": workspace_invitation_token}
        )
        response = api_client.post(
            sp_sso_saml_acs_url,
            data={
                "SAMLResponse": saml_response,
                "RelayState": f"{settings.PUBLIC_WEB_FRONTEND_URL}?{query_string}",
            },
        )
        assert response.status_code == HTTP_302_FOUND
        assert response.headers["Location"].startswith(
            f"{get_frontend_default_redirect_url()}?token="
        )
        token = response.headers["Location"].split("=")[1]
        # ensure the token is valid and a user has been created
        response = api_client.post(
            reverse("api:user:token_verify"),
            {"refresh_token": token},
            format="json",
        )
        assert response.status_code == HTTP_200_OK
        response_json = response.json()
        assert response_json["user"]["username"] is not None

        # assert the user is a member of the workspace
        workspace_user = WorkspaceUser.objects.get(
            user__username=response_json["user"]["username"]
        )
        assert workspace_user.workspace_id == invitation.workspace_id

        # the SAML provider should be verified now
        provider.refresh_from_db()
        assert provider.is_verified

    # 10 minutes later the response is no longer valid
    with freeze_time("2022-11-23T14:33:25.00Z"):
        response = api_client.post(
            sp_sso_saml_acs_url,
            data={
                "SAMLResponse": saml_response,
                "RelayState": get_frontend_default_redirect_url(),
            },
        )
        assert response.status_code == HTTP_302_FOUND
        assert response.headers["Location"] == (
            f"{get_frontend_login_error_url()}?error=errorInvalidSamlResponse"
        )


from aocd.models import Puzzle
from funcy import lmap

import numpy as np

def part_a(draws: list, boards: np.ndarray):
    draw, board, mask = play(draws, boards, mask=np.zeros_like(boards), first_win=True)
    return np.ma.masked_array(board, mask).sum() * draw

def part_b(draws: list, boards: np.ndarray):
    draw, board, mask = play(draws, boards, mask=np.zeros_like(boards), first_win=False)
    return np.ma.masked_array(board, mask).sum() * draw

def play(draws: list, boards: np.ndarray, mask: np.ndarray, first_win: bool):
    def _check_win(marked_: int):
        cols, rows = np.sum(marked_, axis=0), np.sum(marked_, axis=1)
        return 5 in cols or 5 in rows

    for draw in draws:
        winners = []
        mask[np.nonzero(boards == draw)] = 1
        for i, marked in enumerate(mask):
            if i not in winners and _check_win(marked):
                if first_win:
                    return draw, boards[i], mask[i]
                winners.append(i)
        if len(winners) == len(boards):
            return draw, boards[winners[-1]], mask[winners[-1]]

def load(data: str):
    drawing = lmap(int, data.split()[0].split(','))
    boards = np.array([[lmap(int, row.split()) for row in board.splitlines()] for board in data.split('\n\n')[1:]])
    return drawing, boards

puzzle = Puzzle(year=2021, day=4)
ans_a = part_a(*load(puzzle.input_data))
#puzzle.answer_a = ans_a  # 71708
ans_b = part_b(*load(puzzle.input_data))
#puzzle.answer_b = ans_b  # 34726


import pytest
from sansjson.utils import Hasher

@pytest.mark.parametrize(
    'a, p, j',
    [
        # dict
        ({'a': 1, 'b': 2, 'c': 3}, True, False),
        # JSON str
        ('{"a": 1, "b": 2, "c": 3}', False, True),
        # list
        ([1, 3, 2], True, False),
        # JSON str (bad)
        ('{"a": 1, "b": 2, "c: 3}', False, False),
        # int
        (1, False, False),
        # none
        (None, False, False),
        # object
        (Hasher(), False, False)
    ]
)
def test_sortable(a, p, j, sortable_test):
    assert sortable_test


"""
Chris Johnson
Marc Inouye
5/9/2020
CS 3120-001
Machine Learning
Final Project
Solving captcha with machine learning.
- train knn with sample letters
- detect (blobs) of text whose width is less than double the height
- predict each character and build string

resources-
https://medium.com/@ageitgey/how-to-break-a-captcha-system-in-15-minutes-with-machine-learning-dbebb035a710
"""

import os
import cv2
import glob
import imutils
import numpy as np
from imutils import paths
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

imagePath_list = list(paths.list_images("captcha_classes_for_captcha_solver-master/"))  # training data
MODEL_LABELS_FILENAME = "model_labels.dat"  # model labels for training
CAPTCHA_IMAGE_FOLDER = "generated_captcha_images"  # image to predict with trained model
OUTPUT_FOLDER = "extracted_letter_images"  # captcha images split by each glob(potential letter)

neighbors = 1
knn = KNeighborsClassifier(n_neighbors=neighbors, p=1)

def load(image_path_list, verbose=-1):
    data = []
    labels = []

    for (i, imagePath) in enumerate(image_path_list):
        image = cv2.imread(imagePath)
        label = imagePath.split(os.path.sep)[-2]

        image = cv2.resize(image, (32, 32), interpolation=cv2.INTER_CUBIC)

        data.append(image)
        labels.append(label)

        # show and update every `verbose` images
        if verbose > 0 and i > 0 and (i + 1) % verbose == 0:
            print("[INFO] processed {}/{}".format(i + 1,
                                                  len(image_path_list)))

    return np.array(data), np.array(labels)

def train(model):
    # load training images
    (data, labels) = load(imagePath_list, verbose=500)
    data = data.reshape((data.shape[0], 3072))

    # split data 70% training, 10% validation, 20% testing
    (trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.2, random_state=42)
    (trainX, validateX, trainY, validateY) = train_test_split(trainX, trainY, test_size=0.1, random_state=42)

    # train classifier
    model.fit(trainX, trainY)
    # validate after training
    model.fit(validateX, validateY)

    return model

"""
***************************************************************************************/
*    Title: How to break a CAPTCHA system in 15 minutes with Machine Learning
*    Author: Geitgey, Adam
*    Date: Dec 13, 2017
*    Availability: https://medium.com/@ageitgey/how-to-break-a-captcha-system-in-15-minutes-with-machine-learning-dbebb035a710
*    We used the articles method of extracting image blobs for each character in the captcha to test each character separately
*    Methods: resize_to_fit from helpers and split_captcha
***************************************************************************************/
"""

def resize_to_fit(image, width, height):
    # grab the dimensions of the image, then initialize the padding values
    (height, height) = image.shape[:2]

    # if the width is greater than the height then resize along the width
    if height > height:
        image = imutils.resize(image, width=width)

    # otherwise, the height is greater than the width so resize along the height
    else:
        image = imutils.resize(image, height=height)

    # determine the padding values for the width and height to obtain the target dimensions
    pad_w = int((width - image.shape[1]) / 2.0)
    pad_h = int((height - image.shape[0]) / 2.0)

    # pad the image then apply one more resizing to handle any rounding issues
    image = cv2.copyMakeBorder(image, pad_h, pad_h, pad_w, pad_w, cv2.BORDER_REPLICATE)
    image = cv2.resize(image, (width, height))

    # return the pre-processed image
    return image

def split_captcha(captcha_image_files):
    counts = {}
    split_images = []

    # loop over the image paths
    for (i, captcha_image_file) in enumerate(captcha_image_files):
        # Since the filename contains the captcha text (i.e. "2A2X.png" has the text "2A2X"),
        # grab the base filename as the text
        filename = os.path.basename(captcha_image_file)
        captcha_correct_text = os.path.splitext(filename)[0]

        # Load the image and convert it to grayscale
        image = cv2.imread(captcha_image_file)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        # Add some extra padding around the image
        gray = cv2.copyMakeBorder(gray, 8, 8, 8, 8, cv2.BORDER_REPLICATE)

        # threshold the image (convert it to pure black and white)
        thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

        # find the contours (continuous blobs of pixels) the image
        contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        # Hack for compatibility with different OpenCV versions
        contours = contours[1] if imutils.is_cv3() else contours[0]

        letter_image_regions = []
        # Now we can loop through each of the four contours and extract the letter inside of each one
        for contour in contours:
            # Get the rectangle that contains the contour
            (x, y, w, h) = cv2.boundingRect(contour)

            # Compare the width and height of the contour to detect letters that are conjoined into one chunk
            if w / h > 1.25:
                # This contour is too wide to be a single letter!
                # Split it in half into two letter regions!
                half_width = int(w / 2)
                letter_image_regions.append((x, y, half_width, h))
                letter_image_regions.append((x + half_width, y, half_width, h))
            else:
                # This is a normal letter by itself
                letter_image_regions.append((x, y, w, h))

        # If we found more or less than 4 letters in the captcha, our letter extraction
        # didn't work correctly. Skip the image instead of saving bad training data!
        if len(letter_image_regions) != 4:
            continue

        # Sort the detected letter images based on the x coordinate to make sure
        # we are processing them from left-to-right so we match the right image
        # with the right letter
        letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])

        # Save out each letter as a single image
        for letter_bounding_box, letter_text in zip(letter_image_regions, captcha_correct_text):

            # Grab the coordinates of the letter in the image
            x, y, w, h = letter_bounding_box

            # Extract the letter from the original image with a 2-pixel margin around the edge
            letter_image = gray[y - 2:y + h + 2, x - 2:x + w + 2]

            split_images.append(letter_image)

            # write the letter image to a file
            count = counts.get(letter_text, 1)

            # increment the count for the current key
            counts[letter_text] = count + 1

    return split_images

if __name__ == "__main__":

    # KNN classifier
    model_knn = train(knn)

    # directory that contains extracted captcha to analyze
    captcha_files = glob.glob(os.path.join(CAPTCHA_IMAGE_FOLDER, "*"))
    print ("captcha array type = ", type(captcha_files[0]))

    # saving image to print at the end
    image = cv2.imread(captcha_files[0])

    # calling method to split up each character in the target image
    split_images = split_captcha(captcha_files)

    # string to print with each prediction
    prediction = ""

    for items in split_images:

        # adding border for split up characters to match training sets
        current_image = cv2.copyMakeBorder(items, 10, 10, 10, 10, cv2.BORDER_REPLICATE)
        current_image = np.array(cv2.resize(current_image, (32, 32), interpolation=cv2.INTER_CUBIC))

        # convert back to 3 dimensional array
        current_image = cv2.cvtColor(current_image, cv2.COLOR_GRAY2RGB)

        # reshape to test data size
        current_image_shaped = current_image.reshape((1, 3072))

        # make prediction
        guess = model_knn.predict(current_image_shaped)
        print("guess - ", guess, " , ",type(guess))

        # add each predicted character to the string being built
        prediction += str(guess)

    # showing results
    print("Characters found in captcha - ", prediction)

    # showing original image
    cv2.imshow("Target image- ", image)
    cv2.waitKey()


from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include
from django.contrib.auth.views import login, logout, password_reset
from django.conf import settings
from django.conf.urls.static import static
from pagina.views import index
from seguridad.views import perfilUsuario
urlpatterns = [
    url(r'^$', index, name='index'),
    url(r'^perfil/(?P<pid>\d+)$', perfilUsuario, name='perfil'),
    url(r'^pagina/', include('pagina.urls', namespace='pagina')),
    url(r'^login$', login, name="login"),
    url(r'^logout$', logout, name="logout"),
    url('^', include('django.contrib.auth.urls')),
    url(r'^oauth/', include('social_django.urls', namespace='social')),
    url(r'^admin/', admin.site.urls),
    url(r'^mesa/', include('mesa.urls', namespace='mesa')),
    url(r'^seguridad/', include('seguridad.urls', namespace='seguridad')),
    url(r'^lineabase/', include('lineabase.urls', namespace='lineabase')),
    url(r'^lineatiempo/', include('lineatiempo.urls', namespace='lineatiempo')),
    url(r'^formacion/', include('formacion.urls', namespace='formacion')),
    url(r'^foros/', include('foro.urls', namespace='foro')),
    url(r'^servicios_amigables/', include('servicios.urls', namespace='servicios_amigables')),
    url(r'^faq/', include('faq.urls', namespace='faq')),
    url(r'^djga/', include('google_analytics.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

admin.site.site_header = "ADMIN - RED SENTIR"


import taipy.core as tp
from taipy import Config

# Loading of the TOML
Config.load("config/taipy-config.toml")
tp.Core().run()

# Get the scenario configuration
scenario_cfg = Config.scenarios["SC_WINE"]

sc_wine = tp.create_scenario(scenario_cfg)
sc_wine.submit()

df_wine_production = sc_wine.WINE_PRODUCTION_WITH_STATS.read()
df_wine_with_geometry = sc_wine.WINE_PRODUCTION_WITH_GEOMETRY.read()


from datetime import datetime

import pytest

from project import create_app
from project import db
from project import init_db
from project.data_point.data_point import DataPoint
from project.news.news import News

@pytest.fixture
def app():
    app = create_app({"TESTING": True, "SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:"})

    with app.app_context():
        init_db()

        db.session.add_all(
            (
                News(
                    title="News Title 1",
                    content="News Content 1",
                    statement_date="01.01.2020",
                    created=datetime(2021, 3, 12),
                ),
                News(
                    title="News Title 2",
                    content="News Content 2",
                    statement_date="01.02.2020",
                    created=datetime(2021, 3, 12),
                ),
                DataPoint(
                    total=21,
                    sentiment=1.4,
                    point_date="01.01.2020",
                    created=datetime(2020, 1, 1),
                ),
                DataPoint(
                    total=42,
                    sentiment=0.5,
                    point_date="01.02.2020",
                    created=datetime(2020, 2, 1),
                ),
            )
        )
        db.session.commit()

    yield app

@pytest.fixture
def client(app):
    return app.test_client()

@pytest.fixture
def runner(app):
    return app.test_cli_runner()


"""Add invite table

Revision ID: 7505107f9372
Revises: e3dc9b1bcf42
Create Date: 2017-04-06 18:46:25.124808

"""

# revision identifiers, used by Alembic.
revision = '7505107f9372'
down_revision = 'e3dc9b1bcf42'

from alembic import op
import sqlalchemy as sa

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('invite', sa.Column('invite_hash', sa.String(length=128), nullable=True))
    op.drop_column('invite', 'confirmation_hash')
    op.drop_column('invite', 'email')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('invite', sa.Column('email', sa.VARCHAR(length=256), autoincrement=False, nullable=False))
    op.add_column('invite', sa.Column('confirmation_hash', sa.VARCHAR(length=128), autoincrement=False, nullable=True))
    op.drop_column('invite', 'invite_hash')
    # ### end Alembic commands ###


from odoo import models, fields, api
from odoo.tools import float_is_zero
from datetime import  timedelta
import time
import datetime
from collections import OrderedDict
import logging
_logger = logging.getLogger(__name__)

class Analytic_line_Report(models.TransientModel):

    _name = 'report_analytic_lines'
    _inherit = 'account_financial_report_abstract'

    company_id = fields.Many2one('res.company', string='Company')

    date_from = fields.Date()
    date_to = fields.Date()
    date_since = fields.Date()
    group_by_account = fields.Boolean()
    filter_account_type_ids = fields.Many2many(comodel_name='account.account.type')

    proyect_ids = fields.One2many(
        comodel_name='report_analytic_lines_proyect',
        inverse_name='report_id'
    )
    account_ids = fields.One2many(
        comodel_name='report_analytic_lines_account',
        inverse_name='report_id'
    )
    parent_id = fields.Many2one(
        comodel_name='report_analytic_lines',
        ondelete='cascade',
        index=True
    )
    # Data fields, used to browse report data
    child_ids = fields.One2many(
        comodel_name='report_analytic_lines',
        inverse_name='parent_id'
    )

    def formatDate(self, dtDateTime,strFormat="%Y-%m-%d"):
        # format a datetime object as YYYY-MM-DD string and return
        return dtDateTime.strftime(strFormat)

    def mkDateTime(self, dateString,strFormat="%Y-%m-%d"):
        # Expects "YYYY-MM-DD" string
        # returns a datetime object
        eSeconds = time.mktime(time.strptime(dateString,strFormat))
        return datetime.datetime.fromtimestamp(eSeconds)

    def mkFirstOfMonth(self, dtDateTime):
        #what is the first day of the current month
        #format the year and month + 01 for the current datetime, then form it back
        #into a datetime object
        return self.mkDateTime(self.formatDate(dtDateTime,"%Y-%m-01"))

    def mkLastOfMonth(self, dtDateTime):
        if int(dtDateTime.strftime("%m"))==12:
            dYear = str(int(dtDateTime.strftime("%Y"))+1)
        else:
            dYear = dtDateTime.strftime("%Y")        #get the year
        dMonth = str(int(dtDateTime.strftime("%m"))%12+1)#get next month, watch rollover
        dDay = "1"                               #first day of next month
        nextMonth = self.mkDateTime("%s-%s-%s"%(dYear,dMonth,dDay))#make a datetime obj for 1st of next month
        delta = datetime.timedelta(seconds=1)    #create a delta of 1 second
        return nextMonth - delta

    def _prepare_report_analytic_line_child(self, start, end):
        self.ensure_one()
        return {
            'date_from': start,
            'date_to': end,
            'date_since': self.date_since,
            'filter_account_type_ids': [(6, 0, self.filter_account_type_ids.ids)],
            'group_by_account': self.group_by_account,
            'company_id': self.company_id.id,
            'parent_id': self.id
        }

    def get_childs(self):
        _logger.debug('=======GET_CHILDS======%s' % (self.filter_account_type_ids.ids))
        start=datetime.datetime.strptime(self.date_from,"%Y-%m-%d")
        end=datetime.datetime.strptime(self.date_to, "%Y-%m-%d")
        _logger.debug('Start Day: %s' % start)
        _logger.debug('End Day: %s' % end)
        months=OrderedDict(((start + timedelta(_)).strftime(r"%m-%y"), None) for _ in xrange((end - start).days)).keys()
        _logger.debug(months)
        for month in months:
            _month=datetime.datetime.strptime(month, "%m-%y")
            first=self.mkFirstOfMonth(_month)
            last=self.mkLastOfMonth(_month)
            if first<start:
                first=start
            if last>end:
                last=end
            _logger.debug('month %s' % _month)
            _logger.debug('First Day: %s' % first)
            _logger.debug('Last Day: %s' % last)
            model = self.env['report_analytic_lines']
            report_child = model.create(self._prepare_report_analytic_line_child(first,last))
            report_child.compute_data_for_report()

    def _get_format_date_header(self, child_date):
        month=datetime.datetime.strptime(child_date,"%Y-%m-%d")
        month=month.strftime("%b-%Y")
        return month

    def get_month_proyect(self, child, proyect):
        month_proyect=self.env['report_analytic_lines_proyect'].search([
                        ('report_id','=',child.id),
                        ('name','=',proyect.name)])
        value = month_proyect.amount
        value = round(value, 2)
        return value

    def get_month_departure(self, child, departure, proyect):
        month_proyect=self.env['report_analytic_lines_proyect'].search([
                        ('report_id','=',child.id),
                        ('name','=',proyect.name)])
        month_departure=self.env['report_analytic_lines_departure'].search([
                        ('report_id','=',child.id),
                        ('proyect_id','=',month_proyect.id),
                        ('name','=',departure.name)])
        value = month_departure.amount
        value = round(value, 2)
        return value

class Analytic_line_Report_Proyect(models.TransientModel):
    _name = 'report_analytic_lines_proyect'
    _inherit = 'account_financial_report_abstract'

    _order = 'sequence'

    report_id = fields.Many2one(
        comodel_name='report_analytic_lines',
        ondelete='cascade',
        index=True
    )
    departure_ids = fields.One2many(
        comodel_name='report_analytic_lines_departure',
        inverse_name='proyect_id'
    )

    sequence = fields.Integer(index=True, default=1)

    # Data fields, used for report display

    name = fields.Char()

    amount = fields.Float(digits=(16, 2), string='Amount')
    accumulated = fields.Float(digits=(16, 2), string='Accumulated')
    @api.depends('amount', 'accumulated')
    def _compute_amount(self):
        for proyect in self:
            proyect.total = proyect.accumulated+proyect.amount

    total = fields.Float(digits=(16, 2), string='Amount', compute=_compute_amount)

class Analytic_line_Report_Departure(models.TransientModel):
    _name = 'report_analytic_lines_departure'
    _inherit = 'account_financial_report_abstract'
    _order = 'sequence'
    report_id = fields.Many2one(
        comodel_name='report_analytic_lines',
        ondelete='cascade',
        index=True
    )
    proyect_id = fields.Many2one(
        comodel_name='report_analytic_lines_proyect',
        ondelete='cascade',
        index=True
    )
    account_ids = fields.One2many(
        comodel_name='report_analytic_lines_account',
        inverse_name='departure_id'
    )
    sequence = fields.Integer(index=True, default=1)
    name = fields.Char()

    amount = fields.Float(digits=(16, 2), string='Amount')
    accumulated = fields.Float(digits=(16, 2), string='Accumulated')

    @api.depends('amount', 'accumulated')
    def _compute_amount(self):
        for department in self:
            department.total = department.accumulated+department.amount

    total = fields.Float(digits=(16, 2), string='Amount', compute=_compute_amount)

class Analytic_line_Report_Account(models.TransientModel):
    _name = 'report_analytic_lines_account'
    _inherit = 'account_financial_report_abstract'
    _order = 'sequence'

    report_id = fields.Many2one(
        comodel_name='report_analytic_lines',
        ondelete='cascade',
        index=True
    )
    proyect_id = fields.Many2one(
        comodel_name='report_analytic_lines_proyect',
        ondelete='cascade',
        index=True
    )
    departure_id = fields.Many2one(
        comodel_name='report_analytic_lines_departure',
        ondelete='cascade',
        index=True
    )
    sequence = fields.Integer(index=True, default=1)

    # Data fields, used for report display
    account_id = fields.Many2one(
        'account.account',
        index=True
    )
    proyect = fields.Char()
    departure = fields.Char()
    date = fields.Date()
    description = fields.Char()

    amount = fields.Float(digits=(16, 2), string='Amount')
    account_type_id = fields.Many2one('account.account.type')
    currency_id = fields.Many2one('res.currency')
    amount_currency = fields.Float(digits=(16, 2),string='Amount Currency')
    invoice_id = fields.Many2one('account.invoice')
    invoice_display_name = fields.Char()
    partner_id = fields.Many2one('res.partner')

class Analytic_line_ReportCompute(models.TransientModel):
    """ Here, we just define methods.
    For class fields, go more top at this file.
    """

    _inherit = 'report_analytic_lines'

    @api.multi
    def compute_data_for_report(self):
        self.ensure_one()
        _logger.debug('==compute_date====>%s' % (self.filter_account_type_ids) )
        self._inject_proyect_values(self.filter_account_type_ids, self.date_from, self.date_to)
        self._inject_departure_values(self.filter_account_type_ids, self.date_from, self.date_to)
        self._inject_account_values(self.filter_account_type_ids, self.date_from, self.date_to)
        if not self.parent_id:
            self.get_childs()
        return True

    def _query_common_block(self):
        query = """
            account_analytic_line  as aal
            join account_analytic_account as aaa on aal.account_id = aaa.id
            join account_account as aa on aal.general_account_id = aa.id
            left join account_move_line as aml on aml.id = aal.move_id
            left join account_invoice as ai on ai.id = aml.invoice_id
            left join res_partner as rp on aml.partner_id = rp.id
            """
        return query

    def _inject_account_values(self, filter_account_type_ids, date_from, date_to):
        query_inject_account = """
            INSERT INTO
                report_analytic_lines_account
                (
                report_id,
                create_uid,
                create_date,
                sequence,
                proyect,
                departure,
                account_id,
                date,
                invoice_id,
                partner_id,
                description,
                amount,
                account_type_id,
                currency_id,
                amount_currency,
                departure_id,
                proyect_id,
                invoice_display_name
                )
            SELECT
                %s AS report_id,
                %s AS create_uid,
                NOW() AS create_date,
                ROW_NUMBER() OVER () as sequence,
                proyect,
                departure,
                account,
                date,
                invoice_id,
                partner_id,
                description,
                amount,
                account_type,
                currency,
                amount_currency,
                departure_id,
                proyect_id,
                display_name
            FROM (

            select aaa.code as proyect,
                    aaa.name as departure,
                    aa.id as account,
                    aal.date as date,
                    ai.id as invoice_id,
                    rp.id as partner_id,
                    aal.name as description,
                    aal.amount as amount,
                    aa.user_type_id as account_type,
                    aal.currency_id as currency,
                    aal.amount_currency as amount_currency,
                    0 as acumulado,
                    par.id as departure_id,
                    pr.id as proyect_id,
                    ai.document_number as display_name
            from """+self._query_common_block()+"""
                left outer join report_analytic_lines_proyect as pr on aaa.code=pr.name and pr.report_id =%s
                left outer join report_analytic_lines_departure as par on aaa.name=par.name and par.report_id =%s
                and pr.id=par.proyect_id
            where aa.user_type_id in %s and aal.date BETWEEN %s AND %s
            order by aal.date,aa.id
            ) as whatever
            """
        query_inject_account_params = (
            self.id,
            self.env.uid,
            self.id,
            self.id,
            filter_account_type_ids._ids,
            date_from,
            date_to,
        )
        _logger.debug(query_inject_account % query_inject_account_params)
        self.env.cr.execute(query_inject_account, query_inject_account_params)

    def _query_departure_block(self):
        query = """
            select
                pr.id as proyect_id,
                aaa.code as proyect,
                aaa.name as departure,
                sum(aal.amount) as amount
            from account_analytic_line  as aal
                join account_analytic_account as aaa on aal.account_id = aaa.id
                join account_account as aa on aal.general_account_id = aa.id
                left join report_analytic_lines_proyect as pr on aaa.code=pr.name and pr.report_id=%s
            where aa.user_type_id in %s
            """
        return query

    def _inject_proyect_values(self, filter_account_type_ids, date_from, date_to):
        query_inject_account = """
            WITH accounts as (
                    select aaa.code as proyect,
                        sum(aal.amount) as amount
                from """+self._query_common_block()+"""
                where aa.user_type_id in %s and aal.date BETWEEN %s AND %s
                group by aaa.code
                order by aaa.code
            ),
            accumulated as (
                    select aaa.code as proyect,
                        sum(aal.amount) as amount
                from """+self._query_common_block()+"""
                where aa.user_type_id in %s and aal.date BETWEEN %s AND %s
                group by aaa.code
                order by aaa.code
            )
            INSERT INTO
                report_analytic_lines_proyect
                (
                report_id,
                create_uid,
                create_date,
                sequence,
                name,
                amount,
                accumulated
                )
            SELECT
                %s AS report_id,
                %s AS create_uid,
                NOW() AS create_date,
                ROW_NUMBER() OVER () as sequence,
                pro.proyect as name,
                pro.amount as amount,
                acc.amount as accumulated
            FROM
                accounts as pro left outer join accumulated acc on
                pro.proyect=acc.proyect

            """
        query_inject_account_params = (
            filter_account_type_ids._ids,
            date_from,
            date_to,
            filter_account_type_ids._ids,
            self.date_since,
            date_from,
            self.id,
            self.env.uid
        )
        _logger.debug(query_inject_account % query_inject_account_params)
        self.env.cr.execute(query_inject_account, query_inject_account_params)

    def _inject_departure_values(self, filter_account_type_ids, date_from, date_to):
        query_inject_account = """
            WITH
            departures as (
                """+self._query_departure_block()+"""
                and aal.date BETWEEN %s AND %s
                group by pr.id,aaa.code,aaa.name
                order by aaa.name
            ),
            accumulated as (
                """+self._query_departure_block()+"""
                and aal.date BETWEEN %s AND %s
                group by pr.id,aaa.code,aaa.name
                order by aaa.name
            )
            INSERT INTO
                report_analytic_lines_departure
                (
                report_id,
                create_uid,
                create_date,
                sequence,
                name,
                proyect_id,
                amount,
                accumulated
                )
            select
                %s AS report_id,
                %s AS create_uid,
                NOW() AS create_date,
                ROW_NUMBER() OVER () as sequence,
                dp.departure,
                dp.proyect_id,
                dp.amount as amount,
                ac.amount as accumulated
            From departures dp left outer join accumulated as ac
                on dp.proyect=ac.proyect and dp.departure=ac.departure
            """
        query_inject_account_params = (
            self.id,
            filter_account_type_ids._ids,
            date_from,
            date_to,
            self.id,
            filter_account_type_ids._ids,
            self.date_since,
            date_from,
            self.id,
            self.env.uid
        )
        _logger.debug(query_inject_account % query_inject_account_params)
        self.env.cr.execute(query_inject_account, query_inject_account_params)


import os
import pytest

import random
import numpy as np
from scipy.sparse import csr_matrix

from src.vector_store.sparse_inverted_index import AddSparseInvertedIndexer, QuerySparseInvertedIndexer

@pytest.fixture()
def base_path(tmpdir):
    return os.path.join(str(tmpdir), 'sparse_inverted_index')

@pytest.mark.repeat(10)
def test_sparse_inverted_indexed(base_path):
    VOCAB_SIZE = 8000
    NUM_ENTRIES = VOCAB_SIZE
    # in this case we are having like a diagonal matrix
    row = np.array(list(range(VOCAB_SIZE)))
    col = np.array(list(range(NUM_ENTRIES)))
    data = np.array([1] * VOCAB_SIZE)
    matrix = csr_matrix((data, (row, col)), shape=(VOCAB_SIZE, VOCAB_SIZE))
    id_list = list(range(VOCAB_SIZE))

    with AddSparseInvertedIndexer(base_path=base_path) as add_indexer:
        add_indexer.add(id_list, matrix)

    assert len(add_indexer.inverted_index.keys()) == VOCAB_SIZE

    for key, bucket in add_indexer.inverted_index.items():
        assert len(bucket) == 1
        assert key == bucket[0]

    QUERY_ID = random.randint(0, VOCAB_SIZE)
    query_indexer = QuerySparseInvertedIndexer(base_path=base_path)
    assert len(query_indexer.inverted_index.keys()) == VOCAB_SIZE

    for key, bucket in query_indexer.inverted_index.items():
        assert len(bucket) == 1
        assert key == bucket[0]

    results = query_indexer.search(matrix.getrow(QUERY_ID), top_k=1)
    assert len(results) == 1
    assert results[0] == QUERY_ID