"""
To Do:
 - Add system for rewriting docstrings
 - Convert to using click
"""

import ast, os
import openai
import sys, getopt
from query_constants import INDENT, FUNC_EXAMPLE, CLASS_EXAMPLE

from typing import List, Tuple
from dataclasses import dataclass

HELP_STRING = """docstr_maker.py

Adds Python docstrings to functions
Appends _ds to output filename by default

Usage:
    python docstr_maker.py -i <input_file>

Optional args:
 -o <output_file>
 -v Verbose
 -s Use input file as output file
    Incompatable when used with -o
 -h Displays help message

Example:
    python docstr_maker.py -i <input_file> -s
    python docstr_maker.py -i <input_file>
    python docstr_maker.py -i <input_file> -o <output_file> -v
"""

@dataclass
class CodeDefHolder:
    """
    A dataclass to hold the code definition of a function or class.

    Attributes:
        name (str):
            Name of the function or class
        unindented (str):
            The code definition of the function or class, unindented
        indented (str):
            The code definition of the function or class, indented
        node (ast.stmt):
            The node object of the function or class
        generated_docstring (str):
            The docstring generated by the code definition
        single_indent (str):
            The indentation used for the indented code definition
        full_indent (str):
            The indentation used for the indented code definition, including
            the single_indent
    """

    name: str = None
    unindented: str = None
    indented: str = None
    node: ast.stmt = None
    generated_docstring: str = None
    single_indent: str = ""
    full_indent: str = ""

def vprint(value: str, verbose: bool):
    """
    Prints a value only if verbose is true.

    Parameters:
        value (str): A string to be printed
        verbose (bool): A boolean value

    Returns:
        None
    """
    if verbose:
        print(value)

def process_input(argv: List) -> Tuple[str, str, bool]:
    """
    Processes the command line arguments and returns the input and output files.

    Parameters:
        argv (List): A list of command line arguments

    Returns:
        input_file (str): The input file
        output_file (str): The output file
        verbose (bool): Whether or not to print verbose output
    """
    input_file = None
    output_file = None
    verbose = False
    same_file = False

    try:
        opts, args = getopt.gnu_getopt(argv, "hsvi:o:", [])
    except getopt.GetoptError:
        print(HELP_STRING)
        sys.exit(2)

    for opt, arg in opts:
        if opt == "-h":
            print(HELP_STRING)
            sys.exit(2)

        elif opt in ("-i"):
            if os.path.isfile(arg):
                input_file = arg
            else:
                print("Invalid input file")
                sys.exit(2)

        elif opt in ("-o"):
            output_file = arg

        elif opt in ("-s"):
            same_file = True

        elif opt in ("-v"):
            verbose = True

    if not input_file:
        print("No file entered")
        sys.exit(2)

    if not output_file and same_file:
        output_file = input_file

    elif output_file and same_file:
        print("Error: -s (same file specified with output_file")
        sys.exit(2)

    elif not output_file and not same_file:
        period = input_file.rfind(".")
        output_file = input_file[:period] + "_ds" + input_file[period:]

    return (input_file, output_file, verbose)

def get_node_indent(node: ast.stmt, file_code: str) -> Tuple[str, str]:
    """
    Returns the indentation of a node in a file.

    Parameters:
        node (ast.stmt): A node in a file
        file_code (str): The code of the file

    Returns:
        single_indent (str): The indentation of the node
        full_indentation (str): The indentation of the node and all its children
    """
    child = node.body[0]

    start_col = node.col_offset
    end_col = child.col_offset
    row = child.lineno

    r = file_code.splitlines()[row - 1]

    single_indent = r[start_col:end_col]
    full_indentation = r[:end_col]

    return single_indent, full_indentation

def get_body_offset(node: CodeDefHolder) -> int:
    """
    Returns the number of lines between the start of the function and the start of the body

    Parameters:
        node (CodeDefHolder): A CodeDefHolder object

    Returns:
        row (int): The number of lines between the start of the function and the start of the body
    """
    start_row = node.node.lineno

    child = node.node.body[0]

    child_row = child.lineno

    row = child_row - start_row

    while node.unindented.splitlines()[row - 1].strip() == "":
        row -= 1

    return row

def isolate_nodes(file_code: str) -> List[CodeDefHolder]:
    """
    Returns a list of CodeDefHolder objects, each one representing a function or class
    definition in the file.

    Parameters:
        file_code (str): The code of the file to be analyzed

    Returns:
        ans (List[CodeDefHolder]): A list of CodeDefHolder objects
    """
    tree = ast.parse(file_code)
    ans = []

    for stmt in ast.walk(tree):
        if isinstance(stmt, (ast.FunctionDef, ast.ClassDef)):
            name = stmt.name
            unindented = ast.get_source_segment(file_code, stmt, padded=False)
            indented = ast.get_source_segment(file_code, stmt, padded=True)

            node = CodeDefHolder(name, unindented, indented, stmt)
            node.single_indent, node.full_indent = get_node_indent(stmt, file_code)

            for decorator in stmt.decorator_list:
                dec = ""
                if isinstance(decorator, ast.Name):
                    dec = "@" + decorator.id + "\n"

                elif isinstance(decorator, ast.Attribute):
                    d = decorator
                    li = []
                    while isinstance(d, ast.Attribute):
                        li.insert(0, d.attr)
                        d = d.value
                    li.insert(0, d.id)

                    dec = "@" + ".".join(li) + "\n"

                unindented = dec + unindented

                offset = node.full_indent.replace(node.single_indent, "", 1)

                indented = offset + dec + indented

            node.unindented, node.indented = unindented, indented

            ans.append(node)

    return ans

def get_codex_query(query: str) -> str:
    """
    Returns a string of code from the OpenAI API.

    Parameters:
        query (str): A string of code

    Returns:
        ds (str): A string of code
    """
    response = openai.Completion.create(
        engine="davinci-codex",
        prompt=query,
        temperature=0.1,
        max_tokens=1000,
        top_p=1.0,
        frequency_penalty=0.1,
        user="$007",
        stop=['"""', "def "],
    )

    ds = response.choices[0]["text"]

    return ds

def format_docstring(node: CodeDefHolder, docstring: str, indent: str):
    """
    Returns a formatted docstring for a function, class, or method.

    Parameters:
        node (CodeDefHolder): The node to which the docstring belongs
        docstring (str): The docstring to be formatted
        indent (str): The indentation to be used

    Returns:
        ds (str): The formatted docstring
    """
    ds = indent + '"""\n'
    ds += indent + docstring

    if ds[-1] != "\n":
        ds += "\n"

    ds += indent + '"""\n'

    ds = [line.replace(indent, "", 1) for line in ds.splitlines()]

    ds = [node.full_indent + line for line in ds]

    # Remove indentation from empty lines
    ds = [line.rstrip(node.single_indent) for line in ds]

    # rejoin docstring with newline characters between lines
    ds = "\n".join(ds)

    ds = ds.replace(indent, node.single_indent)

    return ds

def get_docstring(block: CodeDefHolder) -> str:
    """
    Returns the docstring of a code block using the codex query.

    Parameters:
        block (CodeDefHolder): A code block to be documented

    Returns:
        docstring (str): The docstring of the code block
    """
    query = None
    if isinstance(block.node, ast.FunctionDef):
        query = f'''{FUNC_EXAMPLE}
{block.unindented.replace(block.single_indent, INDENT)}
"""
{INDENT}'''

    elif isinstance(block.node, ast.ClassDef):
        query = f'''{CLASS_EXAMPLE}
### CLASS BEGIN ###
{block.unindented.replace(block.single_indent, INDENT)}

### DOCSTRING BEGIN ###
"""
{INDENT}'''

    else:
        print("ERROR!")

    docstring = get_codex_query(query)

    return format_docstring(block, docstring, INDENT)

def main():
    """
    Main function to run the program.
    """
    fpath, opath, verbose = process_input(sys.argv[1:])

    with open(fpath) as file:
        file_code = file.read()

    blocks = isolate_nodes(file_code)

    docstring_count = 0

    for i, block in enumerate(blocks):
        if ast.get_docstring(block.node):
            vprint(f"{block.name} already has a docstring", verbose)
            continue

        vprint(f"{i+1}/{len(blocks)} Generating docstring for {block.name}", verbose)

        block.generated_docstring = get_docstring(block)

        docstring_count += 1

    print(f"Generated {docstring_count} docstrings")

    for block in blocks:
        if block.generated_docstring:
            edited_snip = block.indented.splitlines()

            row = get_body_offset(block)

            decorator_count = len(block.node.decorator_list)

            edited_snip.insert(row + decorator_count, block.generated_docstring)

            edited_snip = "\n".join(edited_snip)

            file_code = file_code.replace(block.indented, edited_snip)

    with open(opath, "w+") as file:
        file.write(file_code)

    print("Successfully altered file and wrote to", opath)

openai.api_key = os.getenv("OPENAI_API_KEY")

if __name__ == "__main__":
    main()


'''

-Medium-
*DP*

You are given two integer arrays nums and multipliers of size n and m respectively, where n >= m. The arrays are 1-indexed.

You begin with a score of 0. You want to perform exactly m operations. On the ith operation (1-indexed), you will:

Choose one integer x from either the start or the end of the array nums.
Add multipliers[i] * x to your score.
Remove x from the array nums.
Return the maximum score after performing m operations.

Example 1:

Input: nums = [1,2,3], multipliers = [3,2,1]
Output: 14
Explanation: An optimal solution is as follows:
- Choose from the end, [1,2,3], adding 3 * 3 = 9 to the score.
- Choose from the end, [1,2], adding 2 * 2 = 4 to the score.
- Choose from the end, [1], adding 1 * 1 = 1 to the score.
The total score is 9 + 4 + 1 = 14.
Example 2:

Input: nums = [-5,-3,-3,-2,7,1], multipliers = [-10,-5,3,4,6]
Output: 102
Explanation: An optimal solution is as follows:
- Choose from the start, [-5,-3,-3,-2,7,1], adding -5 * -10 = 50 to the score.
- Choose from the start, [-3,-3,-2,7,1], adding -3 * -5 = 15 to the score.
- Choose from the start, [-3,-2,7,1], adding -3 * 3 = -9 to the score.
- Choose from the end, [-2,7,1], adding 1 * 4 = 4 to the score.
- Choose from the end, [-2,7], adding 7 * 6 = 42 to the score.
The total score is 50 + 15 - 9 + 4 + 42 = 102.

Constraints:

n == nums.length
m == multipliers.length
1 <= m <= 103
m <= n <= 105
-1000 <= nums[i], multipliers[i] <= 1000

'''
from typing import List
from functools import lru_cache
class Solution:
    def maximumScore(self, nums: List[int], multipliers: List[int]) -> int:
        @lru_cache(2000)
        def dp(s, i):
            if i == len(multipliers):
                return 0
            # some explanation to get e:

            # 0            s         e           nums.size()-1
            # |____________|_________|______________|
            # You could see that if current index is i, we have already
            # chosen i elements from nums array, then:

            # (s - 0) + (nums.size() - 1 - e) = i
            #                  e = nums.size() - 1 - (i - s)
            e = len(nums) - (i - s) - 1
            pickStart = nums[s] * multipliers[i] + dp(s + 1, i + 1) # pick left as ith
            pickEnd = nums[e] * multipliers[i] + dp(s, i + 1) # pick right as ith
            return max(pickStart, pickEnd)

        return dp(0, 0)

    def maximumScore2(self, nums: List[int], multipliers: List[int]) -> int:
        n, m = len(nums), len(multipliers)
        dp = [[0]*m for _ in range(m+1)]

        for i in reversed(range(m)):
            for j in range(i, m):
                k = i + m - j - 1
                dp[i][j] = max(nums[i] * multipliers[k] + dp[i+1][j], nums[j-m+n] * multipliers[k] + dp[i][j-1])

        return dp[0][-1]

