from abc import abstractmethod
from abc import ABCMeta
from PIL import Image
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from cftool.misc import shallow_copy_dict
from cftool.data_structures import Workflow

from cfdraw import constants
from cfdraw.utils import server
from cfdraw.utils.misc import offload_run
from cfdraw.schema.plugins import *
from cfdraw.plugins.middlewares import *
from cfdraw.parsers.noli import SingleNodeType
from cfdraw.app.endpoints.upload import ImageUploader
from cfdraw.app.endpoints.upload import FetchImageModel

class ISocketPlugin(IPlugin, metaclass=ABCMeta):
    @abstractmethod
    async def process(self, data: ISocketRequest) -> Any:
        pass

    # internal APIs

    @property
    def middlewares(self) -> List[IMiddleware]:
        return [
            ResponseMiddleware(self),
            TimerMiddleware(self),
            SendSocketMessageMiddleware(self),
        ]

    async def __call__(self, data: ISocketRequest) -> None:
        self.injections = {}
        self.extra_responses = {}
        middlewares = self.middlewares
        for middleware in middlewares:
            await middleware.before(data)
        response = await self.process(data)
        for middleware in middlewares:
            response = await middleware(response)

    def to_react(self) -> Dict[str, Any]:
        return self.settings.to_react(
            self.type,
            self.hash,
            hash_identifier(self.hash, self.identifier),
        )

    # helper methods

    def filter(self, nodes: List[INodeData], target: SingleNodeType) -> List[INodeData]:
        return list(filter(lambda node: node.type == target, nodes))

    async def load_image(self, src: str) -> Image.Image:
        # check whether the incoming url refers to a local image
        # if so, load it from the local file system directly
        if src.startswith("http://") and constants.UPLOAD_IMAGE_FOLDER_NAME in src:
            file = src.split(constants.UPLOAD_IMAGE_FOLDER_NAME)[1][1:]  # remove '/'
            return server.get_image(file)
        data = FetchImageModel(url=src, jpeg=False, return_image=True)
        return await ImageUploader.fetch_image(data)

    def send_progress(
        self,
        progress: Optional[float] = None,
        *,
        textList: Optional[List[str]] = None,
        imageList: Optional[List[str]] = None,
    ) -> bool:
        if textList is None and imageList is None:
            intermediate = None
        else:
            intermediate = ISocketIntermediate(textList=textList, imageList=imageList)
        message = ISocketMessage.make_progress(self.task_hash, progress, intermediate)
        return offload_run(self.send_message(message))

    def send_exception(self, message: str) -> bool:
        message = ISocketMessage.make_exception(self.task_hash, message)
        return offload_run(self.send_message(message))

    def set_extra_response(self, key: str, value: Any) -> None:
        self.extra_responses[key] = value

    def set_workflow(self, workflow: Workflow) -> None:
        self.set_extra_response(constants.WORKFLOW_KEY, workflow.to_json())

    def set_injection(self, key: str, node: INodeData) -> None:
        self.injections[key] = dict(
            node=shallow_copy_dict(node.dict()),
            bboxFields=None if node.transform is None else node.transform.dict(),
        )

class IInternalSocketPlugin(ISocketPlugin, metaclass=ABCMeta):
    @property
    def type(self) -> PluginType:
        return PluginType._INTERNAL

    @property
    def settings(self) -> IPluginSettings:
        return IPluginSettings(w=1, h=1)

__all__ = [
    "ISocketPlugin",
    "IInternalSocketPlugin",
]


import json
from database.config import connectionDB

def getEdif():
    conn = connectionDB()
    cur = conn.cursor()

    sql_cur = "SELECT desed_codigo, desed_codigopadre, desed_descripcion FROM desc_edificacion WHERE desed_estado = 'A' AND (desed_codigo LIKE '02%' OR desed_codigo LIKE '03%' OR desed_codigo LIKE '04%') ORDER BY desed_codigo;"

    cur.execute(sql_cur)

    row_cur = cur.fetchall()

    desed_codigo           = [ row[0] for row in row_cur ]
    desed_codigopadre      = [ row[1] for row in row_cur ]
    desed_descripcion      = [ row[2] for row in row_cur ]

    dic_desed_codigo       = { "desed_codigo"       : [str(desed_codigo[i])         for i in range(len( desed_codigo ))] }
    dic_desed_codigopadre  = { "desed_codigopadre"  : [str(desed_codigopadre[i])    for i in range(len( desed_codigopadre ))]  }
    dic_desed_descripcion  = { "desed_descripcion"  : [str(desed_descripcion[i])    for i in range(len( desed_descripcion ))]  }

    cur.close()
    conn.close()

    return json.dumps((dic_desed_codigo,
                            dic_desed_codigopadre,
                            dic_desed_descripcion), indent=4)

def getEdifPredioCod(claveCata):

    conn = connectionDB()
    cur = conn.cursor()

    sql_cur = "select bp.pre_codigocatastral,bp.blopr_numero,bp.blopr_numpiso from bloques_predio bp where bp.pre_codigocatastral = '" +claveCata+"' order by bp.blopr_numero,blopr_numpiso;"

    cur.execute(sql_cur)

    data_sql_cur = cur.fetchall()
    conn.commit()
    pre_codigocatastral = []
    blopr_numero        = []
    blopr_numpiso       = []
    desed_codigo        = []

    for row in data_sql_cur:
        sql_cur_bloq = "SELECT desed_codigo FROM desc_edif_bloque WHERE pre_codigocatastral = '" + row[0] + "' AND blopr_numero = " + str(row[1]) + " AND blopr_numpiso = " + str(row[2])+ " AND desed_codigo IN(SELECT desed_codigo FROM desc_edificacion WHERE desed_estado = 'A') AND (desed_codigo LIKE '02%' OR desed_codigo LIKE '03%' OR desed_codigo LIKE '04%') ORDER BY desed_codigo;"

        cur.execute(sql_cur_bloq)

        data_sql_cur_bloq = cur.fetchall()
        conn.commit()
        pre_codigocatastral.append(row[0])
        blopr_numero.append(row[1])
        blopr_numpiso.append(row[2])
        desed_codigo_data = [ rows[0] for rows in data_sql_cur_bloq]
        desed_codigo.append(desed_codigo_data)

    pre_codigocatastral = { 'pre_codigocatastral':[str(pre_codigocatastral[i]) for i in range(len(pre_codigocatastral))] }
    blopr_numero        = { 'blopr_numero':[str(blopr_numero[i]) for i in range(len(blopr_numero))]}
    blopr_numpiso       = { 'blopr_numpiso':[str(blopr_numpiso[i]) for i in range(len(blopr_numpiso))]}
    desed_codigo        = { 'desed_codigo':[desed_codigo[i] for i in range(len(desed_codigo))]}

    json_data = json.dumps((pre_codigocatastral,
                            blopr_numero,
                            blopr_numpiso,
                            desed_codigo),indent=4)
    cur.close()
    conn.close()

    return json_data

def getEdifPreBloqPiso(numClaveCata,numBloqCata,numBloqPisoCata,numsBloqPiso,numDesedCodigo,condicion):
    conn = connectionDB()
    cur = conn.cursor()

    if condicion == None:
        condicion = ''

    for i in numsBloqPiso:

        if i[1]=='-':
            sql_delete ="DELETE FROM desc_edif_bloque  WHERE pre_codigocatastral = '" + numClaveCata + "'  AND blopr_numero = " + i[0]+ " AND blopr_numpiso = " + i[2:] +" AND desed_codigo LIKE '"+condicion+"%';"
            cur.execute(sql_delete)
            conn.commit()

        elif i[2] =='-':
            print(i[0:1],'-',i[3:])
            sql_delete ="DELETE FROM desc_edif_bloque  WHERE pre_codigocatastral = '" + numClaveCata + "'  AND blopr_numero = " + i[0]+ " AND blopr_numpiso = " + i[2:] +"AND  desed_codigo LIKE '"+condicion+"%';"
            cur.execute(sql_delete)
            conn.commit()

    for i in range(len(numBloqCata)):
        sql_insert = "INSERT INTO desc_edif_bloque (pre_codigocatastral, blopr_numero, blopr_numpiso, desed_codigo) VALUES('" + numClaveCata + "', " + numBloqCata[i] + "," + numBloqPisoCata[i] + ",'" + numDesedCodigo[i] + "');"
        cur.execute(sql_insert)
        conn.commit()

    cur.close()
    conn.close()

    return 'ok'


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from core.ezrael import Ezrael

import threading
import logging
import logging.config
import getopt
import time
import sys

def usage():
    print('Usage: python ezrael.py [-h]\n\n'
          '-h\tShows this help'
          '-v\tVersion of ezrael'
          '-d\tTurn on debugging')

def main(argv):
    debugging = False

    try:
        opts, args = getopt.getopt(argv, "hvd", ["help", "version", "debug"])
    except getopt.GetoptError as err:
        # Print usage information and exit.
        print(err)
        usage()
        sys.exit(2)

    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(1)
        elif o in ("-v", "--version"):
            print("Version 0.1")
            sys.exit(1)
        elif o in ("-d", "--debug"):
            debugging = True
        else:
            assert False, "unhandled option"

    # Inititalize the logging api ...
    logging.config.fileConfig('config/logging.conf')

    # ... and fetch a logger.
    if debugging:
        logger = logging.getLogger('development')
    else:
        logger = logging.getLogger('production')

    try:
        # Initialize the irc bot, ...
        ezrael = Ezrael(debugging)

        # ... bind the connect method of ezrael to a thread, ...
        ezrael_thread = threading.Thread(None, ezrael.connect)

        # ... make this thread a daemon thread ...
        ezrael_thread.setDaemon(True)

        # ... and start the IRC bot.
        ezrael_thread.start()

        # Enter a loop if you should try to reconnect.
        while ezrael.shouldReconnect:
            time.sleep(5)
    finally:
        logger.info('Ezrael stopped ...')

if __name__ == "__main__":
    main(sys.argv[1:])


import torch
import torchvision
from torch import nn
from torch import optim
import torch.nn.functional as F
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.utils import save_image
from torchvision.datasets import MNIST
import os

#reconstruction_function = nn.MSELoss(size_average=False)
'''
reconstruction_function = nn.MSELoss(size_average=None, reduce=None, reduction='sum')

def loss_function(recon_x, x, mu, logvar):
    """
    recon_x: generating images
    x: origin images
    mu: latent mean
    logvar: latent log variance
    """
    BCE = reconstruction_function(recon_x, x)  # mse loss
    # loss = 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
    KLD_element = mu.pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
    KLD = torch.sum(KLD_element).mul_(-0.5)
    # KL divergence
    return BCE + KLD
'''

def reparameterize(mu, logvar):
    std = logvar.mul(0.5).exp_()
    eps = torch.cuda.FloatTensor(std.size()).normal_()
    return eps.mul(std).add_(mu)

def kl_loss(mu, logvar, prior_mu=0):
    v_kl = mu.add(-prior_mu).pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
    v_kl = v_kl.sum(dim=-1).mul_(-0.5)  # (batch, 2)
    return v_kl

def reconstruction_loss(prediction, target, size_average=False):
    error = (prediction - target).view(prediction.size(0), -1)
    error = error ** 2
    error = torch.sum(error, dim=-1)

    if size_average:
        error = error.mean()
    else:
        error = error.sum()
    return error

