#!/usr/bin/env python
import json
import inspect
import os
import pdb
import sys

import matplotlib.pyplot as plt
import numpy as np

currentdir = os.path.dirname(os.path.abspath(
    inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
gparentdir = os.path.dirname(parentdir)
sys.path.insert(0, parentdir)
sys.path.insert(0, gparentdir)

def sine_wave(t, amplitude_in, period_in):
    return amplitude_in*np.sin(2*np.pi*t/period_in)

def cos_wave(t, amplitude_in, period_in):
    return amplitude_in*np.cos(2*np.pi*t/period_in)

if __name__ == '__main__':

    dir_path = os.path.dirname(os.path.abspath(__file__))
    save_path = os.path.join(dir_path, '..', '..', '..', 'data', 'BlockedData')

    with open(os.path.join(save_path, 'RobotDelayData34.txt'), 'r') as f:
        data_dict = json.loads(f.read())

    impedance_target_horizontal_pose_list = data_dict["impedance_target_horizontal_pose_list"]
    impedance_target_vertical_pose_list = data_dict["impedance_target_vertical_pose_list"]
    measured_horizontal_pose_list = data_dict["measured_horizontal_pose_list"]
    measured_vertical_pose_list = data_dict["measured_vertical_pose_list"]
    measured_horiztonal_force_list = data_dict["measured_horiztonal_force_list"]
    measured_vertical_force_list = data_dict["measured_vertical_force_list"]
    tlist = data_dict["tlist"]
    IMPEDANCE_STIFFNESS_LIST = data_dict["IMPEDANCE_STIFFNESS_LIST"]
    amplitude = data_dict["amplitude"]
    period = data_dict["period"]
    num_periods = data_dict["num_periods"]
    tmax = data_dict["tmax"]
    tmax_margin = data_dict["tmax_margin"]
    base_horizontal_pose = data_dict["base_horizontal_pose"]
    base_vertical_pose = data_dict["base_vertical_pose"]
    filter_params_ = data_dict["filter_params_"]

    min_index = 0
    while tlist[min_index] < period:
        min_index += 1

    max_index = len(tlist)-1
    while tlist[max_index] > tmax:
        max_index -= 1

    tlist = np.array(tlist[min_index:max_index])
    impedance_target_horizontal_pose_list = np.array(
        impedance_target_horizontal_pose_list[min_index:max_index])
    measured_horizontal_pose_list = np.array(
        measured_horizontal_pose_list[min_index:max_index])
    impedance_target_vertical_pose_list = np.array(
        impedance_target_vertical_pose_list[min_index:max_index])
    measured_vertical_pose_list = np.array(
        measured_vertical_pose_list[min_index:max_index])
    measured_horiztonal_force_list = np.array(
        measured_horiztonal_force_list[min_index:max_index])
    measured_vertical_force_list = np.array(
        measured_vertical_force_list[min_index:max_index])

    sine_t = sine_wave(tlist, 1, period)
    cos_t = cos_wave(tlist, 1, period)
    const_t = np.array([1]*len(tlist))

    regression_matrix = np.vstack([cos_t, sine_t, const_t])

    Coeff_Vec_horz = np.linalg.lstsq(np.transpose(
        regression_matrix), measured_horiztonal_force_list)[0]
    Coeff_Vec_vert = np.linalg.lstsq(np.transpose(
        regression_matrix), measured_vertical_force_list)[0]

    delay_horz = np.arctan2(-Coeff_Vec_horz[0],
                            Coeff_Vec_horz[1])/(2*np.pi/period)
    amplitude_horz = np.sqrt(Coeff_Vec_horz[0]**2+Coeff_Vec_horz[1]**2)
    phase_horz = np.arctan2(-Coeff_Vec_horz[0], Coeff_Vec_horz[1])*180.0/np.pi

    delay_vert = np.arctan2(
        Coeff_Vec_vert[1], Coeff_Vec_vert[0])/(2*np.pi/period)
    amplitude_vert = np.sqrt(Coeff_Vec_vert[0]**2+Coeff_Vec_vert[1]**2)
    phase_vert = np.arctan2(Coeff_Vec_vert[1], Coeff_Vec_vert[0])*180.0/np.pi

    fig, axs = plt.subplots(4, 1, figsize=(16, 9))

    # change font size for axes
    for ax in axs.flatten():
        for tick in ax.get_xticklabels():
            tick.set_fontsize(18)
        for tick in ax.get_yticklabels():
            tick.set_fontsize(18)

    axs[0].plot(tlist, impedance_target_horizontal_pose_list,
                marker='.', color='b', label='target')
    # axs[0].plot(tlist, measured_horizontal_pose_list,
    #             marker='o', color='r', label='measured')

    axs[2].plot(tlist, impedance_target_vertical_pose_list,
                marker='.', color='b', label='target')
    # axs[2].plot(tlist, measured_vertical_pose_list,
    #             marker='o', color='r', label='measured')

    axs[3].set_xlabel('Time (s)', fontsize=18)
    # axs[1].set_xlabel('Time (s)')

    axs[0].set_ylabel('Position (m)', fontsize=18)
    axs[2].set_ylabel('Position (m)', fontsize=18)
    axs[1].set_ylabel('Force (N)', fontsize=18)
    axs[3].set_ylabel('Force (N)', fontsize=18)

    # axs[0].legend()
    # axs[1].legend()

    # axs[0].set_title('Horizontal Position')
    # axs[1].set_title('Horizontal Force')

    axs[1].plot(tlist, measured_horiztonal_force_list, color='k')
    # axs[1].plot(tlist, Coeff_Vec_horz[2] + sine_wave(tlist -
    #             delay_horz, amplitude_horz, period), color='r')

    axs[3].plot(tlist, measured_vertical_force_list, color='k')
    # axs[3].plot(tlist, Coeff_Vec_vert[2] + cos_wave(tlist -
    #             delay_vert, amplitude_vert, period), color='r')

    # axs[2].set_title('Vertical Position')
    # axs[3].set_title('Vertical Force')

    print("horizontal delay (s) = ", delay_horz)
    print("vertical delay (s) = ", delay_vert)
    print("phase horz (deg) = ", phase_horz)
    print("phase vert (deg) = ", phase_vert)

    plt.show()


from django.contrib import admin
from .models import *

# Register your models here.
admin.site.register(SchoolProfile)
admin.site.register(StaffProfile)
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
	list_display = ['login_id', 'email']
	search_fields = ['login_id', 'email']


import requests
import re
import xlwt,xlrd
import os

def get_num(url):
    wb=requests.get(url,headers=headers)
    wb.encoding=wb.apparent_encoding
    wbdata=wb.text.split('<')
    for i in range(len(wbdata)):
        if wbdata[i].startswith('em id='):
            aa=wbdata[i].split('>')
            num=aa[1]
            if '万' in num:
                num1=float(num.replace('万',''))*10000
            elif '亿' in num:
                num1=float(num.replace('亿',''))*100000000
            return(num1)
            # print(num)

def get_title(url):
    wb = requests.get(url, headers=headers)
    wb.encoding = wb.apparent_encoding
    wbdata = wb.text
    title_str = re.findall('name="title" content=.*', wbdata)
    if title_str:
        title=title_str[0].split(' ')
        title1=title[1].replace('content="','')
        # print(title[1])
        return(title1)

if __name__ == "__main__":
    cookie='pgv_pvi=9294307328; ptui_loginuin=598564346; RK=LfjkfTO2Y9; ptcz=ff0c0ddbe7b003a1891204d1d575e3ad1627ce75bd6e4f87ef013448667a359a; pgv_pvid=9222305988; tvfe_boss_uuid=c7151d80a1172cf9; video_guid=66066166ce686bb7; video_platform=2; pgv_info=ssid=s5413384000'
    headers={
        'User_Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
        'Cookie':cookie
    }
    url='https://v.qq.com/channel/net_tv'
    wb=requests.get(url,headers=headers)
    # print(wbdata)
    wb.encoding=wb.apparent_encoding
    wbdata=wb.text
    url_list=re.findall('https:.*html',wbdata)
    title_list=[]
    num_list=[]
    for i in range(len(url_list)):
        title=get_title(url_list[i])
        if title not in title_list:
            title_list.append(title)
            # print(title_list)
            num=get_num(url_list[i])
            num_list.append(num)
    os.chdir('C:/Users/Administrator/Desktop')
    wb=xlwt.Workbook()
    ws=wb.add_sheet('腾讯视频观看量')
    for i in range(len(num_list)):
        ws.write(i,1,num_list[i])
        ws.write(i,0,title_list[i])
        wb.save('test.xls')


from typing import Union
from typing import Optional
from typing import List
from typing import Sequence
from typing import IO
from typing import Any
from typing import cast
from typing import overload
from typing import Literal

import os
import io
import tempfile
import pathlib

from rdkit.Chem import PandasTools
from rdkit.Chem import rdmolfiles  # type: ignore

import pandas as pd
import fsspec
import fsspec.utils

import datamol as dm

from .types import Mol

def read_csv(
    urlpath: Union[str, os.PathLike, IO],
    smiles_column: Optional[str] = None,
    mol_column: str = "mol",
    **kwargs: Any,
) -> pd.DataFrame:
    """Read a CSV file.

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        smiles_column: Use this column to build a mol column.
        mol_column: Name to give to the mol column. If not None a mol column will be build.
            Avoid when loading a very large file.
        **kwargs: Arguments to pass to `pd.read_csv()`.

    Returns:
        df: a `pandas.DataFrame`
    """

    df = pd.read_csv(urlpath, **kwargs)
    df = cast(pd.DataFrame, df)

    if smiles_column is not None:
        PandasTools.AddMoleculeColumnToFrame(df, smiles_column, mol_column)

    return df

def read_excel(
    urlpath: Union[str, os.PathLike, IO],
    sheet_name: Optional[Union[str, int, list]] = 0,
    smiles_column: Optional[str] = None,
    mol_column: str = "mol",
    **kwargs: Any,
) -> pd.DataFrame:
    """Read an excel file.

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        sheet_name: see `pandas.read_excel()` doc.
        mol_column: Name to give to the mol column. If not None a mol column will be build.
            Avoid when loading a very large file.
        mol_column: name to give to the mol column.
        **kwargs: Arguments to pass to `pd.read_excel()`.

    Returns:
        df: a `pandas.DataFrame`
    """

    df = pd.read_excel(urlpath, sheet_name=sheet_name, **kwargs)
    df = cast(pd.DataFrame, df)

    if smiles_column is not None:
        PandasTools.AddMoleculeColumnToFrame(df, smiles_column, mol_column)

    return df

def _get_supplier_mols(
    supplier: rdmolfiles.ForwardSDMolSupplier,
    max_num_mols: Optional[int],
) -> List[dm.Mol]:
    """Given a supplier, read the molecules until we reach the `max_num_mols` limit.
    Useful when reading SDF files.
    """
    if max_num_mols is None:
        mols = list(supplier)
    else:
        mols = []
        for _ in range(max_num_mols):
            try:
                mols.append(next(supplier))
            except StopIteration:
                break
    return mols

@overload
def read_sdf(
    urlpath: Union[str, os.PathLike, IO],
    sanitize: bool = ...,
    as_df: Literal[False] = ...,
    smiles_column: Optional[str] = ...,
    mol_column: Optional[str] = ...,
    include_private: bool = ...,
    include_computed: bool = ...,
    strict_parsing: bool = ...,
    remove_hs: bool = ...,
    max_num_mols: Optional[int] = ...,
    discard_invalid: bool = ...,
    n_jobs: Optional[int] = ...,
) -> List[Mol]:
    ...

@overload
def read_sdf(
    urlpath: Union[str, os.PathLike, IO],
    sanitize: bool = ...,
    as_df: Literal[True] = ...,
    smiles_column: Optional[str] = ...,
    mol_column: Optional[str] = ...,
    include_private: bool = ...,
    include_computed: bool = ...,
    strict_parsing: bool = ...,
    remove_hs: bool = ...,
    max_num_mols: Optional[int] = ...,
    discard_invalid: bool = ...,
    n_jobs: Optional[int] = ...,
) -> pd.DataFrame:
    ...

@overload
def read_sdf(
    urlpath: Union[str, os.PathLike, IO],
    sanitize: bool = ...,
    as_df: bool = ...,
    smiles_column: Optional[str] = ...,
    mol_column: Optional[str] = ...,
    include_private: bool = ...,
    include_computed: bool = ...,
    strict_parsing: bool = ...,
    remove_hs: bool = ...,
    max_num_mols: Optional[int] = ...,
    discard_invalid: bool = ...,
    n_jobs: Optional[int] = ...,
) -> Union[List[Mol], pd.DataFrame]:
    ...

def read_sdf(
    urlpath: Union[str, os.PathLike, IO],
    sanitize: bool = True,
    as_df: bool = False,
    smiles_column: Optional[str] = "smiles",
    mol_column: Optional[str] = None,
    include_private: bool = False,
    include_computed: bool = False,
    strict_parsing: bool = True,
    remove_hs: bool = True,
    max_num_mols: Optional[int] = None,
    discard_invalid: bool = True,
    n_jobs: Optional[int] = 1,
) -> Union[List[Mol], pd.DataFrame]:
    """Read an SDF file.

    Note: This function is meant to be used with dataset that fit _in-memory_.
    For a more advanced usage we suggest you to use directly `Chem.ForwardSDMolSupplier`.

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        sanitize: Whether to sanitize the molecules.
        as_df: Whether to return a list mol or a pandas DataFrame.
        smiles_column: Name of the SMILES column. Only relevant if `as_df` is True.
        mol_column: Name of the mol column. Only relevant if `as_df` is True.
        include_private: Include private properties in the columns.  Only relevant if
            `as_df` is True.
        include_computed: Include computed properties in the columns.  Only relevant if
            `as_df` is True.
        strict_parsing: If set to false, the parser is more lax about correctness of the contents.
        remove_hs: Whether to remove the existing hydrogens in the SDF files.
        max_num_mols: Maximum number of molecules to read from the SDF file. Read all by default when set
            to `None`.
        discard_invalid: Discard the molecules that failed to be read correctly. Otherwise,
            invalid molecules will be loaded as `None`.
        n_jobs: Optional number of jobs for parallelization of `to_df`. Leave to 1 for no
            parallelization. Set to -1 to use all available cores. Only relevant is `as_df` is True
    """

    # File-like object
    if isinstance(urlpath, io.IOBase):
        supplier = rdmolfiles.ForwardSDMolSupplier(
            urlpath,
            sanitize=sanitize,
            strictParsing=strict_parsing,
            removeHs=remove_hs,
        )
        mols = _get_supplier_mols(supplier, max_num_mols)

    # Regular local or remote paths
    else:
        with fsspec.open(urlpath, compression="infer") as f:
            supplier = rdmolfiles.ForwardSDMolSupplier(
                f,
                sanitize=sanitize,
                strictParsing=strict_parsing,
                removeHs=remove_hs,
            )
            mols = _get_supplier_mols(supplier, max_num_mols)

    # Discard None values
    if discard_invalid:
        mols = [mol for mol in mols if mol is not None]

    # Convert to dataframe
    if as_df:
        return dm.to_df(
            mols,
            smiles_column=smiles_column,
            mol_column=mol_column,
            include_private=include_private,
            include_computed=include_computed,
            n_jobs=n_jobs,
        )  # type: ignore

    return mols

def to_sdf(
    mols: Union[Mol, Sequence[Mol], pd.DataFrame],
    urlpath: Union[str, os.PathLike, IO],
    smiles_column: Optional[str] = "smiles",
    mol_column: Optional[str] = None,
):
    """Write molecules to a file.

    Args:
        mols: a dataframe, a molecule or a list of molecule.
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        smiles_column: Column name to extract the molecule.
        mol_column: Column name to extract the molecule. It takes
            precedence over `smiles_column`.
    """

    if isinstance(mols, pd.DataFrame):
        mols = dm.from_df(mols, smiles_column=smiles_column, mol_column=mol_column)

    elif isinstance(mols, Mol):
        mols = [mols]

    # Filter out None values
    mols = [mol for mol in mols if mol is not None]

    # File-like object
    if isinstance(urlpath, io.IOBase):
        writer = rdmolfiles.SDWriter(urlpath)
        for mol in mols:
            writer.write(mol)
        writer.close()

    # Regular local or remote paths
    else:
        with fsspec.open(urlpath, mode="w") as f:
            writer = rdmolfiles.SDWriter(f)
            for mol in mols:
                writer.write(mol)
            writer.close()

def read_mol2file(
    urlpath: Union[str, os.PathLike, IO],
    sanitize: bool = True,
    cleanup_substructures: bool = True,
    remove_hs: bool = True,
    fail_if_invalid: bool = False,
) -> List[Mol]:
    """Read a Mol2 File

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        sanitize: Whether to sanitize the molecules.
        remove_hs: Whether to remove the existing hydrogens in the SDF files.
        cleanup_substructures: Whether to clean up substructure in the Mol2 Files.
        fail_if_invalid: If set to true, the parser will raise an exception if the molecule is invalid
            instead of returning None.
    """

    block = []
    mols = []
    with fsspec.open(urlpath, compression="infer") as f:
        f = cast(IO, f)
        fReadLines = f.readlines()
        # reversing due to ambiguous end line for mol2 files
        fReadLines.reverse()
        for line in fReadLines:
            # ignores any header info
            if b"#" not in line:
                block.append(str(line, "utf-8"))
            # since reversed, this is the 'end' a mol2
            if b"@<TRIPOS>MOLECULE" in line:
                block.reverse()
                mol2block = ",".join(block).replace(",", "")
                mol = rdmolfiles.MolFromMol2Block(
                    mol2block,
                    sanitize=sanitize,
                    removeHs=remove_hs,
                    cleanupSubstructures=cleanup_substructures,
                )
                if mol is None and fail_if_invalid:
                    raise ValueError(f"Invalid molecule: {mol2block}")
                mols.append(mol)
                block = []

    mols.reverse()
    return mols

def read_molblock(
    molblock: str,
    sanitize: bool = True,
    strict_parsing: bool = True,
    remove_hs: bool = True,
    fail_if_invalid: bool = False,
) -> Optional[dm.Mol]:
    """Read a Mol block.

    Note that potential molecule properties are **not** read.

    Args:
        molblock: String containing the Mol block.
        sanitize: Whether to sanitize the molecules.
        strict_parsing: If set to false, the parser is more lax about correctness of the contents.
        remove_hs: Whether to remove the existing hydrogens in the SDF files.
        fail_if_invalid: If set to true, the parser will raise an exception if the molecule is invalid
            instead of returning None.
    """

    mol = rdmolfiles.MolFromMolBlock(
        molblock,
        sanitize=sanitize,
        removeHs=remove_hs,
        strictParsing=strict_parsing,
    )

    if mol is None and fail_if_invalid:
        raise ValueError(f"Invalid molecule: {molblock}")

    return mol

def to_molblock(
    mol: Mol,
    include_stereo: bool = True,
    conf_id: int = -1,
    kekulize: bool = True,
    force_V3000: bool = False,
):
    """Convert a molecule to a mol block string.

    Note that any molecule properties are lost.

    Args:
        mol: A molecule.
        include_stereo: Toggles inclusion of stereochemical information in the output.
        conf_id: Selects which conformation to output.
        kekulize: Triggers kekulization of the molecule before it's written,
            as suggested by the MDL spec.
        force_V3000: Force generation a V3000 mol block (happens automatically
            with more than 999 atoms or bonds).
    """

    molblock = rdmolfiles.MolToMolBlock(
        mol,
        includeStereo=include_stereo,
        confId=conf_id,
        kekulize=kekulize,
        forceV3000=force_V3000,
    )

    return molblock

def read_pdbblock(
    molblock: str,
    sanitize: bool = True,
    remove_hs: bool = True,
    flavor: int = 0,
    proximity_bonding: bool = True,
) -> dm.Mol:
    """Read a PDB string block.

    Args:
        molblock: String containing the Mol block.
        sanitize: Whether to sanitize the molecules.
        remove_hs: Whether to remove the existing hydrogens in the SDF files.
        flavor: RDKit flavor options.
        proximity_bonding: Whether to toggles automatic proximity bonding.
    """

    mol = rdmolfiles.MolFromPDBBlock(
        molblock,
        sanitize=sanitize,
        removeHs=remove_hs,
        flavor=flavor,
        proximityBonding=proximity_bonding,
    )
    return mol

def to_pdbblock(mol: Mol, conf_id: int = -1) -> str:
    """Convert a molecule to a PDB string block.

    Args:
        mol: A molecule.
        conf_id: Selects which conformation to use.
    """
    molblock = rdmolfiles.MolToPDBBlock(mol, confId=conf_id)
    return molblock

def read_pdbfile(
    urlpath: Union[str, os.PathLike],
    sanitize: bool = True,
    remove_hs: bool = True,
    flavor: int = 0,
    proximity_bonding: bool = True,
) -> Mol:
    """Read a PDB file.

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        sanitize: Whether to sanitize the molecules.
        remove_hs: Whether to remove the existing hydrogens in the SDF files.
        flavor: RDKit flavor options.
        proximity_bonding: Whether to toggles automatic proximity bonding.

    Returns:
        mol: a molecule
    """

    with fsspec.open(urlpath, "r") as f:
        f = cast(IO, f)
        mol = read_pdbblock(
            f.read(),
            sanitize=sanitize,
            remove_hs=remove_hs,
            flavor=flavor,
            proximity_bonding=proximity_bonding,
        )
    return mol

def to_pdbfile(
    mol: Mol,
    urlpath: Union[str, os.PathLike],
    conf_id: int = -1,
):
    """Save a molecule to a PDB file.

    Args:
        mol: A molecule.
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        conf_id: Selects which conformation to use.
    """
    molblock = to_pdbblock(mol, conf_id=conf_id)
    with fsspec.open(urlpath, "w") as f:
        f = cast(IO, f)
        f.write(molblock)

def to_smi(
    mols: Sequence[Mol],
    urlpath: Union[str, os.PathLike, IO],
    error_if_empty: bool = False,
):
    """Save a list of molecules in an `.smi` file.

    Note: We **strongly** recommend you to use `dm.to_csv` instead
    of `dm.to_smi` since `.smi` files are CSV-like format. The only difference are the
    default settings which changes:

    - The default separator is a space ` ` instead of a comma `,`.
    - The headers of the column are not included.

    By modifying the args of `dm.to_csv()`, you will be able to save a SMI compatible file.

    Args:
        mols: a list of molecules.
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        error_if_empty: whether to raise and error if the input list is empty.
    """

    if len(mols) == 0 and error_if_empty:
        raise ValueError("The list of mols/smiles provided is empty.")

    # Filter out None values
    mols = [mol for mol in mols if mol is not None]

    # File-like object
    if isinstance(urlpath, io.IOBase):
        writer = rdmolfiles.SmilesWriter(urlpath, includeHeader=False, nameHeader="")
        for mol in mols:
            writer.write(mol)
        writer.close()

    # Regular local or remote paths
    else:
        with fsspec.open(urlpath, "w") as f:
            writer = rdmolfiles.SmilesWriter(f, includeHeader=False, nameHeader="")
            for mol in mols:
                writer.write(mol)
            writer.close()

def read_smi(
    urlpath: Union[str, pathlib.Path, io.IOBase, fsspec.core.OpenFile],
) -> Sequence[Mol]:
    """Read a list of smiles from am `.smi` file.

    Note: We **strongly** recommend you to use `dm.read_csv` or `pandas.read_csv` instead
    of `dm.read_smi` since `.smi` files are CSV-like format. The only difference are the
    default settings which changes:

    - The default separator is a space ` ` instead of a comma `,`.
    - The headers of the column are not included.

    By modifying the args of `dm.read_csv()`, you will be able to read an `.smi` files.

    Args:
        urlpath: Path to a file or a file-like object. Path can be remote or local.
    """

    active_path = urlpath

    # NOTE(hadim): the temporary local file copy
    # is because `SmilesMolSupplier` does not support
    # using file-like object, only path.

    # Copy to a local temporary path if the path is a remote one.
    if not fsspec.utils.can_be_local(str(urlpath)):
        active_path = pathlib.Path(tempfile.mkstemp()[1])
        dm.utils.fs.copy_file(urlpath, active_path, force=True)

    # Read the molecules
    supplier = rdmolfiles.SmilesMolSupplier(str(active_path), titleLine=0)
    mols = [mol for mol in supplier if mol is not None]

    # Delete the local temporary path
    if not fsspec.utils.can_be_local(str(urlpath)):
        pathlib.Path(str(active_path)).unlink()

    return mols

def to_xlsx(
    mols: Union[Mol, Sequence[Mol], pd.DataFrame],
    urlpath: Union[str, os.PathLike],
    smiles_column: Optional[str] = "smiles",
    mol_column: str = "mol",
    mol_size: List[int] = [300, 300],
):
    """Write molecules to an Excel file with a molecule column as an RDKit rendered
    image.

    Args:
        mols: a dataframe, a molecule or a list of molecule.
        urlpath: Path to a file or a file-like object. Path can be remote or local.
        smiles_column: Column name to extract the molecule.
        mol_column: Column name to extract the molecule. It takes
            precedence over `smiles_column`.
            Column name to write the RDKit rendered image. If none,
            the molecule images are not written.
    """

    if isinstance(mols, Mol):
        mols = [mols]

    if isinstance(mols, Sequence):
        mols = [mol for mol in mols if mol is not None]
        mols = dm.to_df(mols, smiles_column=smiles_column, mol_column=mol_column)

    if mols is None or mols.empty:  # type: ignore
        raise ValueError("No molecules to write")

    with fsspec.open(urlpath, mode="wb") as f:
        PandasTools.SaveXlsxFromFrame(mols, f, molCol=mol_column, size=mol_size)

EXTENSIONS_DICT = {
    "csv": [
        ".csv",
        ".csv.gz",
        ".csv.bz2",
        ".csv.zip",
        ".csv.xz",
        ".csv.zst",
        ".csv.tar",
        ".csv.tar.gz",
        ".csv.tar.xz",
        ".csv.tar.bz2",
    ],
    "excel": [".xlsx"],
    "parquet": [".parquet"],
    "json": [
        ".json",
        ".json.gz",
        ".json.bz2",
        ".json.zip",
        ".json.xz",
        ".json.zst",
        ".json.tar",
        ".json.tar.gz",
        ".json.tar.xz",
        ".json.tar.bz2",
    ],
    "sdf": [
        ".sdf",
        ".sdf.gz",
    ],
}

def _guess_filetype(path: str):
    """Return a filetype given an input path. Filetypes returned can be from
    `csv, excel, parquet, json, sdf`.
    """
    for name, extensions in EXTENSIONS_DICT.items():
        for ext in extensions:
            if path.endswith(ext):
                return name

def open_df(path: str, **kwargs: Any) -> pd.DataFrame:
    """Open a dataframe file whatever its filetype from
    `csv, excel, parquet, json, sdf`.

    Args:
        path: path to the file.
        **kwargs: keyword arguments to pass to the underlying reader.
    """

    filetype = _guess_filetype(path)

    data = None
    if filetype == "csv":
        data = pd.read_csv(path, **kwargs)
    elif filetype == "excel":
        data = pd.read_excel(path, **kwargs)
    elif filetype == "parquet":
        data = pd.read_parquet(path, **kwargs)
    elif filetype == "json":
        data = pd.read_json(path, **kwargs)
    elif filetype == "sdf":
        kwargs.setdefault("as_df", True)
        data = dm.read_sdf(path, **kwargs)
    else:
        raise ValueError(f"The file type of {path} is not supported.")

    data = cast(pd.DataFrame, data)

    return data

def save_df(
    data: pd.DataFrame,
    path: str,
    **kwargs: Any,
):
    """Save a dataframe file whatever its filetype from
    `csv, excel, parquet, json, sdf`.

    Args:
        data: dataframe to save.
        path: path to save the file.
        **kwargs: additional arguments to pass that are specific to the file save type.
    """

    filetype = _guess_filetype(path)

    if filetype == "csv":
        kwargs.setdefault("index", False)
        data.to_csv(path, **kwargs)
    elif filetype == "excel":
        kwargs.setdefault("index", False)
        data.to_excel(path, **kwargs)
    elif filetype == "parquet":
        data.to_parquet(path, **kwargs)
    elif filetype == "json":
        data.to_json(path, **kwargs)
    elif filetype == "sdf":
        dm.to_sdf(data, path, **kwargs)
    else:
        raise ValueError(f"The file type of {path} is not supported.")


from flask import Flask, request
from logging.config import dictConfig
from flask_sqlalchemy.record_queries import get_recorded_queries

from config import Config

dictConfig(
    {
        "version": 1,
        "formatters": {
            "default": {
                "format": "[%(asctime)s] [%(levelname)s | %(module)s] %(message)s",
                "datefmt": "%B %d, %Y %H:%M:%S %Z",
            },
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "default",
            },
            "file": {
                "class": "logging.FileHandler",
                "filename": "todo.log",
                "formatter": "default",
            },
        },
        "root": {"level": "DEBUG", "handlers": ["file"]},
    }
)

myapp = Flask(__name__)
myapp.config.from_object(Config)

from models import db
from schemas import ma

db.init_app(myapp)
ma.init_app(myapp)

from create.routes import create_bp
from retreive.routes import retreive_bp
from update.routes import update_bp
from delete.routes import delete_bp

myapp.register_blueprint(create_bp)
myapp.register_blueprint(retreive_bp)
myapp.register_blueprint(update_bp)
myapp.register_blueprint(delete_bp)

@myapp.route('/')
def hellofunc():

    myapp.logger.info(">>REQ>> A user visited the home page.")
    return "Hello there!"

@myapp.after_request
def logAfterRequest(response):

    queries = list(get_recorded_queries())
    query_str = ''
    total_duration = 0.0
    for q in queries:
        total_duration += q.duration
        stmt = str(q.statement % q.parameters).replace('\n', '\n       ')
        query_str += 'Query: {0}\nDuration: {1}ms\n\n'.format(stmt, round(q.duration * 1000, 2))

    myapp.logger.info('=' * 80)
    myapp.logger.info(' SQL Queries - {0} Queries Executed in {1}ms'.format(len(queries), round(total_duration * 1000, 2)))
    myapp.logger.info('=' * 80)
    myapp.logger.info(query_str.rstrip('\n'))
    myapp.logger.info('=' * 80)

    myapp.logger.info(
        ">>RESP>> path: %s | method: %s | status: %s | size: %s",
        request.path,
        request.method,
        response.status,
        response.content_length,
    )

    return response

if __name__ == "__main__":
    #with myapp.app_context():
        #db.create_all()

    myapp.run(debug=True)


# 2019 카카오 개발자 겨울 인턴십
# 튜플
import operator

def solution(s):
    answer = []
    numbers = s.replace('{', "").replace('}','').split(',')
    tuples = dict()
    for number in numbers:
        if number in tuples:
            tuples[number] += 1
        else:
            tuples[number] = 1
    tuples = sorted(tuples.items(), key=operator.itemgetter(1), reverse=True)
    for key, value in tuples:
        answer.append(int(key))
    return answer


#!/usr/bin/env python3

from pydantic import BaseModel
from typing import Callable, Dict, Optional

from nested_pipelines.components import (
    combine_factory,
    download_factory,
    parse_factory,
)
from nested_pipelines.pipeline import Pipeline

def parse_combine_pipeline(spec: Dict) -> Dict:
    parse_task = parse_factory(
        parameters={
            "userId": "Integer",
            "id": "Integer",
            "title": "String",
            "completed": "Boolean",
        },
        name="parse-user",
    )(input=spec)
    combine_task = combine_factory(
        parameters={
            "userId": "Integer",
            "id": "Integer",
            "title": "String",
            "completed": "Boolean",
        }
    )(
        userid=parse_task.outputs["userId"],
        id=parse_task.outputs["id"],
        title=parse_task.outputs["title"],
        completed=parse_task.outputs["completed"],
    )
    return combine_task.output

def nested_pipeline(spec: Dict) -> Dict:
    parse_task = parse_factory(parameters={"url": "String"}, name="parse-spec")(input=spec)
    download_task = download_factory(parameters={"user": "typing.Dict"})(
        user=parse_task.outputs["url"]
    )
    return parse_combine_pipeline(download_task.outputs["user"])

class UserSpec(BaseModel):
    userId: int
    id: int
    title: str
    completed: bool

class ParseCombinePipeline(Pipeline[UserSpec]):
    pipeline: Callable[[Dict], Optional[Dict]] = parse_combine_pipeline

class NestedSpec(BaseModel):
    url: str

class NestedPipeline(Pipeline[NestedSpec]):
    pipeline: Callable[[Dict], Optional[Dict]] = nested_pipeline

if __name__ == "__main__":
    pipeline = NestedPipeline()
    pipeline(NestedSpec(url="https://jsonplaceholder.typicode.com/todos/1"))


from ..session import Session
from ..dataloader import DataLoader
from ..nn import Module, Loss
from ..optim import Optimizer

def basic_train(dataloader: DataLoader, model: Module, loss_fn: Loss, optimizer: Optimizer, batch_report: int) -> None:
    """
    Train neural network model.
    This function update gradient.

    [1] DataLoader: Check Dataset inside Dataloader.
    [2] Model: Check each layer information and sub logic (input, output, activation, flatten, dense, add etc...)
    [3] Loss function: Check appropriate loss function.
    [4] Optimizer: Check appropriate Optimizer (arguments, etc...)

    Parameters
    ----------
    `dataloader`: DataLoader
        This parameter serve batch data.
    `model`: Module
        This parameter include layer information, sub logic, for neural network training.
    `loss_fn`: Loss
        This parameter calculate loss about prediction with answer.
    `optimizer`: Optimizer
        This parameter control gradients update value.
    `batch_report`: int
        This parameter report result when batch count is same multiple.
    """

    try :
        data_count = len(dataloader.dataset)
        batch_count = len(dataloader)
        current = 0

        model.train()

        for batch_index, (X, y) in enumerate(dataloader):
            #### Original code ################################
            # pred = model(X)
            # loss = loss_fn(pred, y)
            # optimizer.zero_grad()
            # loss.backward()
            # optimizer.step()
            # batch_size = len(X)
            # current += batch_size

            # if batch_index == 0:
            #     loss = loss.item()
            #     print(f"loss: {loss:>.7f}  [{current:>5d}/{data_count:>5d}]")

            # if batch_index % batch_report == batch_report-1:
            #     loss_value = loss.item()
            #     print("loss: {:.7f}".format(loss_value), " [{:5d}/{:5d}]".format(current, data_count))

            # if batch_index == batch_count-1:
            #     loss_value = loss.item()
            #     print("loss: {:.7f}".format(loss_value), " [{:5d}/{:5d}]".format(data_count, data_count))
            ###################################################

            #### Fixed to new style ###########################
            pred = model(X)
            loss = loss_fn(pred, y)
            optimizer.zero_grad()
            loss_fn.backward()
            optimizer.step()
            batch_size = len(X['#'])
            current += batch_size

            if (batch_index + 1) % batch_report == 0 or batch_index == batch_count - 1:
                proc_count = loss_fn.get_proc_count(pred, y) # 최근 처리에서 실제 loss, accur 계산에 사용된 항의 갯수를 알려준다
                if len(loss) > 1:
                    loss_descs = []
                    loss_sum = 0
                    for key in loss.keys():
                        loss_term = loss[key].item() / proc_count[key]
                        loss_sum += loss_term
                        loss_term_desc = f"{key}:{loss_term:>7f}"
                        loss_descs.append(loss_term_desc)
                    loss_desc = f"{loss_sum:>7f}" + "(" + ",".join(loss_descs) + ")"
                else:
                    loss_term = loss["#"].item() / proc_count["#"]
                    loss_desc = f"{loss_term:>7f}"

                print(f"loss: {loss_desc}  [{current:>5d}/{data_count:>5d}]")
            ###################################################

    except Exception as e :
        raise Exception("Unknown exception occurred.")

def basic_test_classify(dataloader: DataLoader, model: Module, loss_fn: Loss, is_print_log: bool, session: Session) -> float:
    """
    Test neural network model.
    This function do not update gradient.
    Return average loss value.

    Parameters
    ----------
    `dataloader`: DataLoader
        This parameter serve batch data.
    `model`: Module
        This parameter include layer information, sub logic, for neural network training.
    `loss_fn`: Loss
        This parameter calculate loss about prediction with answer.
    `is_print_log`: bool
        This parameter control print-log or ignore.
    `session`: Session
        This parameter serve to connect 'Deep Learning Framework Engine' for ignore update gradient.

    Returns
    -------
    float
    """

    try :
        data_count = len(dataloader.dataset)
        batch_count = len(dataloader)
        test_loss = 0
        test_acc = 0
        correct = 0

        #### (Added) Fixed to new style ###################
        losses_acc = 0
        accurs_acc = 0

        model.eval()
        session.set_no_grad()

        for idx, (X, y) in enumerate(dataloader):
            pred = model(X)
            loss = loss_fn(pred, y)
            #### Original code ################################
            # test_loss += loss.item()

            # # test_acc += loss_fn.eval_accuracy(pred, y).item()   # Bug: Last accuracy is wrong.
            # if idx == batch_count - 1:
            #     # Temporary code until bugfix
            #     over_size = (dataloader.batch_size * batch_count) - data_count
            #     last_data_size = dataloader.batch_size - over_size
            #     correct += (pred.to_ndarray().argmax(1) == y.to_ndarray().flatten()).astype(int)[0:last_data_size].sum()
            # else:
            #     correct += (pred.to_ndarray().argmax(1) == y.to_ndarray().flatten()).astype(int).sum()
            ###################################################

            #### Fixed to new style ###########################
            accur = loss_fn.eval_accuracy(pred, y)
            proc_count = loss_fn.get_proc_count(pred, y) # 실제 loss, accur 계산에 사용된 항의 갯수를 알려준다

            if losses_acc == 0:
                losses_acc = {}
                accurs_acc = {}
                proc_total = {}
                for key in loss:
                    losses_acc[key] = 0
                    accurs_acc[key] = 0
                    proc_total[key] = 0
            for key in loss:
                losses_acc[key] = losses_acc[key] + loss[key].item()
                accurs_acc[key] = accurs_acc[key] + accur[key].item()
                proc_total[key] = proc_total[key] + proc_count[key]
            ###################################################

        session.unset_no_grad()

        #### Original code ################################
        # test_loss /= batch_count
        # # test_acc /= batch_count # Bug: Last accuracy is wrong.
        # correct /= data_count

        # if is_print_log is True:
        #     # print(f"Accuracy: {(100 * test_acc):>0.1f}%")   # Bug: Last accuracy is wrong.
        #     print(f"Accuracy: {(100 * correct):>0.1f}%")
        #     print(f"Avg loss: {test_loss:>.7f}")
        #
        # return test_loss
        ###################################################

        #### Fixed to new style ###########################
        if len(losses_acc) > 1:
            loss_descs = []
            acc_descs = []
            loss_sum = 0
            acc_sum = 0
            for key in losses_acc.keys():
                loss_term = losses_acc[key] / proc_total[key]
                loss_sum += loss_term
                loss_term_desc = f"{key}:{loss_term:>7f}"
                loss_descs.append(loss_term_desc)
                loss_desc = f"{loss_sum:>7f}" + "(" + ",".join(loss_descs) + ")"

                acc_term = accurs_acc[key] / proc_total[key]
                acc_sum += acc_term
                acc_term_desc = f"{key}:{acc_term:>7f}"
                acc_descs.append(acc_term_desc)
                acc_desc = f"{acc_sum:>7f}" + "(" + ",".join(acc_descs) + ")"
        else:
            loss_term = losses_acc["#"] / proc_total["#"]
            loss_desc = f"{loss_term:>7f}"

            acc_term = accurs_acc["#"] / proc_total["#"]
            acc_desc = f"{acc_term:>7f}"

        print(f"Test Result: Loss: {loss_desc}, Accuracy: {acc_desc}")

        return float(loss_desc)
        ###################################################

    except Exception as e :
        raise Exception("Unknown exception occurred.")


import socket
import random
import time

# Server configuration
HOST = 'localhost'
PORT = 8888

# Create a TCP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to a specific address and port
server_socket.bind((HOST, PORT))

# Listen for incoming connections
server_socket.listen(1)

print("Server started. Waiting for connections...")

# Accept a client connection
client_socket, client_address = server_socket.accept()
print("Client connected:", client_address)

# Maximum spaces for each section
max_spaces = [50, 20, 20]

while True:
    start_time = time.time()
    # Generate random available spaces for each section
    available_spaces = [random.randint(0, max_spaces[i]) for i in range(3)]

    # Concatenate the available spaces as a single string separated by commas
    spaces_str = ",".join(str(space) for space in available_spaces)

    # Send the available spaces data to the client
    client_socket.sendall(spaces_str.encode())
    end_time = time.time()
     # Calculate communication speed
    speed = end_time - start_time
    # Sleep for 1 second
    time.sleep(5)

# Close the client connection
    client_socket.close()

# Close the server socket
    server_socket.close()


# -*- coding: utf-8 -*-
import exceptions

class VimbaException(Exception):

    """
    An exception for the AVT Vimba API. It contains a message
    property which is a string indicating what went wrong.

    :param errorCode: Error code to be used to look up error message.
    """

    @property
    def message(self):
        return self._errorCodes[self.errorCode]

    @property
    def errorCode(self):
        return self._errorCode

    _errorCodes = {  # Vimba C API specific errors
        0: 	'No error.',
        -1: 	'Unexpected fault in VimbaC or driver.',
        -2: 	'VmbStartup() was not called before the current command.',
        -3: 	'The designated instance (camera, feature etc.) cannot be found.',
        -4: 	'The given handle is not valid, ensure device open.',
        -5: 	'Device was not opened for usage.',
        -6: 	'Operation is invalid with the current access mode.',
        -7: 	'One of the parameters was invalid (usually an illegal pointer).',
        -8: 	'The given struct size is not valid for this version of the API.',
        -9: 	'More data was returned in a string/list than space was provided.',
        -10:    'The feature type for this access function was wrong.',
        -11:    'The value was not valid; either out of bounds or not an increment of the minimum.',
        -12:    'Timeout during wait.',
        -13:    'Other error.',
        -14:    'Resources not available (e.g. memory).',
        -15:    'Call is invalid in the current context (e.g. callback).',
        -16:    'No transport layers were found.',
        -17:    'API feature is not implemented.',
        -18:   	'API feature is not supported.',
        -19:    'A multiple registers read or write was partially completed.',

        # Custom errors
        -50:	'Could not find the specified camera.',
        -51:	'Not enough memory to assign frame buffer.',
        -52:	'Invalid input.',
        -53:	'Could not find the specified feature.',
        -54:	'Could not find the specified interface.',

        # Miscellaneous errors
        -1000:	'Oops, unknown internal error code!',
        -1001:	'Oops, this VimbaFeature function is not yet implemented in pymba!'}

    def __init__(self, errorCode):
        # if error code does not match expected codes then assign invalid code
        if errorCode in self._errorCodes:
            self._errorCode = errorCode
        else:
            self._errorCode = -1000

        super(VimbaException, self).__init__(self.message)


import cv2 as cv
import numpy  as np
from matplotlib import pyplot as plt

#morphological operations are performed on binaray images

img = cv.imread('images/data/smarties.png', cv.IMREAD_GRAYSCALE)
_, mask = cv.threshold(img, 220, 255, cv.THRESH_BINARY_INV)

#kernal is just a sqaure or some shap we want to apply on image
kernal = np.ones((4,4), np.uint8) # white square

dilation = cv.dilate(mask, kernal, iterations=2)
erosion = cv.erode(mask, kernal, iterations=2)
opening = cv.morphologyEx(mask, cv.MORPH_OPEN, kernal)
closing = cv.morphologyEx(mask, cv.MORPH_CLOSE, kernal)
mg = cv.morphologyEx(mask, cv.MORPH_GRADIENT, kernal)
th = cv.morphologyEx(mask, cv.MORPH_TOPHAT, kernal)

titles = ['images', 'mask', 'dilation', 'erosion', 'opening', 'closing', 'mg', 'th']
images = [img, mask, dilation, erosion, opening, closing, mg, th]

for i in range(len(titles)):
    plt.subplot(2, 4, i+1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])