if __name__ == "__main__":
    print(Solution().maximumScore(nums = [-5,-3,-3,-2,7,1], multipliers = [-10,-5,3,4,6]))


import pandas as pd
import streamlit as st
import os

def apriori(data, minSup, minConf=0.7):

    #! ##############
    L = []
    Ldict = []
    result = find_frequent_one_itemsets(data, minSup)
    L1 = result["firstItemSet"]
    # Include the counts from the first itemset
    all_counts = [result["counts"]]
    L.append(list(L1.keys()))
    Ldict.append(L1)

    C1 = pd.DataFrame([result["counts"].keys(), result["counts"].values()]).T.rename(
        columns={0: 'ItemSet', 1: 'Sup-count'})
    col1, col2 = st.columns(2)
    with col1:
        st.write(f'# C{1}')
        st.dataframe(C1)
    with col2:
        st.write(f'# L{1}')
        st.write(pd.DataFrame(
            [L1.keys(), L1.values()]).T.rename(
            columns={0: 'ItemSet', 1: 'Sup-count'}))

    k = 2

    while len(L[k - 2]) > 0:
        before_pruning_Ck, after_pruning_Ck = apriori_gen(L[k - 2])
        counts = count_itemsets(after_pruning_Ck, data)
        Lk = filter_by_min_sup(counts, minSup)
        Ldict.append(Lk)
        L.append(list(Lk.keys()))
        Ck = pd.DataFrame(
            [counts.keys(), counts.values()]).T.rename(
            columns={0: 'ItemSet', 1: 'Sup-count'})
        col1, col2 = st.columns(2)

        with col1:
            st.write(f'# C{k}')
            st.write(Ck)
        with col2:
            st.write(f'# L{k}')
            st.write(pd.DataFrame(
                [Lk.keys(), Lk.values()]).T.rename(
                columns={0: 'ItemSet', 1: 'Sup-count'}))
        all_counts.append(counts)
        k += 1
    if len(Ldict) > 1:
        st.write(f'### So,the Frequent item sets are in L{L.index(L[-2])+1} ')
        st.write(Ldict[-2])

        all_counts_after_pruning = list2Dict(all_counts)
        # st.write(f'# all_counts_after_pruning')
        # st.write(len(all_counts_after_pruning))

        # all_counts_before_pruning = list2Dict(all_counts_before_pruning)
        # st.write(f'# all_counts_before_pruning')
        # st.write(len(all_counts_before_pruning))
        rules = []
        for itemset in Ldict[-2]:
            # st.write(f'---------------')
            # st.write(f'### {itemset}')
            subsets = []
            itemsetList = list(itemset.split(','))
            # st.write(itemsetList)
            for i in range(1, len(itemsetList)):
                itemList = get_subsets(itemsetList, len(itemsetList)-i)
                for set1 in itemList:
                    set1 = ','.join(map(str, set1))
                    subsets.append(set1)

            # st.write("###### subsets")
            # st.write(subsets)

            for i, Set in zip(range(1, len(subsets)+1), subsets):
                # st.write(f'---')
                # st.write(f'#### Rule{i} of ({itemset}) ')
                # st.write(f'confidant = support({itemset}) / support({Set})')
                # if all_counts_after_pruning[itemset] < all_counts_after_pruning[Set]:
                conf = all_counts_after_pruning[itemset] / \
                    all_counts_after_pruning[Set]
                # else:
                #     conf = all_counts_after_pruning[Set] / \
                #         all_counts_after_pruning[itemset]

                rules.append(
                    [itemset, Set, conf, "accepted" if conf >= minConf else "not accepted"])
                # st.write(
                #     f'confidant = support({all_counts_after_pruning[itemset]}) / support({all_counts_after_pruning[Set]}) = {conf}')
                # st.write(
                #     f'##### {"accepted" if conf>=minConf else "not accepted"}')
        dfRules = pd.DataFrame(
            rules, columns=['itemset', 'subset', 'confidence', 'accepted'])
        st.write(f"# Discovering ARs From L{L.index(L[-2])+1}")
        st.table(dfRules)

def list2Dict(list1):
    dict1 = {}
    for dict in list1:
        for key, item in dict.items():
            dict1.update({key: item})
    return dict1

def find_frequent_one_itemsets(D, minSup):
    counts = {}

    for t in D:
        for item in t:
            item = item.rstrip()
            if str(item) == 'nan':
                continue
            counts[item] = counts.get(item, 0) + 1

    first_item_set = {item: counts[item]
                      for item in counts.keys() if counts[item] >= minSup}
    return {"firstItemSet": first_item_set, "counts": counts}

def apriori_gen(Lk_1):
    new_itemsets_before_pruning = []
    new_itemsets_after_pruning = []
    len_Lk_1 = len(Lk_1)

    for i in range(len_Lk_1):
        for j in range(i + 1, len_Lk_1):
            itemset1 = str(Lk_1[i]).split(',')
            itemset2 = str(Lk_1[j]).split(',')

            # print(itemset1[:-1])
            # print(itemset2[:-1])

            if itemset1[:-1] != itemset2[:-1] and itemset1[-1] == itemset2[-1]:
                continue

            new_itemset = sorted(itemset1 + [str(itemset2[-1])])

            if new_itemset in new_itemsets_before_pruning:
                continue
            new_itemsets_before_pruning.append(new_itemset)

            subsets = get_subsets(new_itemset, len(new_itemset) - 1)

            all_subsets_frequent = all(
                ','.join(map(str, subset)) in Lk_1 for subset in subsets
            )

            if all_subsets_frequent:
                new_itemsets_after_pruning.append(
                    ','.join(map(str, new_itemset)))

    return new_itemsets_before_pruning, new_itemsets_after_pruning

def get_subsets(itemset, k):
    if k == 0:
        return [[]]

    if len(itemset) < k:
        return []

    head, *tail = itemset

    subsets_without_head = get_subsets(tail, k)
    subsets_with_head = [(head, *subset)
                         for subset in get_subsets(tail, k - 1)]

    return subsets_without_head + subsets_with_head

def count_itemsets(Ck, D):
    counts = {}
    for c in Ck:
        counts[c] = 0

    for t in D:
        for c in Ck:
            items = c.split(',')
            if all(item in t for item in items):
                counts[c] = counts.get(c, 0) + 1

    return counts

def filter_by_min_sup(counts, minSup):
    return {itemset: counts[itemset] for itemset in counts.keys()
            if counts[itemset] >= minSup}

def prepare_data(D):
    data = []
    for r in D:
        row = []
        for item in r:
            item = item.strip()
            if item != "":
                row.append(item.rstrip())
        data.append(row)

    return data

# lines = []
# with open("DataSet/fromSlide.csv", "r") as f:
#     for line in f.readlines():
#         lines.append(line.split(','))
#         # if line.strip("\n") != delLine:

# result = apriori(lines, 2)

#################### ? UI start here ################################

datasetLocation = {
    "fromSlide.csv": 'DataSet/fromSlide.csv',
    "retail_dataset.csv": 'DataSet/retail_dataset.csv',
    "tesco.csv": 'DataSet/tesco.csv',
}

selected = st.selectbox(label='Pick dataset', options=datasetLocation.keys())

file = st.file_uploader('pick datasets',
                        type=['csv'],
                        label_visibility='collapsed',
                        help='')

# st.write(file.readlines())
# st.write(dir(file))

lines = []
if file is None:
    with open(datasetLocation[selected], "r") as f:
        for line in f.readlines():
            lines.append(line.split(','))
else:
    try:
        os.mkdir('DataSet')
    except OSError:
        pass

    # with open("DataSet/"+file.name, "wr") as f:
    for line in file.readlines():
        lines.append(line.decode('utf-8').split(','))
    # if line.strip("\n") != delLine:

minSup = st.number_input('min Support', value=2)
minConf = st.slider('min confidant', min_value=0.1, max_value=0.99, value=0.7)
data = prepare_data(lines)
st.write(len(data))

if st.button('start'):

    # csv_file = pd.read_csv("DataSet/"+file.name,
    #                        header=None, error_bad_lines=False)

    # st.write('###############')
    # st.write(csv_file.values.tolist())
    st.table(data[0:20])

    apriori(data, minSup, minConf)


import copy
import re
import traceback
from dataclasses import dataclass
from logging import getLogger
from typing import Any, Callable, Literal, Type, TypeVar

import altair as alt
import commentjson
import jsonschema
import pandas as pd
import pydantic
from langchain.chat_models import ChatOpenAI
from langchain.chat_models.base import BaseChatModel
from langchain.schema import BaseMessage, FunctionMessage, HumanMessage, SystemMessage
from plotly.graph_objs import Figure

from chat2plot.dataset_description import description
from chat2plot.dictionary_helper import delete_null_field
from chat2plot.prompt import (
    JSON_TAG,
    error_correction_prompt,
    explanation_prompt,
    system_prompt,
)
from chat2plot.render import draw_altair, draw_plotly
from chat2plot.schema import PlotConfig, ResponseType, get_schema_of_chart_config

_logger = getLogger(__name__)

T = TypeVar("T", bound=pydantic.BaseModel)
ModelDeserializer = Callable[[dict[str, Any]], T]

# These errors are caught within the application.
# Other errors (e.g. openai.error.RateLimitError) are propagated to user code.
_APPLICATION_ERRORS = (
    pydantic.ValidationError,
    jsonschema.ValidationError,
    ValueError,
    KeyError,
    AssertionError,
)

@dataclass(frozen=True)
class Plot:
    figure: alt.Chart | Figure | None
    config: PlotConfig | dict[str, Any] | pydantic.BaseModel | None
    response_type: ResponseType
    explanation: str
    conversation_history: list[BaseMessage] | None

class ChatSession:
    """chat with conversasion history"""

    def __init__(
        self,
        chat: BaseChatModel,
        df: pd.DataFrame,
        system_prompt_template: str,
        user_prompt_template: str,
        description_strategy: str = "head",
        functions: list[dict[str, Any]] | None = None,
    ):
        self._system_prompt_template = system_prompt_template
        self._user_prompt_template = user_prompt_template
        self._chat = chat
        self._conversation_history: list[BaseMessage] = [
            SystemMessage(
                content=system_prompt_template.format(
                    dataset=description(df, description_strategy)
                )
            )
        ]
        self._functions = functions

    @property
    def history(self) -> list[BaseMessage]:
        return copy.deepcopy(self._conversation_history)

    def query(self, q: str, raw: bool = False) -> BaseMessage:
        prompt = q if raw else self._user_prompt_template.format(text=q)
        response = self._query(prompt)
        return response

    def _query(self, prompt: str) -> BaseMessage:
        self._conversation_history.append(HumanMessage(content=prompt))
        kwargs = {}
        if self._functions:
            kwargs["functions"] = self._functions
        response = self._chat(self._conversation_history, **kwargs)  # type: ignore
        self._conversation_history.append(response)

        if response.additional_kwargs.get("function_call"):
            name = response.additional_kwargs["function_call"]["name"]
            arguments = response.additional_kwargs["function_call"]["arguments"]
            self._conversation_history.append(
                FunctionMessage(name=name, content=arguments)
            )

        return response

    def last_response(self) -> str:
        return self._conversation_history[-1].content