def ort_loss(x, y):
    loss = torch.abs((x * y).sum(dim=1)).sum()
    loss = loss / float(x.size(0))
    return loss

def ang_loss(x, y):
    loss = (x * y).sum(dim=1).sum()
    loss = loss / float(x.size(0))
    return loss

def rgb2gray(img):
    r, g, b = torch.split(img, 1, dim=1)
    return torch.mul(r, 0.299) + torch.mul(g, 0.587) + torch.mul(b, 0.114)

def save_checkpoint(model, epoch, name=""):
    if not os.path.exists("model/"):
        os.makedirs("model/")
    model_path = "model/" + name + "_epoch_{}.pth.tar".format(epoch)
    state = {"epoch": epoch, "state_dict": model.state_dict()}
    torch.save(state, model_path)
    print("checkpoint saved to {}".format(model_path))

def load_model(model, pretrained):
    weights = torch.load(pretrained)
    pretrained_dict = weights["state_dict"]
    model_dict = model.state_dict()
    # 1. filter out unnecessary keys
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
    # 2. overwrite entries in the existing state dict
    model_dict.update(pretrained_dict)
    # 3. load the new state dict
    model.load_state_dict(model_dict)

def set_requires_grad(nets, requires_grad=False):
    if not isinstance(nets, list):
        nets = [nets]
    for net in nets:
        if net is not None:
            for param in net.parameters():
                param.requires_grad = requires_grad

# assign adain_params to AdaIN layers
def assign_adain_params(adain_params, model):
    for m in model.modules():
        if m.__class__.__name__ == "AdaptiveInstanceNorm2d":
            mean = adain_params[:, :m.num_features]
            std = adain_params[:, m.num_features:2*m.num_features]
            m.bias = mean.contiguous().view(-1)
            m.weight = std.contiguous().view(-1)
            if adain_params.size(1) > 2*m.num_features:
                adain_params = adain_params[:, 2*m.num_features:]

def accuracy(output, target, topk=(1,)):
    maxk = max(topk)
    batch_size = target.size(0)

    _, pred = output.topk(maxk, 1, True, True)
    pred = pred.t()
    correct = pred.eq(target.view(1, -1).expand_as(pred))

    res = []
    for k in topk:
        correct_k = correct[:k].view(-1).float().sum(0)
        res.append(correct_k.mul_(100.0 / batch_size))
    return res

def adjust_learning_rate(lr, step, optimizer, epoch):
    scale = 0.457305051927326
    lr = lr * (scale ** (epoch // step))
    print('lr: {}'.format(lr))
    if (epoch != 0) & (epoch % step == 0):
        print('Change lr')
        for param_group in optimizer.param_groups:
            param_group['lr'] = param_group['lr'] * scale

class AverageMeter(object):
    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count


# coding: utf-8

# Computer the posterior probability on a regular grid in the input space

# In[1]:

import numpy as np
from scipy.stats import multivariate_normal
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import sklearn
import sklearn.linear_model
import matplotlib
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score

# In[12]:

n = 100

Y1 = np.random.multivariate_normal([0, 3], [[2, 1], [1, 2]], 100)
Y2 = np.random.multivariate_normal([2, 1], [[1, 0], [0, 1]], 100)

plt.scatter(Y1[:, 0], Y1[:, 1],marker='x',c='b')
plt.scatter(Y2[:, 0], Y2[:, 1],marker='*',c='r')

plt.axis('square')
plt.savefig("sample.png", dpi = 600)
plt.show()

inputSet = np.vstack((Y1, Y2))#combine input data
outputSet = np.vstack((np.ones((n, 1)), (0) * (np.ones((n, 1)))))#genereate class output

i = np.random.permutation(2 * n)#disorganize

dataSet = np.hstack((inputSet[i[0:n * 2]], outputSet[i[0:n * 2]]))
np.savetxt('dataSet.csv', dataSet, delimiter=",")

rData = np.hsplit(dataSet, (2, 3))

inputTrainSet = rData[0].copy()

outputTrainSet = rData[1].copy()

np.savetxt('input.csv', inputTrainSet, delimiter=",")
np.savetxt('output.csv', outputTrainSet, delimiter=",")

# In[13]:

outputTrainSet = np.ravel((outputTrainSet));#become 1-dimentional data
outputTrainSet = np.int_(outputTrainSet);
clf = GaussianNB()#instantiation
clf.fit(inputTrainSet,outputTrainSet)#input data

# In[103]:

def plot_decision_boundary(pred_func):
    # Set min and max values and give it some padding
    x_min, x_max = inputTrainSet[:, 0].min() - .5, inputTrainSet[:, 0].max() + .5
    y_min, y_max = inputTrainSet[:, 1].min() - .5, inputTrainSet[:, 1].max() + .5
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole gid
    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    predictOutputset = pred_func(inputTrainSet)
    print(accuracy_score(outputTrainSet, predictOutputset, normalize =True))
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(inputTrainSet[:, 0], inputTrainSet[:, 1], c=outputTrainSet, cmap=plt.cm.coolwarm)
    plt.annotate('m1,c1', xy=(-3.3, 6), xytext=(-2.9, 6),
            arrowprops=dict(facecolor='red', shrink=0.005),
            )
plt.annotate('m2,c2', xy=(-3.3, 5.5), xytext=(-2.9, 5.5),
            arrowprops=dict(facecolor='blue', shrink=0.005),
            )
    #plt.colorbar()

# In[62]:

plot_decision_boundary(lambda x: clf.predict(x))
plt.title("Naive Bayes-Decision Boundary")
plt.annotate('m1,c1', xy=(-3.3, 6), xytext=(-2.9, 6),
            arrowprops=dict(facecolor='red', shrink=0.005),
            )
plt.annotate('m2,c2', xy=(-3.3, 5.5), xytext=(-2.9, 5.5),
            arrowprops=dict(facecolor='blue', shrink=0.005),
            )
plt.savefig("Decision Boundary of Naive_Bayes.png", dpi = 600)
plt.show()

# In[97]:

x, y = np.mgrid[-6:6:.1, -6:6:.1]
pos = np.dstack((x, y))

rv1 = multivariate_normal.pdf(pos, [0, 3], [[2, 1], [1, 2]])
rv2 = multivariate_normal.pdf(pos, [2, 1], [[1, 0], [0, 1]])

posterior_probability = 1 / (1 + (rv2 / rv1))

fig1 = plt.figure()
ax = Axes3D(fig1)
ax.plot_surface(
    x, y, posterior_probability, rstride=1, cstride=1, cmap='rainbow')#span=1
ax.set_zlabel("Probability")
ax.set_ylabel('Y')
ax.set_xlabel('X')
ax.contourf(x, y, posterior_probability, zdir='xz', offset=-0.01, cmap=plt.get_cmap('rainbow'))
plt.title("3D and projection of posterior probability")
plt.savefig("3DandProOfPosterior.png", dpi = 600)
plt.show()

# Training a Neural Network

# In[98]:

num_examples = len(inputTrainSet) # training set size
nn_input_dim = 2 # input layer dimensionality
nn_output_dim = 2 # output layer dimensionality

# Gradient descent parameters (I picked these by hand)
epsilon = 0.01 # learning rate for gradient descent
reg_lambda = 0.01 # regularization strength

# In[99]:

def calculate_loss(model):
    W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']
    # Forward propagation to calculate our predictions
    z1 = inputTrainSet.dot(W1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(W2) + b2
    exp_scores = np.exp(z2)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    # Calculating the loss
    corect_logprobs = -np.log(probs[range(num_examples), outputTrainSet])
    data_loss = np.sum(corect_logprobs)
    # Add regulatization term to loss (optional)
    data_loss += reg_lambda/2 * (np.sum(np.square(W1)) + np.sum(np.square(W2)))
    return 1./num_examples * data_loss

# In[100]:

def predict(model, x):
    W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']
    # Forward propagation
    z1 = x.dot(W1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(W2) + b2
    exp_scores = np.exp(z2)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    return np.argmax(probs, axis=1)

# In[101]:

def build_model(nn_hdim, num_passes=20000, print_loss=False):

    # Initialize the parameters to random values. We need to learn these.
    np.random.seed(0)
    W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)
    b1 = np.zeros((1, nn_hdim))
    W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)
    b2 = np.zeros((1, nn_output_dim))

    # This is what we return at the end
    model = {}

    # Gradient descent. For each batch...
    for i in range(0, num_passes):

        # Forward propagation
        z1 = inputTrainSet.dot(W1) + b1
        a1 = np.tanh(z1)
        z2 = a1.dot(W2) + b2
        exp_scores = np.exp(z2)
        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)

        # Backpropagation
        delta3 = probs
        delta3[range(num_examples), outputTrainSet] -= 1
        dW2 = (a1.T).dot(delta3)
        db2 = np.sum(delta3, axis=0, keepdims=True)
        delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))
        dW1 = np.dot(inputTrainSet.T, delta2)
        db1 = np.sum(delta2, axis=0)

        # Add regularization terms (b1 and b2 don't have regularization terms)
        dW2 += reg_lambda * W2
        dW1 += reg_lambda * W1

        # Gradient descent parameter update
        W1 += -epsilon * dW1
        b1 += -epsilon * db1
        W2 += -epsilon * dW2
        b2 += -epsilon * db2

        # Assign new parameters to the model
        model = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}

        # Optionally print the loss.
        # This is expensive because it uses the whole dataset, so we don't want to do it too often.
        if print_loss and i % 1000 == 0:
          print("Loss after iteration %i: %f" %(i, calculate_loss(model)))

    return model

# In[104]:

# Build a model with a 3-dimensional hidden layer
model = build_model(3, print_loss=True)

# Plot the decision boundary
plot_decision_boundary(lambda x: predict(model, x))
plt.title("3 hidden layer-Decision Boundary")
plt.savefig("Decision Boundary for hidden layer size 3.png", dpi = 600)
plt.show()

# In[113]:

plt.figure(figsize=(14, 12))
hidden_layer_dimensions = [1,10,20,40]
for i, nn_hdim in enumerate(hidden_layer_dimensions):
    plt.subplot(3, 2, i+1)
    plt.title('%d-Hidden layer-Decision Boundary' % nn_hdim)
    model = build_model(nn_hdim)
    plot_decision_boundary(lambda x: predict(model, x))
    plt.annotate('m2,c2', xy=(-3.3, 5.4), xytext=(-2.9, 5.4),
            arrowprops=dict(facecolor='blue', shrink=0.005),
            )
plt.savefig("Decision Boundary for Neural Network.png", dpi = 600)
plt.show()

# In[114]:

# Build a model with a 3-dimensional hidden layer
model = build_model(40, print_loss=True)

# Plot the decision boundary
plot_decision_boundary(lambda x: predict(model, x))
plt.title("40 hidden layer-Decision Boundary")
plt.annotate('m2,c2', xy=(-3.3, 5.4), xytext=(-2.9, 5.4),
            arrowprops=dict(facecolor='blue', shrink=0.005),
            )
plt.savefig("Decision Boundary for hidden layer size 40.png", dpi = 600)
plt.show()

# In[ ]:


import json
import logging

def handler(event, context):
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    logger.info("request: " + json.dumps(event))

    for record in event["Records"]:
        payload = record["body"]
        logger.info("received message " + payload)