plt.show()


# import pandas as pd

# 读, 写, 改表格
# https://www.cnblogs.com/yunguoxiaoqiao/p/7592000.html
import xlrd   #Xlrd模块只能用来读取数据操作，无法修改数据。
import xlwt
from xlutils.copy import copy   #导入copy模块

from src.adbUtils import APK_CHECKER_PATH

PKG_INFO_FILE = r'%s\pkgInfo.xls'%APK_CHECKER_PATH

COLUMNS_NAME = ""

def readExcelExample():
    data = xlrd.open_workbook(PKG_INFO_FILE)  # 打开.xlsx文件读取数据, need: pip install pyexcel-xls
    table = data.sheets()[0]  # 读取第一个（0）表单
    # 或者通过表单名称获取 table = data.sheet_by_name(u'Sheet1')

    print(table.nrows)  # 输出表格行数
    print(table.ncols)  # 输出表格列数
    print("第一行：", table.row_values(0))  # 输出第一行
    print("第一列：", table.col_values(0))  # 输出第一列
    print("第一行第3列：", table.cell(0, 2).value)  # 输出元素（0,2）的值

def writeExcelExample():
    wb = xlwt.Workbook(encoding='ascii')  # 创建新的Excel（新的workbook），建议还是用ascii编码
    ws = wb.add_sheet('weng')  # 创建新的表单weng
    ws.write(0, 0, label='hello')  # 在（0,0）加入hello
    ws.write(0, 1, label='world')  # 在（0,1）加入world
    ws.write(1, 0, label='你好')
    wb.save('weng.xls')  # 保存为weng.xls文件