class Chat2PlotBase:
    @property
    def session(self) -> ChatSession:
        raise NotImplementedError()

    @property
    def function_call(self) -> bool:
        return False

    def query(self, q: str, config_only: bool = False, show_plot: bool = False) -> Plot:
        raise NotImplementedError()

    def __call__(
        self, q: str, config_only: bool = False, show_plot: bool = False
    ) -> Plot:
        return self.query(q, config_only, show_plot)

class Chat2Plot(Chat2PlotBase):
    def __init__(
        self,
        df: pd.DataFrame,
        chart_schema: Literal["simple"] | Type[pydantic.BaseModel],
        *,
        chat: BaseChatModel | None = None,
        function_call: bool | Literal["auto"] = False,
        language: str | None = None,
        description_strategy: str = "head",
        verbose: bool = False,
        custom_deserializer: ModelDeserializer | None = None,
    ):
        self._target_schema: Type[pydantic.BaseModel] = (
            PlotConfig if chart_schema == "simple" else chart_schema  # type: ignore
        )

        chat_model = _get_or_default_chat_model(chat)

        self._function_call = (
            _has_function_call_capability(chat_model)
            if function_call == "auto"
            else function_call
        )

        self._session = ChatSession(
            chat_model,
            df,
            system_prompt("simple", self._function_call, language, self._target_schema),
            "<{text}>",
            description_strategy,
            functions=[
                get_schema_of_chart_config(self._target_schema, as_function=True)
            ]
            if self._function_call
            else None,
        )
        self._df = df
        self._verbose = verbose
        self._custom_deserializer = custom_deserializer
        self._language = language

    @property
    def session(self) -> ChatSession:
        return self._session

    @property
    def function_call(self) -> bool:
        return self._function_call

    def query(self, q: str, config_only: bool = False, show_plot: bool = False) -> Plot:
        raw_response = self._session.query(q)

        try:
            if self._verbose:
                _logger.info(f"request: {q}")
                _logger.info(f"first response: {raw_response}")
            return self._parse_response(q, raw_response, config_only, show_plot)
        except _APPLICATION_ERRORS as e:
            if self._verbose:
                _logger.warning(traceback.format_exc())
            msg = e.message if isinstance(e, jsonschema.ValidationError) else str(e)
            error_correction = error_correction_prompt(self._function_call).format(
                error_message=msg,
            )
            corrected_response = self._session.query(error_correction)
            if self._verbose:
                _logger.info(f"retry response: {corrected_response}")

            try:
                return self._parse_response(
                    q, corrected_response, config_only, show_plot
                )
            except _APPLICATION_ERRORS as e:
                if self._verbose:
                    _logger.warning(e)
                    _logger.warning(traceback.format_exc())
                return Plot(
                    None,
                    None,
                    ResponseType.FAILED_TO_RENDER,
                    "",
                    self._session.history,
                )

    def __call__(
        self, q: str, config_only: bool = False, show_plot: bool = False
    ) -> Plot:
        return self.query(q, config_only, show_plot)

    def _parse_response(
        self, q: str, response: BaseMessage, config_only: bool, show_plot: bool
    ) -> Plot:
        if self._function_call:
            if not response.additional_kwargs.get("function_call"):
                raise ValueError("Function should be called")
            function_call = response.additional_kwargs["function_call"]
            json_data = commentjson.loads(function_call["arguments"])

            explanation = self._session.query(
                explanation_prompt(self._language, q), raw=True
            ).content
        else:
            explanation, json_data = parse_json(response.content)

        try:
            if self._custom_deserializer:
                config = self._custom_deserializer(json_data)
            else:
                config = self._target_schema.parse_obj(json_data)
        except _APPLICATION_ERRORS:
            _logger.warning(traceback.format_exc())
            # To reduce the number of failure cases as much as possible,
            # only check against the json schema when instantiation fails.
            jsonschema.validate(json_data, self._target_schema.schema())
            raise

        if self._verbose:
            _logger.info(config)

        if config_only or not isinstance(config, PlotConfig):
            return Plot(
                None, config, ResponseType.SUCCESS, explanation, self._session.history
            )

        figure = draw_plotly(self._df, config, show_plot)
        return Plot(
            figure, config, ResponseType.SUCCESS, explanation, self._session.history
        )

class Chat2Vega(Chat2PlotBase):
    def __init__(
        self,
        df: pd.DataFrame,
        chat: BaseChatModel | None = None,
        language: str | None = None,
        description_strategy: str = "head",
        verbose: bool = False,
    ):
        self._session = ChatSession(
            _get_or_default_chat_model(chat),
            df,
            system_prompt("vega", False, language, None),
            "<{text}>",
            description_strategy,
        )
        self._df = df
        self._verbose = verbose

    @property
    def session(self) -> ChatSession:
        return self._session

    def query(self, q: str, config_only: bool = False, show_plot: bool = False) -> Plot:
        res = self._session.query(q)

        try:
            explanation, config = parse_json(res.content)
            if "data" in config:
                del config["data"]
            if self._verbose:
                _logger.info(config)
        except _APPLICATION_ERRORS:
            _logger.warning(f"failed to parse LLM response: {res}")
            _logger.warning(traceback.format_exc())
            return Plot(
                None, None, ResponseType.UNKNOWN, res.content, self._session.history
            )

        if config_only:
            return Plot(
                None, config, ResponseType.SUCCESS, explanation, self._session.history
            )

        try:
            plot = draw_altair(self._df, config, show_plot)
            return Plot(
                plot, config, ResponseType.SUCCESS, explanation, self._session.history
            )
        except _APPLICATION_ERRORS:
            _logger.warning(traceback.format_exc())
            return Plot(
                None,
                config,
                ResponseType.FAILED_TO_RENDER,
                explanation,
                self._session.history,
            )

    def __call__(
        self, q: str, config_only: bool = False, show_plot: bool = False
    ) -> Plot:
        return self.query(q, config_only, show_plot)

def chat2plot(
    df: pd.DataFrame,
    schema_definition: Literal["simple", "vega"] | Type[pydantic.BaseModel] = "simple",
    chat: BaseChatModel | None = None,
    function_call: bool | Literal["auto"] = "auto",
    language: str | None = None,
    description_strategy: str = "head",
    custom_deserializer: ModelDeserializer | None = None,
    verbose: bool = False,
) -> Chat2PlotBase:
    """Create Chat2Plot instance.

    Args:
        df: Data source for visualization.
        schema_definition: Type of json format; "vega" for vega-lite compliant json, "simple" for chat2plot built-in
              data structure. If you want a custom schema definition, pass a type inheriting from pydantic.BaseModel
              as your own chart setting.
        chat: The chat instance for interaction with LLMs.
              If omitted, `ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-0613")` will be used.
        function_call:
        language: Language of explanations. If not specified, it will be automatically inferred from user prompts.
        description_strategy: Type of how the information in the dataset is embedded in the prompt.
              Defaults to "head" which embeds the contents of df.head(5) in the prompt.
              "dtypes" sends only columns and types to LLMs and does not send the contents of the dataset,
              which allows for privacy but may reduce accuracy.
        custom_deserializer: A custom function to convert the json returned by the LLM into a object.
        verbose: If `True`, chat2plot will output logs.

    Returns:
        Chat instance.
    """

    if schema_definition == "simple":
        return Chat2Plot(
            df,
            "simple",
            chat=chat,
            language=language,
            description_strategy=description_strategy,
            verbose=verbose,
            custom_deserializer=custom_deserializer,
            function_call=function_call,
        )
    if schema_definition == "vega":
        return Chat2Vega(df, chat, language, description_strategy, verbose)
    elif issubclass(schema_definition, pydantic.BaseModel):
        return Chat2Plot(
            df,
            schema_definition,
            chat=chat,
            language=language,
            description_strategy=description_strategy,
            verbose=verbose,
            custom_deserializer=custom_deserializer,
            function_call=function_call,
        )
    else:
        raise ValueError(
            f"schema_definition should be one of [simple, vega] or pydantic.BaseClass (given: {schema_definition})"
        )

def _extract_tag_content(s: str, tag: str) -> str:
    m = re.search(rf"<{tag}>(.*)</{tag}>", s, re.MULTILINE | re.DOTALL)
    if m:
        return m.group(1)
    else:
        m = re.search(rf"<{tag}>(.*)<{tag}>", s, re.MULTILINE | re.DOTALL)
        if m:
            return m.group(1)
    return ""

def parse_json(content: str) -> tuple[str, dict[str, Any]]:
    """parse json and split contents by pre-defined tags"""
    json_part = _extract_tag_content(content, "json")  # type: ignore
    if not json_part:
        raise ValueError(f"failed to find {JSON_TAG[0]} and {JSON_TAG[1]} tags")

    explanation_part = _extract_tag_content(content, "explain")
    if not explanation_part:
        explanation_part = _extract_tag_content(content, "explanation")

    # LLM rarely generates JSON with comments, so use the commentjson package instead of json
    return explanation_part.strip(), delete_null_field(commentjson.loads(json_part))

def _get_or_default_chat_model(chat: BaseChatModel | None) -> BaseChatModel:
    if chat is None:
        return ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-0613")  # type: ignore
    return chat

def _has_function_call_capability(chat: BaseChatModel) -> bool:
    if not isinstance(chat, ChatOpenAI):
        return False
    return any(
        chat.model_name.startswith(prefix)
        for prefix in ["gpt-4-0613", "gpt-3.5-turbo-0613"]
    )


#importing necessary packages
from scipy.spatial import distance
from imutils import face_utils
import imutils
import playsound
from threading import Thread
import dlib
import queue
import cv2

def eye_aspect_ratio(eye):
    # compute the euclidean distance between the vertical eye landmark (x, y)-coordinates
	A = distance.euclidean(eye[1], eye[5])
	B = distance.euclidean(eye[2], eye[4])
    # compute the euclidean distance between the horizontal eye landmark (x, y)-coordinates
	C = distance.euclidean(eye[0], eye[3])
    #compute eye aspect ratio
	ear = (A + B) / (2.0 * C)
	return ear

def sound_alarm():
	# play an alarm sound
	playsound.playsound("./alarm.wav")

thresh = 0.25
frame_check = 20
TOTAL = 0
ALARM_ON = False
#Returns the default face detector
detect = dlib.get_frontal_face_detector()
#shape_predictor_68_face_landmarks is our pre-trained model for facial landmarks detector
predict = dlib.shape_predictor("./shape_predictor_68_face_landmarks.dat")