import unittest

from mock import patch
from test_utils import GetExpectedPrintOutput
from tokens_api_test_base import TokensApiPrintTokensTestBase
from utils.admin_api_tool_errors import AdminAPIToolTokenRequestError

_USER_ID = '0'  # Stub user_id.

# PyLint dislikes the method names Python unittest prefers (testXXX).
# pylint: disable=g-bad-name

@patch('admin_sdk_directory_api.tokens_api.TokensApiWrapper.ListTokens')
class TokensApiPrintTokensForUserWithTokenErrorTest(
    TokensApiPrintTokensTestBase):
  """Wrapper to test token print code with just user supplied."""

  def testPrintTokensForUserWithTokenDocEmptyRaisesError(
      self, mock_list_tokens_request_fn):
    mock_list_tokens_request_fn.return_value = {}
    self.assertRaises(
        AdminAPIToolTokenRequestError,
        self._tokens_api.PrintTokensForUser, _USER_ID, long_list=False)

  def testPrintNoTokensFoundMessageForWhenTokenDocNoItemsError(
      self, mock_list_tokens_request_fn):
    mock_list_tokens_request_fn.return_value = {'unexpected': 'notempty'}
    self._tokens_api.PrintTokensForUser(_USER_ID, long_list=True)
    self.assertEqual(GetExpectedPrintOutput('PrintTokensForUser.3'),
                     self._new_stdout.print_messages)

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


import math
import numpy as np
import scipy.constants
from sympy import nsolve, Symbol, cot, sqrt, re
import hole_calculations

def calculate(m, a, omega_a, n):
    ka = Symbol('ka')
    even_eq = ka * cot(ka) + omega_a

    even_kas = np.sort(np.abs(hole_calculations.find_roots(ka, even_eq)))[:int(n/2)]
    odd_kas = np.arange(1, n+1, 2) * math.pi
    if omega_a > 28:
        even_kas = np.arange(1, n+1, 2) * math.pi

    even_ks = even_kas / a
    odd_ks = odd_kas / a

    omega = omega_a / a

    xs = np.linspace(-a, a, 100000)
    eps = xs[1] - xs[0]
    khi = math.sqrt(omega / eps)

    odd_xs = np.copy(xs)
    for i in range(int(len(odd_xs) / 2), len(odd_xs)):
        if odd_xs[i] > 0:
            odd_xs[i] -= 2 * a

    us = list()
    for k in odd_ks:
        A = math.sqrt(1 / a)
        us.append(A * np.sin(k * (odd_xs + a)))

    for k in even_ks:
        A = math.sqrt(2 * k / (2 * k * a - math.sin(2 * k * a)))
        B = (A * math.sin(k * (a - eps))) / (math.exp(khi * eps) + math.exp(-khi * eps))
        tmp = np.zeros(len(xs))
        for i in range(0, len(tmp)):
            if xs[i] < -eps:
                tmp[i] = A * math.sin(k * (xs[i] + a))
            if -eps <= xs[i] <= eps:
                tmp[i] = B * (math.exp(khi * xs[i]) + math.exp(-khi * xs[i]))
            if xs[i] > eps:
                tmp[i] = -A * math.sin(k * (xs[i] - a))
        us.append(tmp)

    return xs, us


from __future__ import division

import io
import random
import threading
import time

from picamera import PiCamera
from PIL import Image
import numpy as np

class Pivideo(object):
    def __init__(self, update_rate=15, debug=False):
        self.debug = debug

        self.update_rate = update_rate  # secs

        self.brightness = 0
        self.variance = 0
        self.rbratio = 0

        self.update()

    def update(self):
        start_time = time.time()
        stream = io.BytesIO()

        with PiCamera() as camera:
            camera.resolution = (640, 480)
            camera.capture(stream, format='jpeg', use_video_port=True,
                           quality=20)

        # Open image
        stream.seek(0)
        image = Image.open(stream)

        # Separate out RGB channels
        rdat = image.getdata(0)
        gdat = image.getdata(1)
        bdat = image.getdata(2)

        # Average RGB channels individually
        sample_size = 1000
        ravg = np.median(random.sample(rdat, sample_size))
        gavg = np.median(random.sample(gdat, sample_size))
        bavg = np.median(random.sample(bdat, sample_size))
        rgb = [ravg, gavg, bavg]

        self.brightness = (np.mean(rgb) * (100 / 125)) - 50

        rscaled = (ravg + 1) * (100 / 125)
        bscaled = (bavg + 1) * (100 / 125)
        self.rbratio = rscaled / bscaled

        histo = image.histogram()
        self.variance = 1e8 / np.var(histo) - 35

        stream.close()

        if self.debug:
            msg = ['Pivideo update',
                   "Brightness: {}".format(self.brightness),
                   "Variance: {}".format(self.variance),
                   "RB Ratio: {}".format(self.rbratio),
                   '']
            print('\n'.join(msg))

        remaining = self.update_rate - (time.time() - start_time)
        threading.Timer(remaining, self.update)

    @property
    def energy(self):
        return int(self.rbratio)

    @property
    def get_disposition(self):
        return int(self.brightness)

    @property
    def get_chaos(self):
        return int(self.variance)


'''
When users post an update on social media,such as a URL, image, status update etc., other users in their network are able to view this new post on their news feed.
Users can also see exactly when the post was published, i.e, how many hours, minutes or seconds ago.

Since sometimes posts are published and viewed in different time zones, this can be confusing. You are given two timestamps
of one such post that a user can see on his newsfeed in the following format:

Day dd Mon yyyy hh:mm:ss +xxxx

Here +xxxx represents the time zone. Your task is to print the absolute difference (in seconds) between them.

Input Format

The first line contains T , the number of testcases.
Each testcase contains 2 lines, representing time t1 and time t2.

Constraints
year<=3000

Input contains only valid timestamps
.
Output Format

Print the absolute difference (t2-t1) in seconds.

Sample Input 0

2
Sun 10 May 2015 13:54:36 -0700
Sun 10 May 2015 13:54:36 -0000
Sat 02 May 2015 19:54:36 +0530
Fri 01 May 2015 13:54:36 -0000
Sample Output 0

25200
88200

'''

#!/bin/python3

import math
import os
import random
import re
import sys
from datetime import datetime  as dt

# Complete the time_delta function below.
def time_delta(t1, t2):
    format1="%a %d %b %Y %H:%M:%S %z"
    t=dt.strptime(t1,format1)
    d=dt.strptime(t2,format1)
    val=(t-d)
    result=abs(int(val.total_seconds()))
    return str(result)
    print(result)

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    t = int(input())

    for t_itr in range(t):
        t1 = input()

        t2 = input()

        delta = time_delta(t1, t2)

        fptr.write(delta + '\n')

    fptr.close()


"""
author: @虫师
date: 2022-03-20
function: 分页器
"""
from django.http import HttpRequest
from django.db.models import QuerySet
from ninja.pagination import PaginationBase
from ninja import Field, Schema
from ninja.conf import settings
from ninja.types import DictStrAny
from .common import response

class CustomPagination(PaginationBase):
    """
    自定义分页器
    """
    class Input(Schema):
        page: int = Field(1, gt=0)
        size: int = 6

    class Output(Schema):
        success: bool = True
        code: dict = {"code": "", "msg": ""}
        total: int
        page: int
        size: int

    def paginate_queryset(self, queryset: QuerySet, pagination: Input, **params):
        page: int = pagination.page
        size: int = pagination.size
        offset = (page - 1) * size
        data = {
            "items": queryset[offset: offset + size],
            "total": len(queryset),
            "page": page,
            "size": size
        }
        return data


from tkinter import *
import googletrans
import textblob
from tkinter import  ttk, messagebox

def Translater():
     for key, value in languages.items():
         if (value == choice_language_origen.get()):
             from_languege_key = key

     for key, value in languages.items():
        if (value == choice_language_Translater.get()):
            to_languege_key = key

     words = textblob.TextBlob(texto.get(1.0,END))
     words = words.translate(from_lang=from_languege_key,to=to_languege_key)
     Traducion.insert(1.0,words)

def Clear():
    texto.delete(1.0,END)
    Traducion.delete(1.0,END)
languages =  googletrans.LANGUAGES

lang_list = list(languages.values())

root = Tk()
root.title('Tradutor')
root.geometry('600x400')

texto =  Text(root,height='10',width='60')
texto.grid(row='0',column='0')

Translater =  Button(root,text='Traduzir',font='30', command=Translater)
Translater.grid(row='0',column='1')

Clear_btn =  Button(root,text='Limpar',font='30',command=Clear)
Clear_btn.grid(row='1',column='1')

Traducion =  Text(root,height='10',width='60')
Traducion.grid(row='2',column='0')

choice_language_origen = ttk.Combobox(root,width=20, value=lang_list)
choice_language_origen.current(1)
choice_language_origen.grid(row=1,column=0)

choice_language_Translater = ttk.Combobox(root,width=20, value=lang_list)
choice_language_Translater.current(1)
choice_language_Translater.grid(row='3',column='0')

root.mainloop()


import numpy as np
import pandas as pd
from itertools import starmap, combinations

def foo(a,b):
    """
    Currently the workhorse function for calculating the day-shifted pairwise difference
    """
    x1 = np.min([a,b])
    x2 = np.max([a,b])
    out1 = x2 - x1
    out2 = x1 - x2 + 24
    #return(np.absolute(a-b, dtype = np.float))
    return(np.min([out1,out2]))

def pairdiff(mat):
    """
    takes an m x n matrix, walks over the columns, and places a
    abs|1 - 2| function on the self-outer product of the
    selected column. it then takes the mean of the upper
    triangular matrix induced by this operation, removing
    nan cells from the size of the average.
    """
    def vectorOperator(vec):
        """takes the outer product of a vector"""
        out = np.array(list(starmap(foo,combinations(vec,2))), dtype = np.float)
        out = out[~np.isnan(out)]
        n = len(out)
        return(np.sum(out,dtype=float)/n)

    return(np.apply_along_axis(vectorOperator, 0, mat))
    #return(np.apply_along_axis(vectorOperator, 0, np.array(mat).T))

def summaries(df, firstcol, lastcol):
    """
    make sure df has nothing extraneous -- in other words,
    limit it to just the reduced data frame on firstcol:lastcol;
    in fact, even remove the days column from the df
    """
    fc = firstcol
    lc = lastcol + 1
    ind = range(fc, lc)
    l = len(ind)
    outmean = np.zeros(l)
    outsd = np.zeros(l)
    outnan = [False] * l

    for i in ind:
        j = i - fc
        outmean[j] = np.mean(df.iloc[:,i])
        outsd[j] = np.std(df.iloc[:,i])
        outnan[j] = np.sum([np.isnan(x) for x in df.iloc[:,i]])

    n, m = df.shape
    return(
        outmean,
        outsd,
        outnan,
        [n] * l
        )

if __name__ == "__main__":
    import random
    random.seed(1)

    mat = np.random.rand(3,5)
    pass


import torch
from torch.optim import Adam, Adagrad, Adadelta, RMSprop, SGD

from yolo_trainer import YoloTrainer
from yolo import Yolov3
import config
from utils import getLoaders, getValLoader

if torch.cuda.is_available():
    torch.cuda.empty_cache()