def editExcelExample():
    rb = xlrd.open_workbook(PKG_INFO_FILE)  # 打开weng.xls文件
    wb = copy(rb)  # 利用xlutils.copy下的copy函数复制
    ws = wb.get_sheet(0)  # 获取表单0
    ws.write(8, 0, label='好的')  # 增加（8,0）的值
    wb.save(PKG_INFO_FILE)  # 保存文件

def saveApkInfo(apkInfo):
    rb = xlrd.open_workbook(PKG_INFO_FILE)  # 打开weng.xls文件
    table = rb.sheets()[0]  # 读取第一个（0）表单
    i = 1
    while (i < table.nrows) :
        if table.cell(i, 0).value == apkInfo.pkgName:
            wb = copy(rb)  # 利用xlutils.copy下的copy函数复制
            ws = wb.get_sheet(0)  # 获取表单0
            if (table.ncols >3) :
                ws.write(i, table.ncols - 2, label=apkInfo.apkVersionInfo)  # 增加（8,0）的值
                ws.write(i, table.ncols - 1, label=apkInfo.apkSignerInfo)  # 增加（8,0）的值
            else :
                ws.write(i, 3, label=apkInfo.apkVersionInfo)  # 增加（8,0）的值
                ws.write(i, 4, label=apkInfo.apkSignerInfo)  # 增加（8,0）的值
            wb.save(PKG_INFO_FILE)  # 保存文件
            return
        i += 1

