import time
import logging
import functools

import numpy as np
from qiskit import ClassicalRegister, QuantumCircuit

from qiskit.aqua.algorithms import QuantumAlgorithm
from qiskit.aqua import AquaError, PluggableType, get_pluggable_class
from qiskit.aqua.utils import find_regs_by_name
from qiskit.aqua.utils.backend_utils import is_aer_statevector_backend

logger = logging.getLogger(__name__)

class VQE(QuantumAlgorithm):
    """
    The Variational Quantum Eigensolver algorithm.

    See https://arxiv.org/abs/1304.3061
    """

    CONFIGURATION = {
        'name': 'VQE',
        'description': 'VQE Algorithm',
        'input_schema': {
            '$schema': 'http://json-schema.org/schema#',
            'id': 'vqe_schema',
            'type': 'object',
            'properties': {
                'operator_mode': {
                    'type': 'string',
                    'default': 'matrix',
                    'oneOf': [
                        {'enum': ['matrix', 'paulis', 'grouped_paulis']}
                    ]
                },
                'initial_point': {
                    'type': ['array', 'null'],
                    "items": {
                        "type": "number"
                    },
                    'default': None
                },
                'batch_mode': {
                    'type': 'boolean',
                    'default': False
                }
            },
            'additionalProperties': False
        },
        'problems': ['energy', 'ising'],
        'depends': ['optimizer', 'variational_form', 'initial_state'],
        'defaults': {
            'optimizer': {
                'name': 'L_BFGS_B'
            },
            'variational_form': {
                'name': 'RYRZ'
            },
            'initial_state': {
                'name': 'ZERO'
            }
        }
    }

    def __init__(self, operator, var_form, optimizer, operator_mode='matrix',
                 initial_point=None, batch_mode=False, aux_operators=None):
        """Constructor.

        Args:
            operator (Operator): Qubit operator
            operator_mode (str): operator mode, used for eval of operator
            var_form (VariationalForm): parametrized variational form.
            optimizer (Optimizer): the classical optimization algorithm.
            initial_point (numpy.ndarray): optimizer initial point.
            batch_mode (bool): evaluate parameter sets in parallel.
            aux_operators (list of Operator): Auxiliary operators to be evaluated at each eigenvalue
        """
        self.validate(locals())
        super().__init__()
        self._operator = operator
        self._var_form = var_form
        self._optimizer = optimizer
        self._operator_mode = operator_mode
        self._initial_point = initial_point
        if initial_point is None:
            self._initial_point = var_form.preferred_init_points
        self._optimizer.set_batch_mode(batch_mode)
        if aux_operators is None:
            self._aux_operators = []
        else:
            self._aux_operators = [aux_operators] if not isinstance(aux_operators, list) else aux_operators
        self._ret = {}
        self._eval_count = 0
        self._eval_time = 0
        logger.info(self.print_setting())

    @classmethod
    def init_params(cls, params, algo_input):
        """
        Initialize via parameters dictionary and algorithm input instance.

        Args:
            params (dict): parameters dictionary
            algo_input (EnergyInput): EnergyInput instance

        Returns:
            VQE: vqe object
        """
        if algo_input is None:
            raise AquaError("EnergyInput instance is required.")

        operator = algo_input.qubit_op

        vqe_params = params.get(QuantumAlgorithm.SECTION_KEY_ALGORITHM)
        operator_mode = vqe_params.get('operator_mode')
        initial_point = vqe_params.get('initial_point')
        batch_mode = vqe_params.get('batch_mode')

        # Set up initial state, we need to add computed num qubits to params
        init_state_params = params.get(QuantumAlgorithm.SECTION_KEY_INITIAL_STATE)
        init_state_params['num_qubits'] = operator.num_qubits
        init_state = get_pluggable_class(PluggableType.INITIAL_STATE,
                                         init_state_params['name']).init_params(init_state_params)

        # Set up variational form, we need to add computed num qubits, and initial state to params
        var_form_params = params.get(QuantumAlgorithm.SECTION_KEY_VAR_FORM)
        var_form_params['num_qubits'] = operator.num_qubits
        var_form_params['initial_state'] = init_state
        var_form = get_pluggable_class(PluggableType.VARIATIONAL_FORM,
                                       var_form_params['name']).init_params(var_form_params)

        # Set up optimizer
        opt_params = params.get(QuantumAlgorithm.SECTION_KEY_OPTIMIZER)
        optimizer = get_pluggable_class(PluggableType.OPTIMIZER,
                                        opt_params['name']).init_params(opt_params)

        return cls(operator, var_form, optimizer, operator_mode=operator_mode,
                   initial_point=initial_point, batch_mode=batch_mode,
                   aux_operators=algo_input.aux_ops)

    @property
    def setting(self):
        """Prepare the setting of VQE as a string."""
        ret = "Algorithm: {}\n".format(self._configuration['name'])
        params = ""
        for key, value in self.__dict__.items():
            if key != "_configuration" and key[0] == "_":
                if "initial_point" in key and value is None:
                    params += "-- {}: {}\n".format(key[1:], "Random seed")
                else:
                    params += "-- {}: {}\n".format(key[1:], value)
        ret += "{}".format(params)
        return ret

    def print_setting(self):
        """
        Preparing the setting of VQE into a string.

        Returns:
            str: the formatted setting of VQE
        """
        ret = "\n"
        ret += "==================== Setting of {} ============================\n".format(self.configuration['name'])
        ret += "{}".format(self.setting)
        ret += "===============================================================\n"
        ret += "{}".format(self._var_form.setting)
        ret += "===============================================================\n"
        ret += "{}".format(self._optimizer.setting)
        ret += "===============================================================\n"
        return ret

    def construct_circuit(self, parameter, backend=None, use_simulator_operator_mode=False):
        """Generate the circuits.

        Args:
            parameters (numpy.ndarray): parameters for variational form.
            backend (qiskit.BaseBackend): backend object.
            use_simulator_operator_mode (bool): is backend from AerProvider, if True and mode is paulis,
                           single circuit is generated.

        Returns:
            [QuantumCircuit]: the generated circuits with Hamiltonian.
        """
        input_circuit = self._var_form.construct_circuit(parameter)
        if backend is None:
            warning_msg = "Circuits used in VQE depends on the backend type, "
            from qiskit import BasicAer
            if self._operator_mode == 'matrix':
                temp_backend_name = 'statevector_simulator'
            else:
                temp_backend_name = 'qasm_simulator'
            backend = BasicAer.get_backend(temp_backend_name)
            warning_msg += "since operator_mode is '{}', '{}' backend is used.".format(
                self._operator_mode, temp_backend_name)
            logger.warning(warning_msg)
        circuit = self._operator.construct_evaluation_circuit(self._operator_mode,
                                                              input_circuit, backend, use_simulator_operator_mode)
        return circuit

    def _solve(self):
        opt_params, opt_val = self.find_minimum_eigenvalue()
        self._ret['eigvals'] = np.asarray([opt_val])
        self._ret['opt_params'] = opt_params
        qc = self._var_form.construct_circuit(self._ret['opt_params'])
        if self._quantum_instance.is_statevector:
            ret = self._quantum_instance.execute(qc)
            self._ret['eigvecs'] = np.asarray([ret.get_statevector(qc)])
        else:
            c = ClassicalRegister(self._operator.num_qubits, name='c')
            q = find_regs_by_name(qc, 'q')
            qc.add_register(c)
            qc.barrier(q)
            qc.measure(q, c)
            ret = self._quantum_instance.execute(qc)
            self._ret['eigvecs'] = np.asarray([ret.get_counts(qc)])

    def _get_ground_state_energy(self):
        if 'eigvals' not in self._ret:
            self._solve()
        self._ret['energy'] = self._ret['eigvals'][0]

    def _eval_aux_ops(self, threshold=1e-12):
        if 'opt_params' not in self._ret:
            self._get_ground_state_energy()
        wavefn_circuit = self._var_form.construct_circuit(self._ret['opt_params'])
        circuits = []
        values = []
        params = []
        for operator in self._aux_operators:
            if not operator.is_empty():
                temp_circuit = QuantumCircuit() + wavefn_circuit
                circuit = operator.construct_evaluation_circuit(self._operator_mode, temp_circuit,
                                                                self._quantum_instance.backend,
                                                                self._use_simulator_operator_mode)
                params.append(operator.aer_paulis)
            else:
                circuit = None
            circuits.append(circuit)

        if len(circuits) > 0:
            to_be_simulated_circuits = functools.reduce(lambda x, y: x + y, [c for c in circuits if c is not None])
            if self._use_simulator_operator_mode:
                extra_args = {'expectation': {
                    'params': params,
                    'num_qubits': self._operator.num_qubits}
                }
            else:
                extra_args = {}
            result = self._quantum_instance.execute(to_be_simulated_circuits, **extra_args)

            for operator, circuit in zip(self._aux_operators, circuits):
                if circuit is None:
                    mean, std = 0.0, 0.0
                else:
                    mean, std = operator.evaluate_with_result(self._operator_mode,
                                                              circuit, self._quantum_instance.backend,
                                                              result, self._use_simulator_operator_mode)
                mean = mean.real if abs(mean.real) > threshold else 0.0
                std = std.real if abs(std.real) > threshold else 0.0
                values.append((mean, std))
        if len(values) > 0:
            aux_op_vals = np.empty([1, len(self._aux_operators), 2])
            aux_op_vals[0, :] = np.asarray(values)
            self._ret['aux_ops'] = aux_op_vals

    def _run(self):
        """
        Run the algorithm to compute the minimum eigenvalue.

        Returns:
            Dictionary of results
        """
        if not self._quantum_instance.is_statevector and self._operator_mode == 'matrix':
            logger.warning('Qasm simulation does not work on {} mode, changing '
                           'the operator_mode to "paulis"'.format(self._operator_mode))
            self._operator_mode = 'paulis'

        self._use_simulator_operator_mode = \
            is_aer_statevector_backend(self._quantum_instance.backend) \
            and self._operator_mode != 'matrix'

        self._quantum_instance.circuit_summary = True
        self._eval_count = 0
        self._solve()
        self._get_ground_state_energy()
        self._eval_aux_ops()
        self._ret['eval_count'] = self._eval_count
        self._ret['eval_time'] = self._eval_time
        return self._ret

    # This is the objective function to be passed to the optimizer that is uses for evaluation
    def _energy_evaluation(self, parameters):
        """
        Evaluate energy at given parameters for the variational form.

        Args:
            parameters (numpy.ndarray): parameters for variational form.

        Returns:
            float or list of float: energy of the hamiltonian of each parameter.
        """
        num_parameter_sets = len(parameters) // self._var_form.num_parameters
        circuits = []
        parameter_sets = np.split(parameters, num_parameter_sets)
        mean_energy = []
        std_energy = []

        for idx in range(len(parameter_sets)):
            parameter = parameter_sets[idx]
            circuit = self.construct_circuit(parameter, self._quantum_instance.backend, self._use_simulator_operator_mode)
            circuits.append(circuit)

        to_be_simulated_circuits = functools.reduce(lambda x, y: x + y, circuits)
        if self._use_simulator_operator_mode:
            extra_args = {'expectation': {
                'params': [self._operator.aer_paulis],
                'num_qubits': self._operator.num_qubits}
            }
        else:
            extra_args = {}
        result = self._quantum_instance.execute(to_be_simulated_circuits, **extra_args)

        for idx in range(len(parameter_sets)):
            mean, std = self._operator.evaluate_with_result(
                self._operator_mode, circuits[idx], self._quantum_instance.backend, result, self._use_simulator_operator_mode)
            mean_energy.append(np.real(mean))
            std_energy.append(np.real(std))
            self._eval_count += 1
            logger.info('Energy evaluation {} returned {}'.format(self._eval_count, np.real(mean)))

        return mean_energy if len(mean_energy) > 1 else mean_energy[0]

    def find_minimum_eigenvalue(self, initial_point=None):
        """Determine minimum energy state.

        Args:
            initial_point (numpy.ndarray[float]) : initial point, or None
                if not provided.

        Returns:
            Optimized variational parameters, and corresponding minimum eigenvalue.

        Raises:
            ValueError:

        """
        initial_point = initial_point if initial_point is not None else self._initial_point

        nparms = self._var_form.num_parameters
        bounds = self._var_form.parameter_bounds

        if initial_point is not None and len(initial_point) != nparms:
            raise ValueError('Initial point size {} and parameter size {} mismatch'.format(len(initial_point), nparms))
        if len(bounds) != nparms:
            raise ValueError('Variational form bounds size does not match parameter size')
        # If *any* value is *equal* in bounds array to None then the problem does *not* have bounds
        problem_has_bounds = not np.any(np.equal(bounds, None))
        # Check capabilities of the optimizer
        if problem_has_bounds:
            if not self._optimizer.is_bounds_supported:
                raise ValueError('Problem has bounds but optimizer does not support bounds')
        else:
            if self._optimizer.is_bounds_required:
                raise ValueError('Problem does not have bounds but optimizer requires bounds')
        if initial_point is not None:
            if not self._optimizer.is_initial_point_supported:
                raise ValueError('Optimizer does not support initial point')
        else:
            if self._optimizer.is_initial_point_required:
                low = [(l if l is not None else -2 * np.pi) for (l, u) in bounds]
                high = [(u if u is not None else 2 * np.pi) for (l, u) in bounds]
                initial_point = self.random.uniform(low, high)

        start = time.time()
        logger.info('Starting optimizer bounds={}\ninitial point={}'.format(bounds, initial_point))
        sol, opt, nfev = self._optimizer.optimize(self._var_form.num_parameters, self._energy_evaluation,
                                                  variable_bounds=bounds, initial_point=initial_point)
        if nfev is not None:
            self._eval_count = self._eval_count if self._eval_count >= nfev else nfev
        self._eval_time = time.time() - start
        logger.info('Optimization complete in {}s found {} num evals {}'.format(
            self._eval_time, opt, self._eval_count))

        return sol, opt