(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_68_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_68_IDXS["right_eye"]
cap=cv2.VideoCapture(0)
flag=0
while True:
    #Getting out image by webcam
	ret, frame=cap.read()
	frame = imutils.resize(frame, width=450)
    #Converting the image to gray scale
	gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Detect faces in the grayscale frame
	subjects = detect(gray, 0)
    #Loop over the face detections
	for subject in subjects:
        #determine the facial landmarks for the face region,
		shape = predict(gray, subject)
        #then, converting the facial landmark(x, y) coordinates to NumPy Array
		shape = face_utils.shape_to_np(shape)
        #extract the left and right eye coordinates, then
		leftEye = shape[lStart:lEnd]
		rightEye = shape[rStart:rEnd]
        #use the coordinates to compute the eye aspect ratio for both eyes
		leftEAR = eye_aspect_ratio(leftEye)
		rightEAR = eye_aspect_ratio(rightEye)
        #compute the average of EAR for both eyes
		ear = (leftEAR + rightEAR) / 2.0
        # compute the convex hull for the left and right eye, then
		leftEyeHull = cv2.convexHull(leftEye)
		rightEyeHull = cv2.convexHull(rightEye)
		# visualize each of the eyes
		cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
		cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)
        # check to see if the eye aspect ratio is below the blink threshold,
		if ear < thresh:
			#and if so, increment the blink frame counter
			flag += 1
			print (flag)
			if flag >= frame_check:

				if not ALARM_ON:
					ALARM_ON = True
					t = Thread(target=sound_alarm)
					t.deamon = True
					t.start()

				#draw on the frame
				cv2.putText(frame, "!!!!!!!!!!!!****ALERT****!!!!!!!!!!!!", (10, 30),
				cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
				cv2.putText(frame, "!!!!!!!!!!!!****ALERT****!!!!!!!!!!!!", (10,325),
				cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

		else:
			#reset the flag
			flag = 0
			ALARM_ON = False

	#show the frame
	cv2.imshow("Frame", frame)
	key = cv2.waitKey(1) & 0xFF
	#if the 'q' key was pressed, break from the loop
	if key == ord("q"):
		break
#do a bit of cleanup
cap.release()
cv2.destroyAllWindows()


import torchtext
import torch
import torch.nn as nn
from torch.autograd import Variable
import matplotlib.pyplot as plt
import numpy as np
from torchtext.vocab import Vectors
from tqdm import tqdm
import os
from sys import version_info
if version_info.major == 2:
    import urllib as urldownload
else:
    import urllib.request as urldownload

import tarfile
import re
import random
from torchtext import data
import keras
import keras.backend as K
class CNN_TRLN(nn.Module):
    def __init__(self, in_channels, out_channels, batch_size,trln):
        super(CNN_TRLN, self).__init__()
        self.nonstatic_embeddings = nn.Embedding(TEXT.vocab.vectors.size()[0], TEXT.vocab.vectors.size()[1])
        self.nonstatic_embeddings.weight.data.copy_(TEXT.vocab.vectors)
        self.embeddings = self.nonstatic_embeddings
        self.trln = trln
        self.convs = nn.ModuleList([nn.Conv1d(in_channels = in_channels, out_channels = in_channels, kernel_size = n) for n in (1,2,3,4)])
        self.dropout_train, self.dropout_test = nn.Dropout(p = 0.5), nn.Dropout(p = 0)
        self.linear = nn.Linear(in_features=801, out_features=out_channels, bias = True)

    def forward(self, x, train = True):
        x, lengths = x

        lengths = Variable(lengths.view(-1, 1).float())
        embedded = self.embeddings(x)
        trln_embed =self.trln.predict(embedded.transpose(0, 1).detach().numpy())

        trln_embed =torch.FloatTensor(trln_embed)
        trln_embed = torch.cat([trln_embed, lengths], dim = 1)

        embedded = embedded.transpose(1, 2)
        embedded = embedded.transpose(0, 2)

        concatted_features = torch.cat([conv(embedded) for conv in self.convs if embedded.size(2) >= conv.kernel_size[0]], dim = 2)
        activated_features = torch.nn.functional.relu(concatted_features)
        pooled = torch.nn.functional.max_pool1d(activated_features, activated_features.size(2)).squeeze(2)

        ensemble = torch.cat([pooled, trln_embed], dim = 1)

        dropped = self.dropout_train(ensemble) if train else self.dropout_test(ensemble)
        output = self.linear(ensemble)

        logits = torch.nn.functional.log_softmax(output, dim = 1)
        return logits

    def predict(self, x):
        logits = self.forward(x, train = False)
        return logits.max(1)[1] + 1

    def train(self, train_iter, val_iter, num_epochs, learning_rate = 1e-3, plot = False):
        criterion = torch.nn.NLLLoss()
        optimizer = torch.optim.Adam(model.parameters(), lr = learning_rate)
        loss_vec = []

        for epoch in tqdm(range(1, num_epochs+1)):
            epoch_loss = 0
            for batch in train_iter:
                x = batch.text
                y = batch.label
                optimizer.zero_grad()
                y_p = self.forward(x)
                loss = criterion(y_p, y-1)
                loss.backward()
                optimizer.step()
                epoch_loss += loss.item()

            self.model = model

            loss_vec.append(epoch_loss / len(train_iter))
            if epoch % 1 == 0:
                acc = self.validate(val_iter)
                print('Epoch {} loss: {} | acc: {}'.format(epoch, loss_vec[epoch-1], acc))
                self.model = model
        if plot:
            plt.plot(range(len(loss_vec)), loss_vec)
            plt.xlabel('Epoch')
            plt.ylabel('Loss')
            plt.show()
        print('\nModel trained.\n')
        self.loss_vec = loss_vec
        self.model = model

    def test(self, test_iter):
        upload, trues = [], []
        for batch in test_iter:
            x, y = batch.text, batch.label
            probs = self.predict(x)
            upload += list(probs.numpy())
            trues += list(y.numpy())

        correct = sum([1 if i == j else 0 for i, j in zip(upload, trues)])
        accuracy = correct / len(trues)
        print('Testset Accuracy:', accuracy)
        #save result
        np.save('pred_trln.npy',upload)
        np.save('y_trln.npy',trues)
        with open("predictions.txt", "w") as f:
            for u in upload:
                f.write(str(u) + "\n")
    def validate(self, val_iter):
        y_p, y_t, correct = [], [], 0
        for batch in val_iter:
            x, y = batch.text, batch.label
            probs = self.model.predict(x)[:len(y)]
            y_p += list(probs.data)
            y_t += list(y.data)

        correct = sum([1 if i == j else 0 for i, j in zip(y_p, y_t)])
        accuracy = correct / len(y_p)
        return accuracy
def get_file_name(file_dir, name="dirs"):
    res_dirs = list()
    res_files = list()
    for root, dirs, files in os.walk(file_dir):
        res_dirs += dirs
        res_files += files

    if name == "dirs":
        return res_dirs
    else:
        return res_files

def replace(matched):
    return " " + matched.group("m") + " "

def tokenize_line_en(line):
   line = re.sub(r"\t", "", line)
   line = re.sub(r"^\s+", "", line)
   line = re.sub(r"\s+$", "", line)
   line = re.sub(r"<br />", "", line)
   line = re.sub(r"(?P<m>\W)", replace, line)
   line = re.sub(r"\s+", " ", line)
   return line.split()

def clean_str(string):
    """
    Tokenization/string cleaning for all datasets except for SST.
    Original taken from https://github.com/yoonkim/CNN_sentence/blob/master/process_data.py
    """
    string = re.sub(r"[^A-Za-z0-9(),!?\'\`]", " ", string)
    string = re.sub(r"\'s", " \'s", string)
    string = re.sub(r"\'ve", " \'ve", string)
    string = re.sub(r"n\'t", " n\'t", string)
    string = re.sub(r"\'re", " \'re", string)
    string = re.sub(r"\'d", " \'d", string)
    string = re.sub(r"\'ll", " \'ll", string)
    string = re.sub(r",", " , ", string)
    string = re.sub(r"!", " ! ", string)
    string = re.sub(r"\(", " \( ", string)
    string = re.sub(r"\)", " \) ", string)
    string = re.sub(r"\?", " \? ", string)
    string = re.sub(r"\s{2,}", " ", string)
    return string.strip()

class BasicDataset(data.Dataset):

    @classmethod
    def download_or_unzip(cls, root):
        if not os.path.exists(root):
            os.mkdir(root)
        path = os.path.join(root, cls.dirname)
        if not os.path.isdir(path):
            tpath = os.path.join(root, cls.filename)
            if not os.path.isfile(tpath):
                print('downloading')
                urldownload.urlretrieve(cls.url, tpath)
            with tarfile.open(tpath, 'r') as tfile:
                print('extracting')
                tfile.extractall(root)
        return os.path.join(path, '')

    @classmethod
    def splits(cls, text_field, label_field, dev_ratio=.1, shuffle=True, root='./data', **kwargs):
        path = cls.download_or_unzip(root)
        examples = cls(text_field, label_field, path=path, **kwargs).examples
        if shuffle: random.shuffle(examples)
        dev_index = -1 * int(dev_ratio*len(examples))

        return (cls(text_field, label_field, examples=examples[:dev_index]),
                cls(text_field, label_field, examples=examples[dev_index:]))

class NewsGroup(BasicDataset):
    '''newsgroups'''
    url ='http://qwone.com/~jason/20Newsgroups/20news-18828.tar.gz'
    filename = '20news-18828.tar.gz'
    dirname = '20news-18828'
    '''mini_newsgroups'''
#    url = "http://archive.ics.uci.edu/ml/machine-learning-databases/20newsgroups-mld/mini_newsgroups.tar.gz"
#    filename = 'mini_newsgroups.tar.gz'
#    dirname = 'mini_newsgroups'
    @staticmethod
    def sort_key(ex):
        return len(ex.text)

    def __init__(self, text_field, label_field, path=None, examples=None, **kwargs):
        text_field.preprocessing = data.Pipeline(clean_str)
        fields = [('text', text_field), ('label', label_field)]
        path = self.dirname if path is None else path

        if examples is None:
            examples = []
            class_dirs = get_file_name(path)
            for class_dir_name in class_dirs:
                class_dir_path = os.path.join(path, class_dir_name)
                file_names = get_file_name(class_dir_path, "files")
                for file in file_names:
                    file_path = os.path.join(class_dir_path, file)
                    try:
                        with open(file_path) as f:
                            raw_data = f.read()
                            if len(raw_data.split(' ')) > 400:
                                raw_data = ' '.join(raw_data.split(' ')[0:400])
                            examples += [data.Example.fromlist([raw_data, class_dir_name], fields)]
                    except:
                        continue
        super(NewsGroup, self).__init__(examples, fields, **kwargs)

def mutual_info_loss(c, c_given_x):
        eps = 1e-8
        conditional_entropy = K.mean(- K.sum(K.log(c_given_x + eps) * c, axis=1))
        entropy = K.mean(- K.sum(K.log(c + eps) * c, axis=1))
        return conditional_entropy + entropy
def mutual_info_loss_n(c, c_given_x):
        eps = 1e-8
        conditional_entropy = K.mean(- K.sum(K.log(c_given_x + eps) * c, axis=1))
        entropy = K.mean(- K.sum(K.log(c + eps) * c, axis=1))
        return -1*(conditional_entropy + entropy)

if __name__ == '__main__':
    print("Loading data...")
    TEXT = data.Field(lower=True, tokenize=tokenize_line_en, include_lengths=True, batch_first=False, sequential=True,fix_length=1000)
    LABEL = data.Field(sequential=False)
    train, test = NewsGroup.splits(TEXT, LABEL)
    print("Building vocabulary...")
    TEXT.build_vocab(train)
    LABEL.build_vocab(train)
    train_iter, test_iter = data.BucketIterator.splits((train, test), sort_key = lambda x:len(x.text),
                                                       sort_within_batch=True,
                                                       batch_size=20, device=-1,
                                                       repeat = False)
    url = 'https://dl.fbaipublicfiles.com/fasttext/vectors-wiki/wiki.{}.vec'
    TEXT.vocab.load_vectors(vectors=Vectors('wiki.simple.vec', url=url))

    trln = keras.models.load_model('embedding.h5',custom_objects={'mutual_info_loss': mutual_info_loss,'mutual_info_loss_n': mutual_info_loss_n})
    model = CNN_TRLN(in_channels = 300, out_channels = 20, batch_size = 20, trln=trln)
    model.train(train_iter = train_iter, val_iter = test_iter, num_epochs = 46, learning_rate = 1e-4, plot = False)
    model.test(test_iter)


# -*-coding:utf-8-*-
from main_app import app
from flask import render_template, jsonify, request
import json
from package_mix_ratio import result_package_new, package_best
from initial_screen import main_initial
from deep_model_strength.strength_prediction import presiction, load_torch_model
from main_util import change_joption_jprice
from mix_ratio_optimization import main_mix_ratio_optimization

model_strength = load_torch_model()  # 让模型一直在内存中
model_strength.eval()

# 设置route
@app.route('/')
@app.route('/index', methods=['GET', 'POST'])
def index():
    ip = request.remote_addr
    return render_template('index.html', user_ip=ip)

# 请求配合比
@app.route('/mixratio', methods=['POST'])
def create_task_test():
    data = json.loads(request.get_data())
    joption = data["option"]
    jprice = data["price"]
    # 获取石和砂是否使用、价格和位置等信息
    joption, jprice = change_joption_jprice(joption, jprice)
    lrecord = main_initial(joption)[:10]
    jresult = result_package_new(joption, jprice, lrecord)
    if len(jresult["result"]) > 0:
        best_record, best_apparent_density, best_unit_price = main_mix_ratio_optimization(joption, jprice, lrecord, model=model_strength)
        if best_record != None:
            jdata = package_best(joption, best_record, best_apparent_density, best_unit_price)  # 优化之后打包
            jresult["result"].insert(0, jdata)  # 优化后的数据插入到最前面
        else:
            print("生成数据失败!")
    return jsonify(jresult), 201

# 混凝土强度预测
@app.route('/mixratio/strength', methods=['POST'])
def strength_prediction():
    data = json.loads(request.get_data())
    jresult = presiction(data, model=model_strength)
    return jsonify(jresult), 201


#First load Mat to get

firstN = 5
from scipy import io
from scipy import linalg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
cfd_datas = io.loadmat("date0.mat")
print(io.whosmat("date0.mat"))

print(cfd_datas.keys())

state_matrix = cfd_datas['p']
print(state_matrix.shape)

nSnapShot = state_matrix.shape[0]
nX = state_matrix.shape[1]
nY = state_matrix.shape[2]
#Perform an Proper orthogonal decomposition

operating_matrix = state_matrix.reshape(nSnapShot,nX*nY)
print(operating_matrix.shape)

u,s,Vh = linalg.svd(operating_matrix)
#Output the firstN modes.
for i in range(firstN):
    ColumnVec = Vh[i].reshape(nX,nY).T
    plt.imshow(ColumnVec)
    plt.savefig("Mode{}.png".format(i))
#Perform an superposition of u s Vh to get the approximated flow

print(u.shape)
print(s.shape)
print(Vh.shape)
#Now test the mutiply of two matrix:
mat1 = np.array([[1,0],[0,1],[0,0]])
print(mat1.shape)
vec1 = np.array([[0],[1]])
print(vec1.shape)
print(mat1.dot(vec1))

fig,ax = plt.subplots(2,1)

ims = []
ax[0].set_title("CDF result")
ax[1].set_title("First {} mode superposition".format(firstN))
for j in range(nSnapShot):
    im0 = ax[0].imshow(state_matrix[j].T,animated=True)
    MatrixVec = operating_matrix[j]
    super = np.zeros_like(MatrixVec)
    for i in range(firstN):
        ColumnVec = Vh[i]
        imagnitude = sum(ColumnVec * MatrixVec)
        super  = super + ColumnVec * imagnitude
    super = super.reshape(nX,nY).T
    #plt.imshow(super)
    #plt.savefig("Snap{}".format(j))
    im1 = ax[1].imshow(super,animated=True)
    ims.append([im0,im1])

#Generating movie and gif
# ani = animation.ArtistAnimation(fig,ims,interval=150,blit=True, repeat_delay=1000)
# ani.save("movie.mp4")
# ani.save("ani.gif",writer='pillow',fps=10)
#Plot EigenValue related

fig,axes = plt.subplots(1,2)
#Left is the eigenvalue
x_axis = np.arange(138)
axes[0].set_yscale('log')
axes[0].plot(x_axis,s)
axes[0].set_title("Eigen value")

axes[1].set_title("Accumulated Energy")
total_Energy = sum(s*s)
accum_Energy = np.zeros_like(x_axis,dtype=float)

for i in range(0,nSnapShot):
    accum_Energy[i] = accum_Energy[i-1] + float(s[i]*s[i]/total_Energy)
#accum_Energy = accum_Energy/total_Energy

axes[1].plot(x_axis,accum_Energy)

plt.savefig("energy.png")


from collections import Counter
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        cl = list(Counter(nums).items())
        ret=[[]]
        return foo(0,cl,ret)

def foo(idx, cnt, ret):
        if idx==len(cnt): return ret
        new_ret=ret.copy()
        num=cnt[idx][0]
        rng=cnt[idx][1]
        #print('idx {} ret {} num {} rng {}'.format(idx,ret,num,rng))

        if idx==0:
                for i in range(1,rng+1):
                        new_ret.append([num]*i)
        else:
                for i in range(1,rng+1):
                        to_app=[num]*i
                        for r in ret:
                                row=r.copy()
                                row.extend(to_app)
                                new_ret.append(row)
        return foo(idx+1,cnt,new_ret)


import numpy as np
from catalyst.constants import LOG_LEVEL
from catalyst.protocol import Portfolio, Positions, Position
from logbook import Logger

log = Logger('ExchangePortfolio', level=LOG_LEVEL)

class ExchangePortfolio(Portfolio):
    """
    Since the goal is to support multiple exchanges, it makes sense to
    include additional stats in the portfolio object. This fills the role
    of Blotter and Portfolio in live mode.

    Instead of relying on the performance tracker, each exchange portfolio
    tracks its own holding. This offers a separation between tracking an
    exchange and the statistics of the algorithm.
    """

    def __init__(self, start_date, starting_cash=None):
        self.capital_used = 0.0
        self.starting_cash = starting_cash
        self.portfolio_value = starting_cash
        self.pnl = 0.0
        self.returns = 0.0
        self.cash = starting_cash
        self.positions = Positions()
        self.start_date = start_date
        self.positions_value = 0.0
        self.open_orders = dict()

    def create_order(self, order):
        """
        Create an open order and store in memory.

        Parameters
        ----------
        order: Order

        """
        log.debug('creating order {}'.format(order.id))

        open_orders = self.open_orders[order.asset] \
            if order.asset is self.open_orders else []

        open_orders.append(order)

        self.open_orders[order.asset] = open_orders

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            order_position = Position(order.asset)
            self.positions[order.asset] = order_position

        order_position.amount += order.amount
        log.debug('open order added to portfolio')

    def _remove_open_order(self, order):
        try:
            open_orders = self.open_orders[order.asset]
            if order in open_orders:
                open_orders.remove(order)

        except Exception:
            raise ValueError(
                'unable to clear order not found in open order list.'
            )

    def execute_order(self, order, transaction):
        """
        Update the open orders and positions to apply an executed order.

        Unlike with backtesting, we do not need to add slippage and fees.
        The executed price includes transaction fees.

        Parameters
        ----------
        order: Order
        transaction: Transaction

        """
        log.debug('executing order {}'.format(order.id))
        self._remove_open_order(order)

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            raise ValueError(
                'Trying to execute order for a position not held:'
                ' {}'.format(order.id)
            )

        self.capital_used += order.amount * transaction.price

        if order.amount > 0:
            if order_position.cost_basis > 0:
                order_position.cost_basis = np.average(
                    [order_position.cost_basis, transaction.price],
                    weights=[order_position.amount, order.amount]
                )
            else:
                order_position.cost_basis = transaction.price

        log.debug('updated portfolio with executed order')

    def remove_order(self, order):
        """
        Removing an open order.

        Parameters
        ----------
        order: Order

        """
        log.info('removing cancelled order {}'.format(order.id))
        self._remove_open_order(order)

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            raise ValueError(
                'Trying to remove order for a position not held: %s' % order.id
            )

        order_position.amount -= order.amount

        log.debug('removed order from portfolio')


from __future__ import absolute_import, division, print_function
from cctbx import miller
from cctbx import crystal
from cctbx import sgtbx
from cctbx import uctbx
from cctbx.array_family import flex
import sys

import boost_adaptbx.boost.python as bp
from six.moves import range
dtrek_ext = bp.import_ext("iotbx_dtrek_ext")

class reflnlist(object):

  def __init__(self, file, header_only=False):
    self.file = file
    self.line_no = 0
    line_1 = self.next_line().split()
    assert len(line_1) in (3,4)
    line_1 = [int(field) for field in line_1]
    if (len(line_1) == 3):
      line_1.append(0)
    self.NumInts = line_1[0]
    assert self.NumInts >= 3
    self.NumFloats = line_1[1]
    self.NumStrings = line_1[2]
    self.NumInfoLines = line_1[3]
    self.InfoLines = []
    for i in range(self.NumInfoLines):
      self.InfoLines.append(self.next_line().strip())
    self.column_info = []
    num_columns = self.NumInts + self.NumFloats + self.NumStrings
    self.column_names = []
    for i in range(num_columns):
      column_name = self.next_line().strip()
      assert len(column_name) > 1
      assert column_name[0] in "nfs"
      if (i < self.NumInts):
        assert column_name[0] == "n"
      elif (i < self.NumInts + self.NumFloats):
        assert column_name[0] == "f"
      else:
        assert column_name[0] == "s"
      self.column_names.append(column_name)
    assert "fIntensity" in self.column_names
    assert "fSigmaI" in self.column_names
    assert self.column_names[:3] == ["nH", "nK", "nL"]
    if (header_only):
      self.miller_indices = None
      self.column_dict = None
    else:
      self.miller_indices = flex.miller_index()
      self.column_dict = {}
      column_list = [None, None, None]
      for i in range(3, num_columns):
        if (i < self.NumInts):
          column_list.append(flex.int())
        elif (i < self.NumInts + self.NumFloats):
          column_list.append(flex.double())
        else:
          column_list.append(flex.std_string())
        self.column_dict[self.column_names[i]] = column_list[-1]
      while 1:
        line = self.next_line()
        if (line is None):
          break
        data_values = line.split()
        assert len(data_values) == num_columns, "Line no. %d" % self.line_no
        h = [int(v) for v in data_values[:3]]
        self.miller_indices.append(h)
        offset = 3
        for i in range(offset, self.NumInts):
          v = int(data_values[i])
          column_list[i].append(v)
        offset = self.NumInts
        for i in range(offset, offset+self.NumFloats):
          v = float(data_values[i])
          column_list[i].append(v)
        offset += self.NumFloats
        for i in range(offset, num_columns):
          column_list[i].append(data_values[i])
    del self.file
    del self.line_no

  def next_line(self):
    line = self.file.readline()
    if (line == ""): return None
    self.line_no += 1
    return line

  def space_group_info(self):
    for info_line in self.InfoLines:
      if (info_line.upper().startswith("CRYSTAL_SPACEGROUP=")):
        assert info_line[-1] == ";"
        space_group_number = info_line[:-1].split("=", 1)[1]
        return sgtbx.space_group_info(symbol=space_group_number)
    return None

  def unit_cell(self):
    for info_line in self.InfoLines:
      if (info_line.upper().startswith("CRYSTAL_UNIT_CELL=")):
        assert info_line[-1] == ";"
        unit_cell = info_line[:-1].split("=", 1)[1]
        return uctbx.unit_cell(unit_cell)
    return None

  def crystal_symmetry(self):
    return crystal.symmetry(
      unit_cell=self.unit_cell(),
      space_group_info=self.space_group_info())

  def show_summary(self, out=None, prefix=""):
    if (out is None): out = sys.stdout
    self.crystal_symmetry().show_summary(f=out, prefix=prefix)
    print(prefix + "Column names:", " ".join(self.column_names[3:]), file=out)
    print(prefix + "Number of reflections:", self.miller_indices.size(), file=out)

  def as_miller_arrays(self,
        crystal_symmetry=None,
        force_symmetry=False,
        merge_equivalents=True,
        base_array_info=None,
        anomalous=None):
    crystal_symmetry_from_file = self.crystal_symmetry()
    crystal_symmetry = crystal_symmetry_from_file.join_symmetry(
      other_symmetry=crystal_symmetry,
      force=force_symmetry)
    if (base_array_info is None):
      base_array_info = miller.array_info(source_type="dtrek_reflnlist")
    miller_arrays = []
    sigmas=self.column_dict["fSigmaI"]
    miller_arrays.append(miller.array(
      miller_set=miller.set(
        crystal_symmetry=crystal_symmetry,
        indices=self.miller_indices,
        anomalous_flag=False),
      data=self.column_dict["fIntensity"],
      sigmas=sigmas)
      .select(sigmas > 0)
      .set_info(base_array_info.customized_copy(
        labels=["Intensity", "SigmaI"],
        crystal_symmetry_from_file=crystal_symmetry_from_file))
      .set_observation_type_xray_intensity())
    if ("fIntensity+" in self.column_dict):
      assert "fSigmaI+" in self.column_dict
      assert "fIntensity-" in self.column_dict
      assert "fSigmaI-" in self.column_dict
      if (crystal_symmetry.space_group_info() is None):
        space_group = sgtbx.space_group() # P 1
      else:
        space_group = crystal_symmetry.space_group()
      ac = dtrek_ext.anomalous_combined(
        space_group,
        self.miller_indices,
        self.column_dict["fIntensity+"],
        self.column_dict["fSigmaI+"],
        self.column_dict["fIntensity-"],
        self.column_dict["fSigmaI-"])
      miller_arrays.append(miller.array(
        miller_set=miller.set(
          crystal_symmetry=crystal_symmetry,
          indices=ac.miller_indices(),
          anomalous_flag=True),
        data=ac.data(),
        sigmas=ac.sigmas())
        .set_info(base_array_info.customized_copy(
          labels=["Intensity+-", "SigmaI+-"],
          crystal_symmetry_from_file=crystal_symmetry_from_file))
        .set_observation_type_xray_intensity())
    for column_name in self.column_names:
      if (column_name in ("nH", "nK", "nL",
                          "fSigmaI", "fIntensity",
                          "fIntensity+", "fSigmaI+",
                          "fIntensity-", "fSigmaI-")):
        continue
      miller_arrays.append(miller.array(
        miller_set=miller.set(
          crystal_symmetry=crystal_symmetry,
          indices=self.miller_indices,
          anomalous_flag=False),
        data=self.column_dict[column_name])
        .set_info(base_array_info.customized_copy(
          labels=[column_name[1:]],
          crystal_symmetry_from_file=crystal_symmetry_from_file)))
    return miller_arrays


from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import datetime, timedelta
from test_python_transformation import test_clean_amount,test_clean_Date

default_args = {
    'owner': 'airflow',
    'start_date': datetime(2023, 8, 28),
    'retries': 1,
    'retry_delay': timedelta(seconds=2),
}

with DAG('Unit_Test_Dag', default_args=default_args, schedule_interval=timedelta(days=1), catchup=False) as dag:

    # Task 2 : transformation et création du nouveau fichier
    t1 = PythonOperator(
        task_id='UnitTestAmount',
        python_callable=test_clean_amount,
    )

     # Task 4 : création de la table Postgres
    t2 = PythonOperator(
        task_id='UnitTestCleanDate',
        python_callable=test_clean_Date,
    )

    # Les deux tâches seront faîtes simultanéments
    [t1,t2]


from django.contrib import admin

from instaparser.models import TaskForParse, Data, InstagramAccount

class TaskForParseAdmin(admin.ModelAdmin):
    """Выводить модель TaskForParse"""

    list_display = ['id', 'user', 'user_to_scrape', 'count_parse_data', 'status', 'file',
                    'next_max_id', 'type_of_parse']
    list_editable = ['status', 'file']

class InstagramAccountAdmin(admin.ModelAdmin):
    """Выводить модель InstagramAccount"""

    list_display = ['id', 'username', 'is_used', 'used_at', 'enc_password']
    list_editable = ['is_used', ]

class DataAdmin(admin.ModelAdmin):
    """Выводить модель TaskForParse"""

    list_display = [
        'id',
        'task_for_parse',
        'username',
        'full_name',
        'biography',
        'is_private',
        'follower_count',
        'following_count',
        'following_tag_count',
        'media_count',
        'usertags_count',
        'contact_phone_number',
        'public_email',
        'whatsapp_number',
        'business_contact_method',
        'instagram_location_id',
    ]

admin.site.register(TaskForParse, TaskForParseAdmin)
admin.site.register(Data, DataAdmin)
admin.site.register(InstagramAccount, InstagramAccountAdmin)


from pydantic import BaseModel
from openai import OpenAI
import json
from nlp_toolkit.llms.openai import OpenAIRequest

class PydanticTool:

    def __init__(self, model:BaseModel):

        if not issubclass(model, BaseModel):
            raise ValueError("Model should be a valid pydantic BaseModel")
        self.model = model

    @property
    def tool_spec(self):
        schema = self.model.schema()
        return {
            "type":"function",
            "function":{
                "name":schema['title'],
                "description":schema['description'],
                "parameters": {
                    "type": "object",
                    "properties":{k: {kk:vv for kk, vv in v.items() if kk!= 'title'}
                                for k, v in schema['properties'].items()}
                }
            }
        }

    def __call__(self, **kwargs):
        return self.model(**kwargs)

class StructuredExtraction:

    def __init__(self, client:"OpenAI", response_model:BaseModel, system_prompt:str = None, **kwargs):
        self.client = client
        self.tool = PydanticTool(response_model)
        if system_prompt is None:
            self.system_prompt = 'you are a nlp bot, that helps to extract entities from texts'
        else:
            self.system_prompt = system_prompt

    def __call__(self, input):

        openai_request = OpenAIRequest(
            client = self.client,
            model = "gpt-3.5-turbo-0613",
            messages = [{'role':'system','content':self.system_prompt}],
            tools = [self.tool.tool_spec],
            tool_choice = 'auto'
        )

        response = openai_request(input)
        args = json.loads(response.choices[0].message.tool_calls[0].function.arguments)
        return self.tool(**args)


#! /usr/bin/env python

#!/usr/bin/env python
#
# Filename      : averages.py
# Author        : Yuhang Ming
# Date          : Feb 2021
# Description   : Command line script to display averages of some numbers.

from averages import mode

import sys
import math
import argparse

def compute_mean(vals):
    sum = 0.
    num = len(vals)
    for v in vals:
        sum = sum + v
    avg_mean = sum / num
    print("Mean: ", avg_mean)

def compute_median(vals):
    num = len(vals)
    # Buble sorting
    for i in range(num-1):
        for j in range(num-i-1):
            if vals[j] > vals[j+1] :
                vals[j], vals[j+1] = vals[j+1], vals[j]
    half = math.ceil(num/2.)
    print("Median: ", vals[half-1])

def compute_mod(vals):
    val_dict = {}
    for v in vals:
        if v in val_dict.keys():
            val_dict[v] = val_dict[v] + 1
        else:
            val_dict[v] = 1
    max_count = max(val_dict.values())
    print("Mod: ", end=' ')
    for val, count in val_dict.items():
        if count == max_count:
            print(val, ", ", end=' ')
    print("")

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Take averages of a set of integers.')
    parser.add_argument('integers', metavar='N', type=int, nargs='*',
                        help='integers to be averaged')
    parser.add_argument('--mean', dest='mean', action='store_true', default=False,
                        help='take the mean')
    parser.add_argument('--mode', dest='mod', action='store_true', default=False,
                        help='take the mode')
    parser.add_argument('--median', dest='median', action='store_true', default=False,
                        help='find the median')
    parser.add_argument('--file', dest='file_name', default="",
                        help='take the average from a file')
    args = parser.parse_args()

    if len(args.file_name) > 0 and len(args.integers) > 0:
        print("ERROR: expected one non-flag input when -file is specified")
        exit(1)

    elif len(args.file_name) > 0 and len(args.integers) == 0:
        print("Reading from ", args.file_name)
        with open(args.file_name) as f:
            array = []
            for line in f: # read rest of lines
                array.append([int(x) for x in line.split()])
        vals = [j for sub in array for j in sub]
        if len(vals) == 0:
            print("ERROR: no integers given.")
            exit(1)

    elif len(args.file_name) == 0 and len(args.integers) > 0:
        print("Reading from command line.")
        vals = args.integers
        if len(args.integers) > 8:
            print("ERROR: expected max 8 integer data points.")
            exit(1)

    else:
        print("ERROR: no file or integers given.")
        exit(1)

    if not args.mean and not args.mod and not args.median:
        compute_mean(vals)
        compute_median(vals)
        compute_mod(vals)

    if args.mean:
        compute_mean(vals)

    if args.median:
        compute_median(vals)

    if args.mod:
        compute_mod(vals)

    mode(vals)


# -*- coding: utf-8 -*-
# @Time    : 2023/3/17 18:33
# @Author  : Flora.Chen
# @File    : conftest.py
# @Software: PyCharm
# @Desc:

# 标准库导入
# 第三方库导入
import pytest
import allure
from loguru import logger
# 本地应用/模块导入
from config.settings import RunConfig
from case_utils.get_driver import GetDriver

@pytest.fixture(scope="function", autouse=True)
def case_skip(request):
    """处理跳过用例"""
    # 使用 request.getfixturevalue() 方法来获取测试用例函数的参数值
    # 注意这里的"case"需要与@pytest.mark.parametrize("case", cases)中传递的保持一致
    case = request.getfixturevalue("case")
    if case.get("run") is None or case.get("run") is False:
        reason = f"{case.get('title')}: 标记了该用例为false，不执行\\n"
        logger.warning(f"{reason}")
        pytest.skip(reason)

def pytest_collection_modifyitems(config, items):
    for item in items:
        # 注意这里的"case"需要与@pytest.mark.parametrize("case", cases)中传递的保持一致
        parameters = item.callspec.params["case"]
        # print(f"测试参数：{type(parameters)}     {parameters}")
        if parameters and parameters.get("severity"):
            if parameters["severity"].upper() == "TRIVIAL":
                item.add_marker(allure.severity(allure.severity_level.TRIVIAL))
            elif parameters["severity"].upper() == "MINOR":
                item.add_marker(allure.severity(allure.severity_level.MINOR))
            elif parameters["severity"].upper() == "CRITICAL":
                item.add_marker(allure.severity(allure.severity_level.CRITICAL))
            elif parameters["severity"].upper() == "BLOCKER":
                item.add_marker(allure.severity(allure.severity_level.BLOCKER))
            else:
                item.add_marker(allure.severity(allure.severity_level.NORMAL))
        else:
            item.add_marker(allure.severity(allure.severity_level.NORMAL))

# ------------------------------------- START: 配置浏览器驱动 ---------------------------------------#
@pytest.fixture(scope="session")
def init_drivers():
    # logger.debug(f"此时的driver类型:{RunConfig.driver_type}")
    drivers = GetDriver(drivers_type=RunConfig.driver_type).get_driver()
    RunConfig.drivers = drivers
    yield drivers
    for driver in drivers:
        driver.close()
        driver.quit()
# ------------------------------------- END: 配置浏览器驱动 ---------------------------------------#


# -*- coding: utf-8 -*-
from flask import request, render_template, flash, redirect, url_for
from extensions.flask_login import current_user, login_required
from mysite import db
from mysite.models import Weixin
from mysite.forms import WeixinForm
from . import weixin

@weixin.route("/edit", methods = ["GET", "POST"])
@login_required
def edit():
	if not current_user.weixin:
		flash(u"您还没绑定微信公众号", "warning")
		return redirect(url_for("weixin.add"))

	weixin = Weixin.query.filter_by(user=current_user).first_or_404()
	form = WeixinForm(request.form, obj=weixin)
	if request.method == "POST" and form.validate():
		form.populate_obj(weixin)
		db.session.add(weixin)
		db.session.commit()
		flash(u"修改成功", "success")
		return redirect(url_for("user.home"))
	return render_template("weixin/form.html", form=form)


from flask import Flask
import pandas as pd
import numpy as np
from flask import jsonify
from recomendacion import recomendations
from buscador_principal import buscador_principal
from filtraje import filtraje
from flask import jsonify
from flask import request
#base de datos
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow, Schema, fields
from sqlalchemy.orm import relationship, backref
from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
import json
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_serializer import SerializerMixin
from marshmallow_sqlalchemy.fields import Nested
from sqlalchemy import and_, or_

app= Flask(__name__)
#app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root@localhost/laravel'
#app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://u398984712_founduss:Siliconvalley1@45.93.101.52/u398984712_founduss'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
#engine = create_engine('mysql+pymysql://root@localhost/laravel', echo = True)
engine = create_engine('mysql+pymysql://u398984712_founduss:Siliconvalley1@45.93.101.52/u398984712_founduss', echo = True)
Base = declarative_base()
Session = sessionmaker(bind = engine)
session = Session()

db=SQLAlchemy(app)
ma=Marshmallow(app)

class Bank(db.Model, SerializerMixin):
    __tablename__ = 'banks'
    serialize_only = ('id', 'name', 'description')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(70),unique=True)
    description = db.Column(db.Text)

    def __init__(self,name,description):
        self.name = name
        self.description = description

product_image = db.Table('product_image',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('image_id', db.Integer, db.ForeignKey('images.id'), primary_key=True)
)
factory_product = db.Table('factory_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('factory_id', db.Integer, db.ForeignKey('factories.id'), primary_key=True)
)
mark_product = db.Table('mark_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('mark_id', db.Integer, db.ForeignKey('marks.id'), primary_key=True)
)
subcategory_product = db.Table('subcategory_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('subcategory_id', db.Integer, db.ForeignKey('subcategories.id'), primary_key=True)
)

class Product(db.Model, SerializerMixin):
    __tablename__ = 'products'
    serialize_only = ('id', 'name', 'description', 'images')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)
    description = db.Column(db.Text)
    images = relationship("Image", secondary=product_image)
    factories = relationship("Factory", secondary=factory_product)
    marks = relationship("Mark", secondary=mark_product)
    subcategories = relationship("Subcategory", secondary=subcategory_product)

    def __init__(self,id,name,description):
        self.id = id
        self.name = name
        self.description = description