def readPkgInfos () :
    # read_excel()用来读取excel文件，记得加文件后缀
    data = xlrd.open_workbook(PKG_INFO_FILE)  # 打开.xlsx文件读取数据, need: pip install pyexcel-xls
    table = data.sheets()[0]  # 读取第一个（0）表单
    return table.col_values(0)
    # sheet_name = r'包名'
    # sheet_data = pd.read_excel(PKG_INFO_FILE, sheet_name=sheet_name)
    # print(sheet_data)

    # print('显示表格的属性:', data.shape[0])  # 打印显示表格的属性，几行几列
    # print('显示表格的列名:', data.columns)  # 打印显示表格有哪些列名
    # # head() 默认显示前5行，可在括号内填写要显示的条数
    # print('显示表格前3行:', data.head(2))
    # print('----------华丽的分割线 -----------')
    # # tail() 默认显示后5行，可在括号内填写要显示的条数
    # print('显示表格后五行:', data.tail(2))

def toExcel (pkgNames) :
    print("toExcel")
    # # nan_excle = pd.DataFrame()
    # # nan_excle.to_excel(PKG_INFO_FILE2)
    # data = pd.read_excel(PKG_INFO_FILE)
    # excel = pd.DataFrame(data).to_excel()
    # writer = pd.ExcelWriter()
    #
    # # # 打开excel
    # # writer = pd.ExcelWriter(PKG_INFO_FILE)
    # # # sheets是要写入的excel工作簿名称列表
    # for sheet in writer.sheets:
    #     # 保存writer中的数据至excel
    #     # 如果省略该语句，则数据不会写入到上边创建的excel文件中
    # writer.save()