# ------------------------------------------------------
def run(model: Yolov3, optimizer: torch.optim):

    t = YoloTrainer()
    container = {'architecture': config.yolo_config}
    # container = YoloTrainer.loadModel('rms_normal_loss')
    # t.trainNet(model, optimizer, load=container)

    try:
        t.trainNet(model, optimizer=algorithm)
        # t.trainNet(model, optimizer, load=container)

    except KeyboardInterrupt as e:
        print('[YOLO TRAINER]: KeyboardInterrupt', e)

    except Exception as e:
        print(e)

    finally:
        savestr = f'optim_{type(optimizer).__name__}'
        YoloTrainer.saveModel(savestr, t.model, t.optimizer, t.supervisor)

# ------------------------------------------------------
def createModel():

    return  Yolov3(config.yolo_config)

# # ------------------------------------------------------
# def createSamples():

#     samples = dict()

#     adam_model = Yolov3(config.yolo_config)
#     adam = Adam(
#         [
#             {'params': adam_model.yolo.parameters()},
#             {'params': adam_model.darknet.parameters()}
#         ],
#         lr=config.LEARNING_RATE
#     )

#     adagrad_model = Yolov3(config.yolo_config)
#     adagrad = Adagrad(adagrad_model.parameters(), lr=config.LEARNING_RATE)

#     adadelta_model = Yolov3(config.yolo_config)
#     adadelta = Adadelta(adadelta_model.parameters(), lr=config.LEARNING_RATE)

#     rmsprop_model = Yolov3(config.yolo_config)
#     rmsprop = RMSprop(rmsprop_model.parameters(), lr=config.LEARNING_RATE)

#     sgd_model = Yolov3(config.yolo_config)
#     sgd = SGD(sgd_model.parameters(), lr=config.LEARNING_RATE)

#     samples = {
#         'adam': [adam_model, adam],
#         'adagrad': [adagrad_model, adagrad],
#         'adadelta': [adadelta_model, adadelta],
#         'rmsprop': [rmsprop_model, rmsprop],
#         'sgd': [sgd_model, sgd]
#     }

#     return samples

# ------------------------------------------------------
if __name__ == "__main__":

    # adam_model = Yolov3(config.yolo_config)
    # adam = Adam(
    #     [
    #         {'params': adam_model.yolo.parameters()},
    #         {'params': adam_model.darknet.parameters()}
    #     ],
    #     lr=config.LEARNING_RATE
    # )

    # adagrad_model = Yolov3(config.yolo_config).to(config.DEVICE)
    # adagrad = Adagrad(
    #     [
    #         {'params': adagrad_model.yolo.parameters()},
    #         {'params': adagrad_model.darknet.parameters()}
    #     ],
    #     lr=config.LEARNING_RATE
    # )

    rmsprop_model = Yolov3(config.yolo_config).to(config.DEVICE)
    rmsprop = RMSprop(
        [
            {'params': rmsprop_model.yolo.parameters()},
            {'params': rmsprop_model.darknet.parameters()}
        ],
        lr=config.LEARNING_RATE
    )

    run(rmsprop_model, rmsprop)

    # sgd_model = Yolov3(config.yolo_config).to(config.DEVICE)
    # sgd = SGD(
    #     [
    #         {'params': sgd_model.yolo.parameters()},
    #         {'params': sgd_model.darknet.parameters()}
    #     ],
    #     lr=config.LEARNING_RATE
    # )

    # run(sgd_model, sgd)

    # adadelta_model = Yolov3(config.yolo_config).to(config.DEVICE)
    # adadelta = Adadelta(
    #     [
    #         {'params': adadelta_model.yolo.parameters()},
    #         {'params': adadelta_model.darknet.parameters()}
    #     ],
    #     lr=config.LEARNING_RATE
    # )

    # run(rmsprop_model, rmsprop)

    # rmsprop_model = Yolov3(config.yolo_config)
    # rmsprop = RMSprop(rmsprop_model.yolo.parameters(), lr=config.LEARNING_RATE)
    # rmsprop = Adam(rmsprop_model.yolo.parameters(), lr=config.LEARNING_RATE)

    # t = YoloTrainer((getValLoader([25, 30, 35, 40, 45]), getValLoader([25, 30, 35, 40, 45])))
    # t = YoloTrainer()

    # container = {'architecture': config.yolo_config}
    # container = YoloTrainer.loadModel('ultralytics_focal_loss')

    # # t.trainNet(rmsprop_model, rmsprop)
    # # t.trainNet(rmsprop_model, rmsprop, load=container)

    # try:
    #     t.trainNet(rmsprop_model, rmsprop)
    #     # t.trainNet(rmsprop_model, rmsprop, load=container)

    # except KeyboardInterrupt as e:
    #     print('[YOLO TRAINER]: KeyboardInterrupt', e)

    # except Exception as e:
    #     print(e)

    # finally:
    #     savestr = f'optim_{type(t.optimizer).__name__}'
    #     YoloTrainer.saveModel(savestr, t.model, t.optimizer, t.supervisor)


"""
해시 테이블 - 개방 주소법
폐쇄 해싱
"""

from enum import Enum
from typing import Any
import hashlib

class Status(Enum):
    OCCUPIED = 0
    EMPTY = 1
    DELETED = 2

class Bucket:
    def __init__(
        self, key: Any = None, value: Any = None, stat: Status = Status.EMPTY
    ) -> None:
        self.key = key
        self.value = value
        self.stat = stat

    def set(self, key: Any, value: Any, stat: Status) -> None:
        self.key = key
        self.value = value
        self.stat = stat

    def set_status(self, stat: Status) -> None:
        self.stat = stat

class OpenHash:
    def __init__(self, capacity: int) -> None:
        self.capacity = capacity
        self.table = [Bucket()] * self.capacity

    def hash_value(self, key: Any) -> int:
        if isinstance(key, int):
            return key % self.capacity
        return int(hashlib.md5(str(key).encode()).hexdigest(), 16) % self.capacity

    def rehash_value(self, key: Any) -> int:
        return (self.hash_value(key) + 1) % self.capacity

    def search_node(self, key: Any) -> Any:
        hash = self.hash_value(key)
        buc = self.table[hash]

        for _ in range(self.capacity):
            if buc.stat == Status.EMPTY:
                break
            elif buc.stat == Status.OCCUPIED and buc.key == key:
                return buc
            hash = self.rehash_value(hash)
            buc = self.table[hash]
        return None

    def search(self, key: Any) -> Any:
        buc = self.search_node(key)
        if buc is not None:
            return buc.value
        else:
            return None

    def add(self, key: Any, value: Any) -> bool:
        if self.search(key) is not None:
            return False

        hash = self.hash_value(key)
        buc = self.table[hash]
        for i in range(self.capacity):
            if buc.stat == Status.EMPTY or buc.stat == Status.DELETED:
                self.table[hash] = Bucket(key, value, Status.OCCUPIED)
                return True
            hash = self.rehash_value(hash)
            buc = self.table[hash]
        return False

    def remove(self, key: Any) -> bool:
        buc = self.search_node(key)
        if buc is None:
            return False
        buc.set_status(Status.DELETED)
        return True

    def dump(self) -> None:
        for i in range(self.capacity):
            print(f"{i:2} ", end="")
            if self.table[i].stat == Status.OCCUPIED:
                print(f"{self.table[i].key} ({self.table[i].value})")
            elif self.table[i].stat == Status.EMPTY:
                print("Not registered")
            elif self.table[i].stat == Status.DELETED:
                print("Removed")


from typing import List
from collections import defaultdict, deque
import sys

class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        if not edges:
            return [0]

        connections = defaultdict(list)

        for a, b in edges:
            connections[a].append(b)
            connections[b].append(a)

        nl = n
        leaves = []

        for node in connections.keys():
            if len(connections[node]) == 1:
                leaves.append(node)

        while nl > 2:
            nl -= len(leaves)
            new_leaves = []

            for leaf in leaves:
                cur = connections[leaf].pop()
                connections[cur].remove(leaf)

                if len(connections[cur]) == 1:
                    new_leaves.append(cur)

            leaves = new_leaves

        return leaves

print(Solution().findMinHeightTrees(4,
[[1,0],[1,2],[1,3]]))


from typing import Iterable

from server.adapters.repository import AbstractRepository
from server.domain.model import make_comment, Comment, Movie

class NonExistentMovieException(Exception):
    pass

class UnknownUserException(Exception):
    pass

def add_comment(comment_text: str, username: str, repo: AbstractRepository, movie_rank: int):
    # Check that the movie exists.
    movie = repo.get_movie_by_rank(movie_rank)
    if movie is None:
        raise NonExistentMovieException

    user = repo.get_user(username)
    print(user, username)
    if user is None:
        raise UnknownUserException

    # Create comment.
    comment = make_comment(comment_text, user, movie)
    print(comment)

    # Update the repository.
    repo.add_comment(comment)

def get_movie(repo: AbstractRepository):
    movies = repo.get_movie()
    count = len(movies)
    return movies_to_dict(movies), count

def get_movie_by_rank(repo: AbstractRepository, rank: int):
    movie = repo.get_movie_by_rank(rank)
    return movie_to_dict(movie)

def get_movie_by_query(repo:AbstractRepository, actor_name: str, genre_name: str, director_name: str):
    movies = repo.get_movie_by_query(actor_name, genre_name, director_name)
    count = len(movies)
    return movies_to_dict(movies), count

def movie_to_dict(movie: Movie):
    movie_dict = {
        'rank': movie.rank,
        'year': movie.year,
        'title': movie.title,
        'description': movie.description,
        'director': movie.director,
        'actors': movie.actors,
        'comments': comments_to_dict(movie.comments),
        'genre': movie.genre,
        'runtime': movie.runtime,
        'rating': movie.rating,
        'vote': movie.vote,
        'revenue': movie.revenue,
        'metascore': movie.metascore,
        'poster': movie.poster
    }
    return movie_dict

def movies_to_dict(movies: Iterable[Movie]):
    return [movie_to_dict(movie) for movie in movies]

def comment_to_dict(comment: Comment):
    comment_dict = {
        'username': comment.user.username,
        'movie_rank': comment.movie.rank,
        'comment_text': comment.comment,
        'timestamp': comment.timestamp
    }
    return comment_dict

def comments_to_dict(comments: Iterable[Comment]):
    return [comment_to_dict(comment) for comment in comments]


import warnings

warnings.simplefilter("ignore", UserWarning)
warnings.simplefilter("ignore", FutureWarning)
warnings.simplefilter("ignore", DeprecationWarning)
import pandas as pd
import numpy as np
from ast import literal_eval
import pandas_profiling as pf
from pandas_profiling import ProfileReport
import plotly.express as px
import plotly.graph_objs as go
import plotly.offline as py
import plotly.figure_factory as ff
import matplotlib.pyplot as plt
# Import TfIdfVectorizer from scikit-learn
from sklearn.feature_extraction.text import TfidfVectorizer
# Import linear_kernel
from sklearn.metrics.pairwise import linear_kernel

credit_movies = pd.read_csv('./Data/tmdb_5000_credits.csv', sep=',')
movies = pd.read_csv('./Data/tmdb_5000_movies.csv')

credit_movies.columns = ['id', 'tittle', 'cast', 'crew']
data = credit_movies.merge(movies, on='id')

# print(data.columns)