class Image(db.Model, SerializerMixin):
    __tablename__ = 'images'
    serialize_only = ('id', 'src')

    id = db.Column(db.Integer, primary_key=True)
    src = db.Column(db.Text)

    def __init__(self,src):
        self.src = src
class Factory(db.Model, SerializerMixin):
    __tablename__ = 'factories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

    def __init__(self,name):
        self.name = name

class Mark(db.Model, SerializerMixin):
    __tablename__ = 'marks'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

    def __init__(self,name):
        self.name = name

class Category(db.Model, SerializerMixin):
    __tablename__ = 'categories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

    def __init__(self,name):
        self.name = name

class Subcategory(db.Model, SerializerMixin):
    __tablename__ = 'subcategories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)
    category_id = db.Column(db.Integer, ForeignKey('categories.id'))
    category = relationship("Category")

    def __init__(self,name,category_id,category):
        self.name = name
        self.category_id = category_id
        self.category = category

class Bankchema(ma.SQLAlchemySchema):
    class Meta:
        model =Bank
    id = ma.auto_field()
    name = ma.auto_field()
    description = ma.auto_field()

bank_schema= Bankchema()
bank_schema= Bankchema(many=True)

class ImageSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Image
    src = ma.auto_field()

images_schema= ImageSchema()
images_schema= ImageSchema(many=True)

class FactorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Factory
    name = ma.auto_field()

factories_schema= FactorySchema()
factories_schema= FactorySchema(many=True)

class MarkSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Factory
    name = ma.auto_field()

marks_schema= MarkSchema()
marks_schema= MarkSchema(many=True)

class CategorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Category
    name = ma.auto_field()

categories_schema= CategorySchema()
categories_schema= CategorySchema(many=True)

class SubcategorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Subcategory
    name = ma.auto_field()
    category_id = ma.auto_field()
    category = Nested(CategorySchema)

subcategories_schema= SubcategorySchema()
subcategories_schema= SubcategorySchema(many=True)

class ProductSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Product
    id = ma.auto_field()
    name = ma.auto_field()
    description = ma.auto_field(dump_only=False)
    images = Nested(ImageSchema,many=True)
    factories = Nested(FactorySchema,many=True)
    marks = Nested(MarkSchema,many=True)
    subcategories = Nested(SubcategorySchema,many=True)

products_schema= ProductSchema()
products_schema= ProductSchema(many=True)

@app.route("/")
def home():
    return 'La pagina esta funcionando bien'

@app.route('/products')
def getProducts():
    return 'datos'

@app.route('/products/<string:product_name>')
def getProduct(product_name):

    return 'nada'

@app.route('/products',methods=['POST'])
def postProducts():
    all_products=Bank.query.all()
    lista_productos= bank_schema.dump(all_products)
    producto_buscar={
        "name":request.json['name'],
        "description":request.json['description'],
    }
    lista_productos_json=json.dumps(lista_productos)

    datos=recomendations(producto_buscar,lista_productos_json)
    datos_recomendacion=json.dumps(datos)
    return datos_recomendacion