#What is the product of the three entries that sum to 2020?
#https://adventofcode.com/2020/day/1

with open('inputs/2020/day_01.csv', 'r') as f:
    report = [line.rstrip('\n') for line in f]

report = [int(i) for i in report]
solution = []

for x in report:
    for y in report:
        if 2020-x-y in report:
           if x not in solution:
                solution.append(x)

print(f"Numbers that add to 2020: {solution[0]}, {solution[1]}, and {solution[2]}")
print(f"Product: {solution[0]*solution[1]*solution[2]}")


from audioop import reverse
from django.http import HttpResponse
from django.shortcuts import redirect, render
from . models import Subject
from . models import Task
from django.core.exceptions import ObjectDoesNotExist

def mainPage(request):
    subjects = Subject.objects.all() # összes adatot lekérjük (Select *)
    subject_tasks = Task.objects.all() #az összes feladat lekérése későbbi szűrésre
    queryparam_subject = request.GET.get('id')

    #ha még nincs megadva subject query-paraméterként (s nincs beállítva vagy üres), akkor a főoldalt dobja ki
    if queryparam_subject is None or queryparam_subject == '':
        return render(request, 'main.html',{'subjects_names':subjects})
    #ha be van állítva az s értéke, akkor tudjuk, hogy melyik tárgyat kell lekérni
    else:
        curr_subject = subjects.filter(id__exact=queryparam_subject) #lekérem id alapján a kiválasztott tárgyat
        filtered_tasks = subject_tasks.filter(subject__exact=curr_subject.first()) # a first()-el megkapom a tárgy nevét stringként és arra szűrök

        try:
            subject_data:Subject = Subject.objects.get(pk=queryparam_subject)
        #ha nem létezik, pl. s=32 van beállítva, akkor kivételkezelés, dobjon vissza a főoldalra
        except ObjectDoesNotExist:
            return redirect('home')
        return render(request, 'tasks.html', {'tasks':filtered_tasks})


from django.urls import path
from .views import *
urlpatterns = [
    path('',HomeView,name = 'home-page'),
    path('sargyt/<str:petname>/',SargytView,name = 'sargyt-page'),
    path('dog/',DogView,name = 'dog-page'),
    path('cat/',CatView,name = 'cat-page'),
    path('fish/',FishView,name = 'fish-page'),
    path('hamster/',HamsterView,name = 'hamster-page'),
    path('bird/',BirdView,name = 'bird-page'),
    path('rabbit/',RabbitView,name = 'rabbit-page'),

]


# -*- coding: utf-8 -*-
from django.db import models
import random
import os

# Create your models here.
def get_filename_ext(filepath):
    nombre_base = os.path.basename(filepath)
    nombre, ext = os.path.splitext(nombre_base)
    return nombre, ext

def upload_image_pathb(instancia, nombrearchivo):
    # print(instancia)
    # print(nombrearchivo)
    nuevo_nombrearchivo = random.randint(1,3910209312)
    nombre, ext = get_filename_ext(nombrearchivo)
    nombrearchivo_final = '{nuevo_nombrearchivo}{ext}'.format(nuevo_nombrearchivo=nuevo_nombrearchivo,ext=ext)
    return "almacen/c-b/{nuevo_nombrearchivo}/{nombrearchivo_final}".format(
            nuevo_nombrearchivo=nuevo_nombrearchivo,
            nombrearchivo_final=nombrearchivo_final
            )

def upload_image_path(instancia, nombrearchivo):
    # print(instancia)
    # print(nombrearchivo)
    nuevo_nombrearchivo = random.randint(1,3910209312)
    nombre, ext = get_filename_ext(nombrearchivo)
    nombrearchivo_final = '{nuevo_nombrearchivo}{ext}'.format(nuevo_nombrearchivo=nuevo_nombrearchivo,ext=ext)
    return "almacen/miniaturas/{nuevo_nombrearchivo}/{nombrearchivo_final}".format(
            nuevo_nombrearchivo=nuevo_nombrearchivo,
            nombrearchivo_final=nombrearchivo_final
            )

class Almacen(models.Model):
    codigo = models.CharField(max_length=50,blank=True,null=True)
    cod_barras = models.ImageField(upload_to=upload_image_pathb, null=True, blank=True)
    descripcion = models.CharField(max_length=200,blank=True,null=True)
    medida = models.CharField(max_length=50,blank=True,null=True)
    unidad = models.CharField(max_length=50,blank=True,null=True)
    existencia = models.IntegerField(blank=True, null=True)
    cantidad_caja = models.PositiveIntegerField(blank=True, null=True)
    cantidad_rb = models.PositiveIntegerField(blank=True, null=True)
    proveedor = models.CharField(max_length=50,blank=True,null=True)
    ubicacion = models.CharField(max_length=50,blank=True,null=True)
    costo = models.DecimalField(blank=True, null=True, max_digits=10, decimal_places=6)
    def __str__(self):
        return self.codigo

class log(models.Model):
    accion = models.CharField(max_length=50,blank=True,null=True)
    timestamp = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.accion


import numpy as np
import tensorflow as tf

from model import cnn_model_fn

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

checkpointing_config = tf.estimator.RunConfig(
    save_checkpoints_steps=500, keep_checkpoint_max=200)
mnist_classifier = tf.estimator.Estimator(
    model_fn=cnn_model_fn, model_dir='checkpoints', config=checkpointing_config)

predict_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": mnist.test.images},
    num_epochs=1,
    shuffle=False)

out = mnist_classifier.predict(input_fn=predict_input_fn)
predictions = [gen["classes"] for gen in out]

accuracy = predictions - np.argmax(mnist.test.labels, axis=1)

pred = 1 - np.count_nonzero(accuracy) / len(mnist.test.labels)

print("Accuracy: ", pred)

### load self made picture

picture = np.load("picture.npy").reshape(28 * 28)
picture = picture[np.newaxis, :]

predict_input_fn2 = tf.estimator.inputs.numpy_input_fn(
    x={"x": picture},
    num_epochs=1,
    shuffle=False)

out2 = mnist_classifier.predict(input_fn=predict_input_fn2)
prediction = [gen["probabilities"] for gen in out2]
print(prediction)


""" 35. Search Insert Position

Question:

    Given a sorted array and a target value, return the index if the target is
    found. If not, return the index where it would be if it were inserted in
    order.

"""

class Solution:
    def searchInsert(self, nums, target):
        lo, hi = 0, len(nums)-1
        while lo <= hi:
            mid = lo + (hi - lo) // 2
            if nums[mid] == target:
                return mid
            if nums[mid] >= target:
                hi = mid - 1
            else:
                lo = mid + 1
        return lo


# Duncan Lee (ddl9be)
# Lab 101
# lab1_fact.py
# January 22, 2018

def factorial1(n):
    if n < 0:
        raise ValueError
    if (n == 0):
        return 1
    answer = 1
    for i in range(1,n+1):
        answer *= i
    return answer

def factorial2(n):
    array = []
    for i in range(0,n+1):
        array.append(factorial1(i))
    #print(array)
    return array

def test_fact1():
    #assert factorial1(-1) == "ValueError", "valueerror not working"
    assert factorial1(0) == 1, "n=0 not returning 1"
    assert factorial1(1) == 1, "n=1 not returning 1"
    assert factorial1(5) == 120, "n=5 not returning 120"

def test_fact2():
    assert factorial2(0) == [1], "n=0 not returning [1]"
    assert factorial2(1) == [1, 1], "n=1 not returning [1, 1]"
    assert factorial2(2) == [1, 1, 2], "n=2 is wrong"
    print(factorial2(-2))

if __name__ == "__main__":
    test_fact1()
    test_fact2()


#for csv:
import pandas as pd

import logging
logging.basicConfig(filename='logs.log', level=logging.INFO, format='%(asctime)s %(message)s')

#for sheets:
import settings
import httplib2
from googleapiclient import discovery
from oauth2client.service_account import ServiceAccountCredentials

#auxulary:
import datetime
sheetname = 'Сводка'
maxrowcount = 10000

def svodka_stripper(arr):
    """
    Вход:\n
    Двумерный массив. В 1 столбце строка\n
    Выход:\n
    Тот же массив, в 1 столбце будут удалены все знаки ' [ ]\n
    """
    for i in range(0,len(arr)):
        arr[i][0] = arr[i][0].replace("'","")
        arr[i][0] = arr[i][0].replace("]","")
        arr[i][0] = arr[i][0].replace("[","")
    return arr

def svodka_data_creator(df:pd.DataFrame):
    """
    Args:\n
    df pandas.DataFrame\n
    В котором есть столбец "Направление" и "Статус согласия" и "Cтатус Согласия"\n
    Returns:\n
    data (list of lists)\n
    data[0] - блок направление\n
    data[1] - инфа об олимпиадниках\n
    data[2] - инфа о заявлениях
    """
    data = []
    try:
        data_cnt = pd.DataFrame(df["Направление"].value_counts()).fillna("").reset_index().to_numpy().tolist()
        svodka_stripper(data_cnt)
        data.append(data_cnt)
    except:
        data.append([['err',"0"]])
        logging.exception('SVODKA: No column named "Направление" in df.')
        print('SVODKA: No column named "Направление" in df.')

    try:
        data_olymp = pd.DataFrame(df["Олимпиадник?"].value_counts())
        data_olymp = data_olymp.rename(index={'Нет': 'Без олимпиад'})

        data_olymp = data_olymp.fillna("").reset_index().to_numpy().tolist()
        data.append(data_olymp)
    except:
        data.append([['err',"0"]])
        logging.exception('SVODKA: No column named "Олимпиадник?" in df.')
        print('SVODKA: No column named "Олимпиадник?" in df.')

    try:
        data_sogl = pd.DataFrame(df["Статус согласия"].value_counts())
        data_sogl = data_sogl.rename(index={'Нет': 'Нет согласия или отзыва'})
        data_sogl = data_sogl.append(pd.DataFrame({'Статус согласия': [df.shape[0]]},index = ['Всего заявлений']).astype('int64'))
        data_sogl = data_sogl.reindex(['Всего заявлений', 'Согл. на зач.: Принято АИС', 'Согл. на зач.: Отзыв принят АИС', 'Согл. на зач.: Отзыв загружен'])
        data_sogl = data_sogl.fillna("").reset_index().to_numpy().tolist()
        data.append(data_sogl)
    except:
        data.append([['err',"0"]])
        logging.exception('SVODKA: No column named "Статус согласия" in df.')
        print('SVODKA: No column named "Статус согласия" in df.')

    return(data)