# preprocessing methods:
# function, weighted_rating() and define a new feature score, of which we'll calculate the value by applying this function to our DataFrame of qualified movies:

# Demographic filtering : Weighted Rating (WR)
def filtering(df):
    """
    :param df: data
    :return: filtered movies
    """
    weighted_avg_rating = df['vote_average'].mean()
    #print("Mean rating for all movies::", weighted_avg_rating)
    minimum_votes = df['vote_count'].quantile(
        0.9)  # Using 90th percentile, movie votes to be equal to or more than 90% as cutoff --> feature in charts
    #print("min_votes_movies:", minimum_votes)
    # filter movies
    q_movies = df.copy().loc[df['vote_count'] >= minimum_votes]
    #print('Filtered Movies: \n ---------------------------\n', q_movies)

    def weighted_rating(x=df, m=minimum_votes, C=weighted_avg_rating):
        v = x['vote_count']
        R = x['vote_average']
        # Calculation based on the IMDB formula
        return (v / (v + m) * R) + (m / (m + v) * C)

    # Define a new feature 'score' and calculate its value with `weighted_rating()`
    q_movies['score'] = q_movies.apply(weighted_rating, axis=1)
    # Sort movies based on score calculated above
    q_movies = q_movies.sort_values('score', ascending=False)
    # Print the top 15 movies
    q_movies = q_movies[['title', 'vote_count', 'vote_average', 'score']]
    #print(q_movies)
    return q_movies

filtering(data)

def popular_movies(df):
    """

    """
    pm = df.sort_values('popularity', ascending=False).head(15)
    fig = px.bar(pm, x="title", y=["popularity"], title="Top 15 Popular Movies")
    fig.show()

popular_movies(data)

# Text-preprocessing
# def text_processing(df):
#print("Data used for recommender processing\n", data['overview'].head(5))
# Define a TF-IDF Vectorizer Object. Remove all english stop words such as 'the', 'a'
tfidf = TfidfVectorizer(stop_words='english')
# Replace NaN with an empty string
data['overview'] = data['overview'].fillna('')
# Construct the required TF-IDF matrix by fitting and transforming the data
tfidf_matrix = tfidf.fit_transform(data['overview'])

# Compute the cosine similarity matrix
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)

# Construct a reverse map of indices and movie titles
indices = pd.Series(data.index, index=data['title']).drop_duplicates()

# Function that takes in movie title as input and outputs most similar movies
def get_recommendations(cosine_sim=cosine_sim):
    # Get the index of the movie that matches the title
    title = input("Enter Movie Name:")

    idx = indices[title]

    # Get the pairwsie similarity scores of all movies with that movie
    sim_scores = list(enumerate(cosine_sim[idx]))

    # Sort the movies based on the similarity scores
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)

    # Get the scores of the 10 most similar movies
    sim_scores = sim_scores[1:11]

    # Get the movie indices
    movie_indices = [i[0] for i in sim_scores]

    # Return the top 10 most similar movies
    print("10 Most Similar Movies to Recommend", data['title'].iloc[movie_indices])
    return data['title'].iloc[movie_indices]

get_recommendations()


import ssl
import json
try:
    import httplib
except ImportError:
    import http.client as httplib

import urllib
from .bldgsim_info import MetaInfo

import uuid

class HTTPConnect(object):
    def __init__(self, status_code, response_obj):
        """
        Construct HTTP connection object

        :param status_code:
        :param response_obj:
        """
        self._status_code = status_code
        self._response_error = ""
        self._original_response = response_obj

        if type(response_obj) is bytes:
            response_obj = response_obj.decode("utf-8", errors='ignore')

        if type(response_obj) is str:
            try:
                self._response = json.loads(response_obj)
            except:
                self._response = response_obj
        elif type(response_obj) is dict:
            try:
                self._response = json.loads(json.dumps(response_obj))
            except:
                self._response = response_obj
        else:
            self._response = response_obj

    @property
    def status_code(self):
        return self._status_code

    def json(self):
        return self._response

    def original_response(self):
        return self._original_response

    def set_error(self, error):
        self._response_error = error

    def get_error(self):
        return self._response_error

    def iter_content(self, chunk_size=1024):
        contents = []

        try:
            chunk = self.response.read(chunk_size)
            while len(chunk) > 0:
                contents.append(chunk)
                chunk = self.response.read(chunk_size)
        except:
            print('ERROR: response object cannot be iter read')
        return contents

def __split_path(path):
    double_slash_idx = path.find('//')
    if double_slash_idx < 0:
        return {'status': 'error', 'error_msg': 'path missing protocol'}

    protocol = path[:double_slash_idx + 2]
    protocol.lower()

    if protocol == 'https://':
        is_ssl = True
        path = path[8:]  # remove https:// part
    elif protocol == 'http://':
        is_ssl = False
        path = path[7:]  # remove http:// part
    else:
        return {'status': 'error', 'error_msg': 'path protocol is not https or http'}

    slash_idx = path.find('/')
    if slash_idx < 0:
        host = path
        req_path = ""
    else:
        host = path[:slash_idx]
        req_path = path[slash_idx:]

    try:
        _create_unverified_https_context = ssl._create_unverified_context()
    except AttributeError:
        # Python < 2.7.9 doesn't support ssl
        conn = httplib.HTTPConnection(host)
    else:
        if is_ssl:
            conn = httplib.HTTPSConnection(host,
                                           context=_create_unverified_https_context)
        else:
            conn = httplib.HTTPConnection(host)

    return {'status': 'success', 'conn': conn, 'req_path': req_path}

"""
def __encode_multipart_formdata(fields, files):
    boundary = 'BuildSimHub_boundary_string'
    crlf = '\r\n'
    form = []

    for (key, value) in fields.items():
        form.append('--' + boundary)
        form.append('Content-Disposition: form-data; name="%s"' % key)
        form.append('')
        form.append(str(value))
    for (key, f) in files.items():
        form.append('--' + boundary)

        # 3.6 will upload the full dir
        # this code extract the file name
        filename = f.name
        slash = max(filename.rfind('/'), filename.rfind('\\'))
        if slash >= 0:
            filename = filename[slash + 1:]

        form.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        form.append('Content-Type: application/octet-stream')
        form.append('')
        form.append(f.read())
    form.append('--' + boundary + '--')
    form.append('')
    body = crlf.join(form)
    return boundary, body
"""

def __encode_multipart_formdata(params, files):
    boundry = uuid.uuid4().hex
    lines = list()
    for key, val in params.items():
        if val is None:
            continue

        lines.append('--' + boundry)
        lines.append('Content-Disposition: form-data; name="%s"' % key)
        lines.extend(['', val])

    for key, f in files.items():
        filename = f.name
        slash = max(filename.rfind('/'), filename.rfind('\\'))
        if slash >= 0:
            filename = filename[slash + 1:]

        lines.append('--' + boundry)
        lines.append('Content-Disposition: form-data; name="{0}"; filename="{1}"'.format(key, filename))
        lines.append('Content-Type: application/octet-stream')
        lines.append('')
        lines.append(f.read())

    lines.append('--%s--' % boundry)

    body = bytes()
    for l in lines:
        if isinstance(l, bytes):
            body += l + b'\r\n'
        else:
            body += bytes(str(l), encoding='utf8') + b'\r\n'

    headers = {'Content-Type' : 'multipart/form-data; boundary=' + boundry}

    return headers, body

def request_large_data(path, params):
    """
    This function is used to request parametric data
    :return:
    """
    start = 0
    result = []
    while True:
        process = __split_path(path)
        if process['status'] == 'success':
            conn = process['conn']
            info = MetaInfo()
            header = {'vendor_key': info.vendor_id}
            # check 2.x and 3.x differences in using urllib
            params['start'] = str(start)
            try:
                conn.request("GET", process['req_path'] + "?" +
                             urllib.urlencode(params), headers=header)
            except AttributeError:
                conn.request("GET", process['req_path'] + "?" +
                             urllib.parse.urlencode(params), headers=header)
            resp = conn.getresponse()

            if resp.status != 200:
                print("Code: " + str(resp.status))
                resp_obj = HTTPConnect(resp.status, resp.read()).json()
                print(resp_obj)
                break
            resp_obj_read = resp.read()
            resp_obj = HTTPConnect(resp.status, resp_obj_read).json()
            if type(resp_obj) is str:
                try:
                    resp_obj = json.loads(resp_obj)
                except:
                    # return error msg
                    print("parse json str failed")
                    # print(resp_obj)
                    break
            elif type(resp_obj) is dict:
                try:
                    resp_obj = json.loads(json.dumps(resp_obj))
                except:
                    print("parse dict failed")
                    print(resp_obj)
                    break
            else:
                print("result not str")
                print(resp_obj)
                break

            total = int(resp_obj['total'])
            next_start = int(resp_obj['next_start'])

            result.extend(resp_obj['data'])
            print("Finish extracting: " + str(start+1) + " to " + str(next_start-1) + " , remaining: "
                  + str(total - next_start))
            start = next_start
            conn.close()
            if start == total:
                break
    return result

def request_get(path, params, stream=False):
    """
    send GET request to server

    :param path: url
    :param params: header
    :param stream:
    :return:
    """
    process = __split_path(path)

    if process['status'] == 'success':
        conn = process['conn']
        info = MetaInfo()
        header = {'vendor_key': info.vendor_id}
        # check 2.x and 3.x differences in using urllib
        try:
            conn.request("GET", process['req_path'] + "?" +
                         urllib.urlencode(params), headers=header)
        except AttributeError:
            conn.request("GET", process['req_path'] + "?" +
                         urllib.parse.urlencode(params), headers=header)

        resp = conn.getresponse()

        if stream:
            resp_obj = resp
        else:
            assert isinstance(resp, object)
            resp_obj = resp.read()
        return HTTPConnect(resp.status, resp_obj)
    else:
        return HTTPConnect(404, process)

def request_post(path, params, files=None, stream=False):
    process = __split_path(path)

    if process['status'] == 'success':
        conn = process['conn']

        if files:
            header, body = __encode_multipart_formdata(params, files)
            info = MetaInfo()
            header['vendor_key'] = info.vendor_id

            conn.request("POST", process['req_path'], body, header)
        else:
            info = MetaInfo()
            header = {'vendor_key': info.vendor_id}
            try:
                conn.request("POST", process['req_path'] + "?" + urllib.urlencode(params), headers=header)
            except AttributeError:
                conn.request("POST", process['req_path'] + "?" + urllib.parse.urlencode(params), headers=header)

        resp = conn.getresponse()

        if stream:
            resp_obj = resp
        else:
            resp_obj = resp.read()
        return HTTPConnect(resp.status, resp_obj)
    else:
        return HTTPConnect(404, process)

def make_url(path, params):
    try:
        url = path + "?" + urllib.urlencode(params)
    except:
        url = path + "?" + urllib.parse.urlencode(params)
    return url


import numpy as np

