from unittest.mock import MagicMock

import pytest

from .util import BerryData, PokeAPI, _calculate_growth_statistics, fetch_all_berry_data

@pytest.fixture()
def mock_session(monkeypatch):
    mock_session = MagicMock()
    monkeypatch.setattr("berries.util.requests.Session", lambda: mock_session)
    return mock_session

@pytest.fixture()
def pokeapi(mock_session):
    return PokeAPI()

def test_pokeapi_get_all_berries(pokeapi, mock_session):
    mock_session.get.return_value.json.return_value = {
        "results": [{"name": "berry1", "url": "url1"}]
    }
    berries = pokeapi.get_all_berries()
    assert len(berries) == 1
    assert berries[0]["name"] == "berry1"
    assert berries[0]["url"] == "url1"

def test_pokeapi_get_berry_growth_time(pokeapi, mock_session):
    mock_session.get.return_value.json.return_value = {"growth_time": 10}
    growth_time = pokeapi.get_berry_growth_time("url1")
    assert growth_time == 10

def test_calculate_growth_statistics():
    growth_times = [1, 2, 3, 4, 5]
    stats = _calculate_growth_statistics(growth_times)
    assert stats["min_growth_time"] == 1
    assert stats["max_growth_time"] == 5
    assert stats["median_growth_time"] == 3
    assert stats["mean_growth_time"] == 3
    assert stats["mode_growth_time"] is None
    assert stats["variance_growth_time"] == 2.5
    assert stats["standard_deviation_growth_time"] == pytest.approx(1.5811, abs=1e-4)

def test_fetch_all_berry_data(pokeapi, mock_session):
    mock_session.get.return_value.json.side_effect = [
        {
            "results": [
                {"name": "berry1", "url": "url1"},
                {"name": "berry2", "url": "url2"},
            ]
        },
        {"growth_time": 10},
        {"growth_time": 20},
    ]
    data = fetch_all_berry_data()
    assert isinstance(data, BerryData)
    assert data.names == ["berry1", "berry2"]
    assert data.growth_times == [10, 20]
    assert data.growth_statistics["min_growth_time"] == 10
    assert data.growth_statistics["max_growth_time"] == 20
    assert data.growth_statistics["median_growth_time"] == 15
    assert data.growth_statistics["mean_growth_time"] == 15
    assert data.growth_statistics["mode_growth_time"] is None
    assert data.growth_statistics["variance_growth_time"] == pytest.approx(50, abs=1e-3)
    assert data.growth_statistics["standard_deviation_growth_time"] == pytest.approx(
        7.03, rel=0.01
    )


import wmi
import cv2

brightness = 80
c = wmi.WMI(namespace='wmi')
methods = c.WmiMonitorBrightnessMethods()[0]
methods.WmiSetBrightness(brightness, 0)

import numpy as np
import cv2
import time

# Connect to the webcam
cap = cv2.VideoCapture(0)

while True:
    # Capture a frame from the webcam
    ret, frame = cap.read()

    # Calculate the average brightness of the frame
    avg_brightness = np.mean(frame)

    # Map the average brightness to a value between 0 and 100
    new_brightness = int(avg_brightness / 255 * 100)

    # Set the screen brightness to the calculated value
    methods.WmiSetBrightness(new_brightness, 0)

    # Break the loop on 'q' key press
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    time.sleep(2.0)

# Release the webcam
cap.release()

# Close all open windows
cv2.destroyAllWindows()


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from sklearn.neighbors import KernelDensity
import seaborn as sns
import pandas as pd
import itertools
from geopy.geocoders import Nominatim

geolocater = Nominatim(domain="localhost/nominatim/", scheme="http")

df = pd.read_excel(open(
    "./dortmund_straßennamen.xlsx",
    "rb"))

resulting_routes = []
i = 0
i_s = len(df)
print(i_s)
df["lat"] = ""
df["lon"] = ""
print(df.head())

for route in df.itertuples(index=True):
    if i == 0:
        i += 1
        continue

    print(i,"/",i_s)
    i+=1
    start = str(route[1]) + " " + str(route[0]) + "," + "Dortmund"

    try:
        print(start)
        print(geolocater.geocode(start))
        request = geolocater.geocode(start).raw
        df.at[i-1, "lat"] = request["lat"]
        df.at[i-1, "lon"] = request["lon"]
    except Exception as e:
        print("Error: ", e)
    print("\n")

writer = pd.ExcelWriter("dortmund_straßennamen_location.xlsx")
df.to_excel(writer, "Sheet1")
writer.save()


from collections import deque

N = int(input())

graph = []

for _ in range(N):
    graph.append(list(map(int, input())))

def bfs(graph, x, y):
    dx = [1, -1, 0, 0]
    dy = [0, 0, 1, -1]
    cnt = 1
    graph[x][y] = 0
    q = deque()
    q.append((x, y))

    while q:
        x, y =  q.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx<0 or nx>=N or ny<0 or ny>=N:
                continue
            if graph[nx][ny] == 0:
                continue
            if graph[nx][ny] == 1:
                 graph[nx][ny] = 0
                 q.append((nx, ny))
                 cnt += 1
    return cnt

count = []

for i in range(N):
    for j in range(N):
        if graph[i][j] == 1:
            count.append(bfs(graph, i,j))

count.sort()
print(len(count))
for i in range(len(count)):
    print(count[i])


import os
from itertools import tee

from twisted.internet.defer import inlineCallbacks, returnValue

from juju.environment.errors import EnvironmentsConfigError
from juju.state.errors import ServiceUnitStateMachineNotAssigned
from juju.state.machine import MachineStateManager
from juju.state.service import ServiceStateManager

def get_environment(options):
    environment = options.environments.get(options.environment)
    if environment is None and options.environment:
        raise EnvironmentsConfigError(
            "Invalid environment %r" % options.environment)
    elif environment is None:
        environment = options.environments.get_default()
    return environment

@inlineCallbacks
def get_ip_address_for_machine(client, provider, machine_id):
    """Returns public DNS name and machine state for the machine id.

    :param client: a connected zookeeper client.
    :param provider: the `MachineProvider` in charge of the juju.
    :param machine_id: machine ID of the desired machine to connect to.
    :return: tuple of the DNS name and a `MachineState`.
    """
    manager = MachineStateManager(client)
    machine_state = yield manager.get_machine_state(machine_id)
    instance_id = yield machine_state.get_instance_id()
    provider_machine = yield provider.get_machine(instance_id)
    returnValue((provider_machine.dns_name, machine_state))

@inlineCallbacks
def get_ip_address_for_unit(client, provider, unit_name):
    """Returns public DNS name and unit state for the service unit.

    :param client: a connected zookeeper client.
    :param provider: the `MachineProvider` in charge of the juju.
    :param unit_name: service unit running on a machine to connect to.
    :return: tuple of the DNS name and a `MachineState`.
    :raises: :class:`juju.state.errors.ServiceUnitStateMachineNotAssigned`
    """
    manager = ServiceStateManager(client)
    service_unit = yield manager.get_unit_state(unit_name)
    machine_id = yield service_unit.get_assigned_machine_id()
    if machine_id is None:
        raise ServiceUnitStateMachineNotAssigned(unit_name)
    returnValue(
        ((yield service_unit.get_public_address()), service_unit))

def expand_path(p):
    return os.path.abspath(os.path.expanduser(p))

class ParseError(Exception):
    """Used to support returning custom parse errors in passthrough parsing.

    Enables similar support to what is seen in argparse, without using its
    internals.
    """

def parse_passthrough_args(args, flags_taking_arg=()):
    """Scans left to right, partitioning flags and positional args.

    :param args: Unparsed args from argparse
    :param flags_taking_arg: One character flags that combine
       with arguments.
    :return: tuple of flags and positional args
    :raises: :class:`juju.control.utils.ParseError`

    TODO May need to support long options for other passthrough commands.
    """
    args = iter(args)
    flags_taking_arg = set(flags_taking_arg)
    flags = []
    positional = []
    while True:
        args, peek_args = tee(args)
        try:
            peeked = peek_args.next()
        except StopIteration:
            break
        if peeked.startswith("-"):
            flags.append(args.next())
            # Only need to consume the next arg if the flag both takes
            # an arg (say -L) and then it has an extra arg following
            # (8080:localhost:80), rather than being combined, such as
            # -L8080:localhost:80
            if len(peeked) == 2 and peeked[1] in flags_taking_arg:
                try:
                    flags.append(args.next())
                except StopIteration:
                    raise ParseError(
                        "argument -%s: expected one argument" % peeked[1])
        else:
            # At this point no more flags for the command itself (more
            # can follow after the first positional arg, as seen in
            # working with ssh, for example), so consume the rest and
            # stop parsing options
            positional = list(args)
            break
    return flags, positional


class Difference:
    def __init__(self, a):
        self.__elements = a

    # Add your code here
    def computeDifference(self):
        max_diff = 0
        for i in self.__elements:
            for j in self.__elements:
                if abs(i - j) > max_diff:
                    max_diff = abs(i - j)
        self.maximumDifference = max_diff

# End of Difference class

_ = input()
a = [int(e) for e in input().split(' ')]

d = Difference(a)
d.computeDifference()

print(d.maximumDifference)


# modulos de PySide2 utilizados
from PySide2.QtWidgets import QMainWindow,QTableWidgetItem,QSizePolicy,QHeaderView
from PySide2.QtCore import Qt

# diseño
from view.ui_elementos import Ui_Elementos