#buscador_python
@app.route('/search/products',methods=['POST'])
def postSearchProducts():
    #listas de filtros
    lista_marca_json=request.json['marks']
    lista_subcategoria_json=request.json['subcategories']
    lista_factories_json=request.json['factories']
    lista_categories_json=request.json['categories']

    filter_group = filtraje(lista_marca_json,lista_subcategoria_json,lista_factories_json,lista_categories_json,Mark,Subcategory,Factory,Category,Product)

    #filtraje por join
    all_products=session.query(Product)\
        .join(Subcategory, Product.subcategories) \
        .join(Mark, Product.marks) \
        .join(Factory, Product.factories) \
        .join(Category, Subcategory.category) \
        .filter(and_(*filter_group)
        )\
        .all()

    #return json.dumps(all_products)
    #array=[]
    #for x in all_products:
     #   for y in x.images:
      #      array.append(y)

    lista_productos= products_schema.dump(all_products)
    #return  json.dumps(lista_productos)

    producto_buscar={
        "name":request.json['name'],
    }
    lista_productos_json=json.dumps(lista_productos)

    datos=buscador_principal(producto_buscar,lista_productos_json)

    datos_buscador=json.dumps(datos)

    return datos_buscador

    the_rock_movies = session.query(Product) \
    .join(Image, Product.images) \
    .all()
    print('###########################################')
    for product in the_rock_movies:
        print(f'el producto es in {product.images}')
        for image in product.images:
             print(f'la imagen es in {image.src}')
        print('')
    lista_productos= products_schema.dump(the_rock_movies)
    return  json.dumps(lista_productos)

if __name__=='__main__':
    app.run()


import random

from direct.gui.DirectGui import (
    DGG,
    DirectButton,
    DirectFrame,
    DirectLabel,
)
from panda3d.core import TransparencyAttrib

from gui import MechanicDesc
from gui.widgets import GUI_PIC, RUST_COL
from utils import take_random