class MeshBase:
    def __init__(
        self, vertices=None, cells=None, cell_markers=None, vertex_markers=None
    ):
        self.vertices = np.asarray(vertices)
        self.cells = np.asarray(cells)
        if vertex_markers:
            self.vertex_markers = np.asarray(vertex_markers)
        else:
            self.vertex_markers = None
        if cell_markers:
            self.cell_markers = np.asarray(cell_markers)
        else:
            self.cell_markers = None

    def set_vertices(self, vertices):
        self.vertices = np.array(vertices, dtype="float")
        for i, vertex in enumerate(vertices):
            self.vertices[i] = vertex

    def set_cells(self, cells, markers=None):
        if markers is not None:
            assert len(markers) == len(cells)

        self.cells = np.array(cells, dtype="int")
        # for i, cell in enumerate(cells):
        # self.cells[i] = cell

        if markers is not None:
            self.set_cell_markers(markers)

    def set_vertex_markers(self, markers):
        assert len(markers) == len(self.vertices)
        self.vertex_markers = np.array(markers, dtype="int")

    def set_cell_markers(self, markers):
        assert len(markers) == len(self.cells)
        self.cell_markers = np.array(markers, dtype="int")
        # for i, mark in enumerate(markers):
        # self.cell_markers[i] = mark

    def set_all_cell_markers(self, marker):
        self.cell_markers = int(marker) * np.ones(len(self.cells))

    def save(self, filename):
        ext = filename.split(".")[-1]
        if ext == "mesh":
            medit_write(
                filename,
                self.vertices,
                self.cells,
                self.cell_markers,
                self.vertex_markers,
            )
        elif ext == "vtk":
            vtk_write(filename, self.vertices, self.cells, self.cell_markers)
        elif ext == "geof":
            zebulon_write(filename, self.vertices, self.cells)
        elif ext == "inp":
            abaqus_write(filename, self.vertices, self.cells, self.cell_markers)
        elif ext == "gnu":
            gnuplot_write(filename, self.vertices, self.cells, self.cell_markers)
        elif ext == "pdf":
            pdf_write(filename, self.vertices, self.cells, self.cell_markers)
        elif ext == "bdf":
            nastran_write(
                filename,
                self.vertices,
                self.cells,
                self.vertex_markers,
                self.cell_markers,
            )
        else:
            raise ValueError("Unknown mesh type: %s" % ext)

    def renumber_cell_markers(self, reverse=False):
        unique_markers, indices = np.unique(self.cell_markers, return_inverse=True)
        if reverse:
            num_unique_markers = len(unique_markers) - 1
            self.cell_markers = num_unique_markers - indices
        else:
            self.cell_markers = indices - 1

    def remove_cells_with_marker(self, marker):

        dim = self.vertices.shape[1]
        if dim == 3:
            raise ValueError("Not implemented for dim == 3")

        old_vertices = self.vertices
        old_cells = self.cells
        old_ids = self.cell_markers

        num_old_cells = old_cells.shape[0]
        num_old_vertices = old_vertices.shape[0]

        renum = -1 * np.ones(num_old_vertices)

        for k in range(num_old_cells):
            if old_ids[k] != marker:
                renum[old_cells[k, 0:3]] = 1

        num_vert = 0
        for k in range(num_old_vertices):
            if renum[k] > -1:
                renum[k] = num_vert
                num_vert += 1

        new_vertices = old_vertices[renum > -1]
        new_cells = old_cells[old_ids != marker]
        for k in range(new_cells.shape[0]):
            new_cells[k, 0:3] = renum[new_cells[k, 0:3]]

        new_ids = old_ids[old_ids != marker]

        self.set_vertices(new_vertices)
        self.set_cells(new_cells)
        self.set_cell_markers(new_ids)

    def characteristic_length(self):
        lc = 0.0
        for cell in self.cells:
            l = np.linalg.norm(self.vertices[cell[0]] - self.vertices[cell[1]])
            l += np.linalg.norm(self.vertices[cell[1]] - self.vertices[cell[2]])
            l += np.linalg.norm(self.vertices[cell[2]] - self.vertices[cell[0]])
            lc += l / 3.0

        return lc / len(self.cells)

    def remove_orphan_vertices(self):

        uvertices = np.unique(np.ravel(self.cells))
        idx = -1 * np.ones(len(self.vertices), dtype=int)
        idx[uvertices] = np.arange(len(uvertices))
        self.vertices = self.vertices[idx > -1]
        if self.vertex_markers is not None:
            self.vertex_markers = self.vertex_markers[idx > -1]
        self.cells = idx[self.cells]

def medit_reader(filename):
    def get_next_line(stream, comment="#"):
        while 1:
            next_line = stream.readline()
            if not next_line:
                return None
            elif next_line.strip().startswith(comment) or len(next_line.strip()) == 0:
                pass
            else:
                return next_line.strip()

    f = open(filename, "r")

    vertices = []
    markers = []

    tri = []
    tri_markers = []
    ntri = 0

    quad = []
    quad_markers = []
    nquad = 0

    tet = []
    tet_markers = []
    ntet = 0

    hex = []
    hex_markers = []
    nhex = 0

    while True:
        next_line = get_next_line(f)
        if not next_line:
            break

        if next_line.startswith("Dimension"):
            if len(next_line.split()) > 1:
                dim = int(next_line.split()[1])
            else:
                dim = int(get_next_line(f).split()[0])

        if next_line.startswith("Vertices"):
            if len(next_line.split()) > 1:
                num_vertex = int(next_line[1])
            else:
                num_vertex = int(get_next_line(f).split()[0])
            for i in range(num_vertex):
                next_line = get_next_line(f)
                vertices.append([float(coord) for coord in next_line.split()[0:dim]])
                markers.append(int(next_line.split()[dim]))

        if next_line.startswith("Triangles"):
            if len(next_line.split()) > 1:
                num_tri = int(next_line[1])
            else:
                num_tri = int(get_next_line(f).split()[0])
            for i in range(num_tri):
                next_line = get_next_line(f)
                tri.append([int(coord) - 1 for coord in next_line.split()[0:3]])
                tri_markers.append(int(next_line.split()[3]))
                ntri += 1

        if next_line.startswith("Quadri"):
            if len(next_line.split()) > 1:
                num_quad = int(next_line[1])
            else:
                num_quad = int(get_next_line(f).split()[0])
            for i in range(num_quad):
                next_line = get_next_line(f)
                quad.append([int(coord) - 1 for coord in next_line.split()[0:4]])
                quad_markers.append(int(next_line.split()[4]))
                nquad += 1

        if next_line.startswith("Tetrahedra"):
            if len(next_line.split()) > 1:
                num_tet = int(next_line[1])
            else:
                num_tet = int(get_next_line(f).split()[0])
            for i in range(num_tet):
                next_line = get_next_line(f)
                tet.append([int(coord) - 1 for coord in next_line.split()[0:4]])
                tet_markers.append(int(next_line.split()[4]))
                ntet += 1

        if next_line.startswith("Hexahedra"):
            if len(next_line.split()) > 1:
                num_hex = int(next_line[1])
            else:
                num_hex = int(get_next_line(f).split()[0])
            for i in range(num_hex):
                next_line = get_next_line(f)
                hex.append([int(coord) - 1 for coord in next_line.split()[0:8]])
                hex_markers.append(int(next_line.split()[8]))
                nhex += 1

    if nhex > 0:
        cells = hex
        cell_markers = hex_markers
    elif ntet > 0:
        cells = tet
        cell_markers = tet_markers
    elif nquad > 0:
        cells = quad
        cell_markers = quad_markers
    else:
        cells = tri
        cell_markers = tri_markers

    mesh = MeshBase()
    mesh.set_vertices(vertices)
    mesh.set_vertex_markers(markers)
    mesh.set_cells(cells)
    mesh.set_cell_markers(cell_markers)

    return mesh

def read_mesh(filename):
    ext = filename.split(".")[-1]
    if ext == "mesh":
        return medit_reader(filename)
    else:
        raise ValueError("Unknown mesh type: %s" % ext)

def extrude_mesh(mesh, offset=None, subdivisions=None):
    def _get_connectivity(v):
        """
        Decompose a prism into three tetrahdra.

        Dompierre, J., Labbe, P., Vallet, M.-G., Camarero, R., 1999. How to
        subdivide pyramids, prisms and hexaedra into tetrahedra. In: 8th
        International Meshing Roundtable. South Lake Tahoe, CA.
        """
        imin = np.argmin(v)
        if imin == 1:
            v = (v[1], v[2], v[0], v[4], v[5], v[3])
        elif imin == 2:
            v = (v[2], v[0], v[1], v[5], v[3], v[4])
        elif imin == 3:
            v = (v[3], v[5], v[4], v[0], v[2], v[1])
        elif imin == 4:
            v = (v[4], v[3], v[5], v[1], v[0], v[2])
        elif imin == 5:
            v = (v[5], v[4], v[3], v[2], v[1], v[0])

        if min(v[1], v[5]) < min(v[2], v[4]):
            c = (
                [v[0], v[1], v[2], v[5]],
                [v[0], v[1], v[5], v[4]],
                [v[0], v[4], v[5], v[3]],
            )
        else:
            c = (
                [v[0], v[1], v[2], v[4]],
                [v[0], v[4], v[2], v[5]],
                [v[0], v[4], v[5], v[3]],
            )
        return c

    lc = mesh.characteristic_length()
    print(lc)

    if offset is not None and subdivisions is not None:
        delta_z = offset / subdivisions
    elif subdivisions is None:
        subdivisions = int(offset / lc) + 1
        delta_z = offset / subdivisions
    else:
        delta_z = lc
        offset = delta_z * subdivisions

    print(delta_z, offset)

    nvert = len(mesh.vertices)
    ncell = len(mesh.cells)

    v = np.zeros(((subdivisions + 1) * nvert, 3))
    v[:, 0:2] = np.tile(mesh.vertices, (subdivisions + 1, 1))

    nt = 3 * ncell
    c = np.zeros((nt * subdivisions, 4), dtype="int")
    m = np.zeros((nt * subdivisions), dtype="int")

    for i in range(ncell):
        (v0, v1, v2) = mesh.cells[i]
        conn = _get_connectivity((v0, v1, v2, v0 + nvert, v1 + nvert, v2 + nvert))
        c[3 * i] = conn[0]
        c[3 * i + 1] = conn[1]
        c[3 * i + 2] = conn[2]
        m[3 * i : 3 * i + 3] = mesh.cell_markers[i]

    for i in range(1, subdivisions):
        v[i * nvert : (i + 1) * nvert, 2] = i * delta_z
        c[i * nt : (i + 1) * nt] = c[(i - 1) * nt : i * nt] + nvert
        m[i * nt : (i + 1) * nt] = m[(i - 1) * nt : i * nt]
    v[subdivisions * nvert : (subdivisions + 1) * nvert, 2] = subdivisions * delta_z

    outmesh = MeshBase()
    outmesh.set_vertices(v)
    outmesh.set_cells(c, m)

    return outmesh

def find_edges(mesh, neighbours=False):

    nv = len(mesh.vertices)
    nt = len(mesh.cells)
    ne = 3 * nt

    last_edge = -1 * np.ones(nv, dtype="int")
    next_edge = -1 * np.ones(ne, dtype="int")
    edges = -1 * np.ones((ne, 4), dtype="int")

    nedges = 0
    for i, cell in enumerate(mesh.cells):
        for k in range(3):
            p = cell[k]
            q = cell[(k + 1) % 3]
            if p > q:
                p, q = q, p

            edge_found = False
            n = last_edge[p]
            while n != -1:
                if edges[n, 0] == p and edges[n, 1] == q:
                    edge_found = True
                    edges[n, 3] = i
                n = next_edge[n]
            if edge_found == False:
                edges[nedges, 0:3] = [p, q, i]
                next_edge[nedges] = last_edge[p]
                last_edge[p] = nedges
                nedges += 1

    if neighbours == False:
        edges = edges[:nedges, 0:2]
    else:
        edges = edges[:nedges]

    return edges