def svodka(file_path,spreadsheetId):
    """
    Вход:\n
    -полный путь к файлу с именем файла и расширением (абсолютный или относительный)\n
    Пример: /data/file.csv\n
    -id таблицы\n
    -имя листа\n
    =====\n
    Выход:\n
    Выгружает полный csv файл в существующую гугл таблицу\n
    """
    #проверим, что файл существует
    try:
        df = pd.read_csv(file_path)
        logging.info(f"SVODKA: successfully opened {file_path}")
        print(f"SVODKA: successfully opened {file_path}")
    except:
        logging.exception(f"SVODKA: Error occured while opening the file {file_path}")
        print(f"SVODKA: Error occured while opening the file {file_path}")
        raise SystemExit(-1)

    #Подключаемся к таблице
    credentials = ServiceAccountCredentials.from_json_keyfile_name(settings.token_service, settings.SCOPES)
    httpAuth = credentials.authorize(httplib2.Http()) # Авторизуемся в системе
    service = discovery.build('sheets', 'v4', http = httpAuth) # Выбираем работу с таблицами и 4 версию API

    #Получаем список листов, все их параметры
    spreadsheet = service.spreadsheets().get(spreadsheetId = spreadsheetId).execute()
    sheetList = spreadsheet.get('sheets')

    #Пока это по сути проверка на то, что лист существует
    #
    #SheetId - айди нужного нам листа
    sheetId = -1
    for sheet in sheetList:
        if sheet['properties']['title'] == sheetname:
            print('SVODKA:', sheet['properties']['sheetId'], sheet['properties']['title'])
            sheetId = sheet['properties']['sheetId']

    if sheetId == -1:
        logging.exception(f'SVODKA: Sheet not found: {sheetname}')
        print(f'SVODKA: Sheet not found: {sheetname}')
        return -1
    else:
        data = svodka_data_creator(df)
        # print()
        # print(data[2])
        name = "Направление"
        listnapr = df[name].unique()
        bu_val_body = {
                "valueInputOption": "USER_ENTERED", # Данные воспринимаются, как вводимые пользователем (считается значение формул)
                "data": [
                    {
                    "range": f"{sheetname}!B2",
                    "majorDimension": "ROWS",     # Сначала заполнять строки, затем столбцы
                    "values": data[0]
                    },
                    {
                    "range": f"{sheetname}!E2",
                    "majorDimension": "ROWS",     # Сначала заполнять строки, затем столбцы
                    "values": data[1]
                    },
                    {
                    "range": f"{sheetname}!H2",
                    "majorDimension": "ROWS",     # Сначала заполнять строки, затем столбцы
                    "values": data[2]
                    },
                    {
                    "range": f"{sheetname}!H10",
                    "majorDimension": "ROWS",     # Сначала заполнять строки, затем столбцы
                    "values": [['Обновлено',datetime.datetime.now().strftime('%d.%m.%Y %H:%M') ]]
                    }
                ]
            }
        #запрос на очистку страницы
        #! Т.К. ПИШЕМ НА ВТОРУЮ СТРОКУ, НЕ НУЖНО СТАВИТЬ startIndex МЕНЬШЕ ДВОЙКИ. ИНАЧЕ БУДЕТ ПРОИСХОДИТЬ ОШИБКА
        clean_request = {"requests": [
            {
                "deleteDimension": {
                    "range": {
                        "sheetId": sheetId,
                        "dimension": "ROWS",
                        "startIndex": 2,
                        "endIndex": maxrowcount
                    }
                }
            },
        ]}
        try:
            bu_response_clean = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheetId, body=clean_request).execute()
        except:
            print()
        try:
            results = service.spreadsheets().values().batchUpdate(spreadsheetId = spreadsheetId, body = bu_val_body).execute()
        except:
            logging.exception("SVODKA: Error while performing batchUpdate to googlesheets.")
            print("SVODKA: Error while performing batchUpdate to googlesheets.")
            return -1
    logging.info('SVODKA: executed successfully')
    print('SVODKA: executed successfully')
    return 0


import sqlite3
from queries.sqlite3_handler import execute_and_commit

"""
    A class that is used to insert values into a table by given database.
"""
class Inserter:
    def __init__(self,*,dbName):
        self.dbName = dbName

    """
        Inserts a row with given values into the passed in table.
    """
    def insert(self,*,tableName,columnsAndValues):
        columns_str = ''
        values_str=''
        for k, v in columnsAndValues.items():
            columns_str += f'{k},\n'
            values_str +=f'"{v}",\n'

        columns_str = columns_str[:-2]
        values_str = values_str[:-2]

        INSERT_ROW_SQL=\
        f'''
INSERT INTO {tableName}(
{columns_str}
)
VALUES(
{values_str}
);
        '''
        print(INSERT_ROW_SQL)
        execute_and_commit(dbName=self.dbName,query=INSERT_ROW_SQL)


#!/usr/bin/env python
#
# description: Matrix Multiplication
# difficulty: Medium
# leetcode_num:
# leetcode_url:
#
# Given two sparse matrices A and B, return the result of AB.
#
# You may assume that A's column number is equal to B's row number.
#
# Example:
#
# A = [
#   [ 1, 0, 0],
#   [-1, 0, 3]
# ]
#
# B = [
#   [ 7, 0, 0 ],
#   [ 0, 0, 0 ],
#   [ 0, 0, 1 ]
# ]
#
#
#      |  1 0 0 |   | 7 0 0 |   |  7 0 0 |
# AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
#                   | 0 0 1 |

def MultiplyMatrices(matrix_a, matrix_b):
    if not matrix_a or not matrix_b:
        return []

    a_rows = len(matrix_a)
    a_cols = len(matrix_a[0])
    b_rows = len(matrix_b)
    b_cols = len(matrix_b[0])
    if a_cols != b_rows:
        return []

    product = [[0 for _ in range(b_cols)] for _ in range(a_rows)]

    for i in range(a_rows):
        for j in range(b_cols):
            for k in range(b_rows):
                product[i][j] += (matrix_a[i][k] * matrix_b[k][j])

    return product


import RPi.GPIO as GPIO
import time

servoPIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(servoPIN, GPIO.OUT)
GPIO.setup(14, GPIO.IN)

p = GPIO.PWM(servoPIN, 50) # GPIO 17 for PWM with 50Hz
p.start(2.5) # Initialization
try:
  while True:

    if GPIO.input(14):
        p.ChangeDutyCycle(5)
    else:
        p.ChangeDutyCycle(10)
    time.sleep(0.5)

except KeyboardInterrupt:
  p.stop()
  GPIO.cleanup()


"""
给你一个长度固定的整数数组 arr，请你将该数组中出现的每个零都复写一遍，并将其余的元素向右平移。
注意：请不要在超过该数组长度的位置写入元素。
要求：请对输入的数组 就地 进行上述修改，不要从函数返回任何东西。

示例 1：
输入：[1,0,2,3,0,4,5,0]
输出：null
解释：调用函数后，输入的数组将被修改为：[1,0,0,2,3,0,0,4]

思路：
果然做题最难得还是读懂题意：遍历arr，遇到一个0则复制一个，最后arr长度不变；
所以：
    遍历arr，在下标为i处遇到0则insert(i,0)，并将最后一个元素pop掉，以保证arr长度不变;
"""

class Solution(object):
    def duplicateZeros(self, arr):
        """
        :type arr: List[int]
        :rtype: None Do not return anything, modify arr in-place instead.
        """
        i = 0
        while i < len(arr) - 1:
            if arr[i] == 0:
                arr.insert(i, 0)
                arr.pop()
                i += 2
            else:
                i += 1

if __name__ == '__main__':
    solution = Solution()
    arr = [1, 0, 2, 3, 0, 4, 5, 0]
    solution.duplicateZeros2(arr)
    print(arr)


import sqlite3
from db_builder import exec, execmany
import sys
import random
from datetime import datetime
from datetime import timedelta
from flask import flash

#==========================general data retrieval functions===========================

# returns user info in a list given an osis
def getUserInfo(osis):
    q = "SELECT * from user_tbl WHERE osis=?"
    inputs = (osis,)
    data = execmany(q, inputs).fetchone()
    info = [data[0],data[1],data[2],data[3],data[4],data[5],data[6]]
    return info

# returns locker info in a list given an osis and locker
def getLockerInfo(locker,osis):
    q = "SELECT * from locker_tbl WHERE locker=? AND owner = ?"
    inputs = (locker,osis)
    data = execmany(q, inputs).fetchone()
    info=[]
    if data is not None:
        for value in data:
            info.append(value)
    return info

# returns transaction info in a list given an osis
def getTransactionInfo(osis):
    q = "SELECT * from transaction_tbl WHERE sender=?"
    inputs = (osis,)
    data = execmany(q, inputs).fetchall()
    info = []
    if(data is None):
        return info
    for value in data:
        if len(value)>0 and value[3] == 1:
            info.append([value[0],value[1],value[2],value[3],value[4],value[5]])
    return info

# returns a list of all info from a desired column of a desired table
def getColumnInfo(column, table):
    q = "SELECT " + column + " FROM " + table + "_tbl"
    rawData = exec(q).fetchall()
    info = []
    for entry in rawData:
        info.append(entry[0])
    return info

# returns a list of info from a desired column of a desired table given specific requirements
def getColumnInfo_Specific(column, table, requirement):
    q = "SELECT " + column + " FROM " + table + "_tbl WHERE " + requirement
    rawData = exec(q).fetchall()
    info = []
    for entry in rawData:
        info.append(entry[0])
    return info

# finds a specific osis from user_tbl and returns True if it exists
def findOsis(osis):
    q = "SELECT * FROM user_tbl WHERE osis = ?"
    inputs=(osis,)
    data=execmany(q,inputs).fetchall()
    if len(data) != 0:
        return True
    return False

# creates dict of transaction/locker data given list of tuples
def getTransLock(data,osis):
    dataDict = {}
    for i in data:
        lock = getLockerInfo(i[0],osis)
        dataDict[i] = lock
    return dataDict

# returns a list of all people who the user received a transaction request from
def getTransactionFrom(osis):
    q="SELECT recipient FROM transaction_tbl WHERE sender=? AND status = ?"
    inputs = (osis,1)
    data = execmany(q,inputs).fetchall()
    info=[]
    if data is None:
        return info
    for value in data:
        info.append(value[0])
    filtered = [x for x in info if x != '']
    return filtered

# returns a list of all people who the user sent a transaction request to
def getTransactionTo(osis):
    q="SELECT sender FROM transaction_tbl WHERE recipient=? AND status=?"
    inputs = (osis,1)
    data = execmany(q,inputs).fetchall()
    info=[]
    if data is None:
        return info
    for value in data:
        info.append(value[0])
    return info

#==========================user profile functions===========================

# checks to see if the user/password combination is valid
def userValid(osis,password):
    q = "SELECT password from user_tbl WHERE osis=?"
    inputs = (osis,)
    data = execmany(q, inputs).fetchone()
    if (data is not None):
        if (data[0] == password):
            return True
        else:
            flash("Incorrect OSIS and password combination.", 'danger')
            return False
    flash("OSIS does not exist. Please sign up for an account.", 'danger')
    return False

# adds user info to user_tbl and locker info to locker_tbl
def addUser(osis, password, grade, buddy, linfo, locker, gender):
    q = "SELECT * FROM user_tbl WHERE osis=?"
    inputs = (osis,)
    data = execmany(q, inputs).fetchone()
    if (data is None):
        if (locker != ""):
            q = "SELECT * FROM locker_tbl WHERE locker='" + locker + "' AND floor='" + linfo[1] + "'"
            data = exec(q).fetchone()
        if(data is None or locker==""):
            q = "INSERT INTO user_tbl VALUES(?, ?, ?, ?, ?, ?, ?)"
            inputs = (osis, password, locker, grade, buddy, "", gender)
            execmany(q, inputs)
            q = "INSERT INTO locker_tbl VALUES(?, ?, ?, ?, ?, ?, ?)"
            inputs = (locker, osis, linfo[0], linfo[1], linfo[2], linfo[3], linfo[4])
            execmany(q, inputs)
            return "done"
        else:
            return "locker"
    return "user"

#==========================editing functions===========================

# updates the survey column of user_tbl given an osis and the proper info
def updateSurvey(osis, info):
    q = "UPDATE user_tbl SET survey=? WHERE osis=?"
    inputs = (info, osis)
    execmany(q, inputs)

# edits user_tbl given an osis, the desired column to be changed, and the new info
def editUserTbl(osis,fxn,new):
    new = "\"" + new + "\""
    q = "UPDATE user_tbl SET " + fxn + "=" + new + " WHERE osis=?"
    inputs = (osis,)
    data = execmany(q,inputs)
    return True

# edits transaction_tbl given an osis, the desired column to be changed, and the new info
def editTransTbl(osis,fxn,new):
    if fxn == "locker":
        q="UPDATE transaction_tbl SET locker = ? WHERE recipient = ?"
        inputs = (new,osis)
        execmany(q,inputs)
    else:
        q = "UPDATE transaction_tbl SET sender = ? WHERE sender = ?"
        inputs = (new, osis)
        execmany(q,inputs)
        q = "UPDATE transaction_tbl SET recipient = ? WHERE recipient = ?"
        inputs = (new, osis)
        execmany(q,inputs)
    return True