class Scenario:
    """The game scenario orchestrator.

    Tracks on which part of the scenario the player is, controls
    the next scenario steps and performs choice consequences effects.

    One scenario chapter includes a situation in which the player
    has to make a decision. Decision will have consequences, positive
    or negative, but in any case the player will become one step
    closer to figuring out the way to survive the Stench. After
    every chapter the player will also get a note written in a
    diary fashion. The note will give the player more info about
    the Stench, Captain, the Adjutant and how the cataclysm
    started to destroy the World.

    Args:
        current_chapter (int): The chapter number to start with.
    """

    def __init__(self, current_chapter=None):
        if current_chapter is not None:  # saved game
            self.current_chapter = current_chapter
        else:  # game start
            self.current_chapter = -1

        self._list = DirectFrame(
            frameSize=(-0.73, 0.73, -0.9, 0.9),
            frameTexture=GUI_PIC + "paper1.png",
            state=DGG.NORMAL,
        )
        self._list.setDepthTest(False)
        self._list.setTransparency(TransparencyAttrib.MAlpha)
        self._list.hide()

        self._name = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.05,
            pos=(-0.4, 0, 0.7),
        )
        self._type = DirectLabel(
            parent=self._list,
            text=base.labels.SCENARIO_LABELS[1],  # noqa: F821
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.035,
            pos=(-0.13, 0, 0.699),
        )
        self._desc = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.6, 0.6, 0.6, 0.6),
            text_scale=0.037,
            pos=(0, 0, 0.55),
        )

        self._buts = []
        z_coor = -0.6
        for _ in range(3):
            self._buts.append(
                DirectButton(
                    parent=self._list,
                    text="Text",
                    text_font=base.main_font,  # noqa: F821
                    text_fg=RUST_COL,
                    text_shadow=(0, 0, 0, 1),
                    frameColor=(0, 0, 0, 0),
                    frameSize=(-9, 9, -0.3, 0.7),
                    scale=(0.047, 0, 0.047),
                    clickSound=base.main_menu.click_snd,  # noqa: F821
                    pos=(0, 0, z_coor),
                )
            )
            z_coor -= 0.08

        self._done_but = DirectButton(
            parent=self._list,
            text=base.labels.DISTINGUISHED[6],  # noqa: F821
            text_font=base.main_font,  # noqa: F821
            text_fg=RUST_COL,
            text_shadow=(0, 0, 0, 1),
            frameColor=(0, 0, 0, 0),
            frameSize=(-9, 9, -0.3, 0.7),
            scale=(0.05, 0, 0.05),
            clickSound=base.main_menu.click_snd,  # noqa: F821
            pos=(0, 0, -0.8),
            command=self.hide_chapter,
        )

    def _choose_variant(self, var):
        """Process the player's choice and do consequences.

        Args:
            var (str): Variant id.
        """
        consequences = base.labels.SCENARIO[self.current_chapter][  # noqa: F821
            "variants"
        ][var]
        for but in self._buts:
            but.hide()

        self._desc["text"] = consequences["desc"]
        for effect in consequences["effects"]:
            getattr(self, effect[0])(*effect[1])

        base.journal.add_page(self.current_chapter)  # noqa: F821
        self._done_but.show()
        base.res_gui.update_resource(  # noqa: F821
            "places_of_interest", str(self.current_chapter + 1) + "/10"
        )

        base.decisions["decision_" + str(self.current_chapter)] = {  # noqa: F821
            "decision": var,
            "goodness": consequences["goodness"],
        }

    def finish_game(self):
        """Completely finish the game."""
        self.hide_chapter()
        taskMgr.doMethodLater(  # noqa: F821
            1, base.effects_mgr.fade_out_screen, "fade_out"  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            4, base.main_menu.show_credits, "show_credits",  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            4.5, base.effects_mgr.fade_in_screen, "fade_in"  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            76, base.restart_game, "restart_game", extraArgs=[]  # noqa: F821
        )
        base.train.ctrl.unset_controls()  # noqa: F821
        base.effects_mgr.stench_effect.stop()  # noqa: F821

        for task in (
            "update_physics",
            "sun_look_at_train",
            "collide_mouse",
            "move_camera_with_mouse",
            "update_speed_indicator",
            "disease",
            "show_teaching_note",
            "calc_cohesion",
            "track_ambient_sounds",
            "stench_step",
            "check_train_contacts",
            "change_sun_color",
        ):
            base.taskMgr.remove(task)  # noqa: F821

        base.sound_mgr.disable()  # noqa: F821
        base.world.drown_ambient_snds()  # noqa: F821

    def do_build_camp_effect(self):
        """Do effects for building a camp for orphans choice."""
        base.helped_children = True  # noqa: F821

    def do_spend_cohesion(self, value):
        """Do effect of decreasing the crew cohesion.

        Args:
            value (int): The amount of the cohesion change.
        """
        base.team.spend_cohesion(value)  # noqa: F821

    def do_get_money(self, money):
        """Get or lose the given amount of money.

        Args:
            money (int): Money amount to get/lose.
        """
        base.dollars += money  # noqa: F821

    def do_plus_resource(self, name, value):
        """Change the given resource amount.

        Args:
            name (str): Resource name.
            value (int): Amount delta.
        """
        base.plus_resource(name, value)  # noqa: F821

    def do_enemy_inc_effect(self):
        """Make enemy stronger effect."""
        base.world.enemy.score += 3  # noqa: F821

    def do_character_effect(self, char, effect):
        """Do choice consequences effect to the given character.

        Args:
            char (units.crew.character.Character):
                The character to do effect to.
            effect (dict): The effect description.
        """
        for key, value in effect.items():
            setattr(char, key, getattr(char, key) + value)

    def do_characters_effect(self, effect, to_one=False):
        """Do choice consequences effects to the crew.

        Args:
            effect (dict): Effect description.
            to_one (bool): Effect targets only one random character.
        """
        if to_one:
            self.do_character_effect(
                random.choice(list(base.team.chars.values())), effect  # noqa: F821
            )
            return

        for char in base.team.chars.values():  # noqa: F821
            self.do_character_effect(char, effect)

    def do_locomotive_damage(self, damage):
        """Do some damage to the Adjutant.

        Args:
            damage (int): Amount of damage to do.
        """
        base.train.get_damage(damage)  # noqa: F821

    def do_no_effect(self):
        """No choice consequences method."""
        pass

    def do_stench_moves_effect(self, steps):
        """Move the Stench frontier several miles deeper into the Silewer.

        Args:
            steps (int): Number of miles to cover with the Stench.
        """
        for _ in range(steps):
            base.world.make_stench_step()  # noqa: F821

    def do_transfusion_effect(self):
        """Do blood transfusion effect of Chapter 9."""
        char = None
        chars = list(base.team.chars.values())  # noqa: F821

        if chars:
            char = take_random(chars)
            char.health -= 30

        if chars:
            take_random(chars).health -= 30
        elif char:
            char.health -= 30

    def do_medicine_save(self):
        """Do save with medicines effect of Chapter 9."""
        if base.resource("medicine_boxes"):  # noqa: F821
            base.plus_resource("medicine_boxes", -1)  # noqa: F821
        else:
            chars = list(base.team.chars.values())  # noqa: F821
            if chars:
                take_random(chars).energy -= 40

    def hide_chapter(self):
        """Hide the scenario GUI."""
        if self.current_chapter == 4:
            MechanicDesc("SCP")

        self._list.hide()

    def start_chapter(self, task):
        """Start a new scenario chapter."""
        self.current_chapter += 1

        base.train.ctrl.set_controls(base.train)  # noqa: F821
        base.camera_ctrl.enable_ctrl_keys()  # noqa: F821

        base.world.outings_mgr.hide_outing()  # noqa: F821
        base.traits_gui.hide()  # noqa: F821

        if self.current_chapter <= 9:
            self.show_chapter_situation()  # noqa: F821

            base.world.drop_place_of_interest()  # noqa: F821

        if self.current_chapter in (1, 3, 4):
            base.add_scp_page()  # noqa: F821
            if self.current_chapter in (4, 7):
                base.world.meet_scp = True  # noqa: F821

        return task.done

    def show_chapter_situation(self):
        """Show the situation description and the possible variants."""
        self._done_but.hide()
        self._name["text"] = base.labels.SCENARIO_LABELS[0] + str(  # noqa: F821
            self.current_chapter + 1
        )
        self._desc["text"] = base.labels.SCENARIO[self.current_chapter][  # noqa: F821
            "intro"
        ]

        if (
            len(base.labels.SCENARIO[self.current_chapter]["variants"])  # noqa: F821
            == 3
        ):
            for index, var in enumerate(
                base.labels.SCENARIO[self.current_chapter]["variants"]  # noqa: F821
            ):
                self._buts[index]["text"] = var
                self._buts[index]["extraArgs"] = [var]
                self._buts[index]["command"] = self._choose_variant
                self._buts[index].show()
        else:
            self._buts[0].hide()
            self._buts[1].hide()

            for var in base.labels.SCENARIO[self.current_chapter][  # noqa: F821
                "variants"
            ]:
                self._buts[2]["text"] = var
                self._buts[2]["extraArgs"] = [var]
                self._buts[2]["command"] = self._choose_variant
                self._buts[2].show()

            self._done_but["command"] = self.finish_game

        self._list.show()


from ProductRegisters.Tools.RootCounting.JordanSet import JordanSet
from ProductRegisters.Tools.RootCounting.OverlappingRectangle import rectangle_solve
from ProductRegisters.Tools.RootCounting.EvaluationFunctions import pessimistic_expected_value
from ProductRegisters.Tools.RootCounting.Combinatorics import binsum, powerset
from ProductRegisters.Tools.RootCounting.PartialOrders import \
    isSubspace, isEmbeddedSet, isEmbeddedSubset, isExactSubset, maximalElements

from ProductRegisters.BooleanLogic import CONST, VAR

from itertools import product

class RootExpression:
    # wrapper for JordanSets, with extra functionality:
    # self.terms is a set of JordanSets.
    def __init__(self,term_list = None):
        if term_list is None:
            self.terms = set()
        else:
            self.terms = set(term_list)

    def extend(self, extension_jordan_set):
        max_mult = 0
        for term in self.terms:
            if isEmbeddedSubset(extension_jordan_set, term):
                max_mult = max(max_mult,term.m)
        return self + RootExpression([JordanSet(extension_jordan_set.roots, max_mult + 1)])

    def __str__(self):
        return " + ".join(str(term) for term in self.terms)

    def __xor__(self, other): return self.__add__(other)
    def __add__(self, other):
        #clean out redundant subsets and merge.
        new_anf = maximalElements(
            leq_ordering=isExactSubset,
            inputs=[self.terms, other.terms]
        )

        return RootExpression(new_anf)

    def __and__(self, other): return self.__mul__(other)
    def __mul__(self, other):
        new_term_sets = []
        for a, b in product(self.terms, other.terms):
            new_term_sets.append(a * b)

        #clean out redundant subsets.
        new_anf = maximalElements(
            leq_ordering = isExactSubset,
            inputs = new_term_sets
        )

        return RootExpression(new_anf)

    @classmethod
    def logical_one(self): return RootExpression([JordanSet({}, 1)])

    @classmethod
    def logical_zero(self): return RootExpression([])

    def __invert__(self): return self ^ RootExpression.logical_one()

    """
    Evaluation
    """

    def upper(self, locked_list = None):
        # initialize values
        linear_complexity = 0
        basis_table = {}

        # Assume any embedded sets are present:
        #  - this means no cleaning is necessary
        #  - but each embedded term might needs to be added to multiple entries in the basis table.
        #       - because the roots span across several subfields.
        for term in self.terms:
            full = []           # - All bases where b == c (contains the 1 coset)
            partial = []        # - All bases where b != c (no embedded sets)

            # Add each (b,c) pair to the right list:
            for b,c in term.roots.items():
                if b == c: full.append((b,binsum(b,c-1)))
                else: partial.append((b,binsum(b,c)))

            # Use the full list to distribute embedded sets to appropriate entries
            #   - every subset of bases in the full list represents a valid subfield
            for modifier in powerset(full):
                pairs = sorted(list(modifier) + partial)
                basis = tuple([x[0] for x in pairs])
                counts = tuple([term.m] + [x[1] for x in pairs])

                if basis in basis_table:
                    basis_table[basis].append(counts)
                else:
                    basis_table[basis] = [counts]

        # evaluate the basis table using hyperrec algorithm
        for x in basis_table.values():
            linear_complexity += rectangle_solve(x)
        return linear_complexity

    #calculate lower bound (ignoring bases in locked list)
    def lower(self, locked_list = None, safety_factor = None):
        # initalize values:
        linear_complexity = 0
        basis_table = {}

        # Evaluate only the maximum coset?
        cleaned_terms = maximalElements(
            leq_ordering = isEmbeddedSet,
            inputs = [self.terms]
        )

        # add each term into the basis table.
        for term in cleaned_terms:
            pairs = sorted([
                (b,pessimistic_expected_value(b,c))
                for b,c in term.roots.items()
            ])

            basis = tuple([x[0] for x in pairs])
            counts = tuple([term.m] + [x[1] for x in pairs])

            if basis in basis_table:
                basis_table[basis].append(counts)
            else:
                basis_table[basis] = [counts]

        #solve basis table using hyperrec algorithm:
        for rectangle_list in basis_table.values():
            linear_complexity += rectangle_solve(rectangle_list)
        return linear_complexity

    """
    ALTERNATE MULTIPLICATION (test speeds/profile as future work).

    def __mul__(self, other):
        new_root_expression = RootExpression()
        for term_a, term_b in product(self.terms, other.terms):
            new_root_expresion += (term_a * term_b)
        return new_root_expression
    """