def find_boundary_edges(mesh):

    edges = find_edges(mesh, neighbours=True)
    boundary_edges = np.asarray(edges[edges[:, 3] == -1])

    for edge in boundary_edges:
        ## check edge orientation
        v0 = edge[0]
        v1 = edge[1]
        t = edge[2]

        dx = mesh.vertices[v1, 0] - mesh.vertices[v0, 0]
        dy = mesh.vertices[v1, 1] - mesh.vertices[v0, 1]

        le = np.sqrt(dx * dx + dy * dy)
        nx = dy / le
        ny = -dx / le

        bary = np.mean(mesh.vertices[mesh.cells[t]], axis=0)
        middle = 0.5 * (mesh.vertices[v0] + mesh.vertices[v1])

        if np.dot([nx, ny], bary - middle) > 0.0:
            edge[0], edge[1] = edge[1], edge[0]

    return boundary_edges[:, 0:2]

def remove_duplicate_faces(mesh):
    nv = len(mesh.vertices)
    nt = len(mesh.cells)

    last_face = -1 * np.ones(nv, dtype="int")
    next_face = -1 * np.ones(nt, dtype="int")
    faces = -1 * np.ones((nt, 4), dtype="int")

    idx = np.zeros(nt)

    nfaces = 0
    for i, cell in enumerate(mesh.cells):
        v = sorted(cell)
        face_found = False
        n = last_face[v[0]]
        while n != -1:
            if faces[n, 0] == v[0] and faces[n, 1] == v[1] and faces[n, 2] == v[2]:
                face_found = True
                break
            n = next_face[n]
        if face_found is False:
            faces[nfaces, :3] = v
            faces[nfaces, 3] = i
            next_face[nfaces] = last_face[v[0]]
            last_face[v[0]] = nfaces
            nfaces += 1
        if face_found is True:
            dupl_idx = faces[n, 3]
            #            print 'Duplicate face %d (%s) with face %d (%s)' % (i, v, dupl_idx, mesh.cells[dupl_idx])
            idx[i] = 1

    mesh.cells = mesh.cells[idx == 0]
    if mesh.cell_markers is not None:
        mesh.cell_markers = mesh.cell_markers[idx == 0]

    return mesh

def merge_meshes(m1, m2, tol=1.0e-6):

    import numpy as np

    all_vert = np.vstack((m1.vertices, m2.vertices))
    all_cell = np.vstack((m1.cells, m2.cells + len(m1.vertices)))

    all_mark = np.zeros(len(all_cell))

    if m1.cell_markers is not None:
        all_mark[: len(m1.cells)] = m1.cell_markers
    if m2.cell_markers is not None:
        all_mark[len(m1.cells) :] = m2.cell_markers

    m = MeshBase(all_vert, all_cell, cell_markers=all_mark)

    xmin = np.min(m.vertices[:, 0])
    ymin = np.min(m.vertices[:, 1])
    zmin = np.min(m.vertices[:, 2])

    lx = np.max(m.vertices[:, 0]) - np.min(m.vertices[:, 0])
    ly = np.max(m.vertices[:, 1]) - np.min(m.vertices[:, 1])
    lz = np.max(m.vertices[:, 2]) - np.min(m.vertices[:, 2])

    lc = np.sqrt(lx ** 2 + ly ** 2 + lz ** 2) / 50.0

    nx = int(lx / lc) + 1
    ny = int(ly / lc) + 1
    nz = int(lz / lc) + 1
    N = nx * ny * nz
    box = []

    for _ in range(N):
        box.append([])

    for i, v in enumerate(m.vertices):
        vx = v[0] - xmin
        vy = v[1] - ymin
        vz = v[2] - zmin
        vi = int(vx / lc)
        vj = int(vy / lc)
        vk = int(vz / lc)
        n = vi + vj * nx + vk * (nx * ny)
        box[n].append(i)

    new_num = list(range(len(m.vertices)))
    for b in box:
        if len(b) > 1:
            for i in range(len(b) - 1):
                for j in range(i + 1, len(b)):
                    vi = m.vertices[b[i]]
                    vj = m.vertices[b[j]]

                    if np.linalg.norm(vi - vj) < tol:
                        bij = min(new_num[b[i]], new_num[b[j]])
                        new_num[b[i]] = new_num[b[j]] = bij

    for i, c in enumerate(m.cells):
        m.cells[i] = [new_num[v] for v in c]

    marker = -1 * np.ones(len(m.vertices))
    for cell in m.cells:
        for p in cell:
            marker[p] = 1
    np = 0
    for i in range(len(marker)):
        if marker[i] > -1:
            marker[i] = np
            np += 1

    m.vertices = m.vertices[marker > -1]
    for i, c in enumerate(m.cells):
        m.cells[i] = [marker[v] for v in c]

    return m

def medit_write(filename, vertices, cells, ids=None, vids=None):
    """Write a mesh to Medit format """
    dim = vertices.shape[1]

    if ids is None:
        ids = np.zeros((len(cells)), dtype="int")

    if vids is None:
        vids = np.zeros((len(vertices)), dtype="int")

    f = open(filename, "w")
    f.write("MeshVersionFormatted 1\n")
    f.write("Dimension\n%d\n" % dim)

    f.write("Vertices\n%d\n" % vertices.shape[0])
    for (v, m) in zip(vertices, vids):
        if dim == 2:
            f.write("%f\t%f\t%d\n" % (v[0], v[1], m))
        elif dim == 3:
            f.write("%f\t%f\t%f\t%d\n" % (v[0], v[1], v[2], m))

    if cells.shape[1] == 3:
        f.write("Triangles\n%d\n" % cells.shape[0])
        for c, m in zip(cells, ids):
            f.write("%d\t%d\t%d\t%d\n" % (c[0] + 1, c[1] + 1, c[2] + 1, m))
    elif dim == 2 and cells.shape[1] == 4:
        f.write("Quadrilaterals\n%d\n" % cells.shape[0])
        for c, m in zip(cells, ids):
            f.write(
                "%d\t%d\t%d\t%d\t%d\n" % (c[0] + 1, c[1] + 1, c[2] + 1, c[3] + 1, m)
            )
    elif dim == 3 and cells.shape[1] == 4:
        f.write("Tetrahedra\n%d\n" % cells.shape[0])
        for i in range(len(cells)):
            f.write(
                "%d\t%d\t%d\t%d\t%d\n"
                % (
                    cells[i, 0] + 1,
                    cells[i, 1] + 1,
                    cells[i, 2] + 1,
                    cells[i, 3] + 1,
                    ids[i],
                )
            )
    elif dim == 3 and cells.shape[1] == 8:
        f.write("Hexahedra\n%d\n" % cells.shape[0])
        for i in range(len(cells)):
            f.write(
                "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n"
                % (
                    cells[i, 0] + 1,
                    cells[i, 1] + 1,
                    cells[i, 2] + 1,
                    cells[i, 3] + 1,
                    cells[i, 4] + 1,
                    cells[i, 5] + 1,
                    cells[i, 6] + 1,
                    cells[i, 7] + 1,
                    ids[i],
                )
            )

    f.write("End")
    f.close()

def vtk_write(filename, vertices, cells, ids=None, point_data=None, cell_data=None):

    dim = vertices.shape[1]

    if cells.shape[1] == 3:
        cell_type = "triangle"
        cell_type_id = 5
    elif dim == 3 and cells.shape[1] == 4:
        cell_type = "tetrahedron"
        cell_type_id = 10
    elif dim == 2 and cells.shape[1] == 4:
        cell_type = "quadrilateral"
        cell_type_id = 9
    elif cells.shape[1] == 8:
        cell_type = "hexahedron"
        cell_type_id = 12

    # print cell_type

    f = open(filename, "w")
    f.write("# vtk DataFile Version 3.0\n")
    f.write("Generated by meshutils\n")
    f.write("ASCII\n")
    f.write("DATASET UNSTRUCTURED_GRID\n")

    f.write("POINTS %d float\n" % len(vertices))
    for i in range(len(vertices)):
        if dim == 2:
            f.write("%f %f %f\n" % (vertices[i, 0], vertices[i, 1], 0.0))
        else:
            f.write("%f %f %f\n" % (vertices[i, 0], vertices[i, 1], vertices[i, 2]))

    f.write("CELLS %d %d\n" % (len(cells), (cells.shape[1] + 1) * len(cells)))

    for i in range(len(cells)):
        if cell_type == "triangle":
            f.write("3 %d %d %d\n" % (cells[i, 0], cells[i, 1], cells[i, 2]))
        elif cell_type == "tetrahedron" or cell_type == "quadrilateral":
            f.write(
                "4 %d %d %d %d\n" % (cells[i, 0], cells[i, 1], cells[i, 2], cells[i, 3])
            )
        elif cell_type == "hexahedron":
            f.write(
                "8 %d %d %d %d %d %d %d %d\n"
                % (
                    cells[i, 0],
                    cells[i, 1],
                    cells[i, 2],
                    cells[i, 3],
                    cells[i, 4],
                    cells[i, 5],
                    cells[i, 6],
                    cells[i, 7],
                )
            )

    f.write("CELL_TYPES %d\n" % len(cells))
    for _ in range(len(cells)):
        f.write("%d\n" % cell_type_id)

    if ids is not None or cell_data is not None:
        f.write("CELL_DATA %s\n" % len(cells))

    if ids is not None:
        f.write("SCALARS marker int 1\n")
        f.write("LOOKUP_TABLE default\n")
        for mark in ids:
            f.write("%s\n" % mark)

    if cell_data is not None:
        for key, data in list(cell_data.items()):
            data_dim = len(data) / len(cells)
            f.write("SCALARS %s float %d\n" % (key, data_dim))
            f.write("LOOKUP_TABLE default\n")
            for i in range(len(cells)):
                if data_dim == 1:
                    f.write("%e\n" % data[i])
                elif data_dim == 2:
                    f.write("%e %e\n" % (data[2 * i], data[2 * i + 1]))
                elif data_dim == 3:
                    f.write(
                        "%e %e %e\n" % (data[3 * i], data[3 * i + 1], data[3 * i + 2])
                    )

    if point_data is not None:
        f.write("POINT_DATA %d\n" % len(vertices))
        for key, data in list(point_data.items()):

            if len(data) > len(vertices):
                f.write("SCALARS %s float 3\n" % key)
                f.write("LOOKUP_TABLE default\n")
                for i in range(len(vertices)):
                    if dim == 2:
                        f.write("%e %e %e\n" % (data[2 * i], data[2 * i + 1], 0))
                    else:
                        f.write(
                            "%e %e %e\n"
                            % (data[3 * i], data[3 * i + 1], data[3 * i + 2])
                        )
            else:
                f.write("SCALARS %s float 1\n" % key)
                f.write("LOOKUP_TABLE default\n")
                for i in range(len(vertices)):
                    f.write("%e\n" % (data[i]))

    f.close()