class MainTablew(QMainWindow):
    def __init__(self):
        super(MainTablew, self).__init__()

        self.raiz = Ui_Elementos()
        self.raiz.setupUi(self)

        # EVENTOS /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

        # llenado de valores *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'definimos una lista de valores'
        self.listadatos=[
                ['a12','nokia','nokia@gmail.com','nokia.org'],
                ['a15','huawei','huawei@gmail.com','huawei.org'],
                ['a16','asus','asus@gmail.com','asus.org'],
                ['a20','blackberry','blackberry@gmail.com','blackberry.org'],
                ['a24','oppo','oppo@gmail.com','oppo.org'],
                    ]

        'llenar tabla, para ello le pasamos la lista de valores'
        self.raiz.btnt1.clicked.connect(lambda : self.llenartabla(self.listadatos))

        # extraer fila,columna,item,lista_fila (evento) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        self.raiz.tablet1.cellClicked.connect(
            lambda fila,columna:
                print(

                    # fila
                    f'\n*fila:\t{fila}',

                    # columna
                    f'\n*colum:\t{columna}',

                    # item seleccionado
                    f'\n*item:\t{self.raiz.tablet1.item(fila, columna).text()}',

                    # elementos de la fila
                    f'\n*lista:\t{[self.raiz.tablet1.item(fila, columna).text() for columna in range(self.raiz.tablet1.columnCount())]}',

                    # solo el 1er elemento (index 0)
                    f'\n*1er item:\t{self.raiz.tablet1.item(fila, 0).text()}',

                )
            )

        # insertar columna y fila en la ultima posicion *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'self.raiz.tablet1.insertRow(self.raiz.tablet1.rowCount())'
        'self.raiz.tablet1.insertColumn(self.raiz.tablet1.columnCount())'

        # crear columna y filas por rango *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'self.raiz.tablet1.setRowCount(10)'
        'self.raiz.tablet1.setColumnCount(10)'

        # insertar columna y fila por index *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'self.raiz.tablet1.insertRow(2)#se basa en index'
        'self.raiz.tablet1.insertColumn(2)#se basa en index'

        # eliminar fila de tabla *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        '''
        para esto deberas agregar un controlador para evitar que
        los elementos se sigan eliminado con el boton.

        En este caso no se le agrego, esto solo es para mostrar la funcionalidad.
        '''
        self.raiz.btnt4.clicked.connect(lambda :
                self.raiz.tablet1.removeRow(
                    #NOTA: con este mismo index podremos eliminarlo de la matriz "self.listadatos"
                    self.raiz.tablet1.currentRow()
                )
            )

        # obtener lista de fila (por boton) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'nota: *funciones en en final del codigo*'
        self.raiz.btnt2.clicked.connect(lambda : self.listaRowTablaUno(self.raiz.tablet1.currentRow()))

        # obtener fila o columna actual *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'self.raiz.tablet1.currentRow()'
        'self.raiz.tablet1.currentColumn()'

        # borrado de elementos *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        self.raiz.btnt3.clicked.connect(lambda : self.raiz.tablet1.setRowCount(0))

        # total de filas y columnas *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        cantidadFilas = self.raiz.tablet1.rowCount()
        cantidadColumnas = self.raiz.tablet1.columnCount()

        # CONFIGURACIONES /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

        # establecer "filas" fija, elastica, interactiva (para todos) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'Fixed Stretch Interactive'
        self.raiz.tablet1.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)

        # establecer "columnas" fija, elastica, interactiva (para todos) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        'Fixed Stretch Interactive'
        self.raiz.tablet1.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # establecer "columna" fija (por index) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        '1. primeramente elegimos el index 0'
        self.raiz.tablet1.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)

        # establecer tamaño de "columnas" por index *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        '2. despues le designamos un tamaño'
        self.raiz.tablet1.setColumnWidth(0, 50)

    def llenartabla(self,lista):
        '''llenar elementos a la tabla'''

        # borrar elementos de la tabla *-*-*-*-*-*-*-*-*
        self.raiz.tablet1.setRowCount(0)

        # crear filas con respecto a los elementos *-*-*-*-*-*-*-*-*
        self.raiz.tablet1.setRowCount(len(lista))

        # reocorrer columnas y lista de items *-*-*-*-*-*-*-*-*
        for fila,listaItem in enumerate(lista):
            # agregar items
            for columna,item in enumerate(listaItem):
                self.raiz.tablet1.setItem(fila, columna, QTableWidgetItem(str(item))) # insertar items
                self.raiz.tablet1.item(fila,columna).setTextAlignment(Qt.AlignCenter|Qt.AlignVCenter) # alinear items

    def listaRowTablaUno(self,fila):
        '''extraer lista de elementos de una fila'''

        #si no se selecciono nada, la fila sera -1
        if(fila>=0):

            # cantidad de columnas *-*-*-*-*-*-*-*-*
            columnas = self.raiz.tablet1.columnCount()

            # recorremos todas las columnas de la fila seleccionada *-*-*-*-*-*-*-*-*
            lista=[self.raiz.tablet1.item(fila, columna).text() for columna in range(columnas)]

            print(lista)


#! /usr/bin/python3.5
import json
import platform
import socket
import fcntl
import struct

from rpc_core.exceptions import BadRequest
from rpc_core.codec.rpc_encoder import JSON_Encoder
from rpc_core.codec.rpc_decoder import JSON_Decoder
from rpc_core.transport.rpc_connector import Bio_Connector

def parse_json_file(config_file):
    with open(config_file) as json_config:
        config_items = json.load(json_config)
    return config_items

def validate_args(args, required_args):
    '''
    This function used to validate the request parameters.
    '''
    assert isinstance(required_args, list)
    if not required_args:
        return True
    else:
        if not args:
            return False
        assert isinstance(args, dict)
        recv_args = args.keys()
        for arg in required_args:
            if arg not in recv_args:
                return False
        return True

def base_request(endpoint, data):
    '''
    Base request framwork with default transport layer and encoder/decoder.
    '''
    assert isinstance(endpoint, tuple)
    proto, (ip, port) = endpoint
    if proto == 'tcp':
        with Bio_Connector(ip, port) as connector:
            connector.send_data(JSON_Encoder, data)
            return connector.recv_data(JSON_Decoder)
    else:
        raise BadRequest("Not supported!")

def make_request(endpoint, method, routing_key, body):
    '''
    Make a request with routing_key and body to remote endpoint.
    Request method - method should be GET/POST/PUT/DELETE.
    '''
    data = {
        "header" : {
            "routing_key" : routing_key,
            "request_method" : method
        },
        "body" : body
    }
    return base_request(endpoint, data)

def rpc_call_request(endpoint, service_name, method_name, \
                        args, kwargs):
    data = {
        "service_name" : service_name,
        "method_name" : method_name,
        "call_args": {
            "args" : args,
            "kwargs" : kwargs
        }
    }
    return base_request(endpoint, data)

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ifname = ifname.encode("utf-8")
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915, # SIOCGIFADDR
        struct.pack('256s', bytes(ifname[:15]))
    )[20:24])

def get_host_ip():
    # this function used to retrive the local ip address for
    # windows and linux platform
    os_type = platform.system()
    if os_type == "Windows":
        return socket.gethostbyname(socket.gethostname())
    elif os_type == "Linux":
        return get_ip_address('eth0')
    else:
        raise RuntimeError("Not supported!")

def handle_result(result):
    if result['status'] == 0:
        return True
    elif result['status'] < 0:
        return False


# -------------------------------------------------------------------------------------------------------------------------------------
# Following code curated for Bio-Diffusion (https://github.com/BioinfoMachineLearning/bio-diffusion):
# -------------------------------------------------------------------------------------------------------------------------------------

import glob
import os
import imageio
import random
import torch
import matplotlib
import wandb
import numpy as np
import matplotlib.pyplot as plt
import prody as pr

from torch import nn
from torch_scatter import scatter
from torch_geometric.data import Batch
from matplotlib.axes._subplots import Axes
from typing import Any, Callable, Dict, List, Optional, Union, Tuple
from wandb.sdk.wandb_run import Run
from pathlib import Path
from rdkit import Chem

from torchtyping import TensorType, patch_typeguard
from typeguard import typechecked

from src.datamodules.components.edm import get_bond_order
from src.utils.pylogger import get_pylogger

log = get_pylogger(__name__)

try:
    from pymol import cmd
except ImportError:
    log.warning("PyMOL not found.")

patch_typeguard()  # use before @typechecked

pr.confProDy(verbosity="none")

matplotlib.use("Agg")

@typechecked
def centralize(
    batch: Batch,
    key: str,
    batch_index: torch.Tensor,
    node_mask: Optional[TensorType["batch_num_nodes"]] = None,
    edm: bool = False
) -> Tuple[torch.Tensor, torch.Tensor]:  # note: cannot make assumptions on output shape
    if node_mask is not None:
        # derive centroid of each batch element
        if edm:
            masked_max_abs_value = batch[key][~node_mask].abs().sum().item()
            assert masked_max_abs_value < 1e-5, f"Masked CoG error {masked_max_abs_value} is too high"

            num_entities = scatter(
                node_mask.float(),
                batch_index,
                dim=0,
                reduce="sum"
            ).unsqueeze(-1)
            entities_sum = scatter(
                batch[key],
                batch_index,
                dim=0,
                reduce="sum"
            )
            entities_centroid = entities_sum / num_entities
        else:
            entities_centroid = scatter(
                batch[key][node_mask],
                batch_index[node_mask],
                dim=0,
                reduce="mean"
            )  # e.g., [batch_size, 3]

        # center entities using corresponding centroids
        if edm:
            entities_centered = batch[key] - (entities_centroid[batch_index] * node_mask.float().unsqueeze(-1))
        else:
            masked_values = (
                torch.zeros_like(batch[key])
                if edm
                else torch.ones_like(batch[key]) * torch.inf
            )
            values = batch[key][node_mask]
            masked_values[node_mask] = (values - entities_centroid[batch_index][node_mask])
            entities_centered = masked_values

    else:
        # derive centroid of each batch element, and center entities using corresponding centroids
        entities_centroid = scatter(batch[key], batch_index, dim=0, reduce="mean")  # e.g., [batch_size, 3]
        entities_centered = batch[key] - entities_centroid[batch_index]

    return entities_centroid, entities_centered

@typechecked
def decentralize(
    batch: Batch,
    key: str,
    batch_index: torch.Tensor,
    entities_centroid: torch.Tensor,
    node_mask: Optional[torch.Tensor] = None,
    edm: bool = False
) -> torch.Tensor:  # note: cannot make assumptions on output shape
    if node_mask is not None:
        if edm:
            entities_centered = batch[key] + (entities_centroid[batch_index] * node_mask.float().unsqueeze(-1))
        else:
            masked_values = torch.ones_like(batch[key]) * torch.inf
            masked_values[node_mask] = (batch[key][node_mask] + entities_centroid[batch_index])
            entities_centered = masked_values
    else:
        entities_centered = batch[key] + entities_centroid[batch_index]
    return entities_centered

@typechecked
def localize(
    x: TensorType["batch_num_nodes", 3],
    edge_index: TensorType[2, "batch_num_edges"],
    norm_x_diff: bool = True,
    node_mask: Optional[torch.Tensor] = None
) -> TensorType["batch_num_edges", 3, 3]:
    row, col = edge_index[0], edge_index[1]

    if node_mask is not None:
        edge_mask = node_mask[row] & node_mask[col]

        x_diff = torch.ones((edge_index.shape[1], 3), device=edge_index.device) * torch.inf
        x_diff[edge_mask] = x[row][edge_mask] - x[col][edge_mask]

        x_cross = torch.ones((edge_index.shape[1], 3), device=edge_index.device) * torch.inf
        x_cross[edge_mask] = torch.cross(x[row][edge_mask], x[col][edge_mask])
    else:
        x_diff = x[row] - x[col]
        x_cross = torch.cross(x[row], x[col])

    if norm_x_diff:
        # derive and apply normalization factor for `x_diff`
        if node_mask is not None:
            norm = torch.ones((edge_index.shape[1], 1), device=x_diff.device)
            norm[edge_mask] = (
                torch.sqrt(torch.sum((x_diff[edge_mask] ** 2), dim=1).unsqueeze(1))
            ) + 1
        else:
            norm = torch.sqrt(torch.sum((x_diff) ** 2, dim=1).unsqueeze(1)) + 1
        x_diff = x_diff / norm

        # derive and apply normalization factor for `x_cross`
        if node_mask is not None:
            cross_norm = torch.ones((edge_index.shape[1], 1), device=x_cross.device)
            cross_norm[edge_mask] = (
                torch.sqrt(torch.sum((x_cross[edge_mask]) ** 2, dim=1).unsqueeze(1))
            ) + 1
        else:
            cross_norm = (torch.sqrt(torch.sum((x_cross) ** 2, dim=1).unsqueeze(1))) + 1
        x_cross = x_cross / cross_norm

    if node_mask is not None:
        x_vertical = torch.ones((edge_index.shape[1], 3), device=edge_index.device) * torch.inf
        x_vertical[edge_mask] = torch.cross(x_diff[edge_mask], x_cross[edge_mask])
    else:
        x_vertical = torch.cross(x_diff, x_cross)

    f_ij = torch.cat((x_diff.unsqueeze(1), x_cross.unsqueeze(1), x_vertical.unsqueeze(1)), dim=1)
    return f_ij

@typechecked
def scalarize(
    vector_rep: TensorType["batch_num_entities", 3, 3],
    edge_index: TensorType[2, "batch_num_edges"],
    frames: TensorType["batch_num_edges", 3, 3],
    node_inputs: bool,
    dim_size: int,
    node_mask: Optional[TensorType["batch_num_nodes"]] = None
) -> TensorType["effective_batch_num_entities", 9]:
    row, col = edge_index[0], edge_index[1]

    # gather source node features for each `entity` (i.e., node or edge)
    # note: edge inputs are already ordered according to source nodes
    vector_rep_i = vector_rep[row] if node_inputs else vector_rep

    # project equivariant values onto corresponding local frames
    if vector_rep_i.ndim == 2:
        vector_rep_i = vector_rep_i.unsqueeze(-1)
    elif vector_rep_i.ndim == 3:
        vector_rep_i = vector_rep_i.transpose(-1, -2)

    if node_mask is not None:
        edge_mask = node_mask[row] & node_mask[col]
        local_scalar_rep_i = torch.zeros((edge_index.shape[1], 3, 3), device=edge_index.device)
        local_scalar_rep_i[edge_mask] = torch.matmul(
            frames[edge_mask], vector_rep_i[edge_mask]
        )
        local_scalar_rep_i = local_scalar_rep_i.transpose(-1, -2)
    else:
        local_scalar_rep_i = torch.matmul(frames, vector_rep_i).transpose(-1, -2)

    # reshape frame-derived geometric scalars
    local_scalar_rep_i = local_scalar_rep_i.reshape(vector_rep_i.shape[0], 9)

    if node_inputs:
        # for node inputs, summarize all edge-wise geometric scalars using an average
        return scatter(
            local_scalar_rep_i,
            # summarize according to source node indices due to the directional nature of GCP2's equivariant frames
            row,
            dim=0,
            dim_size=dim_size,
            reduce="mean"
        )

    return local_scalar_rep_i

@typechecked
def vectorize(
    gate: TensorType["batch_num_entities", 9],
    edge_index: TensorType[2, "batch_num_edges"],
    frames: TensorType["batch_num_edges", 3, 3],
    node_inputs: bool,
    dim_size: int,
    node_mask: Optional[TensorType["batch_num_nodes"]] = None
) -> TensorType["effective_batch_num_entities", 3, 3]:
    row, col = edge_index

    frames = frames.reshape(frames.shape[0], 1, 9)
    x_diff, x_cross, x_vertical = frames[:, :, :3].squeeze(
    ), frames[:, :, 3:6].squeeze(), frames[:, :, 6:].squeeze()

    # gather source node features for each `entity` (i.e., node or edge)
    gate = gate[row] if node_inputs else gate  # note: edge inputs are already ordered according to source nodes

    # derive edge mask if provided node mask
    if node_mask is not None:
        edge_mask = node_mask[row] & node_mask[col]

    # use invariant scalar features to derive new vector features using each neighboring node
    gate_vector = torch.zeros_like(gate)
    for i in range(0, gate.shape[-1], 3):
        if node_mask is not None:
            gate_vector[edge_mask, i:i + 3] = (
                gate[edge_mask, i:i + 1] * x_diff[edge_mask]
                + gate[edge_mask, i + 1:i + 2] * x_cross[edge_mask]
                + gate[edge_mask, i + 2:i + 3] * x_vertical[edge_mask]
            )
        else:
            gate_vector[:, i:i + 3] = (
                gate[:, i:i + 1] * x_diff
                + gate[:, i + 1:i + 2] * x_cross
                + gate[:, i + 2:i + 3] * x_vertical
            )
    gate_vector = gate_vector.reshape(gate_vector.shape[0], 3, 3)

    # for node inputs, summarize all edge-wise geometric vectors using an average
    if node_inputs:
        return scatter(
            gate_vector,
            # summarize according to source node indices due to the directional nature of GCP2's equivariant frames
            row,
            dim=0,
            dim_size=dim_size,
            reduce="mean"
        )

    return gate_vector

@typechecked
def safe_norm(
    x: torch.Tensor,
    dim: int = -1,
    eps: float = 1e-8,
    keepdim: bool = False,
    sqrt: bool = True
):
    norm = torch.sum(x ** 2, dim=dim, keepdim=keepdim)
    if sqrt:
        norm = torch.sqrt(norm + eps)
    return norm + eps

@typechecked
def is_identity(nonlinearity: Optional[Union[Callable, nn.Module]] = None):
    return nonlinearity is None or isinstance(nonlinearity, nn.Identity)

@typechecked
def norm_no_nan(
    x: torch.Tensor,
    dim: int = -1,
    keepdim: bool = False,
    eps: float = 1e-8,
    sqrt: bool = True
):
    """
    From https://github.com/drorlab/gvp-pytorch

    L2 norm of tensor clamped above a minimum value `eps`.

    :param sqrt: if `False`, returns the square of the L2 norm
    """
    out = torch.clamp(torch.sum(torch.square(x), dim=dim, keepdim=keepdim), min=eps)
    return torch.sqrt(out) if sqrt else out

@typechecked
def num_nodes_to_batch_index(
    num_samples: int,
    num_nodes: Union[int, TensorType["batch_size"]],
    device: Union[torch.device, str]
) -> TensorType["batch_num_nodes"]:
    assert isinstance(num_nodes, int) or len(num_nodes) == num_samples
    sample_inds = torch.arange(num_samples, device=device)
    return torch.repeat_interleave(sample_inds, num_nodes)

@typechecked
def save_xyz_file(
    path: str,
    positions: TensorType["batch_num_nodes", 3],
    one_hot: TensorType["batch_num_nodes", "num_atom_types"],
    charges: torch.Tensor,  # TODO: incorporate charges within saved XYZ file
    dataset_info: Dict[str, Any],
    id_from: int = 0,
    name: str = "molecule",
    batch_index: Optional[TensorType["batch_num_nodes"]] = None
):
    try:
        os.makedirs(path)
    except OSError:
        pass

    if batch_index is None:
        batch_index = torch.zeros(len(one_hot))

    for batch_i in torch.unique(batch_index):
        current_batch_index = (batch_index == batch_i)
        num_atoms = int(torch.sum(current_batch_index).item())
        f = open(path + name + "_" + "%03d.xyz" % (batch_i + id_from), "w")
        f.write("%d\n\n" % num_atoms)
        atoms = torch.argmax(one_hot[current_batch_index], dim=-1)
        batch_pos = positions[current_batch_index]
        for atom_i in range(num_atoms):
            atom = atoms[atom_i]
            atom = dataset_info["atom_decoder"][atom]
            f.write("%s %.9f %.9f %.9f\n" % (atom, batch_pos[atom_i, 0], batch_pos[atom_i, 1], batch_pos[atom_i, 2]))
        f.close()

@typechecked
def write_xyz_file(
    positions: TensorType["num_nodes", 3],
    atom_types: TensorType["num_nodes"],
    filename: str
):
    out = f"{len(positions)}\n\n"
    assert len(positions) == len(atom_types)
    for i in range(len(positions)):
        out += f"{atom_types[i]} {positions[i, 0]:.3f} {positions[i, 1]:.3f} {positions[i, 2]:.3f}\n"
    with open(filename, "w") as f:
        f.write(out)

@typechecked
def write_sdf_file(sdf_path: Path, molecules: List[Chem.Mol], verbose: bool = True):
    w = Chem.SDWriter(str(sdf_path))
    for m in molecules:
        if m is not None:
            w.write(m)
    if verbose:
        log.info(f"Wrote generated molecules to SDF file {sdf_path}")

@typechecked
def load_molecule_xyz(
    file: str,
    dataset_info: Dict[str, Any]
) -> Tuple[
    TensorType["num_nodes", 3],
    TensorType["num_nodes", "num_atom_types"]
]:
    with open(file, encoding="utf8") as f:
        num_atoms = int(f.readline())
        one_hot = torch.zeros(num_atoms, len(dataset_info["atom_decoder"]))
        positions = torch.zeros(num_atoms, 3)
        f.readline()
        atoms = f.readlines()
        for i in range(num_atoms):
            atom = atoms[i].split(" ")
            atom_type = atom[0]
            one_hot[i, dataset_info["atom_encoder"][atom_type]] = 1
            position = torch.Tensor([float(e) for e in atom[1:]])
            positions[i, :] = position
        return positions, one_hot

@typechecked
def load_files_with_ext(path: str, ext: str, shuffle: bool = True) -> List[str]:
    files = glob.glob(path + f"/*.{ext}")
    if shuffle:
        random.shuffle(files)
    return files

@typechecked
def visualize_mol(
    path: str,
    dataset_info: Dict[str, Any],
    max_num: int = 25,
    wandb_run: Optional[Run] = None,
    spheres_3d: bool = False,
    mode: str = "molecule",
    verbose: bool = True
):
    files = load_files_with_ext(path, ext="xyz")[0: max_num]
    for file in files:
        positions, one_hot = load_molecule_xyz(file, dataset_info)
        atom_types = torch.argmax(one_hot, dim=-1).numpy()
        dists = torch.cdist(positions.unsqueeze(0), positions.unsqueeze(0)).squeeze(0)
        dists = dists[dists > 0]

        if verbose:
            log.info(f"Average distance between atoms: {dists.mean().item()}")

        plot_data3d(
            positions=positions,
            atom_types=atom_types,
            dataset_info=dataset_info,
            save_path=f"{file[:-4]}.png",
            spheres_3d=spheres_3d
        )

        if wandb_run is not None:
            # log image(s) via WandB
            path = f"{file[:-4]}.png"
            im = plt.imread(path)
            wandb_run.log({mode: [wandb.Image(im, caption=path)]})

@typechecked
def visualize_mol_chain(
    path: str,
    dataset_info: Dict[str, Any],
    wandb_run: Optional[Run] = None,
    spheres_3d: bool = False,
    mode: str = "chain",
    verbose: bool = True
):
    files = load_files_with_ext(path, ext="xyz")
    files = sorted(files)
    save_paths = []

    for file in files:
        positions, one_hot = load_molecule_xyz(file, dataset_info=dataset_info)

        atom_types = torch.argmax(one_hot, dim=-1).numpy()
        fn = f"{file[:-4]}.png"
        plot_data3d(
            positions=positions,
            atom_types=atom_types,
            dataset_info=dataset_info,
            save_path=fn,
            spheres_3d=spheres_3d,
            alpha=1.0
        )

        save_paths.append(fn)

    imgs = [imageio.imread(fn) for fn in save_paths]
    dirname = os.path.dirname(save_paths[0])
    gif_path = os.path.join(dirname, "output.gif")

    if verbose:
        log.info(f"Creating GIF with {len(imgs)} images")

    # add the last frame 10 times so that the final result remains temporally
    # imgs.extend([imgs[-1]] * 10)

    imageio.mimsave(gif_path, imgs, subrectangles=True)

    if wandb_run is not None:
        wandb_run.log({mode: [wandb.Video(gif_path, caption=gif_path)]})

@typechecked
def draw_sphere(
    ax: plt.axis,
    x: float,
    y: float,
    z: float,
    size: float,
    color: str,
    alpha: float
):
    u = np.linspace(0, 2 * np.pi, 100)
    v = np.linspace(0, np.pi, 100)

    xs = size * np.outer(np.cos(u), np.sin(v))
    ys = size * np.outer(np.sin(u), np.sin(v)) * 0.8  # Correct for matplotlib.
    zs = size * np.outer(np.ones(np.size(u)), np.cos(v))

    ax.plot_surface(
        x + xs,
        y + ys,
        z + zs,
        rstride=2,
        cstride=2,
        color=color,
        linewidth=0,
        alpha=alpha
    )

@typechecked
def plot_molecule(
    ax: Axes,
    positions: TensorType["num_nodes", 3],
    atom_types: np.ndarray,
    alpha: float,
    spheres_3d: bool,
    hex_bg_color: str,
    dataset_info: Dict[str, Any]
):
    x = positions[:, 0]
    y = positions[:, 1]
    z = positions[:, 2]

    # Hydrogen, Carbon, Nitrogen, Oxygen, Flourine

    colors_dic = np.array(dataset_info["colors_dic"])
    radius_dic = np.array(dataset_info["radius_dic"])
    area_dic = 1500 * radius_dic ** 2

    areas = area_dic[atom_types]
    radii = radius_dic[atom_types]
    colors = colors_dic[atom_types]

    if spheres_3d:
        for i, j, k, s, c in zip(x, y, z, radii, colors):
            draw_sphere(ax, i.item(), j.item(), k.item(), 0.7 * s, c, alpha)
    else:
        ax.scatter(x, y, z, s=areas, alpha=0.9 * alpha,
                   c=colors)  # , linewidths=2, edgecolors="#FFFFFF")

    for i in range(len(x)):
        for j in range(i + 1, len(x)):
            p1 = np.array([x[i], y[i], z[i]])
            p2 = np.array([x[j], y[j], z[j]])
            dist = np.sqrt(np.sum((p1 - p2) ** 2))

            s = (atom_types[i], atom_types[j])

            draw_edge_int = get_bond_order(
                dataset_info["atom_decoder"][s[0]],
                dataset_info["atom_decoder"][s[1]],
                dist
            )
            line_width = 2

            draw_edge = draw_edge_int > 0
            if draw_edge:
                if draw_edge_int == 4:
                    linewidth_factor = 1.5
                else:
                    # linewidth_factor = draw_edge_int  # note: proportional to number of edges
                    linewidth_factor = 1
                ax.plot(
                    [x[i], x[j]],
                    [y[i], y[j]],
                    [z[i], z[j]],
                    linewidth=line_width * linewidth_factor,
                    c=hex_bg_color,
                    alpha=alpha
                )

@typechecked
def plot_data3d(
    positions: TensorType["num_nodes", 3],
    atom_types: np.ndarray,
    dataset_info: Dict[str, Any],
    camera_elev: int = 0,
    camera_azim: int = 0,
    save_path: str = None,
    spheres_3d: bool = False,
    bg: str = "black",
    alpha: float = 1.0
):
    black = (0, 0, 0)
    white = (1, 1, 1)
    hex_bg_color = "#FFFFFF" if bg == "black" else "#666666"

    fig = plt.figure()
    ax = fig.add_subplot(projection="3d")
    ax.set_aspect("auto")
    ax.view_init(elev=camera_elev, azim=camera_azim)
    if bg == "black":
        ax.set_facecolor(black)
    else:
        ax.set_facecolor(white)

    ax.xaxis.pane.set_alpha(0)
    ax.yaxis.pane.set_alpha(0)
    ax.zaxis.pane.set_alpha(0)
    ax._axis3don = False

    if bg == "black":
        ax.w_xaxis.line.set_color("black")
    else:
        ax.w_xaxis.line.set_color("white")

    plot_molecule(
        ax=ax,
        positions=positions,
        atom_types=atom_types,
        alpha=alpha,
        spheres_3d=spheres_3d,
        hex_bg_color=hex_bg_color,
        dataset_info=dataset_info
    )

    if "GEOM" in dataset_info["name"]:
        max_value = positions.abs().max().item()

        axis_lim = min(40, max(max_value / 1.5 + 0.3, 3.2))
        ax.set_xlim(-axis_lim, axis_lim)
        ax.set_ylim(-axis_lim, axis_lim)
        ax.set_zlim(-axis_lim, axis_lim)
    else:
        max_value = positions.abs().max().item()

        axis_lim = min(40, max(max_value / 1.5 + 0.3, 3.2))
        ax.set_xlim(-axis_lim, axis_lim)
        ax.set_ylim(-axis_lim, axis_lim)
        ax.set_zlim(-axis_lim, axis_lim)

    dpi = 120 if spheres_3d else 50

    if save_path is not None:
        plt.savefig(save_path, bbox_inches="tight", pad_inches=0.0, dpi=dpi)

        if spheres_3d:
            img = imageio.imread(save_path)
            img_brighter = np.clip(img * 1.4, 0, 255).astype("uint8")
            imageio.imsave(save_path, img_brighter)
    else:
        plt.show()
    plt.close()

class ScalarVector(tuple):
    """
    From https://github.com/sarpaykent/GBPNet
    """
    def __new__(cls, scalar, vector):
        return tuple.__new__(cls, (scalar, vector))

    def __getnewargs__(self):
        return self.scalar, self.vector

    @property
    def scalar(self):
        return self[0]

    @property
    def vector(self):
        return self[1]

    # Element-wise addition
    def __add__(self, other):
        if isinstance(other, tuple):
            scalar_other = other[0]
            vector_other = other[1]
        else:
            scalar_other = other.scalar
            vector_other = other.vector

        return ScalarVector(self.scalar + scalar_other, self.vector + vector_other)

    # Element-wise multiplication or scalar multiplication
    def __mul__(self, other):
        if isinstance(other, tuple):
            other = ScalarVector(other[0], other[1])

        if isinstance(other, ScalarVector):
            return ScalarVector(self.scalar * other.scalar, self.vector * other.vector)
        else:
            return ScalarVector(self.scalar * other, self.vector * other)

    def concat(self, others, dim=-1):
        dim %= len(self.scalar.shape)
        s_args, v_args = list(zip(*(self, *others)))
        return torch.cat(s_args, dim=dim), torch.cat(v_args, dim=dim)

    def flatten(self):
        flat_vector = torch.reshape(self.vector, self.vector.shape[:-2] + (3 * self.vector.shape[-2],))
        return torch.cat((self.scalar, flat_vector), dim=-1)

    @staticmethod
    def recover(x, vector_dim):
        v = torch.reshape(x[..., -3 * vector_dim:], x.shape[:-1] + (vector_dim, 3))
        s = x[..., : -3 * vector_dim]
        return ScalarVector(s, v)

    def vs(self):
        return self.scalar, self.vector

    def idx(self, idx):
        return ScalarVector(self.scalar[idx], self.vector[idx])

    def repeat(self, n, c=1, y=1):
        return ScalarVector(self.scalar.repeat(n, c), self.vector.repeat(n, y, c))

    def clone(self):
        return ScalarVector(self.scalar.clone(), self.vector.clone())

    def mask(self, node_mask: TensorType["num_nodes"]):
        return ScalarVector(
            self.scalar * node_mask[:, None],
            self.vector * node_mask[:, None, None]
        )

    def __setitem__(self, key, value):
        self.scalar[key] = value.scalar
        self.vector[key] = value.vector

    def __repr__(self):
        return f"ScalarVector({self.scalar}, {self.vector})"

class VectorDropout(nn.Module):
    """
    From https://github.com/drorlab/gvp-pytorch
    """

    def __init__(self, drop_rate):
        super().__init__()
        self.drop_rate = drop_rate

    def forward(self, x):
        """
        :param x: `torch.Tensor` corresponding to vector channels
        """
        device = x[0].device
        if not self.training:
            return x
        mask = torch.bernoulli((1 - self.drop_rate) * torch.ones(x.shape[:-1], device=device)).unsqueeze(-1)
        x = mask * x / (1 - self.drop_rate)
        return x

class GCPDropout(nn.Module):
    """
    From https://github.com/drorlab/gvp-pytorch
    """

    def __init__(self, drop_rate: float, use_gcp_dropout: bool = True):
        super().__init__()
        self.scalar_dropout = nn.Dropout(drop_rate) if use_gcp_dropout else nn.Identity()
        self.vector_dropout = VectorDropout(drop_rate) if use_gcp_dropout else nn.Identity()

    def forward(self, x: Union[torch.Tensor, ScalarVector]):
        if isinstance(x, torch.Tensor) and x.shape[0] == 0:
            return x
        elif isinstance(x, ScalarVector) and (x.scalar.shape[0] == 0 or x.vector.shape[0] == 0):
            return x
        elif isinstance(x, torch.Tensor):
            return self.scalar_dropout(x)
        return ScalarVector(self.scalar_dropout(x[0]), self.vector_dropout(x[1]))

class GCPLayerNorm(nn.Module):
    """
    From https://github.com/drorlab/gvp-pytorch
    """

    def __init__(self, dims: ScalarVector, eps: float = 1e-8, use_gcp_norm: bool = True):
        super().__init__()
        self.scalar_dims, self.vector_dims = dims
        self.scalar_norm = nn.LayerNorm(self.scalar_dims) if use_gcp_norm else nn.Identity()
        self.use_gcp_norm = use_gcp_norm
        self.eps = eps

    @staticmethod
    def norm_vector(v: torch.Tensor, use_gcp_norm: bool = True, eps: float = 1e-8) -> torch.Tensor:
        v_norm = v
        if use_gcp_norm:
            vector_norm = torch.clamp(torch.sum(torch.square(v), dim=-1, keepdim=True), min=eps)
            vector_norm = torch.sqrt(torch.mean(vector_norm, dim=-2, keepdim=True))
            v_norm = v / vector_norm
        return v_norm

    def forward(self, x: Union[torch.Tensor, ScalarVector]):
        if isinstance(x, torch.Tensor) and x.shape[0] == 0:
            return x
        elif isinstance(x, ScalarVector) and (x.scalar.shape[0] == 0 or x.vector.shape[0] == 0):
            return x
        elif not self.vector_dims:
            return self.scalar_norm(x)
        s, v = x
        return ScalarVector(self.scalar_norm(s), self.norm_vector(v, use_gcp_norm=self.use_gcp_norm, eps=self.eps))


# -*- coding: utf-8 -*-
"""
Created on Sat May 14 09:55:34 2022

@author: tang
"""
import numpy as np
import pandas as pd
from .utils import InitTable

# %% 按条件查询
class QuaryInfo:
    def __init__(self, dic):
        self.dic = dic

    def update(self, reg: dict):
        res = list()
        if (reg['认知层次'] is None or '认知层次' not in reg.keys()) and (reg['模块名'] is None or '模块名' not in reg.keys()):
            res = self.chose_val('科目', reg)
            return self.list2table(res)
        if (reg['认知层次'] is None or '认知层次' not in reg.keys()) and (reg['科目'] is None or '科目' not in reg.keys()):
            res = self.chose_val('模块名', reg)
            return self.list2table(res)
        if (reg['模块名'] is None or '模块名' not in reg.keys()) and (reg['科目'] is None or '科目' not in reg.keys()):
            res = self.chose_val('认知层次', reg)
            return self.list2table(res)
        temp_ = list()
        for k, v in reg.items():
            if v is None:
                continue
            temp_ += self.chose_val(k, reg)
        for t_ in temp_:
            if t_ not in res:
                res.append(t_)
        return self.list2table(res)

    def chose_val(self, name, reg):
        res = list()
        for k in reg[name]:
            res.append([k, self.dic[k]['掌握程度']])
            com = self.dic[k]['内容'][1]
            for c in com:
                res.append([c, self.dic[c]['掌握程度']])
        return res

    def list2table(self, ls):
        table = pd.DataFrame(data=ls,
                             index=[i for i in range(1, len(ls) + 1)],
                             columns=['名称', '掌握程度'])
        return table

class SubWeight:
    def __init__(self, exam_names, *args):
        self.args = args
        self.exam_names = exam_names
        self.sub_score_ = self.get_sub_scores()
        self.sub_weight = self.get_weight(self.sub_score_)
        self.modele_score_ = self.get_module_scores()
        self.modele_weight = self.get_weight(self.modele_score_)

    def get_sub_scores(self):
        score = dict()
        for indc, exam_n in zip(self.args, self.exam_names):
            sub = indc['科目'].unique()
            d = dict()
            for s in sub:
                sco = InitTable.parsing_full_mark(
                    indc=indc,
                    reg={'模块': None, '科目': [s, ], '认知层次': None}
                )
                d[s] = sco
            score[exam_n] = d
        return score

    def get_module_scores(self):
        score = dict()
        for indc, exam_n in zip(self.args, self.exam_names):
            sub = indc['模块'].unique()
            d = dict()
            for s in sub:
                sco = InitTable.parsing_full_mark(
                    indc=indc,
                    reg={'模块': [s, ], '科目': None, '认知层次': None}
                )
                d[s] = sco
            score[exam_n] = d
        return score

    def get_weight(self, score):
        weight, key_s = dict(), list()
        for key, value in score.items():
            key_s.append(set(value.keys()))
        s0 = key_s[0]
        for s in key_s:
            s0 = s0 & s
        for s in s0:
            ls_ = list()
            for key, value in score.items():
                for k, v in value.items():
                    if s == k:
                        ls_.append(v)
            weight[s] = np.asarray(ls_) / sum(ls_)
        return weight

    def update(self, *args):
        table_1 = self.get_table('科目', self.sub_score_, self.sub_weight, *args)
        table_2 = self.get_table('模块', self.modele_score_, self.modele_weight, *args)
        return [table_1, table_2]

    def get_table(self, col, score, weight, *args):
        res = dict()
        for k in weight.keys():
            ls_ = list()
            for dic in args:
                ls_.append(dic[k]['掌握程度'])
            res[k] = np.sum(weight[k] * np.asarray(ls_))
        ukey = self.unique_set(score)
        ures = dict()
        for uk in ukey:
            for dic in args:
                if uk in dic.keys():
                    ures[uk] = dic[uk]['掌握程度']
        data_ls = list()
        for k, v in res.items():
            data_ls.append([k, v])
        # for k, v in ures.items():
        #     data_ls.append([k, v])
        return pd.DataFrame(
            data=data_ls,
            columns=['科目/模块', '掌握程度'],
            index=[i+1 for i in range(len(data_ls))]
        )

    def unique_set(self, score):
        unis, com = set(), list()
        for key, value in score.items():
            unis = unis.union(set(value.keys()))
            com.append(set(value.keys()))
        s0 = com[0]
        for c in com:
            s0 = s0 & c
        ukey = unis - s0
        return ukey

    def intersection_set(self, *args):
        res = set()
        for s in args:
            res = res.union(s)
        return res

    # 传入 update 的 res
    def totle_performance(self, dic_ls, *smtables):
        stable, mtable = smtables[0], smtables[1]
        sub = stable['科目/模块']
        mod = mtable['科目/模块']
        all_sub, all_mod = list(), list()
        for df in self.args:
            all_sub += list(df['科目'].unique())
            all_mod += list(df['模块'].unique())
        all_mod = list(set(all_mod))
        all_sub = list(set(all_sub))
        def chose_uniq(all_obj, ob):
            ret = list()
            for s in all_obj:
                for dic in dic_ls:
                    for k, v in dic.items():
                        if k == s and k not in list(ob):
                            ret.append([s, dic[k]['掌握程度']])
            return ret
        res_sub_table = chose_uniq(all_sub, sub)
        res_mod_table = chose_uniq(all_mod, mod)

        res_sub_table = pd.DataFrame(
            data=res_sub_table,
            columns=['科目/模块', '掌握程度']
        )
        res_mod_table = pd.DataFrame(
            data=res_mod_table,
            columns=['科目/模块', '掌握程度']
        )
        res_sub_table = res_sub_table.append(stable)
        res_sub_table = res_sub_table.reset_index(drop=True)

        res_mod_table = res_mod_table.append(mtable)
        res_mod_table = res_mod_table.reset_index(drop=True)

        return [res_sub_table, res_mod_table]


from selenium import webdriver

drive_path = r'E:\Anaconda\chromedriver.exe'
driver = webdriver.Chrome(executable_path=drive_path)
driver.get('https://www.baidu.com/')

# for cookie in driver.get_cookies():
#     print(cookie)

print(driver.get_cookie('PSTM')) # 获取name为PSTM的cookie信息
driver.delete_cookie('PSTM') # 删除PSTM的cookie
driver.delete_all_cookies() # 删除driver产生的所有cookie


# MNIST is a hand-written digits database. As for softmax, that will what we will do in multi-logistic regression to be able to sum the prob to be 1.

### Softmax Regression

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

import numpy as np
import sys
sys.path.append("/data")

x = tf.placeholder("float", [None, 784])

W = tf.Variable(tf.zeros([784, 10]))
# each column will be weights for each output units. 784*1
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)
# we use a trick here, since x is a 2D tensor with multiple inputs.

y_ = tf.placeholder("float", [None, 10])
#MUTATION#
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

batch_size = 100

"""insert code"""
from scripts.utils.tf_utils import GradientSearcher
gradient_search = GradientSearcher(name="tensorflow_in_ml_grist")
obj_function = tf.reduce_min(tf.abs(y))
obj_grads = tf.gradients(obj_function, x)[0]
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
max_val, min_val = np.max(batch_xs), np.min(batch_xs)
gradient_search.build(batch_size=batch_size, min_val=min_val, max_val=max_val)
"""insert code"""

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
# Tensorflow here return us a single operation which when runned, will do a step of gradient descent training.

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

while True:
    """inserted code"""
    monitor_vars = {'loss': cross_entropy, 'obj_function': obj_function, 'obj_grad': obj_grads}
    feed_dict = {x: batch_xs, y_: batch_ys}
    batch_xs, scores_rank = gradient_search.update_batch_data(session=sess, monitor_var=monitor_vars,
                                                              feed_dict=feed_dict, input_data=batch_xs,
                                                              )
    """inserted code"""

    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

    """inserted code"""
    new_batch_xs, new_batch_ys = mnist.train.next_batch(batch_size)
    new_data_dict = {'x': new_batch_xs, 'y': new_batch_ys}
    old_data_dict = {'x': batch_xs, 'y': batch_ys}
    batch_xs, batch_ys = gradient_search.switch_new_data(new_data_dict=new_data_dict, old_data_dict=old_data_dict,
                                                         scores_rank=scores_rank)
    gradient_search.check_time()
    """inserted code"""


import xgboost as xgb
from xgboost import plot_importance, plot_tree, plotting
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn import preprocessing
from dtreeviz import trees
from dtreeviz.models.xgb_decision_tree import ShadowXGBDTree
import graphviz
import pandas as pd
import numpy as np
import pandas_profiling
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use('TkAgg')

def data_processing(data, z):
    # categorial features to number
    data["Lead"] = data["Lead"].map(lambda x: 1 if x == "Female" else 0)
    X = data.iloc[:, 0:13]

    corr = data.corr()
    leng = len(corr.columns)
    if z == 1:
        for elt in range(leng):
            i = 0
            while i < elt:
                if abs(corr.iloc[elt,i] > .7):
                    X=X.drop(columns=[corr.columns[elt]])
                i += 1

    col_name = X.columns
    # normalization
    X = preprocessing.normalize(X, norm='l2')
    X = pd.DataFrame(X, columns=col_name)
    y = data.iloc[:, 13]
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=70)
    return X_train, X_test, y_train, y_test, corr

    model5 = xgb.XGBClassifier(
        learning_rate=0.1,
        n_estimators=200,
        max_depth=5,
        min_child_weight=4,
        gamma=1,
        subsample=0.8,
        colsample_bytree=0.8,
        objective= 'binary:logistic',
        nthread=None,
        scale_pos_weight=1,
        seed=None)

    reg_alpha = [1e-5, 1e-2, 0.1, 1, 100]
    reg_lambda  =  [1e-5, 1e-2, 0.1, 1, 100]
    param5 = dict(reg_alpha=reg_alpha, reg_lambda=reg_lambda)

    kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=7)

    grid_search = GridSearchCV(model5, param_grid=param5, scoring="neg_log_loss", n_jobs=-1, cv=kfold, verbose=1)
    grid_result = grid_search.fit(X_train, y_train)

    print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))

def model_training(X_train, X_test, y_train, y_test):
    #model = xgb.XGBClassifier(max_depth=5, learning_rate=0.1, n_estimators=200, verbosity=0, objective='binary:logistic')

    model = xgb.XGBClassifier(booster='gbtree', learning_rate=0.1, n_estimators=200,
        max_depth=5, min_child_weight=4, gamma=1, subsample=0.8, colsample_bytree=0.8,
        reg_alpha=0.00001, reg_lambda=1,missing=None,nthread=None, seed=None, silent=None,
        random_state=0,  scale_pos_weight=1, verbosity=0, objective='binary:logistic')

    model.fit(X_train,y_train.values.ravel())

    # predict the label of test set
    y_pred = model.predict(X_test)

    # calculate the accuracy
    accuracy = accuracy_score(y_test,y_pred)
    print( 'accuracy:%2.f%%' %(accuracy*100), '\n')

    print(pd.crosstab(y_pred, y_test), '\n')

    plot_tree(model)

    # show feature importance
    xgb.plot_importance(model)
    plt.show()
    return model

# run cross-validation on train set and test set
def cv_score_train_test(X_train, X_test, y_train, y_test, model):
    num_cv = 10
    score_list = ["neg_log_loss","accuracy","f1", "roc_auc"]
    train_scores = []
    test_scores = []
    for score in score_list:
        train_scores.append(cross_val_score(model, X_train, y_train, cv=num_cv, scoring=score).mean())
        test_scores.append(cross_val_score(model, X_test, y_test, cv=num_cv, scoring=score).mean())
    scores = np.array((train_scores + test_scores)).reshape(2, -1)
    scores_df = pd.DataFrame(scores, index=['Train', 'Test'], columns=score_list)
    print(scores_df)

if __name__ == "__main__":
    data = pd.read_csv("./train.csv")
    a, b, c, d, cor = data_processing(data, 1)
    e = model_training(a, b, c, d)


import pyaudio
import numpy as np
import torch
from typing import Optional, List
from src.core.vad import SileroVad, PyannoteVad
from src.core.vocal_activity import VocalActivity
from src.helpers.clear_line import clear_line

class Recorder:

    def __init__(self):
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        self.RATE = 16000
        self.CHUNK_DURATION_MS = 150
        self.PADDING_DURATION_MS = 300
        self.CHUNK_SIZE = int(self.RATE * self.CHUNK_DURATION_MS / 1000)
        self.PADDING_CHUNKS = int(self.PADDING_DURATION_MS / self.CHUNK_DURATION_MS)

        self.remaining_padding = self.PADDING_CHUNKS
        self.audio = pyaudio.PyAudio()
        self.stream = self.audio.open(format=self.FORMAT,
                                      channels=self.CHANNELS,
                                      rate=self.RATE,
                                      input=True,
                                      start=False,
                                      frames_per_buffer=self.CHUNK_SIZE)
        self.active = False
        self.vad = SileroVad()
        self.buffer: List[bytes] = []
        self.finished = False

    def init(self) -> None:
        self.stream.start_stream()
        print('Listening (ctrl-C to exit)...')

    def iter(self) -> Optional[bytes]:
        if (not self.active):
            self.finished = False
            self.buffer.clear()
        chunk = self._read_stream()
        chunk_tensor = self._stream_to_float_tensor(chunk)
        confidence = self.vad(chunk_tensor)
        vocal_activity = VocalActivity.get_vocal_activity(confidence)
        self._append_buffer(chunk)

        if self._is_finished():
            self.finished = True
            self._set_idle()
        elif self.active:
            self._update_padding_chunks(vocal_activity)
        elif (not self.active) and (vocal_activity == VocalActivity.VOICED):
            self.active = True
        else:
            self._print_current_state_and_confidence(confidence)
            return None

        self._print_current_state_and_confidence(confidence)
        return chunk

    def terminate(self) -> None:
        self.stream.stop_stream()
        self.stream.close()
        self.audio.terminate()

    def _reset_padding_chunks(self) -> None:
        self.remaining_padding = self.PADDING_CHUNKS

    def _decrement_padding_chunks(self) -> None:
        self.remaining_padding -= 1

    def _chunk_to_float_tensor(self, chunk: bytes) -> torch.Tensor:
        audio_int16 = np.frombuffer(chunk, np.int16)
        audio_float32 = self._int2float(audio_int16)
        return torch.from_numpy(audio_float32)

    def _int2float(self, sound: np.ndarray) -> np.ndarray:
        abs_max = np.abs(sound).max()
        sound = sound.astype('float32')
        if abs_max > 0:
            sound *= 1/32768
        sound = sound.squeeze()
        return sound

    def _read_stream(self) -> bytes:
        return self.stream.read(self.CHUNK_SIZE, exception_on_overflow=False)

    def _stream_to_float_tensor(self, stream: bytes) -> torch.Tensor:
        return self._chunk_to_float_tensor(stream)

    def _update_padding_chunks(self, vocal_activity: VocalActivity) -> None:
        if vocal_activity == VocalActivity.UNVOICED:
            self._decrement_padding_chunks()
        else:
            self._reset_padding_chunks()

    def _set_idle(self) -> None:
        self.active = False
        self._reset_padding_chunks()
        # self.buffer.clear()

    def _is_finished(self) -> bool:
        return self.active and self.remaining_padding == 0

    def _print_current_state_and_confidence(self, confidence: float) -> None:
        if self.active:
            print(f'{clear_line}Recording: {confidence}', end='\r', flush=True)
        else:
            print(f'{clear_line}Idling : {confidence}', end='\r', flush=True)

    def _append_buffer(self, chunk: bytes) -> None:
        self.buffer.append(chunk)

    def _get_buffer(self) -> bytes:
        return b''.join(self.buffer)

    def _get_buffer_and_cleanup(self) -> bytes:
        buffer = self._get_buffer()
        self._set_idle()
        return buffer


#Сортування бульбашкою

z = int(input("Скільки чисел потрібно посортувати "))
arr = []
for i in range(z):
    arr.append(int(input("Введіть " + str(i + 1) + " значення\n")))

for p in reversed(range(len(arr))):
    for m in range(p):
        if arr[m] > arr[m+1]:
            arr[m], arr[m+1] = arr[m+1], arr[m]

print(arr)


#   删除链表的倒数第N个节点
# 给定一个链表，删除链表的倒数第 n 个节点，并且返回链表的头结点。

# 示例：

# 给定一个链表: 1->2->3->4->5, 和 n = 2.

# 当删除了倒数第二个节点后，链表变为 1->2->3->5.
# 说明：

# 给定的 n 保证是有效的。

# 进阶：

# 你能尝试使用一趟扫描实现吗？

# Definition for singly-linked list.

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

class Solution:
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        list = []
        current_node = head
        while True:
            if current_node.next != None:
                list.append(current_node)
                current_node = current_node.next
            else:
                list.append(current_node)
                break
        delete_node = list[len(list) - n]
        if len(list) == 1:
            return None
        if delete_node.next == None:
            list[len(list)-2].next = None
        else:
            delete_node.val = delete_node.next.val
            delete_node.next = delete_node.next.next
        return head

node1 = ListNode(1)
node2 = ListNode(2)
node1.next = node2
# node3 = ListNode(3)
# node4 = ListNode(4)
# node5 = ListNode(5)
# node1.next = node2
# node2.next = node3
# node3.next = node4
# node4.next = node5
# # node = node1
# while True:
#     if node.next != None:
#         print(node.val)
#         node = node.next
#     else:
#         print(node.val)
#         break

so = Solution()
head = so.removeNthFromEnd(node1, 1)
print(head.val, head.next)
node = node1
while True:
    if node.next != None:
        print(node.val)
        node = node.next
    else:
        print(node.val)
        break


import os

import requests
from nephele.command import Command

class Telegram:
    def __init__(self, event):
        self._session = requests.Session()
        self._bot_api_url = os.environ["telegramBotApiUrl"]
        self._chat_id = event["chatId"]

        self._markdown_v2_escape_set = {
            "_",
            "*",
            "[",
            "]",
            "(",
            ")",
            "~",
            "`",
            ">",
            "#",
            "+",
            "-",
            "=",
            "|",
            "{",
            "}",
            ".",
            "!",
        }

    def escape_markdown_v2(self, string):
        return "".join(
            [f"\\{ch}" if ch in self._markdown_v2_escape_set else ch for ch in string]
        )

    def send_message(self, text, parse_mode=None):
        url = f"{self._bot_api_url}/sendMessage"
        data = {"chat_id": self._chat_id, "text": text}

        if parse_mode is not None:
            data["parse_mode"] = parse_mode

        response = self._session.post(url, data)
        response.raise_for_status()
        return response

def send_invalid_command_message(event):
    telegram = Telegram(event)
    telegram.send_message("Please send a valid command.")

def send_help_message(event):
    telegram = Telegram(event)

    text = telegram.escape_markdown_v2(
        f"""I can help you access George's cloud-compatible side projects.

You can control me by sending these commands:

*Epic Games Store*
{Command.SUBSCRIBE_EPIC_GAMES_STORE_OFFERS.description}
{Command.UNSUBSCRIBE_EPIC_GAMES_STORE_OFFERS.description}

*Kijiji*
{Command.MY_KIJIJI_REPOST_EVENT.description}
{Command.SET_KIJIJI_REPOST_EVENT.description}
{Command.DELETE_KIJIJI_REPOST_EVENT.description}

*TextNow*
{Command.MY_TEXTNOW_MESSAGE_EVENT.description}
{Command.SET_TEXTNOW_MESSAGE_EVENT.description}
{Command.DELETE_TEXTNOW_MESSAGE_EVENT.description}"""
    )

    text = text.replace("\\*Epic Games Store\\*", "*Epic Games Store*")
    text = text.replace("\\*Kijiji\\*", "*Kijiji*")
    text = text.replace("\\*TextNow\\*", "*TextNow*")

    telegram.send_message(text, "MarkdownV2")


from matplotlib import pyplot as pit
from collections import Counter
movies = ["Энни Холл", "Бен-Гур", "Касабланка", "Ганди", "Вестсайдская история"]
num_oscars = [5, 11, 3, 8, 10]
# ширина столбцов по умолчанию 0.8, поэтому добавим 0.1 к левым
# координатам, чтобы каждый столбец был по центру интервала
#xs = [i + 0.1 for i, _ in enumerate(movies)]
xs = [i + 0.5 for i, _ in enumerate(movies)]
# построить столбцы с левыми Х-координатами [xs] и высотой [num_oscars]
pit.bar(xs, num_oscars)
pit.ylabel("Количество наград")
pit.title("Мои любимые фильмы")
# добавить метки на оси X с названиями фильмов в центре каждого интервала
pit.xticks([i + 0.5 for i, _ in enumerate(movies)], movies)
pit.show()
#Столбчатая диаграмма также хорошо подходит для построения гистограмм сгруппированных значений числового ряда, что позволяет наглядно исследовать характер распределения чисел в числовом ряду (рис. 3.3):
grades = [83, 95, 91, 87, 70, 0, 85, 82, 100, 67, 73, 77, 0]
decile = lambda grade: grade // 10 * 10 # Дециль (десятая часть числа)
histogram = Counter(decile(grade) for grade in grades)
pit.bar([x - 0 for x in histogram.keys()],
        histogram.values(),
        8)
# сдвинуть столбец влево на 4
# высота столбца
# ширина каждого столбца 8
pit.axis ([-5, 105, 0, 5]) # ось X от -5 до 105,
pit.grid(True)
# ось Y от 0 до 5
pit.xticks([10 * i for i in range(11)]) # метки по оси X: 0, 10,..., 100
pit.xlabel("Дециль")
pit.ylabel("Число студентов")
pit.title("Распределение оценок за экзамен № 1")
pit.show()


import sys
sys.stdin = open("input_data", "r")

# merge two nodes, w and y, to a set in the citizens array
def union(x, y, citizens):
    # fins the nodes roots
    x_root = find(x, citizens)
    y_root = find(y, citizens)
    # If they have same root they are already in same set
    if x_root == y_root:
        return
    # if they are not in the same set merge the smaller set with
    # the bigger, by increasing the bigger set with the smaller sets
    # size, and set parent node in smaller set = parent node of bigger
    # set
    if citizens[x_root] > citizens[y_root]:
        citizens[y_root] += citizens[x_root]
        citizens[x_root] = y_root
    elif citizens[x_root] < citizens[y_root]:
        citizens[x_root] += citizens[y_root]
        citizens[y_root] = x_root
    # if the sets are equaly big join y_root with x_root
    else:
        citizens[x_root] += citizens[y_root]
        citizens[y_root] = x_root

# find the root_node of a set, and sets the root_node as parent for all
# the nodes in the set
def find(x, citizens):
    # if it is not already a root node
    if citizens[x] >= 0:
        # goto the nodes parent-node
        citizens[x] = find(citizens[x], citizens)
    # if it is a root node return the index
    if citizens[x] < 0:
        return x
    # if it is not a root node return the roots parent index
    else:
        return citizens[x]

def start():
    # getting test cases
    test_cases = int(input())
    # looping test_cases times
    while test_cases > 0:
        # reading N = citizens, M = couples
        N, M = [int(i) for i in input().split()]
        # creating an N-size array, to store all sets in,
        # with -1 as values. Negative values means they are root
        # nodes in the set and how many nodes that are in the set.
        # Positive value point to the element that is the root of
        # the set it is in.
        citizens = [-1] * N
        for i in range(0, M):
            x, y = [int(i) for i in input().split()]
            # merge to a previous or new set.
            union(x - 1, y - 1, citizens)
        # variable for largest group
        biggest_group = 0
        # loop through the citizens array and finding
        # the number that is the smallest as it is negative
        # for the roots of the sets
        for i in citizens:
            if i < biggest_group:
                biggest_group = i
        # if the biggest set found is -1 then there are no sets
        # with more than one node, so no groups then print 0
        if biggest_group == -1:
            print(0)
        # print the set in positive
        else:
            print(-biggest_group)
        test_cases -= 1

start()


from ..models import Company
from rest_framework.test import APITestCase

class CompanyModelTesteCase(APITestCase):

    def test___str__(self):
        company = Company.objects.create(
            company_name="Company Hero",
            trade_name="Company Hero S.A",
            cnpj="42340981000166",
            address="Rua python, 310",
        )
        self.assertEqual(company.__str__(), company.company_name)
        self.assertEqual(str(company), company.company_name)


# section11

# 파이썬 외부파일 처리
# csv : mime - text/csv

# # ex1
import csv
with open('./resource/sample1.csv', 'r', encoding='euc-kr') as f:
    reader = csv.reader(f)
    # next(reader) - csv table Header 스킵하기
    print(reader)
    print(type(reader))
    print(dir(reader))

    for c in reader:
        print(c)

# ex2 - 구분자 사용 delimiter
with open('./resource/sample2.csv', 'r', encoding='euc-kr') as f:
    reader = csv.reader(f, delimiter='|')
    # next(reader) - csv table Header 스킵하기
    print(reader)
    print(type(reader))
    print(dir(reader))

    for c in reader:
        print(c)

# 예제3 - Dict 변환
with open('./resource/sample1.csv', 'r', encoding='euc-kr') as f:
    reader = csv.DictReader(f)

    for c in reader:
        print(c)
        for k, v in c.items():
            print(k,v)
        print('-----------')

# ex4 - csv 쓰기, 한줄씩
w = [[1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15]]
with open('./resource/sample3.csv', 'w', newline='') as f:
    wt = csv.writer(f)
    for v in w:
        wt.writerow(v)

# ex5 - for문 없이 쓰기
with open('./resource/sample3.csv', 'w', newline='') as f:
    wt = csv.writer(f)
    wt.writerows(w)

# 엑셀(XSL, XLSX)
# - XSL은 이전 버전
# - 엑셀처리 라이브러리 : openpyxl, xlsxwriter, xlrd, xlwt, xlutils, ...
# - pandas를 사용한다(pandas는 openpyxl, xlrd를 사용)
# - pandas는 데이터조작과 분석을 위한 파이썬 라이브러리
# - pip install xlrd
# - pip install openpyxl
# - pip install pandas

import pandas as pd

# sheetname = '시트명' 또는 숫자, header=숫자, skiprow=숫자
xlsx = pd.read_excel('./resource/sample.xlsx', engine='openpyxl')

print(xlsx.head())
print(xlsx.tail())
print(xlsx.shape) # 행, 열의 수

# 엑셀 or CSV 다시쓰기
xlsx.to_excel('./resource/result.xlsx', index=False)
xlsx.to_csv('./resource/result.csv', index=False)


import json
from glob import glob
from tqdm import tqdm
import os

def parse_json(filepath):
    with open(filepath, 'r') as fp:
        data = json.load(fp)
    return data

class Dataset:
    def __init__(self, data_dir):
        self.data_dir = data_dir

        self.label = parse_json(data_dir + 'label.json')
        self.states = self.label['states']
        self.actions = self.label['actions']
        self.images = sorted(glob(data_dir + 'images/*.png'))

    # def __init__(self, data_dir1, data_dir2, data_dir3):
    #     data_dirs = [data_dir1, data_dir2, data_dir3]
    #     self.states = []
    #     self.actions = []
    #     self.images = []

    #     for data_dir in data_dirs:
    #         self.label = parse_json(data_dir + 'label.json')
    #         self.states.append(self.label['states'])
    #         self.actions.append(self.label['actions'])
    #         self.images.append(sorted(glob(data_dir + 'images/*.png')))

    def __len__(self):
        assert len(self.states) == len(self.actions) == len(self.images)
        return len(self.states)

    def __getitem__(self, idx):
        return {'state': self.states[idx], 'action': self.actions[idx], 'image': self.images[idx]}

class CartPoleDataset(Dataset):
    def __init__(self):
        data_dir = '../data/CartPole/'
        super().__init__(data_dir)

    def __getitem__(self, idx):
        item = super().__getitem__(idx)

        cart_pos, cart_vel, pole_angle, pole_angular_vel = item['state']
        item['state'] = {'cart_pos': cart_pos, 'cart_vel': cart_vel, 'pole_angle': pole_angle, 'pole_angular_vel': pole_angular_vel}
        item['action'] = int(item['action'])
        return item

class MountainCarDataset(Dataset):
    def __init__(self):
        data_dir = '../data/MountainCar/'
        super().__init__(data_dir)

    def __getitem__(self, idx):
        item = super().__getitem__(idx)

        car_pos, car_vel = item['state']
        item['state'] = {'car_pos': car_pos, 'car_vel': car_vel}
        item['action'] = int(item['action'])
        return item

class PendulumDataset(Dataset):
    def __init__(self):
        data_dir = '../data/Pendulum/'
        super().__init__(data_dir)

    def __getitem__(self, idx):
        item = super().__getitem__(idx)

        x, y, angular_vel = item['state'][0]
        item['state'] = {'x': x, 'y': y, 'angular_vel': angular_vel}
        item['action'] = float(item['action'])
        return item

class MergedDataset(Dataset):
    def __init__(self):
        data_dir1 = '../data/CartPole/'
        data_dir2 = '../data/MountainCar/'
        data_dir3 = '../data/Pendulum/'
        super().__init__(data_dir1, data_dir2, data_dir3)

if __name__ == '__main__':
    dataset = CartPoleDataset()
    import pdb; pdb.set_trace()


import numpy as np
import re
from tools import *
from pzl_tools import *
from pzl_solvability import *

class PuzzleBoard:

    def __init__(self):
        self.dim = -1
        self.pzl = 0
        self.slt = 0
        self.lck = 0
        self.nb_move = 0
        self.cplx_time = 0
        self.cplx_size = 0

    def addBorder(self):
        border_side = np.full(self.dim, -1, dtype=int)
        border_updown = np.full(self.dim + 2, -1, dtype=int)
        border_board = np.c_[border_side, self.pzl, border_side]
        border_board = np.r_[[border_updown], border_board, [border_updown]]
        self.pzl = border_board
        border_board = np.c_[border_side, self.slt, border_side]
        border_board = np.r_[[border_updown], border_board, [border_updown]]
        self.slt = border_board

    def delBorder(self, board):
        tmp = np.delete(board, 0, 1)
        tmp = np.delete(tmp, 0, 0)
        tmp = np.delete(tmp, self.dim, 1)
        tmp = np.delete(tmp, self.dim, 0)
        return tmp

    def parsePuzzle(self, data:str):
        lines = data.split('\n')
        x = []
        for line in lines:
            line_nb = re.search('^([\d\t ]+).*', line)
            if line_nb == None:
                continue
            for nb in re.findall('(\d+)', line_nb.group(1)):
                if self.dim == -1:
                    self.dim = int(nb)
                else:
                    x.append(int(nb))
        return x

    def checkValues(self, values:list):
        if len(values) != self.dim * self.dim:
            return False
        xcheck = np.arange(self.dim * self.dim)
        for x_val in xcheck:
            x_match = False
            for x in values:
                if x_val == x:
                    x_match = True
            if x_match == False:
                return False
        return True

    def generateSolution(self):
        values = np.arange(self.dim * self.dim)
        values = values[1:]

        solution = np.full((self.dim + 2, self.dim + 2), 0, dtype=int)
        solution[:, 0] = -1
        solution[:, -1] = -1
        solution[0, :] = -1
        solution[-1, :] = -1
        self.lck = np.copy(solution)

        x = 1
        y = 1
        dir = "→"
        for val in values:
            solution[x, y] = val
            dir = get_direction(solution, (x, y), dir)
            if dir == "→":
                y += 1
            elif dir == "↓":
                x += 1
            elif dir == "←":
                y -= 1
            elif dir == "↑":
                x -= 1

        self.slt = self.delBorder(solution)

    def generatePuzzle(self, values=None, dim=3):
        if values == None:
            self.dim = dim
            self.generateSolution()
            values = np.arange(self.dim * self.dim)
            np.random.shuffle(values)
            while not Solvability(self.dim, values, self.slt).solvable:
                np.random.shuffle(values)
        elif not self.checkValues(values):
            print('[Error] Puzzle file values')
            sys.exit(2)
        self.generateSolution()
        if not Solvability(self.dim, values, self.slt).solvable:
            print('[Error] Puzzle is not solvable')
            sys.exit(2)

        values = np.asarray(values)
        self.pzl = np.ndarray((self.dim, self.dim), buffer=values, dtype=int)

# boards = PuzzleBoard()
#
# if len(sys.argv) > 1:
#     file = readFile(sys.argv[1])
#     values = boards.parsePuzzle(file)
#     boards.generatePuzzle(values)
# else:
#     boards.dim = 3
#     boards.generatePuzzle()
#
# print(boards.pzl)


"""
Just used once to remove all html extension from scraped files.
"""

import os

path = "D:\\Code\\projects\\3380scrape\\html\\"

files = os.listdir("../html")

idx = 0
for file in files:
    try:
        os.rename(os.path.join(path, file), os.path.join(path, file[:-5]))
        idx += 1
        if idx % 100 == 0:
            print(idx)

    except:
        continue


import sys
import re

fid = sys.stdin.readlines()

def calc_sentiment(posScore, negScore):
    p = float(posScore)
    n = float(negScore)
    if p + n > .5:
        if p > n:
            return "positive"
        else:
            return "negative"
    else:
        return "neutral"

sentiment_hash = {}
for line in fid:
    if line.startswith("#"):
        continue
    else:
        split_line = line.split()
        posScore = split_line[2]
        negScore = split_line[3]
        for word in split_line[4:]:
            if re.search("[^#]+#\d+", word):
                split_word = word.split("#")
                num = split_word[1]
                word = split_word[0]
                if num == "1":
                    sentiment = calc_sentiment(posScore, negScore)
                    sentiment_hash[word] = sentiment
            else:
                break


#!/usr/bin/env python3
import sys
import os
import logging
import subprocess
import time
import random
import datetime
import time
from telegram.ext import Updater
import json
import requests
from subprocess import call
import schedule
import threading
from NoFilaBot import NoFilaBot

#Check if the given path is an absolute path
def createAbsolutePath(path):
	if not os.path.isabs(path):
		currentDir = os.path.dirname(os.path.realpath(__file__))
		path = os.path.join(currentDir, path)

	return path

#Used to run scheduled task as threads
def run_threaded(job_func):
    job_thread = threading.Thread(target=job_func)
    job_thread.start()

#Defining local parameters
all_settings_dir 	= "Settings"
local_path 			= "local_settings.json"
server_path 		= "server_settings.json"
monitored_path 		= "monitored_market.json"
logFile		 		= "NoFilaBot.log"
local_path 			= createAbsolutePath(os.path.join(all_settings_dir, local_path))
server_path 		= createAbsolutePath(os.path.join(all_settings_dir, server_path))
monitored_path 		= createAbsolutePath(os.path.join(all_settings_dir, monitored_path))
logFile 			= createAbsolutePath(logFile)

#Set logging file
#Update log file if needed
logging.basicConfig(filename=logFile,level=logging.ERROR,format='%(asctime)s %(levelname)-8s %(message)s')

#Load config
config = dict()
try:
	path = local_path
	with open(path) as json_file:
		config['local']			= json.load(json_file)
	path = server_path
	with open(path) as json_file:
		config['server'] 		= json.load(json_file)
	path = monitored_path
	with open(path) as json_file:
		config['supermarkets'] 	= json.load(json_file)
except ValueError:
	print("Cannot load settings - Invalid json ["+str(path)+"]")
	exit()
except FileNotFoundError:
	print("Cannot load settings - Setting file not found ["+str(path)+"]")
	exit()

logging.getLogger().setLevel('INFO')
nfb = NoFilaBot(config, logging)

#On boot action
if len(sys.argv) > 1 and sys.argv[1]=='systemd':
    logging.info("Started by systemd using argument: "+sys.argv[1])

#Schedule actions
schedule.every(config['local']['refresh_rate']).minutes.do(run_threaded, nfb.updateStatus)
logging.info("Update every "+str(config['local']['refresh_rate'])+" minutes")
# ~ schedule.every().minutes.do(nfb.updateStatus)

#Start bot
nfb.start()

#DELETE - FOR Debug only
run_threaded(nfb.updateStatus(disableNotify=True))
# ~ exit()

print('Bot started succesfully')
logging.info("Bot started succesfully")

while 1:
	time.sleep(1)
	schedule.run_pending()


#Longest path in DAG --- here we assumed that the graph is DAG

import numpy as np
import math

def topo_order():
	l = []
	i = 0
	while not visited[i]:
		dfs(i)
		visited[i] = 1
		l = [i] + l
		i += 1
	return l

def dfs(v):
	if visited[v]:
		return
	else:
		for j in range(len(adj_list[v])):
			dfs(adj_list[v][j][0])

if __name__ == "__main__":
	n, m = int(input().split())	# number of nodes and edges respectively
	in_deg = np.zeros(n) # contains the number of incoming edge of a vertex, a.k.a in-degree
	visited = np.zeros(n)
	adj_list = [[] for v in range(n)]
	for i in range(m):
		a, b, w = int(input().split())
		adj_list[a].append([b,w])
		in_deg[b] += 1
		edge_count[a] += 1
	topo = topo_order()
	dp = np.zeros(n) # the array that will save the states of our dynamic programming algorithm
	parent = np.zeros(n) # point to the parent with the heaviest path

	for i in range(n):
		if in_deg[topo[i]] == 0:
			dp[topo[i]] = 0
			parent[topo[i]] = -1
		else:
			for k in range(len(adj_list[topo[i]])):
				dp[adj_list[topo[i]][k]] = max(dp[topo[i]] + adj_list[topo[i]][k][1],dp[adj_list[topo[i]][k]])
				if adj_list[topo[i]][k] == dp[topo[i]] + adj_list[topo[i]][k][1]:
					parent[adj_list[topo[i]][k]] = topo[i] # save the parent with the heaviest path

	dist = -1
	flag = -1
	path = []
	for i in range(n):
		dist = max(dist, dp[i])
		if dist == dp[i]:
			flag = i

	v = flag
	while parent[v] != -1:
		path = [v] + path
		v = parent[v]

	print('Weight of the longest path', dist)
	print(path)


import datetime
from urlparse import urlparse
from urllib import unquote

from django.db import IntegrityError

from tastypie import fields
from tastypie.authentication import ApiKeyAuthentication
from tastypie.http import HttpResponse
from tastypie.resources import ModelResource
from tastypie.serializers import Serializer

from myjobs.models import User
from mysearches.helpers import validate_dotjobs_url
from mysearches.models import SavedSearch

class UserResource(ModelResource):
    searches = fields.ToManyField('myjobs.api.SavedSearchResource',
                                  'savedsearch_set')

    class Meta:
        filtering = {"email": "exact"}
        queryset = User.objects.all()
        resource_name = 'user'
        list_allowed_methods = ['get']
        detail_allowed_methods = []
        authentication = ApiKeyAuthentication()
        always_return_data = True
        serializer = Serializer(formats=['json', 'jsonp'],
                                content_types={'json': 'application/json', 'jsonp': 'text/javascript'})

    def create_response(self, request, data, response_class=HttpResponse, **response_kwargs):
        """
        Intercepts the default create_reponse(). Checks for existing user
        and creates a new user if one matching the email doesn't exist.

        Creates new JSON formatted "data" based on the success, failure,
        or error in user creation. Returns new data to the default
        create_response().

        """
        email = request.GET.get('email', '')
        if not email:
            data = {'email': 'No email provided'}
            return super(UserResource, self).create_response(request, data, response_class=HttpResponse,
                                                             **response_kwargs)

        try:
            kwargs = {'email': email,
                      'password1': request.GET.get('password', '')}
            user, created = User.objects.create_inactive_user(**kwargs)

            data = {
                'user_created': created,
                'email': email
                }
        except IntegrityError:
            data = {'email': 'That username already exists'}

        return super(UserResource, self).create_response(request, data, response_class=HttpResponse, **response_kwargs)

class SavedSearchResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user')

    class Meta:
        filtering = {"email": "exact", "url": "exact"}
        queryset = SavedSearch.objects.all()
        resource_name = 'savedsearch'
        list_allowed_methods = ['get']
        detail_allowed_methods = []
        authentication = ApiKeyAuthentication()
        always_return_data = True
        serializer = Serializer(formats=['json', 'jsonp'],
                                content_types={'json': 'application/json', 'jsonp': 'text/javascript'})

    def create_response(self, request, data, response_class=HttpResponse, **response_kwargs):
        """
        Intercepts the default create_reponse(). Checks for existing saved
        search matching the user and url. If one doesn't exist, it creates
        a new saved search with daily email and the date/time created in
        the notes.

        Creates new JSON formatted "data" based on the success, failure, or
        error in saved search creation. Returns this data to the default
        create_response().

        """

        # Confirm email was provided, and that the user exists
        email = request.GET.get('email', '')
        if not email:
            data = {'email': 'No email provided'}
            return super(SavedSearchResource, self).create_response(request, data, response_class=HttpResponse,
                                                                    **response_kwargs)
        else:
            user = User.objects.get_email_owner(email=email)
            if not user:
                data = {'email': 'No user with email %s exists' % email}
                return super(SavedSearchResource, self).create_response(request, data, response_class=HttpResponse,
                                                                        **response_kwargs)

        # Confirm that url was provided, and that it's a valid .jobs search
        url = request.GET.get('url', '')
        url = unquote(url)
        if not url:
            data = {'url': 'No .JOBS feed provided'}
            return super(SavedSearchResource, self).create_response(request, data, response_class=HttpResponse,
                                                                    **response_kwargs)
        else:
            label, feed = validate_dotjobs_url(url)
            if not (label and feed):
                data = {'url': 'This is not a valid .JOBS feed'}
                return super(SavedSearchResource, self).create_response(request, data, response_class=HttpResponse,
                                                                        **response_kwargs)

        # Create notes field noting that it was created as current date/time
        now = datetime.datetime.now().strftime('%A, %B %d, %Y %l:%M %p')
        notes = 'Saved on ' + now
        if url.find('//') == -1:
            url = 'http://' + url
        netloc = urlparse(url).netloc
        notes += ' from ' + netloc

        search_args = {'url': url,
                       'label': label,
                       'feed': feed,
                       'user': user,
                       'email': email,
                       'frequency': 'D',
                       'day_of_week': None,
                       'day_of_month': None,
                       'notes': notes}
        new_search = False

        # if there's no search for that email/user, create it
        try:
            search = SavedSearch.objects.get(user=search_args['user'],
                                             email__iexact=search_args['email'],
                                             url=search_args['url'])
        except SavedSearch.DoesNotExist:
            search = SavedSearch(**search_args)
            search.save()
            search.send_initial_email()
            new_search = True

        data = {'email': email,
                'frequency': 'D',
                'new_search': new_search}

        return super(SavedSearchResource, self).create_response(request, data, response_class=HttpResponse,
                                                                **response_kwargs)


# -*- coding:utf-8 -*

import numpy
import numpy as np

import cv2 as cv
import cv2
def showimg(img,nm="pic"):
    cv2.imshow(nm,img)
    return cv2.waitKey()

def readlines(fname):
    with open(fname) as fp:
        list=fp.readlines()
    for id, item in enumerate(list):
        list[id]=item.strip()
    return list

#@2018-12-8
def get_obj_v(fnm):
    lines=readlines(fnm)
    v=[]
    for line in lines:
        sz=line.split()

        if len(sz)>=4 and sz[0]=="v":
            v.append( [ float(x) for x in sz[1:4] ] )
        if len(sz)==4 and sz[0]=="f":
            break
    v = np.array( v ).astype(np.float32)

    #print(v.shape)
    return v

def get_obj_v_f(fnm):
    lines=readlines(fnm)
    v=[]
    f=[]
    for line in lines:
        sz=line.split()

        if len(sz)>=4 and sz[0]=="v":
            v.append( [ float(x) for x in sz[1:4] ] )

        if len(sz)==4 and sz[0]=="f":
            f.append( [ int(x) for x in sz[1:4] ] )

    v = np.array( v ).astype(np.float32)
    f = np.array( f ).astype(np.int32) - 1 #!!! 1-base to 0-base
    #p(v.shape)
    return v, f

def get_obj_v_t_f(fnm):
    lines=readlines(fnm)
    v=[]
    t=[]
    f=[]
    for line in lines:
        sz=line.split()

        if len(sz)>=4 and sz[0]=="v":
            v.append( [ float(x) for x in sz[1:4] ] )
            t.append( [ float(x) for x in sz[4:7] ] )

        if len(sz)==4 and sz[0]=="f":
            f.append( [ int(x) for x in sz[1:4] ] )

    v = np.array( v ).astype(np.float32)
    t = np.array( t ).astype(np.float32)
    f = np.array( f ).astype(np.int32) - 1 #!!! 1-base to 0-base

    return v, t, f

def save_obj(fname, vtx, face=None, tex=None, decimals=5, v_fmt=None):
    if v_fmt is not None: print("don't use v_fmt")
    vtx = vtx.reshape(-1, 3)
    if tex is not None:
        tex[tex < 0] = 0
        tex[tex > 1] = 1
        tex = tex.reshape(-1, 3)

    #num = vtx.shape[0]
    if tex is not None:
        vtx = np.hstack( (vtx, tex) )
    vtx=np.around(vtx, decimals=decimals).astype(np.str).tolist()
    with open(fname, "w") as fp:
        for vec in vtx:
            s = " ".join(vec)
            s = f"v {s}\n"
            fp.write(s)

        if face is None: return
        face=face+1
        face = face.astype(np.str).tolist()
        for f in face:
            s = " ".join(f)
            s = f"f {s}\n"
            fp.write(s)


import re

name = 'regex_sum_1223586.txt'
sum = 0

for line in open(name) :
    numbers = re.findall('[0-9]+', line)
    print(numbers)
    for num in numbers :
        realnum = float(num)
        sum = sum + realnum

print(sum)


# * coding: utf8 *

from odoo import fields, models

class DocType(models.Model):
    _name = "fhir.doctype"
    _rec_name = 'name'
    _description = "fhir.doctype"

    code = fields.Char("Codigo")
    name = fields.Char("Tipo de documento")


import pickle
import logging
import io
import spacy
logging.basicConfig(filename='data_gather_log.log', level=logging.DEBUG)

nlp = spacy.load('en_core_web_sm')

with open('definitions_from_math_world', 'rb') as fp:
    definitions = pickle.load(fp)

thefile = io.open('definitions_from_math_world_text.txt', 'w', encoding='utf-16')
for idx,item in enumerate(definitions):
    try:
        sentence = ''
        doc = nlp(item)
        for token in doc:
            sentence=sentence+" "+token.text
        thefile.write(sentence.rstrip().replace('\n',' '))
        thefile.write('\n')
    except :
        continue

print("Done")

#prime number(basic definitions)


def PatternFind(seq, subseq):
	global len_p, len_s
	if len(seq)>=len_p:
		# pos=[seq.find(item[0], pos[-1]) for item in subseq]
		pos=[seq.find(subseq[0][0])]
		for i in range(1,len(subseq)):
			pos.append(seq.find(subseq[i][0], pos[-1]+subseq[i-1][1]+1))

		if -1 in pos:
			return -1
		for i in range(1, len(pos)):
			if pos[i]-1-subseq[i-1][1]!=pos[i-1]:
				return PatternFind(seq[pos[0]+pos[i]-1-subseq[i-1][1]-pos[i-1]:], subseq) or -1
		return pos[0] + len_s-len(seq)
	else:
		return -1

s=input()
p=input()
len_s=len(s)
len_p=len(p)
pattern=[]
for word in p.split('@'):
	if pattern and word=='':
		pattern[-1][1]+=1
	else:
		pattern.append([word, len(word)])

print(PatternFind(s, pattern))


import os
import cv2
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ['CUDA_VISIBLE_DEVICES'] = '0'

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
  try:
    for gpu in gpus:
      tf.config.experimental.set_memory_growth(gpu, True)
  except RuntimeError as e:
    print(e)

class DeeplabInference():
  def __init__(self, model_path, ros_structure=False):
    self.model = tf.keras.models.load_model(model_path, custom_objects={"tf": tf})
    self.ros_structure = ros_structure
    self.imagenet_normalization = [103.939, 116.779, 123.68]
    self.mask_id_to_color = {0: (0, 0, 0),
                        1: (255, 255, 255),
                        2: (255, 0, 0),
                        3: (0, 255, 0),
                        4: (0, 0, 255)}

  def predict(self, img):
    img_process = img.copy()
    img_process[:,:,0] -= self.imagenet_normalization[0]
    img_process[:,:,1] -= self.imagenet_normalization[1]
    img_process[:,:,2] -= self.imagenet_normalization[2]
    img_process = np.expand_dims(img_process, axis=0)

    prediction = self.model.predict(img_process, verbose=0)          # Shape (batch, h, w, channels)
    prediction = np.squeeze(prediction)                              # Shape (h, w, channels)
    prediction = np.argmax(prediction, axis=2)                       # Shape (index_of_class)

    mask = img.copy()
    for i in self.mask_id_to_color:
      mask[prediction==i] = self.mask_id_to_color[i]

    if self.ros_structure:
      return mask
    else:
      self.visualize(img, mask)

  def visualize(self, img, mask):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img_with_mask = img.copy()
    cv2.addWeighted(src1=img, alpha=0.5, src2=mask, beta=0.5, gamma=0, dst=img_with_mask)

    fig = plt.figure(figsize = (10,10))
    axs = np.zeros(3, dtype=object)
    gs = fig.add_gridspec(4, 4, wspace=0.5)
    axs[0] = fig.add_subplot(gs[0:2,1:3])
    axs[1] = fig.add_subplot(gs[2:4,0:2])
    axs[2] = fig.add_subplot(gs[2:4,2:4])

    axs[0].imshow(img_with_mask/255)
    axs[0].set_title('Original image with predicted mask')
    axs[1].imshow(img/255)
    axs[1].set_title('Original image')
    axs[2].imshow(mask/255)
    axs[2].set_title('Predicted mask')
    plt.show(block=False)


from scipy import ndimage
import glob
import numpy as np
from sklearn.model_selection import train_test_split
from PIL import Image
from random import shuffle
from keras.callbacks import EarlyStopping

def check_predictions(predictions, indices_test):

	import matplotlib.pyplot as plt
	import matplotlib.image as mpimg

	with open("box_coordinates.csv") as f:
	    photos = f.readlines()

	for i,index in enumerate(indices_test):
	    title = photos[index].split(',')[0]
	    img = mpimg.imread("data/BioID/"+title)
	    simgplot = plt.imshow(img)
	    x_coords = predictions[i][0::2]
	    y_coords = predictions[i][1::2]
	    plt.plot(x_coords, y_coords)
	    plt.show()

from keras.models import Sequential, Model
from keras.layers import Input, Convolution2D, Flatten, MaxPooling2D
from keras.layers.core import Dense, Activation

print("Compiling model...")

model = Sequential()
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(288, 360, 3)))
model.add(MaxPooling2D((8,8)))
model.add(Convolution2D(16, 3, 3, border_mode='same'))
model.add(MaxPooling2D((4,4)))
model.add(Convolution2D(32, 3, 3, border_mode='same'))
model.add(MaxPooling2D((2,2)))
model.add(Flatten())
model.add(Dense(4))
model.summary()

model.compile(loss='mse', optimizer='rmsprop')

X = []
y = []

with open("dlib/box_coordinates.csv") as f:
    c = 0
    lines = f.readlines()
    shuffle(lines)
    for line in lines[:20000]:
        c += 1
        print(" ", "{0:.2f}".format(100*float(c)/3000), end="\r")
        data = line.split(",")

        if not "Left" in data[0] and not "Right" in data[0]:
            y.append(np.asarray([float(x) for x in data[1:]]))
            img = Image.open("videos/"+data[0])
            img = img.resize((360, 288), Image.ANTIALIAS)
            img = np.asarray(img)
            X.append(img)
            # print(data, "HWAT")

print(len(X))
indices = range(len(X))
print("Splitting data..")
X_train, X_test, y_train, y_test, indices_train, indices_test = train_test_split(X, y, indices, test_size=0.15, random_state=37)

X_train = np.asarray(X_train)
y_train = np.asarray(y_train)

X_test = np.asarray(X_test)
y_test = np.asarray(y_test)

print("Fitting the data...")

early_stopping = EarlyStopping(monitor='val_loss', patience=2)

model.fit(X_train, y_train, nb_epoch=10, batch_size=20, verbose=1, callbacks=[early_stopping], validation_split=0.1)
np.set_printoptions(threshold=np.nan)
pred = model.predict(X_test, batch_size = 16, verbose=1)

check_predictions(pred, indices_test)


import re

# 사전 파일 경로
dict_file = 'input/ejdict-hand-utf8.txt'

# 반복하여 실행 --- (1)
while True:
    # 정규식 입력 받기 --- (2)
    print('정규식을 입력해주세요. (q 입력시 종료)')
    re_str = input()
    if re_str == '': continue
    if re_str == 'q': break
    # 영어 사전에서 정규 표현에 대응하는 단어 검색 --- (3)
    with open(dict_file, 'rt', encoding='utf-8') as f:  #--- (3a)
        cnt = 0
        while True: #--- (3b)
            # 한 행 읽기
            line = f.readline()
            if not line: break #--- (3c)
            # 영단어 얻기
            word, mean = line.split('\t')
            # 정규식 매치 --- (4)
            if re.search(re_str, word):
                print(word) # 매치하면 출력
                cnt += 1
                if cnt > 50: break # 최대 50건