# edits locker_tbl given an osis, the locker, the desired column to be changed, and the new info
def editLockerTbl(locker,fxn,new, osis):
    if fxn == "locker" or fxn == "floor":
        q="SELECT locker, floor FROM locker_tbl WHERE locker = ?"
        inputs=(locker,)
        old = execmany(q,inputs).fetchone()
        if fxn == "locker":
            q = "SELECT locker, floor FROM locker_tbl WHERE locker = ?"
            inputs=(new,)
            data = execmany(q,inputs).fetchall()
        else:
            q = "SELECT locker, floor FROM locker_tbl WHERE floor = ?"
            inputs=(new,)
            data = execmany(q,inputs).fetchall()
        if data is not None:
            for value in data:
                if value[0] == old[0] and value[1] == old[1]:
                    return False
    new = "\"" + new + "\""
    q = "UPDATE locker_tbl SET " + fxn + "=" + new + " WHERE owner=?"
    inputs = (osis,)
    d= execmany(q, inputs)
    q= "SELECT floor FROM locker_tbl WHERE owner = ? AND locker = ?"
    inputs = (osis, locker)
    d= execmany(q,inputs).fetchone()
    if d is not None:
        q = "UPDATE transaction_tbl SET floor = ? WHERE locker=? AND floor = ?"
        inputs = (new, locker, d[0])
        data = execmany(q,inputs)
    else:
        q = "UPDATE transaction_tbl SET floor = ? WHERE locker=?"
        inputs = (new, locker)
        data = execmany(q,inputs)
    return True

# edits user/locker/transaction_tbl depending on the new information provided by the user
def editUser(oldosis, osis, oldpassword, password, grade, locker, gender, combo, floor, level, type):
    bool = True
    if(userValid(oldosis,oldpassword)):
        if (password != ""): editUserTbl(oldosis,"password",password)
        if (grade != ""): editUserTbl(oldosis,"grade", grade)
        if (gender != ""): editUserTbl(oldosis,"gender", gender)
        q = "SELECT locker FROM user_tbl WHERE osis=?"
        inputs = (oldosis,)
        oldlocker = execmany(q,inputs).fetchone()[0]
        if (combo != ""): editLockerTbl(oldlocker,"combo", combo, oldosis)
        if (floor != ""): bool = bool and editLockerTbl(oldlocker,"floor", floor, oldosis)
        if (level != ""): editLockerTbl(oldlocker,"level", level, oldosis)
        if (type != ""): editLockerTbl(oldlocker,"location", type, oldosis)
        # if the user wants to change their owned locker
        if (locker != ""):
            if(editLockerTbl(oldlocker, "locker", locker, oldosis)):
                editUserTbl(oldosis, "locker", locker)
                editTransTbl(oldosis, "locker", locker)
            else:
                bool = False
        # if the user wants to change their osis
        if (osis != ""):
            if not (findOsis(osis)):
                editTransTbl(oldosis,"notifs",osis)
                q = "UPDATE locker_tbl SET owner=? WHERE owner=?"
                inputs = (osis,oldosis)
                data = execmany(q, inputs)
                editUserTbl(oldosis,"osis",osis)
            else:
                bool = False
    return bool

# deletes an entry from transaction_tbl given the user, recipient, and type of request
def deleteTrans(user, recipient, type):
    # if the user wants to take their locker off the market
    if (recipient == "" and type == 'L'):
        q = "UPDATE locker_tbl SET status='OWNED' WHERE owner=" + user
        exec(q)
    q = "DELETE FROM transaction_tbl WHERE sender=? AND recipient=? AND request=?"
    inputs=(user,recipient,type)
    execmany(q,inputs)
    return True

#==========================locker trading functions===========================

# returns a dict of transaction_tbl tuples and locker_tbl lists of all available lockers
def tradeableLockers():
    q = "SELECT * FROM transaction_tbl WHERE status=1 AND request='L' AND recipient=''"
    data = exec(q).fetchall()
    dataDict = {}
    for i in data:
        q = "SELECT * from locker_tbl WHERE locker=? AND status='TRADING'"
        inputs = (i[0],)
        data = execmany(q, inputs).fetchone()
        info=[]
        for value in data:
            info.append(value)
        dataDict[i] = info
    return dataDict

# returns a dict of transaction_tbl tuple and locker_tbl list of searched locker
def searchLocker(searchBy, query):
    if (searchBy == "Locker Number"):
        if (len(query) != 5):
            return False
        head,space,tail = query.partition("-")
        q = "SELECT * FROM transaction_tbl WHERE recipient='' AND locker=" + tail + " AND floor=" + head
        data = exec(q).fetchall()
        dataDict = {}
        for i in data:
            q = "SELECT * from locker_tbl WHERE locker=? AND floor=?"
            inputs = (tail,head)
            data = execmany(q, inputs).fetchone()
            info=[]
            if data is not None:
                for value in data:
                    info.append(value)
            dataDict[i] = info
        return dataDict
    else:
        if (len(query) != 9):
            return False
        q = "SELECT * FROM transaction_tbl WHERE recipient='' AND sender=" + query
        data = exec(q).fetchall()
        return getTransLock(data,query)

# searches for all lockers that meet the given criteria with possible searches in floor, level, and location of locker
def filterLocker(floor,level,location):
    # filters based on owner
    q = "SELECT owner FROM locker_tbl WHERE status='TRADING'"
    if (floor != ""):
        q += " AND floor=" + floor
    if (level != ""):
        q += " AND level='" + level + "'"
    if (location != ""):
        q += " AND location='" + location + "'"
    data = exec(q).fetchall()
    dictRes = {}
    for i in data:
        # searches for those specific owners and their lockers
        dictRes.update(searchLocker("Owner", i[0]))
    return dictRes

# adds a locker to transaction_tbl and updates its status
def putOnMarket(locker,osis):
    linfo = getLockerInfo(locker,osis)
    q = "INSERT INTO transaction_tbl VALUES (?,?,?,?,?,?)"
    inputs = (locker,"",linfo[1],1,'L',linfo[3])
    execmany(q,inputs)
    q = "UPDATE locker_tbl SET status='TRADING' WHERE locker=" + str(locker) + " AND owner=" + str(osis)
    exec(q)

# adds a locker request to transaction_tbl given two people
def lockerRequest(to,sender):
    owner = getUserInfo(to)
    locker = getLockerInfo(owner[2],to)
    q = "INSERT INTO transaction_tbl VALUES (?,?,?,?,?,?)"
    inputs=(owner[2],to, sender, 1, "L", locker[3])
    execmany(q,inputs)

# updates the user/locker/transaction_tbl to switch two lockers for two people
def acceptLocker(me,you):
    owner = getUserInfo(me)
    ownerL = getLockerInfo(owner[2],me)
    recipient = getUserInfo(you)
    recipientL = getLockerInfo(recipient[2],you)
    q = "UPDATE user_tbl SET locker=" + str(recipient[2]) + " WHERE osis=" + str(me)
    exec(q)
    q = "UPDATE user_tbl SET locker=" + str(owner[2]) + " WHERE osis=" + str(you)
    exec(q)
    q = "UPDATE locker_tbl SET status='OWNED',locker=" + str(recipientL[0]) + ",combo=" + str(recipientL[2]) + ",floor=" + str(recipientL[3]) + ",level='" + str(recipientL[4]) + "',location='" + str(recipientL[5]) + "' WHERE owner=" + str(me)
    exec(q)
    q = "UPDATE locker_tbl SET status='OWNED',locker=" + str(ownerL[0]) + ",combo=" + str(ownerL[2]) + ",floor=" + str(ownerL[3]) + ",level='" + str(ownerL[4]) + "',location='" + str(ownerL[5]) + "' WHERE owner=" + str(you)
    exec(q)
    q = "UPDATE transaction_tbl SET status=0 WHERE recipient=" + str(me) + " AND sender=" + str(you)
    exec(q)
    deleteTrans(me,"","L")
    deleteTrans(you,"","L")
    return True

#==========================buddy matching functions===========================

# returns survey info from user_tbl in a list given an osis
def getSurveyInfo(osis):
    q = "SELECT survey from user_tbl WHERE osis=?"
    inputs = (osis,)
    data = execmany(q, inputs).fetchone()
    info = []
    if(data[0] != ""):
        info = data[0].split("|")
    return info

# filters the buddy search by using the filterUser and filterLock helper functions, returns a list of osis
def filter(query,osis):
    info1=filterUser(query, osis)
    info2=filterLock(query, osis)
    info=[]
    # intersects the two data sets
    for value in info1:
        if value in info2:
            info.append(value)
    return info

# returns a list of all people who fit query criteria found in user_tbl
def filterUser(query,osis):
    q="SELECT osis FROM user_tbl WHERE osis != " + osis
    q+= " AND BUDDY = ''"
    info=[]
    if query[0] != "":
        q+=" AND osis = '" + query[0]+"'"
    if query[1] != "":
        q+=" AND locker = '" + query[1]+"'"
    if query[2] != "" and  query[2] != "None":
        q+=" AND survey LIKE '%" + query[2] +"%'"
    if query[3] != "" and  query[3] != "None":
        q+=" AND survey LIKE '%" + query[3] +"%'"
    if query[4] != "" and  query[4] != "None":
        q+=" AND grade = '" + query[4]+"'"
    if query[5] != "" and  query[5] != "None":
        q+=" AND gender = '" + query[5]+"'"
        q+=";"
    data=exec(q).fetchall()
    for value in data:
        info.append(str(value[0]))
    return info

# returns a list of all people who fit query criteria found in locker_tbl
def filterLock(query,osis):
    info=[]
    q="SELECT owner FROM locker_tbl WHERE owner != " + osis
    if query[6] != "" and  query[6] != "None":
        q+=" AND floor = '" + query[6]+"'"
    if query[7] != "" and  query[7] != "None":
        q+=" AND location = '" + query[7]+"'"
    if query[8] != "" and  query[8] != "None":
        q+=" AND level = '" + query[8]+"'"
    q+=";"
    data=exec(q).fetchall()
    for value in data:
        info.append(str(value[0]))
    return info

# adds a buddy request to transaction_tbl
def buddyRequest(to, sender):
    locker = getUserInfo(to)
    if locker == '':
        locker = getUserInfo(sender)[2]
    q = "INSERT INTO transaction_tbl VALUES (?,?,?,?,?,?)"
    inputs=(locker[2],to, sender, 1, "B", getLockerInfo(locker[2],to)[3])
    execmany(q,inputs)
    return True

# confirms a buddy request by updating user_tbl buddy columns for both people
def confirmB(user, recipient):
    q="UPDATE transaction_tbl SET status = 0 WHERE request = ? AND (sender=? OR recipient = ? OR sender = ? OR recipient = ?)"
    inputs=("B",user,user,recipient,recipient)
    execmany(q,inputs)
    q="UPDATE user_tbl SET buddy = ? WHERE osis = ?"
    inputs=(user, recipient)
    execmany(q,inputs)
    q="UPDATE user_tbl SET buddy = ? WHERE osis = ?"
    inputs=(recipient, user)
    execmany(q,inputs)
    return True

# returns a list of senders who want to dissolve a buddy pair with a given user
def getDissolveInfo(user):
    q = "SELECT sender FROM transaction_tbl WHERE recipient=?"
    inputs=(user,)
    data=execmany(q,inputs).fetchall()
    info=[]
    for value in data:
        info.append(value[0])
    return info

# updates user_tbl by removing the buddy pair of two people
def dissolveBuddy(user, sender):
    q = "UPDATE transaction_tbl SET status = ? WHERE (sender = ? OR recipient = ?) AND request = ?"
    inputs=(0,user,user,"D")
    execmany(q,inputs)
    q = "UPDATE user_tbl SET buddy = ? WHERE osis = ?"
    inputs=("",user)
    execmany(q,inputs)
    inputs=("",sender)
    execmany(q,inputs)
    return True

# adds a dissolve buddy request to transaction_tbl
def breakB(user, recipient):
    q = "INSERT INTO transaction_tbl VALUES (?,?,?,?,?,?)"
    inputs=("" , recipient, user, 1, "D", "")
    execmany(q,inputs)
    return True