import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import argparse
import torch.utils.data.sampler as sampler

from create_dataset import *
from utils import *

parser = argparse.ArgumentParser(description='Multi-task: Attention Network')
parser.add_argument('--weight', default='equal', type=str, help='multi-task weighting: equal, uncert, dwa, pcgrad')
parser.add_argument('--dataroot', default='/data/dataset/nyuv2', type=str, help='dataset root')
parser.add_argument('--temp', default=2.0, type=float, help='temperature for DWA (must be positive)')
parser.add_argument('--apply_augmentation', action='store_true', help='toggle to apply data augmentation on NYUv2')
parser.add_argument('--apply_weightdeacay', action='store_true', help='toggle to apply weight decay 1e-5 on learning rate')
parser.add_argument('--apply_pcgrad', action='store_true', help='toggle to apply gradient surgery')

opt = parser.parse_args()

import torch
import resnet

from resnet_dilated import ResnetDilated
#from aspp import DeepLabHead
from resnet import Bottleneck, conv1x1

class MTANDeepLabv3(nn.Module):
    def __init__(self):
        super(MTANDeepLabv3, self).__init__()
        backbone = ResnetDilated(resnet.__dict__['resnet18'](pretrained=True))
        ch = [64,128,256,512]
        #ch = [256, 512, 1024, 2048]

        self.class_nb = 13
        self.logsigma = nn.Parameter(torch.FloatTensor([-0.5, -0.5, -0.5]))

        self.tasks = ['1', '2', '3', '4', '5','6','7','8','9','10']
        #self.num_out_channels = {'segmentation': 13, 'depth': 1, 'normal': 3}

        self.shared_conv = nn.Sequential(backbone.conv1, backbone.bn1, backbone.relu1, backbone.maxpool)

        # We will apply the attention over the last bottleneck layer in the ResNet.
        self.shared_layer1_b = backbone.layer1[:-1]
        self.shared_layer1_t = backbone.layer1[-1]

        self.shared_layer2_b = backbone.layer2[:-1]
        self.shared_layer2_t = backbone.layer2[-1]

        self.shared_layer3_b = backbone.layer3[:-1]
        self.shared_layer3_t = backbone.layer3[-1]

        self.shared_layer4_b = backbone.layer4[:-1]
        self.shared_layer4_t = backbone.layer4[-1]

        # Define task specific attention modules using a similar bottleneck design in residual block
        # (to avoid large computations)
        self.encoder_att_1 = nn.ModuleList([self.att_layer(ch[0], ch[0] // 4, ch[0]) for _ in self.tasks])
        self.encoder_att_2 = nn.ModuleList([self.att_layer(2 * ch[1], ch[1] // 4, ch[1]) for _ in self.tasks])
        self.encoder_att_3 = nn.ModuleList([self.att_layer(2 * ch[2], ch[2] // 4, ch[2]) for _ in self.tasks])
        self.encoder_att_4 = nn.ModuleList([self.att_layer(2 * ch[3], ch[3] // 4, ch[3]) for _ in self.tasks])

        # Define task shared attention encoders using residual bottleneck layers
        # We do not apply shared attention encoders at the last layer,
        # so the attended features will be directly fed into the task-specific decoders.
        self.encoder_block_att_1 = self.conv_layer(ch[0], ch[1] // 4)
        self.encoder_block_att_2 = self.conv_layer(ch[1], ch[2] // 4)
        self.encoder_block_att_3 = self.conv_layer(ch[2], ch[3] // 4)

        self.down_sampling = nn.MaxPool2d(kernel_size=2, stride=2)
        self.final_pool = nn.AdaptiveAvgPool2d((1, 1))
        self.classfier = nn.ModuleList([nn.Linear(512, 10) for _ in self.tasks])
         # or 20

        # Define task-specific decoders using ASPP modules
        #self.decoders = nn.ModuleList([DeepLabHead(2048, self.num_out_channels[t]) for t in self.tasks])

    # def forward(self, x, out_size):
    def forward(self, x, task_id):
        img_size  = x.size()[-2:]
        # Shared convolution
        x = self.shared_conv(x)

        # Shared ResNet block 1
        u_1_b = self.shared_layer1_b(x)
        u_1_t = self.shared_layer1_t(u_1_b)

        # Shared ResNet block 2
        u_2_b = self.shared_layer2_b(u_1_t)
        u_2_t = self.shared_layer2_t(u_2_b)

        # Shared ResNet block 3
        u_3_b = self.shared_layer3_b(u_2_t)
        u_3_t = self.shared_layer3_t(u_3_b)

        # Shared ResNet block 4
        u_4_b = self.shared_layer4_b(u_3_t)
        u_4_t = self.shared_layer4_t(u_4_b)

        # Attention block 1 -> Apply attention over last residual block
        a_1_mask = [att_i(u_1_b) for att_i in self.encoder_att_1]  # Generate task specific attention map
        a_1 = [a_1_mask_i * u_1_t for a_1_mask_i in a_1_mask]  # Apply task specific attention map to shared features
        a_1 = [self.down_sampling(self.encoder_block_att_1(a_1_i)) for a_1_i in a_1]

        # Attention block 2 -> Apply attention over last residual block
        a_2_mask = [att_i(torch.cat((u_2_b, a_1_i), dim=1)) for a_1_i, att_i in zip(a_1, self.encoder_att_2)]
        a_2 = [a_2_mask_i * u_2_t for a_2_mask_i in a_2_mask]
        a_2 = [self.encoder_block_att_2(a_2_i) for a_2_i in a_2]

        # Attention block 3 -> Apply attention over last residual block
        a_3_mask = [att_i(torch.cat((u_3_b, a_2_i), dim=1)) for a_2_i, att_i in zip(a_2, self.encoder_att_3)]
        a_3 = [a_3_mask_i * u_3_t for a_3_mask_i in a_3_mask]
        a_3 = [self.encoder_block_att_3(a_3_i) for a_3_i in a_3]

        # Attention block 4 -> Apply attention over last residual block (without final encoder)
        a_4_mask = [att_i(torch.cat((u_4_b, a_3_i), dim=1)) for a_3_i, att_i in zip(a_3, self.encoder_att_4)]
        a_4 = [a_4_mask_i * u_4_t for a_4_mask_i in a_4_mask]

        for i, t in enumerate(self.tasks):
            if t == task_id:
                z = torch.flatten(a_4[i], 1)
                out = self.classfier[i](z)
                return out

    def att_layer(self, in_channel, intermediate_channel, out_channel):
        return nn.Sequential(
            nn.Conv2d(in_channels=in_channel, out_channels=intermediate_channel, kernel_size=1, padding=0),
            nn.BatchNorm2d(intermediate_channel),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=intermediate_channel, out_channels=out_channel, kernel_size=1, padding=0),
            nn.BatchNorm2d(out_channel),
            nn.Sigmoid())

    def conv_layer(self, in_channel, out_channel):
        downsample = nn.Sequential(conv1x1(in_channel, 4 * out_channel, stride=1),
                                   nn.BatchNorm2d(4 * out_channel))
        return Bottleneck(in_channel, out_channel, downsample=downsample)

'''
        # Task specific decoders
        out = [0 for _ in self.tasks]
        for i, t in enumerate(self.tasks):
            # out[i] = F.interpolate(self.decoders[i](a_4[i]), size=out_size, mode='bilinear', align_corners=True)
            out[i] = F.interpolate(self.decoders[i](a_4[i]), img_size, mode='bilinear', align_corners=True)
            if t == 'segmentation':
                out[i] = F.log_softmax(out[i], dim=1)
            if t == 'normal':
                out[i] = out[i] / torch.norm(out[i], p=2, dim=1, keepdim=True)
        return [out[0], out[1], out[2]], self.logsigma
'''

# define model, optimiser and scheduler
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Resnet_MTAN = MTANDeepLabv3().to(device)

from pcgrad import PCGrad

if opt.apply_pcgrad:
    optimizer = optim.Adam(Resnet_MTAN.parameters(), lr=1e-4)
    weight_optimizer = PCGrad(optimizer)
    print('Applying gradient surgery on optimizer.')
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=100, gamma=0.5)
else:
    if opt.apply_weightdeacay:
        optimizer = optim.Adam(Resnet_MTAN.parameters(), lr=1e-4, weight_decay=1e-5)
        print('Applying weight decay 1e-5 on learning rate.')
    else:
        optimizer = optim.Adam(Resnet_MTAN.parameters(), lr=1e-4)
        print('Not applying weight decay on learning rate.')
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=100, gamma=0.5)

print('Parameter Space: ABS: {:.1f}, REL: {:.4f}'.format(count_parameters(Resnet_MTAN),
                                                         count_parameters(Resnet_MTAN) / 24981069))
print('LOSS FORMAT: SEMANTIC_LOSS MEAN_IOU PIX_ACC | DEPTH_LOSS ABS_ERR REL_ERR | NORMAL_LOSS MEAN MED <11.25 <22.5 <30')

# define dataset

dataset_path = opt.dataroot
if opt.apply_augmentation:
    nyuv2_train_set = NYUv2(root=dataset_path, train=True, augmentation=True)
    print('Applying data augmentation on NYUv2.')
else:
    nyuv2_train_set = NYUv2(root=dataset_path, train=True)
    print('Standard training strategy without data augmentation.')

nyuv2_test_set = NYUv2(root=dataset_path, train=False)

batch_size = 8
nyuv2_train_loader = torch.utils.data.DataLoader(
    dataset=nyuv2_train_set,
    batch_size=batch_size,
    shuffle=True)

nyuv2_test_loader = torch.utils.data.DataLoader(
    dataset=nyuv2_test_set,
    batch_size=batch_size,
    shuffle=False)

# Train and evaluate multi-task network
if opt.apply_pcgrad:
    multi_task_trainer_pcgrad(nyuv2_train_loader,
                       nyuv2_test_loader,
                       Resnet_MTAN,
                       device,
                       weight_optimizer,
                       scheduler,
                       opt,
                       200)
else:
    multi_task_trainer(nyuv2_train_loader,
                       nyuv2_test_loader,
                       Resnet_MTAN,
                       device,
                       optimizer,
                       scheduler,
                       opt,
                       200)


import gulp
import os, sys, random
from colored import fg, bg, attr

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px

import pandas as pd
import numpy as np
from sklearn.metrics import mean_squared_error
# ase API
from ase import Atoms
# quippy API
from quippy.potential import Potential

print()
print(f'{fg(15)} {bg(5)} Visualisation {attr(0)}')
print()
print()

binwidth = 0.05
sig2 = 0.005

Arg = sys.argv
EIGVEC = Arg[1]
STEP = int(Arg[2])
RANK_from = int(Arg[3])
RANK_to = int(Arg[4])
Breath = Arg[5]
cutoff= float(Arg[6])
sparse = int(Arg[7])

EIGVEC = EIGVEC.split()
_EIGVEC = '-'.join(EIGVEC)

wd_name = f'GAP_{_EIGVEC}_{STEP}_{RANK_from}-{RANK_to}_{Breath}_{cutoff}_{sparse}'

GULP = gulp.GULP(STEP, EIGVEC, SP='set')

cwd = os.getcwd()
wd = [os.path.join(cwd, x) for x in os.listdir('./') if os.path.isdir(x) and wd_name in x]
try:
    full_wd = wd[0]
except IndexError:
    print("WARNING: Probably you didn't run {gap_1} and {gap_2}")
    sys.exit()

ext_fpath = os.path.join(full_wd, 'ext_movie.xyz')
FIT_dir_path = os.path.join(full_wd, 'FIT')
FIT_dir_path = os.path.join(full_wd, 'FIT')

Training_xyz_path = os.path.join(FIT_dir_path, 'Training_set.xyz')
Valid_xyz_path = os.path.join(FIT_dir_path, 'Valid_set.xyz')

#############################################################
# prepare dimer curve data using the Interatomic  potential #
#############################################################
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)

print(f"{fg(1)} Al-F GAP pairwise interaction {attr(0)}")
dimers = [Atoms("AlF", positions=[[0,0,0], [x, 0,0]]) for x in np.arange(0.0, 6.02, 0.02)] #int(cutoff)+1.02, 0.02)]
print(full_wd)
pot = Potential('IP GAP', param_filename='%s/FIT/GAP.xml' % (full_wd))
dimer_curve = []
for dim in dimers:
    dim.set_calculator(pot)
    dimer_curve.append(dim.get_potential_energy())
x_axis = np.array([dim.positions[1,0] for dim in dimers])
y_axis = np.array(dimer_curve)
data = np.c_[x_axis, y_axis]
output_list = data.tolist()
df = pd.DataFrame (output_list, columns = ['r', 'Al-F(GAP)'])
del dim, dimers, dimer_curve, x_axis, y_axis, data, output_list

# Al-F scaled to match with scaled F-F
dimers_AlF_scaled = [Atoms("AlF", positions=[[0,0,0], [round(x/np.sqrt(3), 3),0,0]]) for x in np.arange(0.0, 6.02, 0.02)]
dimer_curve_AlF_scaled = []
for dim_AlF_scaled in dimers_AlF_scaled:
    dim_AlF_scaled.set_calculator(pot)
    dimer_curve_AlF_scaled.append(dim_AlF_scaled.get_potential_energy())
x_axis_AlF_scaled = np.array([dim_AlF_scaled.positions[1,0] for dim_AlF_scaled in dimers_AlF_scaled])
y_axis_AlF_scaled = np.array(dimer_curve_AlF_scaled)
data_AlF_scaled = np.c_[x_axis_AlF_scaled, y_axis_AlF_scaled]
output_list_AlF_scaled = data_AlF_scaled.tolist()
df_AlF_scaled = pd.DataFrame (output_list_AlF_scaled, columns = ['r_scaled', 'Al-F(GAP)_scaled'])
del dim_AlF_scaled, dimers_AlF_scaled, dimer_curve_AlF_scaled, x_axis_AlF_scaled, y_axis_AlF_scaled, data_AlF_scaled, output_list_AlF_scaled
print()

print(f"{fg(3)} Al-Al GAP  pairwise interaction {attr(0)}")
dimers = [Atoms("AlAl", positions=[[0,0,0], [x, 0,0]]) for x in np.arange(0.0, 6.02, 0.02)]
dimer_curve = []
for dim in dimers:
    dim.set_calculator(pot)
    dimer_curve.append(dim.get_potential_energy())
x_axis = np.array([dim.positions[1,0] for dim in dimers])
y_axis = np.array(dimer_curve)
data = np.c_[x_axis, y_axis]
output_list = data.tolist()
dff = pd.DataFrame (output_list, columns = ['x2', 'Al-Al(GAP)'])
del dimers, dimer_curve, x_axis, y_axis, data, output_list
print()

print(f"{fg(2)} F-F GAP pairwise interaction {attr(0)}")
dimers = [Atoms("FF", positions=[[0,0,0], [x,0,0]]) for x in np.arange(0.0, 6.02, 0.02)]
dimer_curve = []
for dim in dimers:
    dim.set_calculator(pot)
    dimer_curve.append(dim.get_potential_energy())
x_axis = np.array([dim.positions[1,0] for dim in dimers])
y_axis = np.array(dimer_curve)
data = np.c_[x_axis, y_axis]
output_list = data.tolist()
dfff = pd.DataFrame (output_list, columns = ['x3', 'F-F(GAP)'])
del dimers, dimer_curve, y_axis, data, output_list
print()

df = df.join(dff)
df = df.join(dfff)
df = df.join(df_AlF_scaled)
df.drop(columns=['x2', 'x3'], inplace=True)
del dff, dfff, df_AlF_scaled

print('\n\n\nPlotting the pairwise interaction energy as a function of interatomic distances...\n\n\n')

###################################################
# calculating Interatomic distance and binning it #
###################################################
with open(Training_xyz_path, 'r') as f:
    lines = f.readlines()
no_of_atoms = int(lines[0])
lines = [x for x in lines if len(x) > 10 and 'Properties' not in x][:-2]

coordinates = []
ID = []
for i in lines:
    line = [float(x) for x in i.split()[1:]][:3]
    coordinates += line
    ID.append( i.split(' ')[0])
del lines

From = []
To = []
with open(ext_fpath, 'r') as f:
    lines = f.readlines()
for numi, i in enumerate(lines):
    if len(i) <= 10:
        From.append(numi)
        To.append(numi)

To.append(len(lines))
To = To[1:]

block = {From[i]: To[i] for i in range(len(From))}
del From, To
keys_list = list(block.keys())  # shuffle() wants a list
random.shuffle(keys_list)       # randomize the order of the keys

nkeys_80 = int(1.0 * len(keys_list))  # how many keys does 80% equal
keys_80 = keys_list[:nkeys_80]
keys_20 = keys_list[nkeys_80:]
del nkeys_80

train_80 = {k: block[k] for k in keys_80}
valid_20 = {k: block[k] for k in keys_20}
del keys_80, keys_20

coordinates = np.asarray(coordinates)
coordinates = np.reshape(coordinates, (len(train_80.keys()), no_of_atoms, 3))
ID = np.asarray(ID)
ID = np.reshape(ID, (len(train_80.keys()), no_of_atoms))

all_het_dist = []
all_homo_dist = []

for numi, i in enumerate(coordinates):
    nbins, npairs_all, npairs_het, npairs_homo, all_dist, het_dist, homo_dist, opdata = GULP.RDF(numi+1, no_of_atoms, i, ID[numi], binwidth, sig2)
    all_het_dist += het_dist
    all_homo_dist += homo_dist

#################################
# Plotting Born-Mayer, GAP, RDF #
#################################
# E vs r
fig = go.FigureWidget()

# Generated Born-Mayer potential
def BM(x):
    return 3760*np.exp(-x/0.222)

def deriv_BM(x):
    return -1880000*np.exp(-500*x/111)/111

def buck4(x):           # 2.73154 Å F-F distance
    if x.all() < 2.0:
        return 1127.7*np.exp(-x/0.2753)
    elif 2.0 <= x.all() < 2.726:
        return -3.976*x**5 + 49.0486*x4 -241.8573*x**3+ 597.2668*x**2 -741.117*x + 371.2706
    elif 2.726 <= x.all() < 3.031:
        return -0.361*x**3 +  3.2362*x**2 -9.6271*x +9.4816
    elif x.all() >= 3.031:
        return -15.83/P3035**6

# Born-Mayer Al-F potential
BM_color = 'rgb(10, 120, 24)'
df['Al-F(BM)'] = BM(x_axis)

trace1 = fig.add_scatter(x=x_axis, y=BM(x_axis), mode='lines', name='Al-F Born-Mayer',\
        line = dict(shape='linear', color=BM_color, dash='dot')
        )
# Buckingham 4-region F-F potential
df['F-F(buck4)'] = buck4(x_axis)
df.to_csv(f'{full_wd}/GAP_pot_tabulated.csv', index=False)

trace2 = fig.add_scatter(x=x_axis, y=buck4(x_axis), mode='lines', name='F-F Buck4',\
        line = dict(shape='linear', color='firebrick', dash='dot')
        )

#####################
### GAP potential ###
#####################
# Al-F
trace3 = fig.add_scatter(x=df['r'], y=df[df.columns[1]], mode='lines', name='Al-F GAP potential',\
        line = dict(shape='linear', color = BM_color))#, secondary_y=False,)

## Al-F (same results but the data points' x-axis is match with F-F scaled)
#trace_ = fig.add_scatter(x=df['r_scaled'], y=df['Al-F(GAP)_scaled'], mode='lines', name='Al-F GAP potential_2',\
#        line=dict(shape='linear', color=BM_color))

# F-F original
trace4 = fig.add_scatter(x=df['r'], y=df['F-F(GAP)'], mode='lines', name='F-F GAP potential',\
line = dict(shape = 'linear', color = 'firebrick')) # , secondary_y=False,)

# F-F scaled
scaling = df['r'].tolist()
scaling = [round(x/np.sqrt(3), 3) for x in scaling]
trace5 = fig.add_scatter(x=df['r_scaled'], y=df['F-F(GAP)'], mode='lines', name='F-F GAP potential_scaling', visible='legendonly')
df.drop(columns=['Al-F(BM)', 'Al-Al(GAP)'], inplace=True)

# Al-F + F-F
df['GAP_sum'] = df['F-F(GAP)'] + df['Al-F(GAP)_scaled']
df.to_csv('df_gap_sum.csv')
trace6 = fig.add_scatter(x=df['r_scaled'], y=df['GAP_sum'], mode='lines', name='sum(GAP)', visible='legendonly')

## MSE (± 0.5 from the equilibrium interatomic distnace)
from_point = list(df['r']).index([x for x in df['r'] if 1.57705-0.5 < x][0])
to_point = list(df['r']).index([x for x in df['r'] if x < 1.57705+0.5][-1])
MSE_catan = round(mean_squared_error(df['Al-F(GAP)'][from_point:to_point], BM(x_axis)[from_point:to_point], squared=False), 4)
from_point_a = list(df['r']).index([x for x in df['r'] if 2.73154-0.5 < x < 2.73154+0.5][0])
to_point_a = list(df['r']).index([x for x in df['r'] if x < 2.73154+0.5][-1])
MSE_an = round(mean_squared_error(df['F-F(GAP)'][from_point_a:to_point_a], buck4(x_axis)[from_point_a:to_point_a], squared=False), 4)
with open(f'{wd_name}/MSE.txt', 'w') as f:
    f.write(str(MSE_catan))
    f.write('\n')
    f.write(str(MSE_an))
print(f'RMSE(cat-an): {MSE_catan}')
print(f'RMSE(an-an): {MSE_an}')

# Histogram above the potential figure (uppger panel)
trace7 = fig.add_histogram(x=all_het_dist, xbins=dict(start=0, end=6, size=0.005), marker_color=BM_color,\
                            name='Number of hetero species interatomic distance', yaxis='y2')
trace8 = fig.add_histogram(x=all_homo_dist, xbins=dict(start=0, end=6, size=0.005), marker_color='firebrick',\
                            name='Number of homo species interatomic distance', yaxis='y2')

fig.layout = dict(xaxis=dict(domain=[0, 0.8], showgrid=False, zeroline=False, title='Interatomic distance / Å'),
                  yaxis=dict(domain=[0, 0.8], range=[-20, 50], showgrid=False, zeroline=True, title='Potential energy / eV'),
                  margin=dict(l=80, r=80, t=80, b=150),
                  width=1800,
                  height=800,
                  hovermode='closest',
                  bargap=0.8,
                  xaxis2=dict(domain=[0.85, 1], showgrid=False, zeroline=False, ),
                  yaxis2=dict(domain=[0.85, 1], showgrid=False, zeroline=False, title='Count'),
                  font=dict(size=20),
                  )

# Transparent vertical region where from the shortest to longest interatomic distance covered by the training structure
fig.add_vrect(
    x0=min(all_het_dist) ,x1=max(all_het_dist) ,
    fillcolor=BM_color, opacity=0.4,
    layer="below", line_width=1,)

fig.add_vrect(
    x0=min(all_homo_dist) ,x1=max(all_homo_dist) ,
    fillcolor='firebrick', opacity=0.4,
    layer="below", line_width=1,)

# Vertial-dash line to show equilibrium interatomic distances for Al-F, F-F
fig.add_vline(x=1.57705, line_width=2, line_dash="dash", line_color=BM_color)
fig.add_vline(x=2.73154, line_width=2, line_dash="dash", line_color="firebrick")
fig.add_annotation(
            #size=15,
            x=0.6,
            y=0.7,
            text=f"RMSE(Al-F) = {MSE_catan}
 RMSE(F-F) = {MSE_an}",
            xanchor='left',
            xref="paper",
            yref="paper")

#fig.add_annotation(
#            #size=15,
#            x=0,
#            y=-0.25,
#            text=f"RMSE = {MSE_catan} (at nearest distance > 1.57 Å \
#between V(GAP[Al-F]) and V(BM[Al-F])
 RMSE = {MSE_an} \
#(at nearest distance > 2.7 Å between V(GAP[F-F]) and V(buck4[F-F])",
#            xanchor='left',
#            xref="paper",
#            yref="paper")

fig.write_html(f'./{wd_name}/plot.html')

print(f'\n\n\n The plot (./{wd_name}/plot.html) is saved -- Good luck!\n\n\n')


from openai import OpenAI
from decouple import config

def get_openai_response(input_text):
    openai_api_key = config('OPENAI_API_KEY')

    client = OpenAI(api_key=openai_api_key)

    response = client.chat.completions.create(
        model="gpt-3.5-turbo-1106",
        messages=[
            {"role": "system", "content": "HealthPoint a diagnosis chatbot that also give precautions and only answers medical or health questions"},
            {"role": "user", "content": input_text}
        ]
    )
    return response.choices[0].message.content


import mimetypes
import re
from threading import Thread

from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import (QDialog, QFileDialog, QGridLayout, QLabel,
                               QLineEdit, QMainWindow, QMessageBox,
                               QPushButton, QStackedWidget, QVBoxLayout,
                               QWidget)

from audio_cutter import AudioCutter
from cut_files_view import CutFilesView
from select_files_view import SelectFilesView

class MainWindow(QMainWindow):
    def __init__(self) -> None:
        super().__init__()
        self.audio_cutter = AudioCutter()

        self.create_layout()

        self.select_files_view.files_selected.connect(self.on_files_selected)

    def create_layout(self) -> None:
        self.setWindowTitle("App")
        self.resize(600, 200)

        self.stack = QStackedWidget()
        self.select_files_view = SelectFilesView(self.audio_cutter)
        self.cut_files_view = CutFilesView(self.audio_cutter)

        self.stack.addWidget(self.select_files_view)
        self.stack.addWidget(self.cut_files_view)
        self.setCentralWidget(self.stack)

        self.stack.setCurrentWidget(self.select_files_view)

    @Slot()
    def on_files_selected(self) -> None:
        self.stack.setCurrentWidget(self.cut_files_view)
        # Running in a separate thread so as not to block UI.
        # thread = Thread(target=self.audio_cutter.start_cutting)
        # thread.start()
        self.audio_cutter.start_cutting()


from habitat import Config, logger
from habitat_baselines.rl.ppo import PPOTrainer, PPO
from custom_pointnav_policy import CustomPointNavPolicy, CustomPointNavNet

class CustomPPOTrainer(PPOTrainer):

	def _setup_actor_critic_agent(self, ppo_cfg: Config) -> None:
		r"""Sets up actor critic and agent for PPO.

		Args:
			ppo_cfg: config node with relevant params

		Returns:
			None
		"""
		logger.add_filehandler(self.config.LOG_FILE)
		#print(ppo_cfg)

		# consolidate all net hyperparam in net_args
		# alternative would be to modify this method
		# which would cause further modification in this class
		ppo_cfg.net_args.hidden_size = ppo_cfg.hidden_size
		self.actor_critic = PreTrainedPointNavPolicy(
			observation_space=self.envs.observation_spaces[0],
			action_space=self.envs.action_spaces[0],
			hidden_size=ppo_cfg.net_args,
			goal_sensor_uuid=self.config.TASK_CONFIG.TASK.GOAL_SENSOR_UUID,
		)
		self.actor_critic.to(self.device)

		self.agent = PPO(
			actor_critic=self.actor_critic,
			clip_param=ppo_cfg.clip_param,
			ppo_epoch=ppo_cfg.ppo_epoch,
			num_mini_batch=ppo_cfg.num_mini_batch,
			value_loss_coef=ppo_cfg.value_loss_coef,
			entropy_coef=ppo_cfg.entropy_coef,
			lr=ppo_cfg.lr,
			eps=ppo_cfg.eps,
			max_grad_norm=ppo_cfg.max_grad_norm,
			use_normalized_advantage=ppo_cfg.use_normalized_advantage,
		)


from freezegun import freeze_time

from database import orders
from database.schemas import Chips
from database.schemas import Drink
from database.schemas import ExtraCheese
from database.schemas import ExtraTomato
from database.schemas import Hamburger
from database.schemas import Meat
from database.schemas import Order
from tests.utils import assert_dicts

@freeze_time('2020-02-10')
def test_calculate_prices_1(order_1):
    expected = Order(
        barista='txema',
        hamburgers=[
            Hamburger(
                meats=[
                    Meat(
                        type='pollo',
                        size='250g',
                        cooked='al punto',
                        price=2.5,
                    )
                ],
                extra_cheese=ExtraCheese(
                    type='cheddar',
                    price=1.5,
                ),
                extra_tomato=ExtraTomato(
                    type='normal',
                    price=1.0,
                ),
                price=10.0,
            ),
        ],
        chips=[
            Chips(
                type='gajo',
                size='pequeñas',
                price=2.5,
            ),
        ],
        price=12.5,
        promotions=[],
    )
    result = orders.calculate_prices(order=order_1)
    assert_dicts(original=result.dict(), expected=expected.dict())

@freeze_time('2020-02-10')
def test_calculate_prices_2(order_2):
    expected = Order(
        barista='txema',
        hamburgers=[
            Hamburger(
                meats=[
                    Meat(
                        type='cerdo',
                        size='250g',
                        cooked='al punto',
                        price=2.5,
                    ),
                    Meat(
                        type='cerdo',
                        size='380g',
                        cooked='al punto',
                        price=3.5,
                    ),
                ],
                extra_tomato=ExtraTomato(
                    type='normal',
                    price=1.0,
                ),
                price=12.0 * (100 - 15) / 100,
            ),
        ],
        chips=[
            Chips(
                type='de la abuela',
                size='grandes',
                price=3.5,
            ),
        ],
        drinks=[
            Drink(
                type='burribeer',
                price=2.5,
            ),
        ],
        price=16.2,
        promotions=['burrimenu'],
    )
    result = orders.calculate_prices(order=order_2)
    assert_dicts(original=result.dict(), expected=expected.dict())

@freeze_time('2020-02-10')
def test_calculate_prices_3(order_3):
    expected = Order(
        barista='txema',
        chips=[
            Chips(
                type='deluxe',
                size='grandes',
                price=3.5,
            ),
            Chips(
                type='gajo',
                size='grandes',
                price=3.5,
            ),
        ],
        drinks=[
            Drink(
                type='burribeer',
                price=2.5,
            ),
        ],
        price=9.5,
        promotions=[],
    )
    result = orders.calculate_prices(order=order_3)
    assert_dicts(original=result.dict(), expected=expected.dict())

@freeze_time('2020-10-01 17:00:00')
def test_order_is_ready_listo(order_data):
    assert orders.order_is_ready(order=order_data) == 'listo'


# #from numpy import array, zeros
# from array import *
import numpy as np
#from numpy import fabs

'''
a=np.array([[25,5,1],
        [64,8,1],
        [144,12,1]],float)
b=[106.8,177,279.2]
n= len(b)
x= np.zeros(n,float)

# Elimination
for k in range(n - 1):
    for i in range(k + 1, n):
        if a[i, k] == 0:
            continue
        factor = a[k, k] / a[i, k]
        for j in range(k, n):
            a[i, j] = a[k, j] - a[i, j] * factor
        b[i] = b[k] - b[i] * factor
print(a)

print(b)

# Back-Substitution
x[n - 1] = b[n - 1] / a[n - 1, n - 1]
for i in range(n - 2, -1, -1):
    sum_ax = 0
    for j in range(i + 1, n):
        sum_ax += a[i, j] * x[j]
    x[i] = (b[i] - sum_ax) / a[i, i]

print(x)
'''

### Gauss Elimination Method with Partial Pivoting
##3 defining array
## Coefficient Matrix
'''
a= np.array([[0,7,-1,3,1],
             [0,3,4,1,7],
             [6,2,0,2,-1],
             [2,1,2,0,2],
             [3,4,1,-2,1]],float)
## Constant vector
b = np.array([5,7,2,3,4],float)
'''
'''
a=np.array([[25,5,1],
        [64,8,1],
        [144,12,1]],float)
b=np.array([106.8,177,279.2],float)
'''
a=np.array([[20,15,10],
            [-3,-2.249,7],
            [5,1,3]],float)
b=np.array([45,1.751,9],float)

## length of the vector
n= len(b)
# defining zeros to fill the entries of x
x= np.zeros(n,float)
##

## --------------Partial Pivoting---------------
## if there is zero on the main diagonal the we have to interchange the row with another row which has greater value then zero
for k in range(n-1):
    if abs(a[k,k])<1.0e-10:
        for i in range(k+1, n):  ### I have to check here what if i take n instead of (n-1), can we interchange the pivot row with the last row.
            if abs(a[i,k])> abs(a[k,k]): #we can also write (1.0e-10) instead of a([k,k])### it doesn't matter whether we take n or n-1in the previous range.
                a[[i,k]]=a[[k,i]]
                b[[k,i]]=b[[i,k]]
                break

    # Elimination---->

    #for k in range(n-1):
    for i in range(k+1,n):
        if a[i,k]==0:
            continue
        factor= a[k,k]/a[i,k]
        for j in range(k,n):
            a[i,j]= a[k,j]- a[i,j]*factor
        b[i]=b[k]-b[i]*factor
print("the upper triangular matrix ")
U=a
print(np.round(U,1))
## back-Substitution---->

x[n-1]= b[n-1]/a[n-1,n-1]
for i in range(n-2,-1,-1):
    sum_ax=0
    for j in range(i+1,n):
        sum_ax+=a[i,j]*x[j]
    x[i]= (b[i]-sum_ax)/a[i,i]

print("The solution vector is: ")
print(np.round(x,1))


# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Private helpers for futures."""

import logging
import threading

_LOGGER = logging.getLogger(__name__)

def start_daemon_thread(*args, **kwargs):
    """Starts a thread and marks it as a daemon thread."""
    thread = threading.Thread(*args, **kwargs)
    thread.daemon = True
    thread.start()
    return thread

def safe_invoke_callback(callback, *args, **kwargs):
    """Invoke a callback, swallowing and logging any exceptions."""
    # pylint: disable=bare-except
    # We intentionally want to swallow all exceptions.
    try:
        return callback(*args, **kwargs)
    except Exception:
        _LOGGER.exception('Error while executing Future callback.')


"""
@author: varulobo

Siemens coding test for practise

"""

''' Question 1 a:
Provide 2 or 3 different ways to calculate the pair of values (one value in each array) with the smallest non-negative difference.

Return the elements in the array and the smallest non-negative difference.'''

def func(arr1, arr2):

    lowest_num = []

    for i in arr1:

        for j in arr2:

            lowest_num.append(abs(i-j))

    return min(lowest_num)

arr1 = [47,24,95,184,13,3,12,18]
arr2 = [83,9,32,29,52,90,108,14]

L=func(arr1,arr2)

for i in range(0,len(arr1),1):

    for j in range(0,len(arr2),1):

        if abs(arr1[i] - arr2[j])==L:

            print("The number in the 1st array is:" + str(arr1[i]))
            print("The number in the 2nd array is:" + str(arr2[j]))
            print("The smallest difference is:" + str(L))
            break


from selenium import webdriver

rootPath = ".."
driver = webdriver.Chrome(
    executable_path="{}/chrome/chromedriver74".format(rootPath),
)

url = "http://dart.fss.or.kr/"
driver.get(url)

driver.find_element_by_id("textCrpNm")\
    .send_keys("셀트리온")

driver.find_element_by_xpath("//*[@id='searchForm']/fieldset/p[4]/input")\
    .click()
pageString = driver.page_source
print(pageString)


import pandas as pd
from flask import Flask, render_template
from datetime import date

month = date.today().strftime("%b-%Y")
app = Flask(__name__)
app.config['STATIC_FOLDER'] = 'static'

@app.route('/')
def scoreboard():
    df = pd.read_csv(f"{month}_Summary.csv")
    limited_data = df.head(25).to_dict(orient='records')  # First 15 rows
    full_data = df.to_dict(orient='records')  # All rows
    return render_template('scoreboard.html', limited_data=limited_data, full_data=full_data)


from flask_restful import Resource

from flask_restful import request, abort
from datetime import datetime

# models
from apps.api.models import db
from apps.api.models.models import App

# resources
from apps.api.endpoints.app.fields import all_apps, marshal_with
from apps.api.endpoints.app.parsers import post_app, put_app

# security
from apps.api.endpoints.security import decorators as auth

class AppEndpoint(Resource):

    @auth.login_required
    @marshal_with(all_apps)
    def get(self):
        return db.session.query(App).limit(25).all()

    @auth.login_required
    @marshal_with(all_apps)
    def post(self):
        args = post_app()
        try:
            posted = App()
            posted.name = args.name
            posted.public_key = args.public_key
            if 'is_active' in request.json:
                posted.is_active = args.is_active
            else:
                posted.is_active = False
            posted.created_at = datetime.now()
            db.session.add(posted)
            db.session.commit()
            return db.session.query(App).limit(25).all()
        except Exception as e:
            return abort(400, message='Your request has been failed')

class AppUidEndpoint(Resource):

    @auth.login_required
    @marshal_with(all_apps)
    def get(self, id):
        return db.session.query(App).get(id)

    @auth.login_required
    @marshal_with(all_apps)
    def delete(self, id):
        delete_app = db.session.query(App).get(id)
        db.session.delete(delete_app)
        db.session.commit()
        return db.session.query(App).limit(25).all()

    @auth.login_required
    @marshal_with(all_apps)
    def put(self, id):
        try:
            args = put_app()
            update_app = db.session.query(App).get(id)
            update_app.name = args.name
            update_app.public_key = args.public_key
            if 'is_active' in request.json:
                update_app.is_active = args.is_active
            else:
                update_app.is_active = False
            db.session.commit()
            return db.session.query(App).limit(25).all()
        except Exception as e:
            return abort(400, message='Your request has been failed')


from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
db = "https://embedded-systems-cf93d-default-rtdb.europe-west1.firebasedatabase.app/"
keyfile = "embedded-systems-cf93d-firebase-adminsdk-amky8-e0a50b80ba.json"
scopes = [
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/firebase.database"
]

credentials = service_account.Credentials.from_service_account_file(keyfile, scopes=scopes)

authed_session = AuthorizedSession(credentials)

def updatefree(space, status):
    path = f"parkingspaces/{space}.json"

    if status == 'true':
        update = {"Free": "True"}
    else:
        update = {"Free": "False"}

    resp = authed_session.patch(db + path, json=update)

    if resp.ok:
        print("Updated free status of space {}".format(space))
    else:
        raise


from typing import Any, List, Tuple

from auth.datadef import UserInfo
from base.model import db
from base.store import Store
from connector.gino import get_bind
from ..cfg import logger
from ..command import Command
from ..context import Context
from ..datadef import Initiator
from ..entity import Entity
from ..event import Event, EventEntity
from ..proxy import Proxy
from ..response import BaseResponse, Response
from ..statemgr.state_manager import StateMgr
from .domain_handler import DomainHandler
from .domain_register import DomainRegister

class DomainProcess(DomainRegister, DomainHandler):
    def __init__(self, user: UserInfo, initiator: Initiator):
        self.__store__ = Store()
        self.__context__ = Context(self, user, initiator)
        self.__response__ = Response()
        self.__statemgr__ = StateMgr(self)
        self.__proxy__ = Proxy(self, self.__statemgr__)
        self.__command__ = Command(self.__context__, self.__proxy__)
        self.__event__ = Event(self, self.__statemgr__)

    def process_command(self, entity_name: str, data: dict):
        logger.debug("> Process command")
        Entity = self.lookup_entity(entity_name)
        entity = Entity(data=data)
        command = self.lookup_command_handler(Entity)
        self.command.push((self.__namespace__, command, entity))
        # command = self.lookup_command_handler(entity)
        # [command_process for command_process in command.commit()]

    async def commit(self) -> List[BaseResponse]:
        async def distribute_aggregate(aggregate: Tuple[str, Entity, Any]):
            if aggregate is None:
                return
            logger.debug(
                "~~~> Aggregate: %r"
                % (
                    (
                        aggregate[0],
                        aggregate[1].__class__.__name__,
                        aggregate[2].__name__,
                    ),
                )
            )
            if isinstance(aggregate[1], EventEntity):
                await self.event.execute(aggregate)
            if isinstance(aggregate[1], BaseResponse):
                self.response.push(aggregate)

        async def _commit():
            async for aggregate in self.command.commit():
                await distribute_aggregate(aggregate)
            # await self.event.commit()
            state_msg = [result async for result in self.statemgr.commit()]
            logger.info(">>>> State_msg: \n%r", state_msg)
            return [resp async for resp in self.response.commit()]

        con = await get_bind()
        async with con.transaction():
            return await _commit()

    @property
    def command(self) -> Command:
        return self.__command__

    @property
    def event(self) -> Event:
        return self.__event__

    @property
    def store(self) -> Store:
        return self.__store__

    @property
    def context(self) -> Context:
        return self.__context__

    @property
    def response(self) -> Response:
        return self.__response__

    @property
    def proxy(self) -> Proxy:
        return self.__proxy__


# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError

class ResPartner(models.Model):
    _inherit = "res.partner"

    rea_office = fields.Many2one("res.country.state", string="Office Province")
    rea_code = fields.Char("REA Code", size=20)
    rea_capital = fields.Float("Share Capital")
    rea_member_type = fields.Selection(
        [("SU", "Unique Member"), ("SM", "Multiple Members")], "Member Type"
    )
    rea_liquidation_state = fields.Selection(
        [("LS", "In liquidation"), ("LN", "Not in liquidation")], "Liquidation State"
    )

    @api.constrains("rea_office", "rea_code", "company_id")
    def constrain_rea_code(self):
        for partner in self:
            if not partner.rea_office or not partner.rea_code:
                continue
            rea_domain = [
                ("rea_office", "=", partner.rea_office.id),
                ("rea_code", "=", partner.rea_code),
                ("company_id", "=", partner.company_id.id),
                ("id", "!=", partner.id),
            ]
            other_rea_partners = self.search(rea_domain)
            if other_rea_partners:
                raise ValidationError(
                    _(
                        "The REA Code and Office Province must "
                        "be unique per company.\n"
                        "Please edit '{this_partner}' "
                        "or '{other_partners}' and try again."
                    ).format(
                        this_partner=partner.display_name,
                        other_partners=", ".join(
                            other_rea_partners.mapped("display_name")
                        ),
                    )
                )


# Taken from Geeksforgeeks & this book
'''
Binary tree: each node has up to 2 children
Ternary tree: each node has up to 3 children
so on and so forth...

Binary search tree: a special binary tree, every node fits a specific order
    if value < root, add it to left child
    if value > root, add it to right child
    if first level full, repeat progress as you go to higher lvls, putting new values at new spots

Full binary tree: every node has either 0/2 children, or no nodes have only one child
Perfect binary tree: tree has max. nodes for its lvl, all leaf nodes at same lvl. (tree looks like a complete pyramid)
Degenerate tree: every node has exactly one child, such trees are same as linked list

'''

class Node:

    def __init__(self, key):
        self.left = None
        self.right = None
        self.val = key

root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)


# use yahoo_fin library to parse data

import yahoo_fin.stock_info as si
from datetime import datetime, timedelta

def convert_currency(src, dst, amount):
    # construct the currency pair symbol
    symbol = f'{src} {dst}=X'

    # use get_data() from stock_info to pass the symbol of currency
    # pass "1m" as the interval parameter in the get_data() method to retrieve data for the current minute
    # not the default current day
    latest_data = si.get_data(symbol, interval='1m', start_date=datetime.now() - timedelta(days=2))
    # extract minute data from the last 2 days, because there be problems with the course on the weekend

    # get the latest datetime
    latest_datetime = latest_data.index[-1].to_pydatetime()

    # get the last price
    last_price = latest_data.iloc[-1].close

    # return the latest data and converted amount
    return latest_datetime, last_price * amount

if __name__ == "__main__":
    import sys
    # get currency and amount
    source_currency = sys.argv[1]
    destination_currency = sys.argv[2]

    amount = float(sys.argv[3])

    latest_datetime, exchange_rate = convert_currency(source_currency, destination_currency, amount)

    print(f'Last update time: {latest_datetime}')
    print(f'{amount} {source_currency} = {exchange_rate} {destination_currency}')


import pymongo, datetime, certifi, requests
from bs4 import BeautifulSoup
from variables import mongo_string
from data import stocks_list

# stocks_list = ['ANWARGALV', 'BSRMSTEEL']

myclient = pymongo.MongoClient(mongo_string, tlsCAFile=certifi.where())
mydb = myclient["stockanalyst"]

data_setting = mydb.settings.find_one()

if data_setting['dataInsertionEnable'] == 0:
  print('exiting script')
  exit()

for stock in stocks_list:
  stock_data = mydb.fundamentals.find_one({
    'tradingCode': stock
  })

  if 'epsQuaterly' in stock_data :
    eps_data = sorted(stock_data['epsQuaterly'], key=lambda d: str(d['year']), reverse=True)[0]

    count = 0

    if 'q4' in eps_data:
      count = count + 1
    if 'q3' in eps_data:
      count = count + 1
    if 'q2' in eps_data:
      count = count + 1
    if 'q1' in eps_data:
      count = count + 1

    if count == 0:
      eps = 0
    else:
      total = eps_data['q1'] if 'q1' in eps_data else 0 + eps_data['q2'] if 'q2' in eps_data else 0 + eps_data['q3'] if 'q3' in eps_data else 0 + eps_data['q4'] if 'q4' in eps_data else 0

      eps = round((total / count) * 4, 3)

    # print(stock, eps)

    myquery = { 'tradingCode': stock }

    newvalues = { "$set": {
        "epsCurrent": eps,
    } }

    mydb.fundamentals.update_one(myquery, newvalues)

  else:
    print(stock, 'error occured!')


#!/usr/bin/python3
from tkinter import *
import serial
import time
from TFmini_I2C import *

root = Tk()
root.geometry("450x300")

def readSerial():
    Sensor0 = TFminiI2C(1, 0x10)

    counter = 0
    while(counter <= 1):
    #print( Sensor0.readAll(), "\t")
        if (Sensor0.readDistance() >= 4 and Sensor0.readDistance() <= 110):
            v.set(Sensor0.readDistance())
            print("Dist:", Sensor0.readDistance())
        else:
            print("Dist:",0)
            v.set(0)
        counter += 1
    root.after(1, readSerial)

v = StringVar()
Label(root, anchor='center', bg='white', textvariable=v,font=("Helvetica", 40), height='125', width='125').pack()
v.set('--.-')
root.after(100, readSerial)
root.mainloop()


"""
主要方法
"""
import requests
import json
import xlwt

import tools

# 获取各页的视频bvid
def getPagesBvId(mid):
    # 初始化变量
    videoDataLists = []
    index = 0
    pages = 0
    # 循环取bvid
    while True:
        # 测试数据：https://api.bilibili.com/x/space/arc/search?mid=691415738&jsonp=jsonp&pn=1
        pageURL = "https://api.bilibili.com/x/space/arc/search?mid=" + mid + "&jsonp=jsonp&pn=" + str(index + 1)
        videoDataList = grab_info(pageURL)
        # 如果是第一页，就去判断是否有数据，顺便获取总共有几页视频和作者信息
        if index == 0:
            if videoDataList == "":
                tools.error("【error】：mid为【" + mid + "】的UP没有视频，请重新选择操作！")
                return False
            elif videoDataList == "null":
                tools.error("【error】：查不到mid为：【" + mid + "】的UP数据，请重新选择操作！")
                return False
            # 计算该UP总共有多少个视频
            pages = int(
                (videoDataList['page']['count'] + videoDataList['page']['ps'] - 1) / videoDataList['page']['ps'])
            author = videoDataList['list']['vlist'][0]['author']
            print("【" + author + "】总共有", pages, "页视频")
        # 如果是最后一页 则去计算最后一页有多少个视频
        if videoDataList['page']['pn'] == pages:
            videoDataList['page']['ps'] = videoDataList['page']['count'] - (videoDataList['page']['pn'] - 1) * 30
        # 获取视频数据，添加到videoDataLists
        for i in range(videoDataList['page']['ps']):
            videoDataLists.append(videoDataList['list']['vlist'][i])
        print("第", index + 1, "页:", pageURL, "完成")
        # 累加页码
        index += 1
        # 当最后一页执行完之后 退出循环
        if index == pages:
            break
    return videoDataLists

# 获取地址的json信息
def grab_info(FullURL):
    # 代理头部
    headers = {
        "User-Agent": tools.getRandomUserAgent()
    }
    # 获取一个返回信息
    response = requests.get(FullURL, headers=headers).content.decode('utf-8')
    # 把json转换为python对象
    content = json.loads(response)
    # 利用json提取主体视频信息
    if content['code'] == 0:
        data = content['data']
        if len(data['list']['vlist']) == 0:
            return ""
    else:
        return "null"
    return data

# 根据list生成excel文件
def createExcel(dateList, functionName):
    workbook = xlwt.Workbook(encoding="utf-8")  # 实例化book对象
    sheet = workbook.add_sheet(tools.getSheetName(dateList, functionName))  # 生成sheet

    # 设置excel的title、数据列表中的key和列宽
    titleList = tools.getTitleList(functionName)[0]
    listKey = tools.getTitleList(functionName)[1]
    titleWidth = tools.getTitleList(functionName)[2]

    # 设置title宽度
    for i in range(len(titleWidth)):
        sheet.col(i).width = titleWidth[i]

    # 写入标题
    for col, column in enumerate(titleList):
        sheet.write(0, col, column)

    # 写入数据
    for row, data in enumerate(dateList):
        for i in range(len(listKey)):
            # 0为序号列 i>0为数据列
            if i == 0:
                sheet.write(row + 1, i, row + 1)
            else:
                if listKey[i] == 'created':
                    # 如果该列为created:上传时间,需要将时间戳转换为时间
                    sheet.write(row + 1, i, tools.timeStampToTime(data[listKey[i]]))
                else:
                    sheet.write(row + 1, i, data[listKey[i]])
    workbook.save(tools.getExcelName(dateList, functionName))

# 创建bat文件
def createBat(dataList, functionName):
    # TODO 通过配置文件读取cd地址
    cdCommand = "CD D:/Project/PyCharm/bilibiliDown/downloader\nD:\n"
    downCommand = tools.getDownCommand(dataList, functionName)

    # 生成bat文件 common.getBatName(dateList, functionName)=>获取bat文件名
    with open(tools.getBatName(dataList, functionName) + ".bat", 'w', encoding='utf-8') as f:
        f.write(cdCommand + downCommand)
    f.close()


stringa1 = "Per quanti giorni ha intenzione di noleggiare uno scooter 50cc?"
stringa2 = "Il prezzo è di"
r1 = 45.00
r2 = 80.00
r3 = 120.00
r4 = 160.00
print(stringa1)
a = int(input("Inserisci il numero di giorni: "))
p_g_extra = r4 + (a-4)*40
if a == 1 :
    print(stringa2, r1, "€")
if a == 2 :
    print(stringa2, r2, "€")
if a == 3 :
    print(stringa2, r3, "€")
if a == 4 :
    print(stringa2, r4, "€")
if a > 4 :
    print(stringa2, p_g_extra, "€")


import langchain
from aiogram import Bot, Dispatcher, executor, types

#Associar o bot ao código
bot = Bot(token = 'SEU_TOKEN')
dp = Dispatcher(bot)

#Lista de resposta
Mensagem =['Mensagem']

#Carregando os documentos utilizados para consulta pelo GPT
loader = langchain.document_loaders.DirectoryLoader('Directory/',
                                                    glob="**/*.txt",
                                                    loader_cls=langchain.document_loaders.TextLoader)
documents = loader.load()
len(documents)
text_splitter = langchain.text_splitter.RecursiveCharacterTextSplitter(chunk_size =2300,
                                                                       chunk_overlap  =10,
                                                                       length_function =len,
                                                                       separators="\n\n")
texts = text_splitter.split_documents(documents)

#Função para comparar a pergunta aos textos e trazer as respostas
def query_gpt(input):
    embeddings = langchain.embeddings.OpenAIEmbeddings(openai_api_key = '')
    doc_search = langchain.vectorstores.Chroma.from_documents(texts, embeddings)
    chain = langchain.VectorDBQA.from_chain_type(llm=langchain.OpenAI(openai_api_key = ''),
                                                 chain_type = 'stuff',
                                                 vectorstore = doc_search)
    Mensagem[0] = chain.run(input)

#Função para receber a pergunta do usuário e responde-la pelo telegram
@dp.message_handler()
async def gpt(message:types.message):
    query_gpt(message.text)
    await message.reply(Mensagem[0])

if __name__ =='__main__':
    executor.start_polling(dp)


from Module import sptool
import requests
from pyquery import PyQuery as pq
from pprint import pprint
import re
from queue import Queue
from threading import Thread
import time

class PTT:
    def __init__(self):
        self.sp = sptool.sp()
        self.data = []
        self.chpage = []
        self.ptt_pack = []
        # self.ptt_date_list = []
        # self.ptt_title_list = []
        # self.ptt_url_list = []
        self.thread_page_num = 50
        self.page_Q = Queue()

    def Get_Ptt(self, url):
        res = requests.get(url)
        data = pq(res.content.decode())
        self.data = data
        # print(data)
        return self.data

    def Ptt_Btn(self):
        data = self.data
        btn = data('a.btn.wide')
        pages = ['old', 'last', 'next', 'new']
        # pages=[]
        for i in range(len(pages)):
            if pq(btn[i]).attr('href'):
                pages[i] = 'https://www.ptt.cc'+ pq(btn[i]).attr('href')
            else:
                pages[i] = None
            self.chpage.append(pages[i])
        # print(self.chpage)
        return self.chpage

    def Allpage(self):
        # url = self.chpage[1]
        chpage = self.Ptt_Btn()
        max_page = re.findall(r"\d+", chpage[1])[0]
        links = []
        # print(max_page)
        for i in range(int(max_page)+1):  #int(max_page)+1
            links.append('https://www.ptt.cc/bbs/Grad-ProbAsk/index{}.html'.format(str(i)))
        # pprint(links)
        return links

    def Ptt_Parse(self, link):
        data = self.Get_Ptt(link)
        rent = data('div.r-ent')
        titles = rent('div.title')
        dates = rent('div.date')
        for i in range(len(titles)):
            temp = {}
            title = pq(titles[i])
            try:
                url = 'https://www.ptt.cc'+ pq(title)('a').attr('href')
            except: # 本文章已刪除
                url = '本文章已刪除'
            temp["url"] = url
            temp["date"] = (pq(dates[i]).text())
            temp["title"] = (title.text())
            self.ptt_pack.append(temp)
        # self.ptt_pack["date"] = self.ptt_date_list
        # self.ptt_pack["title"] = self.ptt_title_list
        # self.ptt_pack["url"] = self.ptt_url_list
        print(self.ptt_pack)
        return self.ptt_pack

if __name__ == '__main__':
    obj = PTT()
    url = 'https://www.ptt.cc/bbs/Grad-ProbAsk/index1255.html'
    # obj.Get_Ptt(url)
    # obj.Ptt_Btn()
    # obj.Allpage()
    obj.Ptt_Parse(url)


# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def sameTree(self, t1, t2):
        if t1 is None and t2 is None:
            return True
        if t1 is None or t2 is None:
            return False
        return t1.val == t2.val and self.sameTree(t1.left, t2.left) and self.sameTree(t1.right, t2.right)

    def dfs(self, cur):
        if cur:
            if self.sameTree(cur, self.t):
                yield True
            for x in self.dfs(cur.left):
                yield x
            for x in self.dfs(cur.right):
                yield x

    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """
        self.t = t
        for _ in self.dfs(s):
            return True
        return False


import pygame as pg

scrWidth = 600
scrHeight = 400
win = pg.display.set_mode((scrWidth,scrHeight))

pg.display.set_caption("First Game")

# This goes outside the while loop, near the top of the program
walkRight = [pg.image.load('R1.png'), pg.image.load('R2.png'), pg.image.load('R3.png'), pg.image.load('R4.png'), pg.image.load('R5.png'), pg.image.load('R6.png')]
walkLeft = [pg.image.load('L1.png'), pg.image.load('L2.png'), pg.image.load('L3.png'), pg.image.load('L4.png'), pg.image.load('L5.png'), pg.image.load('L6.png')]
background = pg.image.load('background.png')
char = pg.image.load('R1.png')

clock = pg.time.Clock()

x = 50
y = 350
chrWidth = 17
chrHeight = 27
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
direction = 'right'
walkCount = 0

def redrawWindow():
    global walkCount, direction

    win.blit(background, (0,0))

    if walkCount + 1 >= 18:
        walkCount = 0

    if left == True:
        win.blit(walkLeft[walkCount // 3], (x,y))
        walkCount += 1
        direction = 'left'
    elif right == True:
        win.blit(walkRight[walkCount // 3], (x,y))
        walkCount += 1
        direction = 'right'
    else:
        if direction == 'right':
            win.blit(walkRight[0], (x,y))
        elif direction == 'left':
            win.blit(walkLeft[0], (x,y))

    pg.display.update()

# main loop
run = True
while run:
    clock.tick(18)

    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

    keys = pg.key.get_pressed()

    if keys[pg.K_LEFT] and x > vel:
        x -= vel
        left = True
        right = False
    elif keys[pg.K_RIGHT] and x < scrWidth - chrWidth - vel:
        x += vel
        right = True
        left = False
    else:
        right = False
        left = False
        walkCount = 0

    if isJump == False:
        if keys[pg.K_SPACE]:
            isJump = True
            right = False
            left = False
            walkCount = 0
    elif isJump == True:
        if jumpCount >= 0:
            y -= (jumpCount ** 2) * 0.35
            jumpCount -= 1
        elif jumpCount < 0:
            y += (jumpCount ** 2) * 0.35
            jumpCount -= 1
        if jumpCount < -10:
            isJump = False
            jumpCount = 10

    redrawWindow()

pg.quit()


import qgis
from qgis.PyQt.QtCore import (QObject,
                              QCoreApplication)
from qgis.core import QgsProject

from asistente_ladm_col.lib.logger import Logger
from asistente_ladm_col.config.translation_strings import (TranslatableConfigStrings,
                                                           ERROR_LAYER_GROUP)
from asistente_ladm_col.config.query_names import QueryNames

class QgisModelBakerUtils(QObject):

    def __init__(self):
        QObject.__init__(self)
        self.logger = Logger()
        from asistente_ladm_col.config.config_db_supported import ConfigDBsSupported
        self._dbs_supported = ConfigDBsSupported()
        self.translatable_config_strings = TranslatableConfigStrings()

    def get_generator(self, db):
        if 'QgisModelBaker' in qgis.utils.plugins:
            tool = self._dbs_supported.get_db_factory(db.engine).get_model_baker_db_ili_mode()

            QgisModelBaker = qgis.utils.plugins["QgisModelBaker"]
            generator = QgisModelBaker.get_generator()(tool,
                db.uri, "smart2", db.schema, pg_estimated_metadata=False)
            return generator
        else:
            self.logger.critical(__name__, QCoreApplication.translate("AsistenteLADMCOLPlugin",
                "The QGIS Model Baker plugin is a prerequisite, install it before using LADM-COL Assistant."))
            return None

    def get_model_baker_db_connection(self, db):
        generator = self.get_generator(db)
        if generator is not None:
            return generator._db_connector

        return None

    def load_layers(self, db, layer_list):
        """
        Load a selected list of layers from qgis model baker.
        This call should configure relations and bag of enums
        between layers being loaded, but not when a layer already
        loaded has a relation or is part of a bag of enum. For
        that case, we use a cached set of relations and bags of
        enums that we get only once per session and configure in
        the Asistente LADM-COL.
        """
        translated_strings = self.translatable_config_strings.get_translatable_config_strings()

        if 'QgisModelBaker' in qgis.utils.plugins:
            QgisModelBaker = qgis.utils.plugins["QgisModelBaker"]

            tool = self._dbs_supported.get_db_factory(db.engine).get_model_baker_db_ili_mode()

            generator = QgisModelBaker.get_generator()(tool, db.uri, "smart2", db.schema, pg_estimated_metadata=False)
            layers = generator.layers(layer_list)
            relations, bags_of_enum = generator.relations(layers, layer_list)
            legend = generator.legend(layers, ignore_node_names=[translated_strings[ERROR_LAYER_GROUP]])
            QgisModelBaker.create_project(layers, relations, bags_of_enum, legend, auto_transaction=False)
        else:
            self.logger.critical(__name__, QCoreApplication.translate("AsistenteLADMCOLPlugin",
                "The QGIS Model Baker plugin is a prerequisite, install it before using LADM-COL Assistant."))

    def get_required_layers_without_load(self, layer_list, db):
        """
        Gets a list of layers from a list of layer names using QGIS Model Baker.
        Layers are register in QgsProject, but not loaded to the canvas!
        :param layer_list: list of layers names (e.g., ['lc_terreno', 'lc_lindero'])
        :param db: db connection
        :return: list of QgsVectorLayers registered in the project
        """
        layers = list()
        if 'QgisModelBaker' in qgis.utils.plugins:
            QgisModelBaker = qgis.utils.plugins["QgisModelBaker"]

            tool = self._dbs_supported.get_db_factory(db.engine).get_model_baker_db_ili_mode()
            generator = QgisModelBaker.get_generator()(tool, db.uri, "smart2", db.schema, pg_estimated_metadata=False)
            model_baker_layers = generator.layers(layer_list)

            for model_baker_layer in model_baker_layers:
                layer = model_baker_layer.create()  # Convert Model Baker layer to QGIS layer
                QgsProject.instance().addMapLayer(layer, False)  # Do not load it to canvas
                layers.append(layer)
        else:
            self.logger.critical(__name__, QCoreApplication.translate("AsistenteLADMCOLPlugin",
                "The QGIS Model Baker plugin is a prerequisite, install it before using LADM-COL Assistant."))

        return layers

    def get_layers_and_relations_info(self, db):
        """
        Called once per session, this is used to get information
        of all relations and bags of enums in the DB and cache it
        in the Asistente LADM-COL.
        """
        if 'QgisModelBaker' in qgis.utils.plugins:
            generator = self.get_generator(db)

            layers = generator.get_tables_info_without_ignored_tables()
            relations = [relation for relation in generator.get_relations_info()]
            self.logger.debug(__name__, "Relationships before filter: {}".format(len(relations)))
            self.filter_relations(relations)
            self.logger.debug(__name__, "Relationships after filter: {}".format(len(relations)))
            return (layers, relations, {})
        else:
            self.logger.critical(__name__, QCoreApplication.translate("AsistenteLADMCOLPlugin",
                "The QGIS Model Baker plugin is a prerequisite, install it before using LADM-COL Assistant."))
            return (list(), list(), dict())

    def filter_relations(self, relations):
        """
        Modifies the input list of relations, removing elements that meet a condition.

        :param relations: List of a dict of relations.
        :return: Nothing, changes the input list of relations.
        """
        to_delete = list()
        for relation in relations:
            if relation[QueryNames.REFERENCING_FIELD].startswith('uej2_') or relation[QueryNames.REFERENCING_FIELD].startswith('ue_'):
                to_delete.append(relation)

        for idx in to_delete:
            relations.remove(idx)

    def get_tables_info_without_ignored_tables(self, db):
        if 'QgisModelBaker' in qgis.utils.plugins:
            generator = self.get_generator(db)
            return generator.get_tables_info_without_ignored_tables()
        else:
            self.logger.critical(__name__, QCoreApplication.translate("AsistenteLADMCOLPlugin",
                "The QGIS Model Baker plugin is a prerequisite, install it before using LADM-COL Assistant."))

    def get_first_index_for_layer_type(self, layer_type, group=QgsProject.instance().layerTreeRoot()):
        if 'QgisModelBaker' in qgis.utils.plugins:
            import QgisModelBaker
            return QgisModelBaker.utils.qgis_utils.get_first_index_for_layer_type(layer_type, group)
        return None

    @staticmethod
    def get_suggested_index_for_layer(layer, group):
        if 'QgisModelBaker' in qgis.utils.plugins:
            import QgisModelBaker
            return QgisModelBaker.utils.qgis_utils.get_suggested_index_for_layer(layer, group)
        return None


from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer, ChatterBotCorpusTrainer

bot = ChatBot('chatbot', read_only=False,
              logic_adapters=[
                  {
                      'import_path':'chatterbot.logic.BestMatch'

                      }])

list_to_train = [
    "hi",
    "hi,there",
    "what is your name?",
    "i am jsut a chatbot"
]

chatterbotCorpusTrainer = ChatterBotCorpusTrainer(bot)

#list_trainer = ListTrainer(bot)
#list_trainer.train(list_to_train)
chatterbotCorpusTrainer .train('chatterbot.corpus.english')

def index(request):
    return render(request, 'blog/index.html')

def specific(request):
    return HttpResponse("list1")

def getResponse(request):
    userMessage = request.GET.get('userMessage')
    chatResponse = str(bot.get_response(userMessage))
    return HttpResponse(chatResponse)


from parsivar import FindStems, Tokenizer, Normalizer, normalizer
import re
from read_contents import read_contents, Counter
from sklearn.feature_selection import chi2, SelectKBest

file = open('StopWords', 'r', encoding='UTF-8')
lines = file.readlines()
stop_words_list = []
for line in lines:
    stop_words_list.append(line.rstrip('\n'))
badChars = ['.', '!', '?', ':', ';', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E',
            'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', '<', '>', '=', '-',
            ]
emails1 = "Spam-Filtering-For-Persian-master/emails/spamtraining"
emails2 = "Spam-Filtering-For-Persian-master/emails/hamtraining"

transformer = SelectKBest().fit()
# def preprocess_words(address, index):
#     email = read_contents(address, index)
#     string = ""
#     l = []
#     for i in email:
#         if i != '' and i != '\n':
#             string = string + i
#             l.append(i)
#     for sentence in l:
#         sentence.replace("/", "")
#     string.replace("/", "")
#     pattern = '[' + ''.join(badChars) + ']'
#     string = re.sub(pattern, '', string)
#     my_normalizer = Normalizer()
#     my_tokenizer = Tokenizer()
#     words = my_tokenizer.tokenize_words(my_normalizer.normalize(string))
#     return l


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('students', '0001_initial'),
    ]

    operations = [
        migrations.AlterField(
            model_name='tests',
            name='exam_title',
            field=models.CharField(max_length=256, null=True, verbose_name='\u041d\u0430\u0437\u0432\u0430 \u0435\u043a\u0437\u0430\u043c\u0435\u043d\u0443 '),
        ),
        migrations.AlterField(
            model_name='tests',
            name='notes',
            field=models.TextField(null=True, verbose_name='\u041d\u043e\u0442\u0430\u0442\u043a\u0438', blank=True),
        ),
        migrations.AlterField(
            model_name='tests',
            name='teacher',
            field=models.CharField(max_length=256, null=True, verbose_name='\u0412\u0438\u043a\u043b\u0430\u0434\u0430\u0447'),
        ),
    ]


# Узел двусвязного списка
class Node:
    # 1ТП4Т Конструктор
    def __init__(self, data=None, prev=None, next=None):
        self.data = data
        self.prev = prev
        self.next = next

# Вспомогательная функция для помещения узла в начало двусвязного списка
def push(head, data):

    node = Node(data, None, head)

    # изменяет `prev` существующего головного узла, чтобы он указывал на новый узел.
    if head:
        head.prev = node

    # обновить указатель заголовка и возврат
    head = node
    return head

# Вспомогательная функция # для печати узлов двусвязного списка
def printDDL(msg, head):

    print(msg, end='')
    while head:
        print(head.data, end=' —> ')
        head = head.next

    print('None')

# Функция для замены указателей `next` и `prev` данного узла
def swap(node):

    prev = node.prev
    node.prev = node.next
    node.next = prev

# Функция для обращения двусвязного списка
def reverseDDL(head):

    prev = None
    curr = head

    # пройтись по списку
    while curr:
        # поменять местами указатели `next` и `prev` для текущего узла
        swap(curr)

        # обновляет предыдущий узел перед переходом к следующему узлу
        prev = curr

        # перейти к следующему узлу в двусвязном списке
        # (переход с использованием указателя `prev`, так как указатели `next` и `prev` поменялись местами)
        curr = curr.prev

    # обновляет указатель заголовка на последний узел
    if prev:
        head = prev

    return head

if __name__ == '__main__':

    head = None
    for key in range(1, 6):
        head = push(head, key)

    printDDL('Original A: ', head)
    head = reverseDDL(head)
    printDDL('Reversed A: ', head)


try:
  from .. import unzip_requirements
except ImportError:
  pass
from gevent import monkey
monkey.patch_all()
import json
import boto3
import invokust
from locust import HttpLocust, TaskSet, task
import os

class TaskPostWithBodyAndHeaders(TaskSet):
    @task()
    def post_method(self):
        self.client.post(path,
                         data=body,
                         headers=headers)

class TaskPostWithBody(TaskSet):
    @task()
    def post_method(self):
        self.client.post(path,
                         data=body)

class TaskPostWithHeaders(TaskSet):
    @task()
    def post_method(self):
        self.client.post(path,
                         headers=headers)

class TaskPost(TaskSet):
    @task()
    def post_method(self):
        self.client.post(path)

class TaskGetWithBodyAndHeaders(TaskSet):
    @task()
    def get_method(self):
        self.client.get(path,
                        data=body,
                        headers=headers)

class TaskGetWithBody(TaskSet):
    @task()
    def get_method(self):
        self.client.get(path,
                        data=body)

class TaskGetWithHeaders(TaskSet):
    @task()
    def get_method(self):
        self.client.get(path,
                        headers=headers)

class TaskGet(TaskSet):
    @task()
    def get_method(self):
        self.client.get(path)

class TestLogicGetWithBodyAndHeaders(HttpLocust):
    task_set = TaskGetWithBodyAndHeaders

class TestLogicGetWithBody(HttpLocust):
    task_set = TaskGetWithBody

class TestLogicGetWithHeaders(HttpLocust):
    task_set = TaskGetWithHeaders

class TestLogicGet(HttpLocust):
    task_set = TaskGet

class TestLogicPostWithBodyAndHeaders(HttpLocust):
    task_set = TaskPostWithBodyAndHeaders

class TestLogicPostWithBody(HttpLocust):
    task_set = TaskPostWithBody

class TestLogicPostWithHeaders(HttpLocust):
    task_set = TaskPostWithHeaders

class TestLogicPost(HttpLocust):
    task_set = TaskPost

def push_not_available_if_not_float(value):
    try:
        temp = float(value)
    except Exception as e:
        temp = float(0)
    return temp

def start(event, context):
    print('Processing SQS trigger for notify.')
    client = boto3.client('sqs')

    print('Get the current Queue URL.')
    currentQueueArn = str(event["Records"][0]["eventSourceARN"])
    response = client.get_queue_url(
        QueueName=currentQueueArn.split(":")[5],
        QueueOwnerAWSAccountId=currentQueueArn.split(":")[4]
    )
    queueUrl = response["QueueUrl"]
    print('Managed to fetch the current queue url -> {}'.format(queueUrl))

    message = json.loads(event["Records"][0]["body"])
    url = str(message["url"])
    numClients = int(message["numClients"])
    hatchRate = int(message["hatchRate"])
    runTime = str(message["runTime"])
    requestId = str(message["requestId"])
    maxThreads = int(message["maxThreads"])
    threadCount = str(message["threadCount"])
    method = str(message["method"])

    global path
    global body
    global headers
    global request_name

    path = str(message["path"])
    body = str(message["body"])
    headers = str(message["headers"])
    request_name = "{}_{}".format(method, path)

    print('Removing message from queue.')
    try:
        client.delete_message(
            QueueUrl=queueUrl,
            ReceiptHandle=event['Records'][0]['receiptHandle']
        )
    except Exception as e:
        print("Message was already deleted or \"receiptHandle\" is invalid.")
        pass

    print('Starting shell subprocess for loadtest with threadCount {}.'.format(threadCount))

    # Set up the load test settings
    if method == "POST":
        if body == "{}" and headers == "{}":
            settings = invokust.create_settings(
                classes=[TestLogicPost],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body == "{}" and headers != "{}":
            settings = invokust.create_settings(
                classes=[TestLogicPostWithHeaders],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body != "{}" and headers == "{}":
            settings = invokust.create_settings(
                classes=[TestLogicPostWithBody],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body != "{}" and headers != "{}":
            settings = invokust.create_settings(
                classes=[TestLogicPostWithBodyAndHeaders],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

    if method == "GET":
        if body == "{}" and headers == "{}":
            settings = invokust.create_settings(
                classes=[TestLogicGet],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body == "{}" and headers != "{}":
            settings = invokust.create_settings(
                classes=[TestLogicGetWithHeaders],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body != "{}" and headers == "{}":
            settings = invokust.create_settings(
                classes=[TestLogicGetWithBody],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

        if body != "{}" and headers != "{}":
            settings = invokust.create_settings(
                classes=[TestLogicGetWithBodyAndHeaders],
                host=url,
                num_clients=numClients,
                hatch_rate=hatchRate,
                run_time=runTime
            )

    # Start the load test
    try:
        loadtest = invokust.LocustLoadTest(settings)
        loadtest.run()
    except Exception as e:
        print('Encountered error when running loadtest with threadCount {}. Error = {}'.format(
            threadCount, str(e)))

    stats = loadtest.stats()

    print("Finished tests.")
    responseValue={
        "input": {
            "url": url,
            "numClients": numClients,
            "hatchRate": hatchRate,
            "runTime": runTime,
            "maxThreads": maxThreads,
            "requestId": requestId,
            "threadCount": threadCount,
            "method": method,
            "path": path
        },
        "stats": stats
    }

    queue = os.environ.get("PostResultSqsUrl")
    client.send_message_batch(
        QueueUrl=queue,
        Entries=[{
            "Id": threadCount,
            "MessageBody": json.dumps(responseValue),
            "DelaySeconds": 0
        }]
    )

    return "Done"