def gnuplot_write(filename, vertices, cells, ids):
    f = open(filename, "w")
    for points in cells:
        for pt in points:
            f.write("%f %f\n" % tuple(vertices[pt]))
        f.write("%f %f\n\n" % tuple(vertices[points[0]]))
    f.close()

def pdf_write(filename, vertices, cells, ids):

    import matplotlib.pyplot as plt

    fig = plt.figure()
    for points in cells:
        plt.fill(
            vertices[points, 0], vertices[points, 1], facecolor="0.9", edgecolor="k"
        )
        plt.gca().set_aspect("equal")
    plt.gca().set_axis_off()
    fig.savefig(filename)

def zebulon_write(filename, vertices, cells):
    """Write mesh to Zebulon format (*.geof)"""
    dim = vertices.shape[1]
    if cells.shape[1] == 3:
        cell_type = "c2d3"
    else:
        cell_type = "c3d4"
    f = open(filename, "w")
    f.write("***geometry\n")
    f.write("**node\n")
    f.write("%d %d\n" % (vertices.shape[0], vertices.shape[1]))
    for i, v in enumerate(vertices):
        if dim == 2:
            f.write("    %d %e %e\n" % (i + 1, v[0], v[1]))
        else:
            f.write("    %d %e %e %e\n" % (i + 1, v[0], v[1], v[2]))
    f.write("**element\n")
    f.write("%d\n" % cells.shape[0])
    for i, c in enumerate(cells):
        if cell_type == "c2d3":
            f.write(
                "    %d %s %d %d %d\n"
                % (i + 1, cell_type, c[0] + 1, c[1] + 1, c[2] + 1)
            )
        else:
            f.write(
                "    %d %s %d %d %d %d\n"
                % (i + 1, cell_type, c[0] + 1, c[1] + 1, c[2] + 1, c[3] + 1)
            )
    f.write("***return")
    f.close()

def _write_by_line(f, data, max_per_line=8, sep=","):
    out = ""
    nline = len(data) // max_per_line
    for k in range(nline):
        out += "".join(
            "%d%s " % (x, sep) for x in data[k * max_per_line : (k + 1) * max_per_line]
        )
        out += "\n"
    out += "".join("%d%s " % (x, sep) for x in data[nline * max_per_line :])
    if len(data) % max_per_line:
        out += "\n"

    f.write("%s" % out)

def abaqus_write(
    filename, vertices, cells, ids=None, nsets=None, elsets=None, cell_type=None, tol=1e-4
):
    """Write mesh to Abaqus formt (*.inp)"""
    dim = vertices.shape[1]

    if cell_type is None:
        if dim == 2 and cells.shape[1] == 3:
            cell_type = "cps3"
        elif dim == 2 and cells.shape[1] == 4:
            cell_type = "cps4"
        elif dim == 3 and cells.shape[1] == 4:
            cell_type = "c3d4"
        elif dim == 3 and cells.shape[1] == 8:
            cell_type = "c3d8"
        else:
            raise ValueError("Unknown element type in dim  %s" % dim)

    f = open(filename, "w")

    # Write nodes
    f.write("*node\n")
    for i, v in enumerate(vertices):
        f.write(str(i + 1))
        for c in v:
            f.write(", " + str(c))
        f.write("\n")

    # Write elements
    f.write("*element, type=" + cell_type + "\n")
    for i, c in enumerate(cells):
        f.write(str(i + 1))
        for v in c:
            f.write(", " + str(v + 1))
        f.write("\n")

    # Write elsets
    if ids is not None:
        for idx in np.unique(ids):
            f.write("*elset, elset=elset%d\n" % idx)
            elem = np.where(ids == idx)[0] + 1
            _write_by_line(f, elem)
    elif elsets:
        for key, value in elsets.items():
            f.write("*elset, elset=%s\n" % key)
            _write_by_line(f, value + 1)

    # Write nsets
    xmin = np.min(vertices, axis=0)
    xmax = np.max(vertices, axis=0)

    nset = np.where(np.abs(vertices[:, 0] - xmin[0]) < tol)[0]
    f.write("*nset, nset=xmin\n")
    _write_by_line(f, nset + 1)

    nset = np.where(np.abs(vertices[:, 0] - xmax[0]) < tol)[0]
    f.write("*nset, nset=xmax\n")
    _write_by_line(f, nset + 1)

    nset = np.where(np.abs(vertices[:, 1] - xmin[1]) < tol)[0]
    f.write("*nset, nset=ymin\n")
    _write_by_line(f, nset + 1)

    nset = np.where(np.abs(vertices[:, 1] - xmax[1]) < tol)[0]
    f.write("*nset, nset=ymax\n")
    _write_by_line(f, nset + 1)

    if dim == 3:
        nset = np.where(np.abs(vertices[:, 2] - xmin[2]) < tol)[0]
        f.write("*nset, nset=zmin\n")
        _write_by_line(f, nset + 1)

        nset = np.where(np.abs(vertices[:, 2] - xmax[2]) < tol)[0]
        f.write("*nset, nset=zmax\n")
        _write_by_line(f, nset + 1)

    f.write("*nset, nset=all, generate\n")
    f.write("1, %d\n" % len(vertices))

    if nsets:
        for key, value in nsets.items():
            f.write("*nset, nset=%s\n" % key)
            _write_by_line(f, value + 1)

    f.close()

def nastran_write(filename, vertices, cells, tags=None, ids=None):

    if tags is None:
        tags = np.zeros(len(vertices))

    if ids is None:
        ids = np.zeros(len(cells))

    nv = len(vertices)

    with open(filename, "w") as f:
        f.write("$ Created by meshutils.py\n")
        for k, (v, t) in enumerate(zip(vertices, tags)):
            f.write(
                "%-8s%16d%16d%16.6e%16.6e%-8s\n%-8s%16.6e\n"
                % ("GRID*", k + 1, 0, v[0], v[1], "*", "*", v[2])
            )
        # for k, (c,i) in enumerate(zip(cells, ids)):
        #     f.write('%-8s%16d%16d%16d%16d%-8s\n%-8s%16d%16d\n' % ('CTETRA*', k, i, c[0], c[1], '*N%d' % (k + nv), '*N%d' % (k + nv), c[2], c[3]))
        for k, (c, i) in enumerate(zip(cells, ids)):
            f.write(
                "%-8s%8d%8d%8d%8d%8d%8d\n"
                % ("CTETRA", k + 1, i, c[0] + 1, c[1] + 1, c[2] + 1, c[3] + 1)
            )

        f.write("ENDDATA\n")


import os
import datetime

# Define function to create a unique filename and write to it
def create_unique_file(code):
    # Get the current timestamp and format it to a string
    timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

    # Create a base filename and append the timestamp to create a unique filename
    base_filename = "output"
    filename = f"{base_filename}_{timestamp}.py"

    # Check if a file already exists with the same name
    counter = 1
    while os.path.isfile(filename):
        # If a file exists, append an additional number to the filename to make it unique
        filename = f"{base_filename}_{timestamp}_{counter}.py"
        counter += 1

    # Open the file with the unique filename in write mode
    with open(filename, "w") as file:
        # Write the extracted code to the file
        file.write(code)

    # Return the unique filename
    return filename

def read_from_file(subdirectory, filename):
    """
    Reads the content of a file from the specified subdirectory and filename.
    :param subdirectory: The subdirectory inside the 'prompts' directory where the file is located.
    :param filename: The name of the file to read.
    :return: The content of the file as a string.
    """
    path = os.path.join('prompts', subdirectory, filename)
    with open(path, 'r') as file:
        return file.read().strip()

def write_to_file(subdirectory, filename, content):
    """
    Writes content to a file in the specified subdirectory and filename.
    :param subdirectory: The subdirectory inside the 'prompts' directory where the file will be created/overwritten.
    :param filename: The name of the file to write.
    :param content: The content to write to the file.
    """
    path = os.path.join('prompts', subdirectory, filename)
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, 'w') as file:
        file.write(content)

# Additional utility functions for file handling can be added here.

def save_conversation(messages, filename='saved_conversations.txt'):
    while True:
        save_input = input("Would you like to save any portions of the conversation? (Y/N/EXIT): ")
        if save_input.upper() == 'Y':
            for message in messages:
                print(f"\n[Message Type]: {message['role']}\n[Content]: {message['content']}")
                save_message = input("Would you like to save this message? (Y/N): ")
                if save_message.upper() == 'Y':
                    with open(filename, 'a') as file:
                        file.write(f"[Message Type]: {message['role']}\n[Content]: {message['content']}\n\n")
        elif save_input.upper() == 'EXIT':
            break


from PyQt5 import QtWidgets
from PyQt5 import uic
import os
import sys
import logging as log
log.basicConfig(level=log.INFO)
logging = log.getLogger(__name__)

class ScriptHelpWidget(QtWidgets.QWidget):
    def __init__(self, selfself):
        super(ScriptHelpWidget, self).__init__()
        if getattr(sys, 'frozen', False):
            # frozen
            packagedir = os.path.dirname(sys.executable)+'/RTOC/RTOC_GUI'
        else:
            # unfrozen
            packagedir = os.path.dirname(os.path.realpath(__file__))
        uic.loadUi(packagedir+"/ui/scriptHelpWidget.ui", self)
        self.self = selfself
        self.logger = self.self.logger

        self.listWidget.clicked.connect(self.addFuncToScriptEdit)
        self.signalListWidget.clicked.connect(self.addSignalToScriptEdit)
        self.listWidget_default.clicked.connect(self.addDefaultToScriptEdit)
        self.listWidget_default_2.clicked.connect(self.addDefaultToScriptEdit2)

    def addFuncToScriptEdit(self):
        text = self.listWidget.selectedItems()[0].text()
        self.self.addTextToScriptEdit(text)

    def addSignalToScriptEdit(self):
        text = self.signalListWidget.selectedItems()[0].text()
        self.self.addTextToScriptEdit(text)

    def addDefaultToScriptEdit(self):
        text = self.listWidget_default.selectedItems()[0].text()
        self.self.addTextToScriptEdit(text)

    def addDefaultToScriptEdit2(self):
        text = self.listWidget_default_2.selectedItems()[0].text()
        self.self.addTextToScriptEdit(text)

    def updateListWidget(self):
        self.listWidget.clear()
        self.signalListWidget.clear()
        self.signalListWidget.addItem("clock")
        for element in self.logger.pluginParameters.keys():
            if self.logger.pluginStatus[element.split('.')[0]] == True:
                if element.split(".")[1] not in ["run", "smallGUI", 'widget', 'samplerate','lockPerpetialTimer']:
                    self.listWidget.addItem(element)
        for element in self.logger.pluginFunctions.keys():
            if self.logger.pluginStatus[element.split('.')[0]] == True:
                if element.split(".")[1] not in ["loadGUI", "updateT", "stream", "plot", "event", "createTCPClient", "close", "cancel", "start", "setSamplerate","setDeviceName",'setPerpetualTimer','setInterval','getDir']:
                    parStr = ', '.join(self.logger.pluginFunctions[element][1])
                    self.listWidget.addItem(element+"("+parStr+")")
        for element in self.logger.database.signalNames():
            self.signalListWidget.addItem(".".join(element))

    def closeEvent(self, event, *args, **kwargs):
        self.self.helpButton.setChecked(False)
        super(ScriptHelpWidget, self).closeEvent(event)