# searches transaction_tbl to see if a user wants to dissolve a buddy pair
def ifDissolve(user):
    q = "SELECT * FROM transaction_tbl WHERE (recipient=? OR sender=?) AND status = ? AND request = ?"
    inputs=(user,user,1,"D")
    data=execmany(q,inputs).fetchall()
    if len(data)!=0:
        return True
    return False

#==========================notifications functions===========================

# returns a list of transaction requests sent to the user to be displayed as messages
def getMess(osis,num):
    q="SELECT * FROM transaction_tbl WHERE recipient=? AND status = ?"
    inputs = (osis,num)
    data = execmany(q,inputs).fetchall()
    info=[]
    temp=[]
    if data is None:
        return info
    for value in data:
        for cell in value:
            temp.append(cell)
        info.append(temp)
        temp=[]
    return info

# returns a list of all notifications the user was sent
def getAllNotifs(osis):
    q="SELECT * FROM transaction_tbl WHERE recipient=?"
    inputs = (osis,)
    data = execmany(q,inputs).fetchall()
    info=[]
    temp=[]
    if data is None:
        return info
    for value in data:
        for cell in value:
            temp.append(cell)
        info.append(temp)
        temp=[]
    return info


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from math import sqrt
from time import perf_counter

class Specimen:
    __slots__ = ("param", "sigma", "mse")
    tau = None
    data = None
    def __init__(self, param: np.ndarray, sigma: np.ndarray) -> None:
        self.param: np.ndarray[float] = param
        self.sigma: np.ndarray[float] = sigma
        self.mse: float = self.evaluate()

    def mutate(self):
        r = [np.random.normal(0, s) for s in self.sigma]
        param = self.param + r
        r1 = np.exp(Specimen.tau[0]*np.random.normal())
        r2 = np.exp(Specimen.tau[1]*np.array([np.random.normal() for i in range(len(self.sigma))]))
        sigma = self.sigma*r2*r1
        return Specimen(param, sigma)

    def evaluate(self) -> float:
        a, b, c = self.param
        data = Specimen.data
        o = a*(np.square(data['X'])-b*np.cos(c*np.pi*data['X']))
        mse = (np.sum(np.square(data['Y']-o)))/len(data['Y'])
        return mse

    def __str__(self) -> str:
        a,b,c = self.param
        s1,s2,s3 = self.sigma
        return f"a:{a:.4f} b:{b:.4f} c:{c:.4f} \u03C3a:{s1:.5f} \u03C3b:{s2:.5f} \u03C3c:{s3:.5f}"

    def plotdata(self) -> None:
        a, b, c = self.param
        data = Specimen.data
        o = a*(np.square(data['X'])-b*np.cos(c*np.pi*data['X']))
        # plt.plot(data['X'], data['Y'], color = "#000000", label = "Original", linewidth = 1, alpha = 0.95)
        plt.plot(data['X'], data['Y'],'o', color = "#000000", label = "Original", markersize = 1.5, alpha = 0.95)
        plt.plot(data['X'], o, color = "#00FFFF", label = "Approximation" ,linewidth = 1.7, alpha = 0.5)
        plt.legend()
        plt.show()

class EvoStrategy:
    def __init__(self, maxiter: int, mselim: float, popsize: int, child_coef: int, datafilepath: str, approach: str = "mi+lam", chromlen: int = 6) -> None:
        self.maxiter: int = maxiter
        self.mselim: float = mselim
        self.popsize: int = popsize
        self.child_coef: int = child_coef
        self.approach: str = approach
        self.chromlen: int = chromlen
        self.data: pd.DataFrame = self.read_data(datafilepath)
        self.population: list[Specimen] = []
        self.children: list[Specimen] = []
        self.convergence = False
        self.differ = 0

    def read_data(self, path: str) -> pd.DataFrame:
        file = pd.read_csv(path, delim_whitespace=True,
                           header=None, names=['X', 'Y'])
        return file

    def pop_init(self):
        for i in range(self.popsize):
            param = np.random.uniform(-10, 10, self.chromlen//2)
            sigma = np.random.uniform(0, 10, self.chromlen//2)
            self.population.append(Specimen(param, sigma))

    def child_init(self):
        children = []
        for parent in self.population:
            for i in range(self.child_coef):
                children.append(parent.mutate())
        self.children = children

    def check_convergence(self):
        parent_eval = []
        for pop in self.population:
            parent_eval.append(pop.mse)
        best_parent_mse = sorted(parent_eval)
        best_parent_mse = best_parent_mse[0]
        child_eval = []
        for pop in self.children:
            child_eval.append(pop.mse)
        best_child_mse = sorted(child_eval)
        best_child_mse = best_child_mse[0]
        if abs(best_child_mse - best_parent_mse) < self.mselim:
            self.convergence = True
        self.differ = abs(best_child_mse - best_parent_mse)

    def evaluate_population(self):
        if self.approach == "mi+lam":
            population: list[Specimen] = self.population
            population.extend(self.children)
        elif self.approach == "mi,lam":
            population: list[Specimen] = self.children
        pop_eval = []
        for pop in population:
            pop_eval.append(pop.mse)
        population = [pop for pop, _ in sorted(zip(population, pop_eval), key = lambda x: x[1])]
        self.population = population[:self.popsize]

    def mainloop(self):
        start = perf_counter()
        Specimen.tau = [1/(sqrt(2*self.chromlen)), (1/sqrt(2*(sqrt(self.chromlen))))]
        Specimen.data = self.data
        self.pop_init()
        self.children.extend(self.population)
        self.evaluate_population()
        best_individual = self.population[0]
        UP = "\x1B[3A"
        CLR = "\x1B[0K"
        print("\n\n")
        for i in range(self.maxiter):
            self.child_init()
            self.check_convergence()
            if self.convergence:
                break
            self.evaluate_population()
            best_individual = self.population[0]

            line1 = f"Iteration {i+1 :>2}, MSE: {best_individual.mse:.4f} " + str(best_individual) + '\n'
            line2 = f"Difference between best parent and offspring: {self.differ:.7f}"
            print(f"{UP}{line1}{CLR}{line2}{CLR}\n",end="\n")
        print(f"Ended on iteration {i+1} MSE:{best_individual.mse:.6f}", best_individual)
        print(f"Difference between best parent and offspring: {self.differ}")
        print(f"time: {perf_counter()-start}")
        best_individual.plotdata()
        return (i+1, best_individual.mse)

if __name__ == "__main__":
    Es = EvoStrategy(150, 10**-5, 500, 5, "model5.txt", 'mi,lam')
    Es.mainloop()

    # popsizes = [50, 200, 500, 800]
    # modes = ['mi+lam', 'mi,lam']
    # kids = [1, 2, 5, 8]
    # repeat = 5
    # with open('data.txt', 'w') as file:
    #     file.write("Mode;Popsize;Offspring;MeanIter;MeanMse\n")
    #     for mode in modes:
    #         for popsize in popsizes:
    #             for kid in kids:
    #                 iterat = []
    #                 mses = []
    #                 for i in range(repeat):
    #                     es = EvoStrategy(250, 10**-5, popsize, kid, 'model5.txt', mode)
    #                     it, mse = es.mainloop()
    #                     iterat.append(it)
    #                     mses.append(mse)
    #                 mean_iter = round(sum(iterat)/repeat, 2)
    #                 mean_mse = round(sum(mses)/repeat, 4)
    #                 file.write(f'{mode};{popsize};{kid};{mean_iter};{mean_mse}\n')


from random import randint

import pygame

from game_src.level_handler import create_level
from game_src.pause_screen import pause_screen
from sprites_classes.dead_frog import Dead_Frog
from image.image_handler import get_player_sprite, get_get_sprite, get_mob_sprite, \
    get_life_sprite, get_dead_sprite, get_beer_sprite, get_floating_mob_sprite

from sprites_classes.npc import Mob, Goat, Floating_mob
from sprites_classes.player import Player
from quiz_ui.quiz_handler import quiz_window, quiz
from music_and_sound.sound_handler import get_level_music, get_goat_music, get_drunk_music
from game_src.window_handler import screen, lose_window, win_window

# This function updates the window with sprites_classes each loop
def redraw_window(animals, wise_goat, dead_frog, background_image, lanes, floating_lanes):
    screen.blit(background_image, (0, 0))
    screen.blit(get_life_sprite(), (10, 315))
    screen.blit(pygame.transform.flip(get_life_sprite(), True, True), (10, 205))
    life_x = 10
    beer_y = 285
    for i in range(animals.drunk_meter):
        screen.blit(get_beer_sprite(), (10, beer_y))
        beer_y -= 25
    for i in range(animals.lives):
        screen.blit(get_life_sprite(), (life_x, 10))
        life_x += 25
    for lane in floating_lanes:
        for mob in lane.floating_mobs:
            screen.blit(mob.image, mob.mob_rect)

    if dead_frog.is_dead:
        screen.blit(dead_frog.img, (dead_frog.dead_x, dead_frog.dead_y))
        screen.blit(animals.update_img()[0], (1000, 1000))

    else:
        screen.blit(animals.update_img()[0], animals.update_img()[1])
    for lane in lanes:
        for car in lane.mobs:
            screen.blit(car.image, car.mob_rect)
    # screen.blit(get_get_sprite(), (animals.player_x - 20, wise_goat.get_y))
    pygame.display.update()

# This function runs the main game
def game_loop(sound_fx, volume):
    clock = pygame.time.Clock()
    get_level_music()
    animals = Player(400, 570, 40, 30, 0, get_player_sprite(0))
    dead_frog = Dead_Frog()
    wise_goat = Goat(animals.player_x, 200, 40, 30)
    pygame.display.set_caption("Drunk Frogger")

    q = True

    level_number = 1
    while True:
        level = create_level(level_number)
        running = True
        while running:
            clock.tick(30)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    quit()

            level.update_lanes()
            level.spawn_mobs()

            keys = pygame.key.get_pressed()
            if dead_frog.is_dead:
                dead_frog.check_time_of_death()
            else:
                animals.move(keys)
            if keys[pygame.K_p]:
                level.spawn_paused()
                volume = pause_screen(volume)
                level.spawn_resumed()
                # volume = Sound_settings(volume)
                if not volume:
                    return
            for lane in level.lanes:
                for car in lane.mobs:
                    if animals.check_collide(car):
                        if animals.lives != 1:
                            animals.lives -= 1
                            dead_frog.player_died(animals.player_x, animals.player_y)
                            sound_fx.play_splat()
                            animals.reset()
                        else:
                            lose_window()
                            return
            animals.floating = False
            for lane in reversed(level.floating_lanes):
                if animals.floating == False:
                    for floating_mob in lane.floating_mobs:
                        if animals.check_collide(floating_mob):
                            animals.floating = True
                            if lane.is_left:
                                animals.player_x -= lane.velocity
                            else:
                                animals.player_x += lane.velocity
                            break
                        else:
                            animals.floating = False

            if animals.player_y < 225 and not animals.floating:
                if animals.lives != 1:
                    animals.lives -= 1
                    dead_frog.player_died(animals.player_x, animals.player_y)
                    sound_fx.play_splat()
                    animals.reset()
                else:
                    lose_window()
                    return

            # This if statement checks if the player has reached the safe zone and triggers the quiz function
            if animals.player_y <= 300 and q is False:
                get_goat_music()
                level.spawn_paused()

                # This if statement checks if the player answers correctly. If the player answers correctly they trigger the win function
                # if they do not answer correctly they get moved to the start position and adds one to the drunk_meter integer
                if not quiz_window(quiz()):
                    if animals.drunk_meter == 3:
                        lose_window()
                        return
                    animals.drunk_meter += 1
                    dead_frog.img = get_dead_sprite(animals.drunk_meter)
                    sound_fx.play_burp()
                    animals.drunken_consequence()
                    get_drunk_music(animals.drunk_meter)
                    animals.reset()
                    q = False
                else:
                    win_window()
                    animals.reset()
                    running = False
                level.spawn_resumed()

            redraw_window(animals, wise_goat, dead_frog, level.background_image, level.lanes, level.floating_lanes)
        if level_number == 3:
            level_number = 1