import ast
import fnmatch
import os

from nuitka.__past__ import iter_modules
from nuitka.importing.Importing import locateModule
from nuitka.importing.Recursion import decideRecursion
from nuitka.plugins.PluginBase import NuitkaPluginBase
from nuitka.utils.ModuleNames import ModuleName
from nuitka.utils.Utils import isMacOS, isWin32Windows
from nuitka.utils.Yaml import getYamlPackageConfiguration

class NuitkaPluginImplicitImports(NuitkaPluginBase):
    plugin_name = "implicit-imports"

    plugin_desc = (
        "Provide implicit imports of package as per package configuration files."
    )

    def __init__(self):
        self.config = getYamlPackageConfiguration()

        self.lazy_loader_usages = {}

    @staticmethod
    def isAlwaysEnabled():
        return True

    def _resolveModulePattern(self, pattern):
        parts = pattern.split(".")

        current = None

        for count, part in enumerate(parts):
            if not part:
                self.sysexit(
                    "Error, invalid pattern with empty parts used '%s'." % pattern
                )

            # TODO: Checking for shell pattern should be done in more places and shared code.
            if "?" in part or "*" in part or "[" in part:
                if current is None:
                    self.sysexit(
                        "Error, cannot use pattern for first part '%s'." % pattern
                    )

                module_filename = self.locateModule(
                    module_name=ModuleName(current),
                )

                for sub_module in iter_modules([module_filename]):
                    if not fnmatch.fnmatch(sub_module.name, part):
                        continue

                    if count == len(parts) - 1:
                        yield current.getChildNamed(sub_module.name)
                    else:
                        child_name = current.getChildNamed(sub_module.name).asString()

                        for value in self._resolveModulePattern(
                            child_name + "." + ".".join(parts[count + 1 :])
                        ):
                            yield value

                return
            else:
                if current is None:
                    current = ModuleName(part)
                else:
                    current = current.getChildNamed(part)

        yield current

    def _handleImplicitImportsConfig(self, module, config):
        full_name = module.getFullName()

        for dependency in config.get("depends", ()):
            if dependency.startswith("."):
                if (
                    module.isUncompiledPythonPackage()
                    or module.isCompiledPythonPackage()
                ):
                    dependency = full_name.getChildNamed(dependency[1:]).asString()
                elif full_name.getPackageName() is None:
                    # Not a package, potentially a naming conflict, when
                    # compiling with "--module" something that matches a PyPI
                    # name.
                    continue
                else:
                    dependency = full_name.getSiblingNamed(dependency[1:]).asString()

            if "*" in dependency or "?" in dependency:
                for resolved in self._resolveModulePattern(dependency):
                    yield resolved
            else:
                yield dependency

    def _getImportsByFullname(self, module, full_name):
        """Provides names of modules to imported implicitly."""
        # Many variables, branches, due to the many cases, pylint: disable=too-many-branches,too-many-statements

        # Checking for config, but also allowing fall through.
        for entry in self.config.get(full_name, section="implicit-imports"):
            if self.evaluateCondition(
                full_name=full_name, condition=entry.get("when", "True")
            ):
                for dependency in self._handleImplicitImportsConfig(
                    config=entry, module=module
                ):
                    yield dependency

        # Support for both pycryotodome (module name Crypto) and pycyptodomex (module name Cryptodome)
        if full_name.hasOneOfNamespaces("Crypto", "Cryptodome"):
            crypto_module_name = full_name.getTopLevelPackageName()

            if full_name == crypto_module_name + ".Cipher._mode_ofb":
                yield crypto_module_name + ".Cipher._raw_ofb"

            elif full_name == crypto_module_name + ".Cipher.CAST":
                yield crypto_module_name + ".Cipher._raw_cast"

            elif full_name == crypto_module_name + ".Cipher.DES3":
                yield crypto_module_name + ".Cipher._raw_des3"

            elif full_name == crypto_module_name + ".Cipher.DES":
                yield crypto_module_name + ".Cipher._raw_des"

            elif full_name == crypto_module_name + ".Cipher._mode_ecb":
                yield crypto_module_name + ".Cipher._raw_ecb"

            elif full_name == crypto_module_name + ".Cipher.AES":
                yield crypto_module_name + ".Cipher._raw_aes"
                yield crypto_module_name + ".Cipher._raw_aesni"
                yield crypto_module_name + ".Util._cpuid"

            elif full_name == crypto_module_name + ".Cipher._mode_cfb":
                yield crypto_module_name + ".Cipher._raw_cfb"

            elif full_name == crypto_module_name + ".Cipher.ARC2":
                yield crypto_module_name + ".Cipher._raw_arc2"

            elif full_name == crypto_module_name + ".Cipher.DES3":
                yield crypto_module_name + ".Cipher._raw_des3"

            elif full_name == crypto_module_name + ".Cipher._mode_ocb":
                yield crypto_module_name + ".Cipher._raw_ocb"

            elif full_name == crypto_module_name + ".Cipher._EKSBlowfish":
                yield crypto_module_name + ".Cipher._raw_eksblowfish"

            elif full_name == crypto_module_name + ".Cipher.Blowfish":
                yield crypto_module_name + ".Cipher._raw_blowfish"

            elif full_name == crypto_module_name + ".Cipher._mode_ctr":
                yield crypto_module_name + ".Cipher._raw_ctr"

            elif full_name == crypto_module_name + ".Cipher._mode_cbc":
                yield crypto_module_name + ".Cipher._raw_cbc"

            elif full_name == crypto_module_name + ".Util.strxor":
                yield crypto_module_name + ".Util._strxor"

            elif full_name == crypto_module_name + ".Util._cpu_features":
                yield crypto_module_name + ".Util._cpuid_c"

            elif full_name == crypto_module_name + ".Hash.BLAKE2s":
                yield crypto_module_name + ".Hash._BLAKE2s"

            elif full_name == crypto_module_name + ".Hash.BLAKE2b":
                yield crypto_module_name + ".Hash._BLAKE2b"

            elif full_name == crypto_module_name + ".Hash.SHA1":
                yield crypto_module_name + ".Hash._SHA1"

            elif full_name == crypto_module_name + ".Hash.SHA224":
                yield crypto_module_name + ".Hash._SHA224"

            elif full_name == crypto_module_name + ".Hash.SHA256":
                yield crypto_module_name + ".Hash._SHA256"

            elif full_name == crypto_module_name + ".Hash.SHA384":
                yield crypto_module_name + ".Hash._SHA384"

            elif full_name == crypto_module_name + ".Hash.SHA512":
                yield crypto_module_name + ".Hash._SHA512"

            elif full_name == crypto_module_name + ".Hash.MD2":
                yield crypto_module_name + ".Hash._MD2"

            elif full_name == crypto_module_name + ".Hash.MD4":
                yield crypto_module_name + ".Hash._MD4"

            elif full_name == crypto_module_name + ".Hash.MD5":
                yield crypto_module_name + ".Hash._MD5"

            elif full_name == crypto_module_name + ".Hash.keccak":
                yield crypto_module_name + ".Hash._keccak"

            elif full_name == crypto_module_name + ".Hash.RIPEMD160":
                yield crypto_module_name + ".Hash._RIPEMD160"

            elif full_name == crypto_module_name + ".Hash.Poly1305":
                yield crypto_module_name + ".Hash._poly1305"

            elif full_name == crypto_module_name + ".Protocol.KDF":
                yield crypto_module_name + ".Cipher._Salsa20"
                yield crypto_module_name + ".Protocol._scrypt"

            elif full_name == crypto_module_name + ".Cipher._mode_gcm":
                yield crypto_module_name + ".Hash._ghash_clmul"
                yield crypto_module_name + ".Hash._ghash_portable"
                yield crypto_module_name + ".Util._galois"

            elif full_name == crypto_module_name + ".Cipher.Salsa20":
                yield crypto_module_name + ".Cipher._Salsa20"

            elif full_name == crypto_module_name + ".Cipher.ChaCha20":
                yield crypto_module_name + ".Cipher._chacha20"

            elif full_name == crypto_module_name + ".PublicKey.ECC":
                yield crypto_module_name + ".PublicKey._ec_ws"
                yield crypto_module_name + ".PublicKey._ed25519"
                yield crypto_module_name + ".PublicKey._ed448"

            elif full_name == crypto_module_name + ".Cipher.ARC4":
                yield crypto_module_name + ".Cipher._ARC4"

            elif full_name == crypto_module_name + ".Cipher.PKCS1_v1_5":
                yield crypto_module_name + ".Cipher._pkcs1_decode"

            elif full_name == crypto_module_name + ".Math._IntegerCustom":
                yield crypto_module_name + ".Math._modexp"

        elif full_name in ("pynput.keyboard", "pynput.mouse"):
            if isMacOS():
                yield full_name.getChildNamed("_darwin")
            elif isWin32Windows():
                yield full_name.getChildNamed("_win32")
            else:
                yield full_name.getChildNamed("_xorg")
        elif full_name == "cryptography":
            yield "_cffi_backend"
        elif full_name == "bcrypt._bcrypt":
            yield "_cffi_backend"

    def getImplicitImports(self, module):
        full_name = module.getFullName()

        # TODO: This code absolutely doesn't belong here.
        # Read the .pyi file, and provide as implicit dependency.
        if module.isPythonExtensionModule():
            for used_module_name in module.getPyIModuleImportedNames():
                yield used_module_name

        if full_name == "pkg_resources.extern":
            # TODO: A package specific lookup of compile time "pkg_resources.extern" could
            # be done here, but this might be simpler to hardcode for now. Once we have
            # the infrastructure to ask a module that after optimization, we should do
            # that instead, as it will not use a separate process.
            for part in (
                "packaging",
                "pyparsing",
                "appdirs",
                "jaraco",
                "importlib_resources",
                "more_itertools",
                "six",
                "platformdirs",
            ):
                yield "pkg_resources._vendor." + part

        for item in self._getImportsByFullname(module=module, full_name=full_name):
            yield item

    def _getPackageExtraScanPaths(self, package_dir, config):
        for config_package_dir in config.get("package-dirs", ()):
            yield os.path.normpath(os.path.join(package_dir, "..", config_package_dir))

            yield package_dir

        for config_package_name in config.get("package-paths", ()):
            module_filename = self.locateModule(config_package_name)

            if module_filename is not None:
                if os.path.isfile(module_filename):
                    yield os.path.dirname(module_filename)
                else:
                    yield module_filename

    def getPackageExtraScanPaths(self, package_name, package_dir):
        for entry in self.config.get(package_name, section="import-hacks"):
            if self.evaluateCondition(
                full_name=package_name, condition=entry.get("when", "True")
            ):
                for item in self._getPackageExtraScanPaths(
                    package_dir=package_dir, config=entry
                ):
                    yield item

    def _getModuleSysPathAdditions(self, module_name, config):
        module_filename = self.locateModule(module_name)

        if os.path.isfile(module_filename):
            module_filename = yield os.path.dirname(module_filename)

        for relative_path in config.get("global-sys-path", ()):
            candidate = os.path.abspath(os.path.join(module_filename, relative_path))

            if os.path.isdir(candidate):
                yield candidate

    def getModuleSysPathAdditions(self, module_name):
        for entry in self.config.get(module_name, section="import-hacks"):
            if self.evaluateCondition(
                full_name=module_name, condition=entry.get("when", "True")
            ):
                for item in self._getModuleSysPathAdditions(
                    module_name=module_name, config=entry
                ):
                    yield item

    def onModuleSourceCode(self, module_name, source_filename, source_code):
        if module_name == "numexpr.cpuinfo":
            # We cannot intercept "is" tests, but need it to be "isinstance",
            # so we patch it on the file. TODO: This is only temporary, in
            # the future, we may use optimization that understands the right
            # hand size of the "is" argument well enough to allow for our
            # type too.
            source_code = source_code.replace(
                "type(attr) is types.MethodType", "isinstance(attr, types.MethodType)"
            )

        if module_name == "site":
            if source_code.startswith("def ") or source_code.startswith("class "):
                source_code = "\n" + source_code

            source_code = """\
__file__ = (__nuitka_binary_dir + '%ssite.py') if '__nuitka_binary_dir' in dict(__builtins__ ) else '<frozen>';%s""" % (
                os.path.sep,
                source_code,
            )

            # Debian stretch site.py
            source_code = source_code.replace(
                "PREFIXES = [sys.prefix, sys.exec_prefix]", "PREFIXES = []"
            )

        # Source code should use lazy_loader, this may not be good enough
        # for all things yet.
        attach_call_replacements = (
            (
                "lazy.attach_stub(__name__, __file__)",
                "lazy.attach('%(module_name)s', %(submodules)s, %(attrs)s)",
            ),
        )

        for attach_call, attach_call_replacement in attach_call_replacements:
            if attach_call in source_code:
                result = self._handleLazyLoad(
                    module_name=module_name,
                    source_filename=source_filename,
                )

                # Inline the values, to avoid the data files.
                if result is not None:
                    source_code = source_code.replace(
                        attach_call,
                        attach_call_replacement
                        % {
                            "module_name": module_name.asString(),
                            "submodules": result[0],
                            "attrs": result[1],
                        },
                    )

            if module_name == "huggingface_hub":
                if (
                    "__getattr__, __dir__, __all__ = _attach(__name__, submodules=[], submod_attrs=_SUBMOD_ATTRS)"
                    in source_code
                ):
                    huggingface_hub_lazy_loader_info = (
                        self.queryRuntimeInformationSingle(
                            setup_codes="import huggingface_hub",
                            value="huggingface_hub._SUBMOD_ATTRS",
                            info_name="huggingface_hub_lazy_loader",
                        )
                    )

                    self.lazy_loader_usages[module_name] = (
                        [],
                        huggingface_hub_lazy_loader_info,
                    )

        return source_code

    def _handleLazyLoad(self, module_name, source_filename):
        pyi_filename = source_filename + "i"

        if os.path.exists(pyi_filename):
            try:
                import lazy_loader
            except ImportError:
                pass
            else:
                with open(pyi_filename, "rb") as f:
                    stub_node = ast.parse(f.read())

                # We are using private code here, to avoid use duplicating,
                # pylint: disable=protected-access
                visitor = lazy_loader._StubVisitor()
                visitor.visit(stub_node)

                self.lazy_loader_usages[module_name] = (
                    visitor._submodules,
                    visitor._submod_attrs,
                )

                return self.lazy_loader_usages[module_name]

    def createPreModuleLoadCode(self, module):
        full_name = module.getFullName()

        for entry in self.config.get(full_name, section="implicit-imports"):
            if "pre-import-code" in entry:
                if self.evaluateCondition(
                    full_name=full_name, condition=entry.get("when", "True")
                ):
                    code = "\n".join(entry.get("pre-import-code"))

                    # TODO: Add a description to the Yaml file.
                    yield code, "According to Yaml configuration."

    def createPostModuleLoadCode(self, module):
        full_name = module.getFullName()

        for entry in self.config.get(full_name, section="implicit-imports"):
            if "post-import-code" in entry:
                if self.evaluateCondition(
                    full_name=full_name, condition=entry.get("when", "True")
                ):
                    code = "\n".join(entry.get("post-import-code"))

                    # TODO: Add a description to the Yaml file.
                    yield code, "According to Yaml configuration."

    unworthy_namespaces = (
        "setuptools",  # Not performance relevant.
        "distutils",  # Not performance relevant.
        "wheel",  # Not performance relevant.
        "pkg_resources",  # Not performance relevant.
        "pycparser",  # Not performance relevant.
        #        "cffi",  # Not performance relevant.
        "numpy.distutils",  # Largely unused, and a lot of modules.
        "numpy.f2py",  # Mostly unused, only numpy.distutils import it.
        "numpy.testing",  # Useless.
        "nose",  # Not performance relevant.
        "coverage",  # Not performance relevant.
        "docutils",  # Not performance relevant.
        "pytest",  # Not performance relevant.
        "_pytest",  # Not performance relevant.
        "unittest",  # Not performance relevant.
        "pexpect",  # Not performance relevant.
        "Cython",  # Mostly unused, and a lot of modules.
        "cython",
        "pyximport",
        "IPython",  # Mostly unused, and a lot of modules.
        "wx._core",  # Too large generated code
        "pyVmomi.ServerObjects",  # Too large generated code
        "pyglet.gl",  # Too large generated code
        "telethon.tl.types",  # Not performance relevant and slow C compile
        "importlib_metadata",  # Not performance relevant and slow C compile
        "comtypes.gen",  # Not performance relevant and slow C compile
        "win32com.gen_py",  # Not performance relevant and slow C compile
        "phonenumbers.geodata",  # Not performance relevant and slow C compile
        "site",  # Not performance relevant and problems with .pth files
        "packaging",  # Not performance relevant.
        "appdirs",  # Not performance relevant.
        "dropbox.team_log",  # Too large generated code
        "asyncua.ua.object_ids",  # Too large generated code
        "asyncua.ua.uaerrors._auto",  # Too large generated code
        "asyncua.server.standard_address_space.standard_address_space_services",  # Too large generated code
        "azure.mgmt.network",  # Too large generated code
        "azure.mgmt.compute",  # Too large generated code
        "transformers.utils.dummy_pt_objects",  # Not performance relevant.
        "transformers.utils.dummy_flax_objects",  # Not performance relevant.
        "transformers.utils.dummy_tf_objects",  # Not performance relevant.
    )

    def decideCompilation(self, module_name):
        if module_name.hasOneOfNamespaces(self.unworthy_namespaces):
            return "bytecode"

    def onModuleUsageLookAhead(
        self, module_name, module_filename, module_kind, get_module_source
    ):
        # Getting the source code will also trigger our modification
        # and potentially tell us if any lazy loading applies.
        if get_module_source() is None:
            return

        if module_name in self.lazy_loader_usages:
            from nuitka.HardImportRegistry import (
                addModuleAttributeFactory,
                addModuleDynamicHard,
                addModuleTrust,
                trust_module,
                trust_node,
            )

            addModuleDynamicHard(module_name)

            sub_module_names, sub_module_attr = self.lazy_loader_usages[module_name]

            for sub_module_name in sub_module_names:
                addModuleTrust(module_name, sub_module_name, trust_module)

                sub_module_name = module_name.getChildNamed(sub_module_name)
                addModuleDynamicHard(sub_module_name)

                _lookAhead(using_module_name=module_name, module_name=sub_module_name)

            for (
                sub_module_name,
                attribute_names,
            ) in sub_module_attr.items():
                sub_module_name = module_name.getChildNamed(sub_module_name)
                addModuleDynamicHard(sub_module_name)

                _lookAhead(using_module_name=module_name, module_name=sub_module_name)

                for attribute_name in attribute_names:
                    addModuleTrust(module_name, attribute_name, trust_node)
                    addModuleAttributeFactory(
                        module_name,
                        attribute_name,
                        makeExpressionImportModuleNameHardExistsAfterImportFactory(
                            sub_module_name=sub_module_name,
                            attribute_name=attribute_name,
                        ),
                    )

def makeExpressionImportModuleNameHardExistsAfterImportFactory(
    sub_module_name,
    attribute_name,
):
    from nuitka.HardImportRegistry import trust_node_factory
    from nuitka.nodes.ImportHardNodes import (
        ExpressionImportModuleNameHardExists,
    )

    key = (sub_module_name, attribute_name)
    if key in trust_node_factory:
        return lambda source_ref: trust_node_factory[key](source_ref=source_ref)

    return lambda source_ref: ExpressionImportModuleNameHardExists(
        module_name=sub_module_name,
        import_name=attribute_name,
        module_guaranteed=False,
        source_ref=source_ref,
    )

def _lookAhead(using_module_name, module_name):
    (
        _module_name,
        package_filename,
        package_module_kind,
        finding,
    ) = locateModule(
        module_name=module_name,
        parent_package=None,
        level=0,
    )

    assert module_name == _module_name

    if finding != "not-found":
        decideRecursion(
            using_module_name=using_module_name,
            module_filename=package_filename,
            module_name=module_name,
            module_kind=package_module_kind,
        )


from bs4 import BeautifulSoup
import sys
import io

sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = 'utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = 'utf-8')

html = """

naver

daum

daum

google

tistory

"""

soup = BeautifulSoup(html, 'html.parser')

links = soup.find_all("a")
# print('links', type(links))
a = soup.find_all("a", string='daum')
# print('a', a)
b = soup.find_all("a", limit=3)
# print('b', b)
c = soup.find_all(string=["naver", "google"])
print(c)
for link in links:
    # print('link', type(link), link)
    href = link.attrs['href']
    txt = link.string
    # print('txt >> ', txt, 'href >> ', href)


import random
import json

import numpy as np
import torch

# Custom imports
import data
from model_eval import evaluate

class LSTM(torch.nn.Module):
    def __init__(self, embedding: torch.FloatTensor):
        super().__init__()

        # Embedding wrapper
        self.__embedding = torch.nn.Embedding.from_pretrained(
            embedding, freeze=True, padding_idx=0)

        # RNN layers
        self.__rnn1 = torch.nn.LSTM(300, 150,
                                    num_layers=2, batch_first=False)
        self.__rnn2 = torch.nn.LSTM(300, 150,
                                    num_layers=2, batch_first=False)

        # FC layers
        self.__fc1 = torch.nn.Linear(150, 150)
        self.__fc2 = torch.nn.Linear(150, 1)

    def all_params(self):
        params = []

        params.extend(self.__rnn1.parameters())
        params.extend(self.__rnn2.parameters())
        params.extend(self.__fc1.parameters())
        params.extend(self.__fc2.parameters())
        params.extend(self.__embedding.parameters())

        return params

    def forward(self, x):
        x = self.__embedding(x)
        x = torch.transpose(x, 0, 1)

        # Consists of (h, c)
        hidden = None

        y, hidden = self.__rnn1(x, hidden)
        y, hidden = self.__rnn2(x, hidden)

        # Last output
        y = y[-1]

        # Linear layer
        y = self.__fc1(y)
        y = torch.relu(y)

        return self.__fc2(y)

    def predict(self, x):
        with torch.no_grad():
            y = torch.sigmoid(self.forward(x))
            y = y.round().int().squeeze(-1)

        return y

def train(model: torch.nn.Module, data,
          optimizer, criterion):
    # Set state for training
    model.train()

    # Go through batches
    losses = list()
    for batch_num, batch in enumerate(data):
        model.zero_grad()

        # Calculate loss
        logits = model.forward(batch[0]).squeeze(-1)
        y = batch[1].float()
        loss = criterion(logits, y)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.all_params(), 0.25)
        optimizer.step()

        losses.append(float(loss))

    # At the end of an epoch print loss
    #print(f"loss = {np.mean(losses)}")

    return np.mean(losses)

if __name__ == "__main__":
    # Statistics
    hyperparameters = dict()
    hyperparameters["max_size"] = -1
    hyperparameters["min_freq"] = 1
    hyperparameters["train_batch_size"] = 10
    hyperparameters["valid_batch_size"] = 32
    hyperparameters["test_batch_size"] = 32
    hyperparameters["learning_rate"] = 1e-4
    statistics = dict()
    statistics["hyperparameters"] = hyperparameters

    # Frequencies
    frequencies = data.getFrequencies(data.TRAIN_DATASET_PATH)
    labelFrequencies = data.getLabelFrequencies(data.TRAIN_DATASET_PATH)

    # Vocabs
    x_vocab = data.Vocab(
        frequencies, max_size=hyperparameters["max_size"], min_freq=hyperparameters["min_freq"])
    y_vocab = data.Vocab(labelFrequencies, labels=True)

    # Datasets
    train_dataset = data.NLPDataset.from_file(data.TRAIN_DATASET_PATH)
    valid_dataset = data.NLPDataset.from_file(data.VALID_DATASET_PATH)
    test_dataset = data.NLPDataset.from_file(data.TEST_DATASET_PATH)

    # Embedding matrix
    embedding = data.generateEmbeddingMatrix(
        x_vocab, data.VECTOR_REPR_PATH)

    # Baseline model
    lstm = LSTM(embedding)

    optimizer = torch.optim.Adam(
        lstm.all_params(), lr=hyperparameters["learning_rate"])
    criterion = torch.nn.BCEWithLogitsLoss()

    iters = 5
    epochs = 5
    for i in range(iters):
        print(f"RUN {i+1}")

        # Set seed
        seed = random.randint(0, 7052020)
        np.random.seed(seed)
        torch.manual_seed(seed)

        statistics[seed] = dict()
        statistics[seed]["train_loss"] = None
        statistics[seed]["valid"] = list()

        for epoch in range(epochs):
            print(f"Epoch {epoch+1}:")

            dataloader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=hyperparameters["train_batch_size"],
                                                     shuffle=True, collate_fn=data.pad_collate_fn)
            print("\tTraining...")
            train_loss = train(lstm, dataloader,
                               optimizer, criterion)
            statistics[seed]["train_loss"] = train_loss

            dataloader = torch.utils.data.DataLoader(dataset=valid_dataset, batch_size=hyperparameters["valid_batch_size"],
                                                     shuffle=False, collate_fn=data.pad_collate_fn)
            print("\tValidating...")
            valid_evals = evaluate(lstm, dataloader, criterion)
            statistics[seed]["valid"].append(valid_evals)

        # Test dataset
        dataloader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=32,
                                                 shuffle=False, collate_fn=data.pad_collate_fn)
        print("Testing...")
        test_evals = evaluate(lstm, dataloader, criterion)
        statistics[seed]["test"] = test_evals

    print("\nAll done.")

    # Write to statistics file
    with open("c:/workspace/fer-dl/lab03/stats/lstm_stats.json", "w") as stats_file:
        stats_file.write(json.dumps(statistics))


import serial
import time
import struct
import logging as trace
import threading

class Communication(object):
    data_chars = [b'!', b'"', b'#', b'$', b'%', b'&', b"'", b'(']
    response_timeout = 2 #second
    _handle = serial.Serial()
    _error_counter = 0
    _done = False
    _thread = None

    def __init__(self, address=None):
        # Initialize class parameters

        # perform port configuration at start-up
        self._handle.port = "/dev/ttyUSB0"
        self._handle.baudrate = 115200
        self._handle.bytesize = serial.EIGHTBITS  # number of bits per bytes
        self._handle.parity = serial.PARITY_NONE  # set parity check: no parity
        self._handle.stopbits = serial.STOPBITS_ONE  # number of stop bits

        self._handle.timeout = 0.25  # non-block read
        self._handle.writeTimeout = 0.25  # timeout for write

        trace.debug('serial port configuration done')

        # self._address = address

        # Only one data stream per port
        self.data = []
        self.devices = {}
        self.sync_data_ready = threading.Event()
        self.async_data_ready = threading.Event()
        self.bin_data_ready = threading.Event()
        self._thread = threading.Thread(name='serial_thr', target= self._read_from_device)

    def __del__(self):
        self.disconnect()

    def connect(self, port_name="/dev/ttyUSB0"):
        """
        Connect device
        :param port_name: Specify serial port name if different
                          than /dev/ttyUSB0
        :return: True if connected, False if connection failed
        """

        # if port is different than default use it
        if self._handle.port != port_name:
            self._handle.port = port_name

        # start connecting
        trace.debug("Trying to connect..")
        try:
            self._handle.open()
        except Exception as e:
            trace.error("error open serial port: " + str(e))
            return False

        if self._handle.isOpen():
            trace.debug('serial port opened')
        else:
            trace.debug('serial port not opened')
            return False

        # flush buffers at start-up
        try:
            self._handle.flushInput()
            self._handle.flushOutput()
        except Exception as e:
            trace.error("error flushing input " + str(e))

        # at this point device should be connected
        self._thread.start()
        return True

    def disconnect(self):

        # mark job as done (this flag is for background thread)
        self._done = True

        # wait until background thread is done
        # if it is still running
        self._thread.join()

        # close serial port
        if self._handle.isOpen():
            self._handle.close()
            trace.debug('serial port closed')

    def init_device(self, idn):
        self.devices[idn] = {'sync': [], 'async': []}

    def write_command(self, command, idn):
        """
        Write command to device
        :param command: self-explanatory
        :return: None
        """

        # add prefix and CR on the end
        command = str(idn) + ":" + command + '\n'
        trace.debug('writing command: ' + command)
        self._handle.write(bytes(command, 'utf8'))

    def write_command_ret(self, command, idn):
        """
        Writes a command to device and waits for standard response
        :param command: self-explanatory
        :return: None
        """
        self.sync_data_ready.clear()
        self.write_command(command,idn)
        self.sync_data_ready.wait(self.response_timeout)
        if not bool(self.devices.get(idn).get('sync')):
            resp=self.devices.get(idn).get('sync').pop()
            trace.debug("Command: \""+str(command)+"\" successfully sent. Response: \""+str(resp)+"\"")
            return resp
        else:
            trace.debug("No response for command: \"" + str(command) + "\"")
            return None

    def write_command_stdr(self, command, idn):
        """
        Writes a command to device and waits for standard response
        :param command: self-explanatory
        :return: None
        """
        self.sync_data_ready.clear()
        self.write_command(command,idn)
        self.sync_data_ready.wait(self.response_timeout)
        if not bool(self.devices.get(idn).get('sync')):
            resp=self.devices.get(idn).get('sync').pop()
            if resp.rsplit()[0] == command.rsplit()[0]:
                trace.debug("Command: \""+str(command)+"\" successfully sent. Response: \""+str(resp)+"\"")
            else:
                trace.error("Wrong response for command: \"" + str(command) + "\". Response: \"" + str(resp) + "\" , expected: \""+str(command.rsplit()[0]))
            if len(resp.rsplit()) > 1:
                return resp.rsplit()[1]
            else:
                return None

    def decode_binvalue(self,seq):
        # Data format is: CSHHHHH\r
        # C - is a prefix that also serves as a 3 bit-long counter (starts with prefix0)
        # S - status byte (6 bits: 1 + negated 5 bits representing input lines)
        # HHHHH - is a 18-bit hex value (should be treated as value with sign)
        # \r - terminating CR
        # Extended format is: CSHHHHHhH\r
        # 0 ascii 0/1 sin+- X X 0/1 shutter 0/1 shutter~ X X
        # where CSH are as above and h is H (hex digit) with highest bit set
        # this signals the fact that also fractional part is sent so the bit should
        # be cleared, whole value treated as int and later divided by 256
        flag_count=seq[0]-ord('!')
        c = seq[1]
        flag_al=bool(c & 0b01000000)
        flag_dl=bool(c & 0b00001000)
        c = seq[2]
        value = (-1 if c >= ord('8') else 0)  # test for sign bit (in hex digit)
        shift = False

        for c in list(seq)[3:]:
            if (c & 0x80):
                c &= 0x7F
                shift = True

            if c >= ord('0') and c <= ord('9'):
                nibble = c - ord('0')
            elif c >= ord('A') and c <= ord('F'):
                nibble = c - (ord('A') - 10)
            else:
                break
            value <<= 4
            value |= nibble

        return (float(value) / 256   if shift else float(value))* 6.25 / 65536,flag_count,flag_al,flag_dl

    def read_line(self, line):
        coms = line.split(b'\r')
        for com in coms:
            if com[0] >= ord('!') and com[0] <= ord('('):
                value = self.decode_binvalue(com)
                self.data.append(list(value))
                self.bin_data_ready.set()
                trace.debug('Data value:'+ str(value))
            else:
                idn, com_type, message = tuple(com.partition(b'.'))
                # First char after the id number
                if com_type == b'.':
                    com_type = 'sync'
                else:
                    # if not, try other ordering character
                    idn, com_type, message = tuple(com.partition(b';'))
                    if com_type == b';':
                        com_type = 'async'
                    else:
                        trace.error('Major parsing fuckup, good luck')
                    return -1

                idnn = int(idn)
                if idnn not in self.devices.keys():
                    self.init_device(idnn)
                message=message.decode('ascii') #convert bytes to string
                self.devices[idnn][com_type].append(message)
                if com_type == 'sync':
                    self.sync_data_ready.set()
                elif com_type == 'async':
                    self.async_data_ready.set()
                trace.debug('Device ID: %d Communication type: %s Message: %s', idnn, com_type, message)

    def _read_from_device(self):
        """
        Read from device. This function is executed in separate
        thread. Function also updates necessary parameters for
        this class
        """
        self.rawdata = bytearray()
        while not self._done:

            # if incoming bytes are waiting to be
            # read from the serial input buffer
            if self._handle.inWaiting():
                # read and remove all whitespaces
                # on the right side, including '\n'
                self.rawdata.extend( self._handle.read(self._handle.inWaiting()))

                while True:
                    line,sep,rest=tuple(self.rawdata.partition(b'\r'))
                    if sep != b'\r':
                        break
                    trace.debug("new data to parse: " + str(line))
                    self.read_line(line.strip())
                    self.rawdata=rest

            # sleep for a moment (pseudo-yield in python)
            time.sleep(0.0001)


from absl.testing import parameterized
import dataclasses
import tensorflow as tf

from official.core import config_definitions as cfg
from official.core import input_reader
from official.modeling import hyperparams
from official.vision.beta.dataloaders import tfds_detection_decoders
from official.vision.beta.projects.yolo.dataloaders import yolo_detection_input

@dataclasses.dataclass
class Parser(hyperparams.Config):
  """Dummy configuration for parser."""
  output_size: int = (416, 416)
  num_classes: int = 80
  fixed_size: bool = True
  jitter_im: float = 0.1
  jitter_boxes: float = 0.005
  min_process_size: int = 320
  max_process_size: int = 608
  max_num_instances: int = 200
  random_flip: bool = True
  seed: int = 10
  shuffle_buffer_size: int = 10000

@dataclasses.dataclass
class DataConfig(cfg.DataConfig):
  """Input config for training."""
  input_path: str = ''
  tfds_name: str = 'coco/2017'
  tfds_split: str = 'train'
  global_batch_size: int = 10
  is_training: bool = True
  dtype: str = 'float16'
  decoder = None
  parser: Parser = Parser()
  shuffle_buffer_size: int = 10

class YoloDetectionInputTest(tf.test.TestCase, parameterized.TestCase):

  @parameterized.named_parameters(('training', True), ('testing', False))
  def test_yolo_input(self, is_training):
    params = DataConfig(is_training=is_training)

    decoder = tfds_detection_decoders.MSCOCODecoder()
    anchors = [[12.0, 19.0], [31.0, 46.0], [96.0, 54.0], [46.0, 114.0],
               [133.0, 127.0], [79.0, 225.0], [301.0, 150.0], [172.0, 286.0],
               [348.0, 340.0]]
    masks = {'3': [0, 1, 2], '4': [3, 4, 5], '5': [6, 7, 8]}

    parser = yolo_detection_input.Parser(
        output_size=params.parser.output_size,
        num_classes=params.parser.num_classes,
        fixed_size=params.parser.fixed_size,
        jitter_im=params.parser.jitter_im,
        jitter_boxes=params.parser.jitter_boxes,
        min_process_size=params.parser.min_process_size,
        max_process_size=params.parser.max_process_size,
        max_num_instances=params.parser.max_num_instances,
        random_flip=params.parser.random_flip,
        seed=params.parser.seed,
        anchors=anchors,
        masks=masks)
    postprocess_fn = parser.postprocess_fn(is_training=is_training)

    reader = input_reader.InputReader(params,
                                      dataset_fn=tf.data.TFRecordDataset,
                                      decoder_fn=decoder.decode,
                                      parser_fn=parser.parse_fn(
                                          params.is_training))
    dataset = reader.read(input_context=None).batch(10).take(1)
    if postprocess_fn:
      image, _ = postprocess_fn(
          *tf.data.experimental.get_single_element(dataset))
    else:
      image, _ = tf.data.experimental.get_single_element(dataset)
    print(image.shape)
    self.assertAllEqual(image.shape, (10, 10, 416, 416, 3))
    self.assertTrue(
        tf.reduce_all(tf.math.logical_and(image >= 0, image <= 1)))

if __name__ == '__main__':
  tf.test.main()


from rest_framework.routers import DefaultRouter

from messaging import api_view

router = DefaultRouter()
router.register('message', api_view.MessageVewSet, base_name='message')
router.register('chat', api_view.GroupBlogViewSet, base_name='chat')
urlpatterns = [
]
urlpatterns += router.urls


"""Retreive extracts wrt. previous lexicon update cycle.

Update extracts.json and output cycle extracts as extracts-{cycle}.txt for easy inspection

Example
    $ python3 get_extracts.py 4 working_folder
    $ python3 get_extracts.py 4 _aroma_NOUN+ADJ

Args:
    n (int): number of (CPU Threads) processes to use
    working_folder:

Required in working folder:
    extracts.json: {"cycle":[([seeds], extract, parsed_extract),..],..}
    lexicon.json:   [
                        # cycle 0
                        [
                            # entry 0 in cycle: all coincident extracts corresponding to a pattern
                            (
                                [("_sharp_ADJ", "_lemon_NOUN"), ... ],  #list of coincident vocabulary tuples tagetted by pattern A
                                pattern_A,
                            ),
                            ....
                        ],
                        ....
                    ]
required in datasets:
    harvesting.json: {"book_code": [sentence, parsed sentence tuples],.. }
"""

import json
import multiprocessing
import os
import re
import sys

import regex
from tqdm import tqdm
# add libraries to path
sys.path.append(os.path.join(sys.path[0], "libraries"))
# add working folder to path
sys.path.append(os.path.join(sys.path[0], sys.argv[2]))

from CHUNKS import chunks
from pattern_abstraction import convert_patterns, expand_chunks, to_chunks
from PATTERNS import extraction_patterns, identification_patterns

def main(argv):

    # CL arguments
    folder = argv[1]
    n = int(argv[0])

    # get a list of previously seen extracts, from all prior cycles
    extracts_file = folder + "/extracts.json"
    previous_extracts, current_cycle = get_extracts(extracts_file)
    # previous_extracts = {"cycle":[([seeds], extract, parsed_extract),..],..}

    print(f"current cycle = {current_cycle}")

    seen_extracts = extracts_as_set(previous_extracts)
    # seen_extracts = {set of unparsed extracts previously seen}

    # Collect the previous cycle's lexicon entries
    with open(folder + "/lexicon.json", "r") as f:
        lexicon = json.load(f)
    vocabulary = get_lexicon(lexicon)  # [(compiled re, (coincident phrases),..]
    # [(compiled re, (coincident phrases),..]

    # compile previously seen abstractions
    seen_abstractions = identification_patterns
    seen_patterns = compile_patterns(seen_abstractions)

    # ITERATE THROUGH HARVESTING SET, extracting where
    #   * an extract is unseen
    #   * and where known patterns do not match

    with open("./datasets/harvesting.json", "r") as f:
        dataset = json.load(f)
    # dataset = {"book_code": [(sentence, parsed sentence),..]}

    # iterate through the harvesting set
    for book_index, (book_code, extracts) in enumerate(tqdm(dataset.items())):

        # discard extracts already seen
        extracts_trimmed = trim_extracts(extracts, seen_extracts)  # [(extract, parsed_extract),...]

        # split extracts n chunks, for multi-proccessing
        extract_sets = group_extracts(extracts_trimmed, n)  # [[(extract, parsed_extract),...],...]

        processes = []
        queue = multiprocessing.Queue()
        # iterate through the extract chunks as separate processes
        for i in range(n):

            # run vocabulary pattern matching against trimmed extracts
            process = multiprocessing.Process(
                target=mapped_function, args=(extract_sets[i], vocabulary, seen_patterns, queue,),
            )
            process.start()
            processes.append(process)

        # collect process output
        for r in range(n):
            previous_extracts[current_cycle] += queue.get()

        # terminate the processes
        for process in processes:
            process.join()

        # save to json
        with open(folder + "/extracts.json", "w") as f:
            json.dump(previous_extracts, f, ensure_ascii=False)

        # save ouput to text files for inspection
        with open(folder + f"/extracts-{current_cycle}.txt", "w") as f:
            for phrases, extract, parsed_extract in previous_extracts[current_cycle]:
                f.write("\n\n")
                f.write(f"{phrases}")
                f.write("\n" + extract)
                f.write("\n" + parsed_extract)

def mapped_function(extract_set, vocabulary, seen_patterns, queue):
    """Iterate through the extract_set and return a list of those extracts matching the previous lexicon cycle entries.
    """

    returned = []

    for extract, parsed_extract in extract_set:

        for v_pattern, phrases in vocabulary:
            mo_lexicon = regex.search(v_pattern, parsed_extract)

            if mo_lexicon:
                # check does not conform to a seen pattern
                mo_seen = None
                for seen_abstraction, seen_compiled in seen_patterns:
                    mo_seen = regex.match(seen_compiled, parsed_extract)
                    if mo_seen:
                        print("\n\nseen pattern")
                        print(extract)
                        print(seen_abstraction)
                        break  # break seen pattern loop

            if mo_lexicon and not mo_seen:
                # if both vocab match and not conforming to seen_patterns
                returned.append((phrases, extract, parsed_extract))
                # print("\n\naccepted")
                # print(extract)

    queue.put(returned)

def get_extracts(file):
    """Return existing extracts file container or create new.
    """

    # if file exists, then load
    if os.path.exists(file):
        with open(file, "r") as f:
            previous_extracts = json.load(f)
        # save as "folder/extracts.json" in case wish to revert
        with open(file, "w") as f:
            json.dump(previous_extracts, f, ensure_ascii=False, indent=4)
        # add new cycle
        previous_extracts[str(len(previous_extracts.keys()))] = []
    # if file doesn't exist, create new
    else:
        previous_extracts = {"0": []}

    # get the current cycle's index key for extracts
    current_cycle = str(list(previous_extracts.keys())[-1])

    return previous_extracts, current_cycle

def extracts_as_set(extracts):
    """Return the extracts to date as a set
    Args:
        extracts (dict): {"cycle":[([seeds], extract, parsed_extract),..],..}

    Return:
        set of seen extracts
    """

    seen_extracts = []

    for keys, values in extracts.items():
        for phrase, extract, parsed_extract in values:
            seen_extracts.append(extract)
    seen_extracts = set(seen_extracts)

    return seen_extracts

def get_lexicon(lexicon):
    """Return preivious lexicon vocab as a list of (compiled re, (coincident phrases)).
    Args:
        lexicon.json:   [
                            # cycle 0
                            [

                                # list of entries, each entry corresponds to pattern
                                [
                                    [(phrase0, phrase1), ..],  # list of coincidents phrases matched (e.g., adj, noun collection)
                                    pattern_A
                                ],
                                [
                                    [(phrase0, phrase1), ..],
                                    pattern_B
                                ]
                                ....
                            ],
                            ....
                        ]
"""
    patterns = []
    for entry in lexicon[-1]:  # each entry in previous cycle
        for phrases in entry[0]:
            try:
                converted_compounded_phrases = ""
                for phrase in phrases:
                    converted_compounded_phrases += ".*" + convert_patterns([phrase],chunks)[0]

                patterns.append((regex.compile(converted_compounded_phrases), phrases))
            except:
                print(f"lexicon error, please correct, token: {phrases}")

    return patterns

def compile_patterns(abstractions):
    """Assemble list of (abstracted_pattern, compiled) tuples of abstracted patterns.

    Args:
        abstractions: []
    Returns:
        [(abstracted_pattern, compiled),...]
    """
    # assemble (new) extraction patterns in python re format
    patterns = []  # patterns = [(abstraction, compiled pattern), ..]
    for abstraction in abstractions:
        print(abstraction)
        patterns.append(
            (
                abstraction,
                regex.compile(
                    "^.*" + convert_patterns([abstraction], chunks)[0] + ".*",
                    re.MULTILINE,
                ),
            )
        )

    return patterns

def trim_extracts(extracts, seen_extracts):
    """Return a list of (extract, parsed_extract) for unseen extracts, not conforming to a known pattern.
    Args:
        extracts (list): [(sentence, parsed sentence),..]
    """
    # trim extract set, based on seen extracts
    extracts_trimmed = []
    for extract, parsed_extract in extracts:
        if extract not in seen_extracts:
            extracts_trimmed.append((extract, parsed_extract))

    return extracts_trimmed

def group_extracts(extracts, n):
    """Return extracts as a list of n lists of extracts (for multiprocessing)
       e.g., where n = 4, [[(extract, parsed_extract),...],[],[],[]]

    Args:
        extracts: [(sentence, parsed sentence),..]
    """
    extract_sets = [[] for i in range(n)]
    for i in range(0, len(extracts), n):
        for j in range(0, n):
            try:
                extract_sets[j].append(extracts[i + j])
            except:
                pass

    return extract_sets

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


#!/home/gabriel/funcam/venv/bin/python3
# ONLY TESTED ON LINUX
# To run using ./run.py [args] on your terminal (without python3)
# point the first line to some python interpreter containing the requirements
# or create a venv inside this project.
# Or delete this to use another method.

from cam import Cam
from vcam import VCam
import argparse

if __name__ == '__main__':

    parser = argparse.ArgumentParser()

    parser.add_argument('-v', '--virtual',help='enable virtual cam',action='store_true')
    parser.add_argument('--video', help='choose video input', type=int, default=0)
    parser.add_argument('--maxhands', help='set max hands for detection', type=int, default=1)
    parser.add_argument('-d', help='enable draw for marks and functional areas', action='store_true')
    parser.add_argument('--finger', help='choose the finger for control', type=int, default=8, choices=[4, 8, 12, 16, 20])
    parser.add_argument('-p', help='enable camera to take photos', action='store_true')
    args = parser.parse_args()

    if args.virtual:
        # virtual cam
        vc = VCam(video=args.video, mxhand=args.maxhands, du=args.d, f=args.finger)
        vc.start()

    else:
        # own cam
        cam = Cam(video=args.video, mxhand=args.maxhands, du=args.d, f=args.finger, p=args.p)
        cam.open()


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

from path import Path

logger = logging.getLogger(__name__)

def get_mipname(fastq_file):
    """Takes a demux fastq file and returns a MIP compatible fastq file

    Args:
        fastq_file (str): a FQP to a fastq file.

    Returns (str): A MIP compatible fastq file.
    """
    dirparts = fastq_file.split("/")
    nameparts = dirparts[-1].split("_")

    # H3LGFCCXX-l1t21_973470_CGGCTATG_L001_R2_001.fastq.gz
    # H3LGFCCXX-l1t21_Undetermined_CGGCTATG_L001_R1_001.fastq.gz
    # RNA1460A10_dual10_TCCGGAGA-ATAGAGGC_L001_R1_001.fastq.gz
    # RNA1460A10_TCCGGAGA-ATAGAGGC_L001_R1_001.fastq.gz

    index = nameparts[-4]
    # no worries, this'll always work, right?
    fc = dirparts[-5].split("_")[-1][1:]
    lane = int(nameparts[-3][-1:])
    readdirection = nameparts[-2][-1:]
    rundir = dirparts[-5]
    date = rundir.split("_")[0]
    sample_id = dirparts[-2].split("_")[1]

    # X stuff
    undetermined = ''
    if nameparts[1] == 'Undetermined':
        undetermined = '-Undetermined'

    tile = ''
    if '-' in nameparts[0]:
        # H2V2YCCXX-l2t21
        tile = nameparts[0].split('-')[1].split('t')[1]
        tile = '-' + tile

    newname = "{lane}_{date}_{fc}{tile}{undetermined}_{sample}_{index}_{readdirection}.fastq.gz".format(
        lane=lane,
        date=date,
        fc=fc,
        sample=sample_id,
        index=index,
        readdirection=readdirection,
        undetermined=undetermined,
        tile=tile
    )

    return newname

def make_link(source, dest, link_type='hard'):
    Path(dest).remove_p()

    try:
        if link_type == 'soft':
            logger.debug("ln -s {} {} ...".format(source, dest))
            Path(source).symlink(dest)
        else:
            real_source = Path(source).realpath()
            logger.debug("ln {} {} ...".format(real_source, dest))
            Path(real_source).link(dest)
    except Exception as error:
        # catch, print, and continue
        logger.error(repr(error))
        return False

    return True


from collections import defaultdict
def longestPalindrome(s):
	maxlen, maxp, l, dit = 0, "", len(s), defaultdict(list)
	for i in range(l):
		dit[s[i]].append(i)
		for j in dit[s[i][::-1]]:
			if s[j:i+1] == s[j:i+1][::-1]:
				if len(s[j:i+1]) > maxlen:
					maxlen = len(s[j:i+1])
					maxp = s[j:i+1]
					break
	return maxp

st=input()
print(longestPalindrome(st))


import numpy as np
import pandas as pd
from flask import Flask, request, jsonify, render_template
import pickle

app = Flask(__name__)
from keras.models import load_model
model = load_model('customer-churn\saved_model (1).pb')
# Importing the dataset
dataset = pd.read_csv('customer_churn_large_dataset.csv')
# Extracting dependent and independent variables:
# Extracting independent variable:
X = dataset.iloc[:,3:13].values
# Extracting dependent variable:
y = dataset.iloc[:, 5].values
# Encoding Categorical data:
# Encoding the Independent Variable
from sklearn.preprocessing import LabelEncoder
labelencoder_X = LabelEncoder()
X[:, 1] = labelencoder_X.fit_transform(X[:, 1])
# Encoding Categorical data:
# Encoding the Independent Variable
from sklearn.preprocessing import LabelEncoder
labelencoder_X = LabelEncoder()
X[:, 2] = labelencoder_X.fit_transform(X[:, 2])
#dummy encoding.
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
columnTransformer = ColumnTransformer([('yograj', OneHotEncoder(), [1])],remainder='passthrough')
X=columnTransformer.fit_transform(X)
#dummy encoding.

 # Dummy Variable trapping
X = X[:, 1:]
# Splitting the Dataset into the Training set and Test set

# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)
# Feature Scaling
# Standard Scaling:  Standardization = X'=X-mean(X)/standard deviation
# normal scaling : Normalization= X'=X-min(X)/max(x)-min(X)

from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)

@app.route('/')
def home():

    return render_template("index.html")

@app.route('/predict',methods=['GET'])
def predict():
  '''
  For rendering results on HTML GUI
  '''
  creditscore = int(request.args.get('CustomerID'))
  geo = int(request.args.get('Name'))
  age = int(request.args.get('Age'))
  tenure = int(request.args.get('Gender'))
  balance = int(request.args.get('Location'))
  numofproducts = int(request.args.get('Subscription_Length_Months'))
  creditcards=int(request.args.get('Monthly_Bill'))
  activemember = int(request.args.get('Total_Usage_GB'))

  salary = int(request.args.get('Churn'))

  y_pred= model.predict(sc_X.transform(np.array([[0,1,CustomerID ,Name,Age,Gender,Location,
                                                 Subscription_Length_Months ,Monthly_Bill,Total_Usage_GB,Churn]])))
  y_pred = (y_pred > 0.5)
  if y_pred>0.5:
    result="Customer will not churn"
  else:
    result="Customer will exit to"

  return render_template('index.html', prediction_text='Model  has predicted  : {}'.format(result))


import subprocess
import time
import os
import math
from PIL import Image
import psutil
import re
from skyfield.api import Star
import numpy as np
import threading
import select
from pathlib import Path
import fitsio
import Nexus
import Coordinates
import Display

home_path = str(Path.home())
version = "21_7"
#os.system('pkill -9 -f eFinder.py') # stops the autostart eFinder program running
x = y = 0  # x, y  define what page the display is showing
deltaAz = deltaAlt = 0
expInc = 1 # sets how much exposure changes when using handpad adjust (seconds)
gainInc = 5 # ditto for gain
offset_flag = False
align_count = 0
offset = 640, 480
star_name = "no star"
solve = False
sync_count = 0
sDog = True
gotoFlag = False

def xy2rd(x, y):  # returns the RA & Dec equivalent to a camera pixel x,y
    result = subprocess.run(
        [
            "wcs-xy2rd",
            "-w",
            destPath + "capture.wcs",
            "-x",
            str(x),
            "-y",
            str(y),
        ],
        capture_output=True,
        text=True,
    )
    result = str(result.stdout)
    line = result.split("RA,Dec")[1]
    ra, dec = re.findall("[-,+]?\d+\.\d+", line)
    return (float(ra), float(dec))

def pixel2dxdy(pix_x, pix_y):  # converts a pixel position, into a delta angular offset from the image centre
    deg_x = (float(pix_x) - 640) * pix_scale / 3600  # in degrees
    deg_y = (480 - float(pix_y)) * pix_scale / 3600
    dxstr = "{: .1f}".format(float(60 * deg_x))  # +ve if finder is left of Polaris
    dystr = "{: .1f}".format(
        float(60 * deg_y)
    )  # +ve if finder is looking below Polaris
    return (deg_x, deg_y, dxstr, dystr)

def dxdy2pixel(dx, dy):
    pix_x = dx * 3600 / pix_scale + 640
    pix_y = 480 - dy * 3600 / pix_scale
    dxstr = "{: .1f}".format(float(60 * dx))  # +ve if finder is left of Polaris
    dystr = "{: .1f}".format(float(60 * dy))  # +ve if finder is looking below Polaris
    return (pix_x, pix_y, dxstr, dystr)

def imgDisplay():  # displays the captured image on the Pi desktop.
    for proc in psutil.process_iter():
        if proc.name() == "display":
            proc.kill()  # delete any previous image display
    im = Image.open(destPath + "capture.jpg")
    #im.show()

def capture():
    global param
    if param["Test mode"] == "1":
        if offset_flag == False:
            m13 = True
            polaris_cap = False
        else:
            m13 = False
            polaris_cap = True
    else:
        m13 = False
        polaris_cap = False
    radec = nexus.get_short()
    camera.capture(
        int(float(param["Exposure"]) * 1000000),
        int(float(param["Gain"])),
        radec,
        m13,
        polaris_cap,
        destPath,
    )

def solveImage():
    global offset_flag, solve, solvedPos, elapsed_time, star_name, star_name_offset, solved_radec, solved_altaz
    scale_low = str(pix_scale * 0.9)
    scale_high = str(pix_scale * 1.1)
    name_that_star = ([]) if (offset_flag == True) else (["--no-plots"])
    handpad.display("Started solving", "", "")
    limitOptions = [
        "--overwrite",  # overwrite any existing files
        "--skip-solved",  # skip any files we've already solved
        "--cpulimit",
        "10",  # limit to 10 seconds(!). We use a fast timeout here because this code is supposed to be fast
    ]
    optimizedOptions = [
        "--downsample",
        "2",  # downsample 4x. 2 = faster by about 1.0 second; 4 = faster by 1.3 seconds
        "--no-remove-lines",  # Saves ~1.25 sec. Don't bother trying to remove surious lines from the image
        "--uniformize",
        "0",  # Saves ~1.25 sec. Just process the image as-is
    ]
    scaleOptions = [
        "--scale-units",
        "arcsecperpix",  # next two params are in arcsecs. Supplying this saves ~0.5 sec
        "--scale-low",
        scale_low,  # See config above
        "--scale-high",
        scale_high,  # See config above
    ]
    fileOptions = [
        "--new-fits",
        "none",  # Don't create a new fits
        "--solved",
        "none",  # Don't generate the solved output
        "--match",
        "none",  # Don't generate matched output
        "--corr",
        "none",  # Don't generate .corr files
        "--rdls",
        "none",  # Don't generate the point list
    ]
    cmd = ["solve-field"]
    captureFile = destPath + "capture.jpg"
    options = (
        limitOptions + optimizedOptions + scaleOptions + fileOptions + [captureFile]
    )
    start_time = time.time()
    # next line runs the plate-solve on the captured image file
    result = subprocess.run(
        cmd + name_that_star + options, capture_output=True, text=True
    )
    elapsed_time = time.time() - start_time
    print("solve elapsed time " + str(elapsed_time)[0:4] + " sec\n")
    print(result.stdout)  # this line added to help debug.
    result = str(result.stdout)
    if "solved" not in result:
        print("Bad Luck - Solve Failed")
        handpad.display("Not Solved", "", "")
        solve = False
        return
    if (offset_flag == True) and ("The star" in result):
        table, h = fitsio.read(destPath + "capture.axy", header=True)
        star_name_offset = table[0][0], table[0][1]
        lines = result.split("\n")
        for line in lines:
            if line.startswith("  The star "):
                star_name = line.split(" ")[4]
                print("Solve-field Plot found: ", star_name)
                break
    solvedPos = applyOffset()
    ra, dec, d = solvedPos.apparent().radec(coordinates.get_ts().now())
    solved_radec = ra.hours, dec.degrees
    solved_altaz = coordinates.conv_altaz(nexus, *(solved_radec))
    nexus.set_scope_alt(solved_altaz[0] * math.pi / 180)
    arr[0, 2][0] = "Sol: RA " + coordinates.hh2dms(solved_radec[0])
    arr[0, 2][1] = "   Dec " + coordinates.dd2dms(solved_radec[1])
    arr[0, 2][2] = "time: " + str(elapsed_time)[0:4] + " s"
    solve = True
    deltaCalc()

def applyOffset():
    x_offset, y_offset, dxstr, dystr = dxdy2pixel(
        float(param["d_x"]), float(param["d_y"])
    )
    print('applied_offset_pixels x,y',x_offset,y_offset)
    ra, dec = xy2rd(x_offset, y_offset)
    solved = Star(
        ra_hours=ra / 15, dec_degrees=dec
    )  # will set as J2000 as no epoch input
    solvedPos_scope = (
        nexus.get_location().at(coordinates.get_ts().now()).observe(solved)
    )  # now at Jnow and current location
    return solvedPos_scope

def deltaCalc():
    global deltaAz, deltaAlt, elapsed_time
    deltaAz = solved_altaz[1] - nexus.get_altAz()[1]
    if abs(deltaAz) > 180:
        if deltaAz < 0:
            deltaAz = deltaAz + 360
        else:
            deltaAz = deltaAz - 360
    deltaAz = 60 * (
        deltaAz * math.cos(nexus.get_scope_alt())
    )  # actually this is delta'x' in arcminutes
    deltaAlt = solved_altaz[0] - nexus.get_altAz()[0]
    deltaAlt = 60 * (deltaAlt)  # in arcminutes
    deltaXstr = "{: .2f}".format(float(deltaAz))
    deltaYstr = "{: .2f}".format(float(deltaAlt))
    arr[0, 3][0] = "Delta: x= " + deltaXstr
    arr[0, 3][1] = "       y= " + deltaYstr
    arr[0, 3][2] = "time: " + str(elapsed_time)[0:4] + " s"

def align():
    global align_count, solve, sync_count, param, offset_flag, arr, x,y
    new_arr = nexus.read_altAz(arr)
    arr = new_arr
    capture()
    imgDisplay()
    solveImage()
    if solve == False:
        handpad.display(arr[x, y][0], "Solved Failed", arr[x, y][2])
        return
    align_ra = ":Sr" + coordinates.dd2dms((solved_radec)[0]) + "#"
    align_dec = ":Sd" + coordinates.dd2aligndms((solved_radec)[1]) + "#"
    valid = nexus.get(align_ra)
    print(align_ra)
    if valid == "0":
        print("invalid position")
        handpad.display(arr[x, y][0], "Invalid position", arr[x, y][2])
        time.sleep(3)
        return
    valid = nexus.get(align_dec)
    print(align_dec)
    if valid == "0":
        print("invalid position")
        handpad.display(arr[x, y][0], "Invalid position", arr[x, y][2])
        time.sleep(3)
        return
    reply = nexus.get(":CM#")
    nexus.read_altAz(arr)
    deltaCalc()
    print("reply: ", reply)
    p = nexus.get(":GW#")
    print("Align status reply ", p)
    if nexus.is_aligned() == False: # wasnt aligned before this action
        align_count += 1
        if p[1] != "T": # and still not aligned
            arr[0,4][0] = "'OK' aligns"
            arr[0,4][1] = "Align count " + str(align_count)
            arr[0,4][2] = "Nexus reply:" + p[0:3]
            handpad.display(arr[0,4][0],arr[0,4][1],arr[0,4][2])
        else:
            arr[0,4][0] = "'OK' now syncs"
            arr[0,4][1] = "Sync count " + str(sync_count)
            arr[0,4][2] = "Nexus reply:" + p[0:3]
            arr[2,0][1] = "Nexus is aligned"
            handpad.display(arr[0,4][0],arr[0,4][1],arr[0,4][2])
            nexus.set_aligned(True)
    else:
        sync_count +=1
        arr[0,4][0] = "'OK' syncs"
        arr[0,4][1] = "Sync count " + str(sync_count)
        arr[0,4][2] = ""
        handpad.display(arr[0,4][0],arr[0,4][1],arr[0,4][2])
    print("Nexus is aligned:",nexus.is_aligned())
    return

def measure_offset():
    global offset_str, offset_flag, param, scope_x, scope_y, star_name
    offset_flag = True
    handpad.display("started capture", "", "")
    capture()
    imgDisplay()
    solveImage()
    if solve == False:
        handpad.display("solve failed", "", "")
        return
    scope_x = star_name_offset[0]
    scope_y = star_name_offset[1]
    print('pixel_offset x,y',star_name_offset)
    d_x, d_y, dxstr, dystr = pixel2dxdy(scope_x, scope_y)
    param["d_x"] = d_x
    param["d_y"] = d_y
    save_param()
    offset_str = dxstr + "," + dystr
    arr[2, 1][1] = "new " + offset_str
    arr[2, 2][1] = "new " + offset_str
    handpad.display(arr[2, 1][0], arr[2, 1][1], star_name + " found")
    offset_flag = False

def up_down(v):
    global x
    x = x + v
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])

def left_right(v):
    global y
    y = y + v
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])

def up_down_inc(inc, sign):
    arr[x, y][1] = int(float(arr[x, y][1])) + inc * sign
    param[arr[x, y][0]] = float(arr[x, y][1])
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])
    update_summary()
    time.sleep(0.1)

def flip():
    global param
    arr[x, y][1] = 1 - int(float(arr[x, y][1]))
    param[arr[x, y][0]] = str((arr[x, y][1]))
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])
    update_summary()
    time.sleep(0.1)

def update_summary():
    global param
    arr[1, 0][0] = (
        "Ex:" + str(param["Exposure"]) + "  Gn:" + str(param["Gain"])
    )
    arr[1, 0][1] = "Test:" + str(param["Test mode"]) + " GoTo++:" + str(param["Goto++ mode"])
    save_param()

def go_solve():
    global x, y, solve, arr
    new_arr = nexus.read_altAz(arr)
    arr = new_arr
    handpad.display("Image capture", "", "")
    capture()
    imgDisplay()
    handpad.display("Plate solving", "", "")
    solveImage()
    if solve == True:
        handpad.display("Solved", "", "")
    else:
        handpad.display("Not Solved", "", "")
        return
    x = 0
    y = 3
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])

def gotoDistant():
    nexus.read_altAz(arr)
    nexus_radec = nexus.get_radec()
    deltaRa = abs(nexus_radec[0]-goto_radec[0])*15
    if deltaRa > 180:
        deltaRa = abs(deltaRa - 360)
    deltaDec = abs(nexus_radec[1]-goto_radec[1])
    print('goto distance, RA,Dec :',deltaRa,deltaDec)
    if deltaRa+deltaDec > 5:
        return(True)
    else:
        return(False)

def readTarget():
    global goto_radec,goto_ra,goto_dec
    goto_ra = nexus.get(":Gr#")
    if (
        goto_ra[0:2] == "00" and goto_ra[3:5] == "00"
    ):  # not a valid goto target set yet.
        print("no GoTo target")
        handpad.display("no GoTo target","set yet","")
        return
    goto_dec = nexus.get(":Gd#")
    ra = goto_ra.split(":")
    dec = re.split(r"[:*]", goto_dec)
    goto_radec = (float(ra[0]) + float(ra[1]) / 60 + float(ra[2]) / 3600), math.copysign(
            abs(abs(float(dec[0])) + float(dec[1]) / 60 + float(dec[2]) / 3600),
            float(dec[0]),
    )
    print("Target goto RA & Dec", goto_ra, goto_dec)

def goto():
    global gotoFlag
    handpad.display("Attempting", "GoTo", "")
    gotoFlag = True
    readTarget()
    if gotoDistant():
        if sDog == True:
            nexus.write(":Sr" + goto_ra + "#")
            nexus.write(":Sd" + goto_dec + "#")
            reply = nexus.get(":MS#")
        else:
            gotoStr = '%s%06.3f %+06.3f' %("g",goto_radec[0],goto_radec[1])
            print("Target goto RA & Dec", gotoStr)
            servocat.send(gotoStr)
        handpad.display("Performing", " GoTo", "")
        time.sleep(1)
        gotoStopped()
        handpad.display("Finished", " GoTo", "")
        go_solve()
        if int(param["Goto++ mode"]) == 0:
            return
    align() # close, so local sync scope to true RA & Dec
    if sDog == True:
        nexus.write(":Sr" + goto_ra + "#")
        nexus.write(":Sd" + goto_dec + "#")
        reply = nexus.get(":MS#")
    else:
        gotoStr = '%s%06.3f %+06.3f' %("g",goto_radec[0],goto_radec[1])
        print('GoToStr: ',gotoStr)
        servocat.send(gotoStr)
    gotoStopped()
    gotoFlag = False
    handpad.display("Finished", " GoTo++", "")
    go_solve()

def getRadec():
    nexus.read_altAz(None)
    return(nexus.get_radec())

def gotoStopped():
    radecNow = getRadec()
    while True:
        time.sleep(1)
        radec = getRadec()
        print(radec[0],radecNow[0],radec[1],radecNow[1])
        if (abs(radecNow[0] - radec[0])*15 < 0.01) and (abs(radecNow[1] - radec[1]) < 0.01):
            return
        else:
            radecNow = radec

def reset_offset():
    global param, arr
    param["d_x"] = 0
    param["d_y"] = 0
    offset_str = "0,0"
    arr[2,1][1] = "new " + offset_str
    arr[2,2][1] = "new " + offset_str
    handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])
    save_param()

def get_param():
    global param, offset_str, pix_scale
    if os.path.exists(home_path + "/Solver/eFinder.config") == True:
        with open(home_path + "/Solver/eFinder.config") as h:
            for line in h:
                line = line.strip("\n").split(":")
                param[line[0]] = str(line[1])
        pix_scale = float(param["pixel scale"])
        pix_x, pix_y, dxstr, dystr = dxdy2pixel(
            float(param["d_x"]), float(param["d_y"])
        )
        offset_str = dxstr + "," + dystr

def save_param():
    global param
    with open(home_path + "/Solver/eFinder.config", "w") as h:
        for key, value in param.items():
            #print("%s:%s\n" % (key, value))
            h.write("%s:%s\n" % (key, value))

def reader():
    global button
    while True:
        if handpad.get_box() in select.select([handpad.get_box()], [], [], 0)[0]:
            button = handpad.get_box().readline().decode("ascii").strip("\r\n")
        time.sleep(0.1)

def home_refresh():
    global x,y
    while True:
        if x == 0 and y == 0:
            time.sleep(1)
        while x ==0 and y==0:
            nexus.read_altAz(arr)
            radec = nexus.get_radec()
            ra = coordinates.hh2dms(radec[0])
            dec = coordinates.dd2dms(radec[1])
            handpad.display('Nexus live',' RA:  '+ra, 'Dec: '+dec)
            time.sleep(0.5)
        else:
            handpad.display(arr[x, y][0], arr[x, y][1], arr[x, y][2])
            time.sleep (0.5)

# main code starts here

handpad = Display.Handpad(version)
coordinates = Coordinates.Coordinates()
nexus = Nexus.Nexus(handpad, coordinates)
nexus.read()
param = dict()
get_param()

# array determines what is displayed, computed and what each button does for each screen.
# [first line,second line,third line, up button action,down...,left...,right...,select button short press action, long press action]
# empty string does nothing.
# example: left_right(-1) allows left button to scroll to the next left screen
# button texts are infact def functions
p = ""
home = [
    "Nexus live",
    " RA:",
    "Dec:",
    "",
    "up_down(1)",
    "",
    "left_right(1)",
    "align()",
    "goto()",
]
nex = [
    "Nex: RA ",
    "    Dec ",
    "",
    "",
    "",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
sol = [
    "No solution yet",
    "'OK' solves",
    "",
    "",
    "",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
delta = [
    "Delta: No solve",
    "'OK' solves",
    "",
    "",
    "",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
aligns = [
    "'OK' aligns",
    "not aligned yet",
    str(p),
    "",
    "",
    "left_right(-1)",
    "",
    "align()",
    "",
]
polar = [
    "'OK' Bright Star",
    offset_str,
    "",
    "",
    "",
    "left_right(-1)",
    "left_right(1)",
    "measure_offset()",
    "",
]
reset = [
    "'OK' Resets",
    offset_str,
    "",
    "",
    "",
    "left_right(-1)",
    "left_right(1)",
    "reset_offset()",
    "",
]
summary = ["", "", "", "up_down(-1)", "up_down(1)", "", "left_right(1)", "go_solve()", ""]
exp = [
    "Exposure",
    param["Exposure"],
    "",
    "up_down_inc(expInc,1)",
    "up_down_inc(expInc,-1)",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
gn = [
    "Gain",
    param["Gain"],
    "",
    "up_down_inc(gainInc,1)",
    "up_down_inc(gainInc,-1)",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
gotoMode = [
    "Goto++ mode",
    int(param["Goto++ mode"]),
    "",
    "flip()",
    "flip()",
    "left_right(-1)",
    "",
    "go_solve()",
    "goto()",
]
mode = [
    "Test mode",
    int(param["Test mode"]),
    "",
    "flip()",
    "flip()",
    "left_right(-1)",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
status = [
    "Nexus via " + nexus.get_nexus_link(),
    "Nex align " + str(nexus.is_aligned()),
    "Brightness",
    "up_down(-1)",
    "",
    "",
    "left_right(1)",
    "go_solve()",
    "goto()",
]
bright = [
    "Handpad",
    "Display",
    "Bright Adj",
    "",
    "",
    "left_right(-1)",
    "",
    "go_solve()",
    "goto()",
]
arr = np.array(
    [
        [home, nex, sol, delta, aligns],
        [summary, exp, gn, mode, gotoMode],
        [status, polar, reset, bright, bright],
    ]
)
update_summary()
deg_x, deg_y, dxstr, dystr = dxdy2pixel(float(param["d_x"]), float(param["d_y"]))
offset_str = dxstr + "," + dystr
new_arr = nexus.read_altAz(arr)
arr = new_arr
if nexus.is_aligned() == True:
    arr[0, 4][1] = "Nexus is aligned"
    arr[0, 4][0] = "'OK' syncs"
    #arr[2,0][1] = "Nexus is aligned"

if param["Camera Type ('QHY' or 'ASI')"]=='ASI':
    import ASICamera2
    camera = ASICamera2.ASICamera(handpad)
elif param["Camera Type ('QHY' or 'ASI')"]=='QHY':
    import QHYCamera2
    camera = QHYCamera2.QHYCamera(handpad)

if param["Drive ('scopedog' or 'servocat')"].lower()=='servocat':
    import ServoCat
    servocat = ServoCat.ServoCat()
    sDog = False
    print('ServoCat mode')
    arr[2,0][1] = "ServoCat mode"
else:
    print('ScopeDog mode')
    arr[2,0][1] = "ScopeDog mode"

if param["Ramdisk"].lower()=='true':
    destPath = "/var/tmp/"
else:
    destPath = home_path + "/Solver/images/"
print('Working folder: '+destPath)

handpad.display("ScopeDog eFinder", "ver " + version, "Drive: "+param["Drive ('scopedog' or 'servocat')"])
time.sleep(3)
button = ""

scan = threading.Thread(target=reader)
scan.daemon = True
scan.start()

while True:  # next loop looks for button press and sets display option x,y
    if button == "20":
        exec(arr[x, y][7])
    elif button == "21":
        exec(arr[x, y][8])
    elif button == "18":
        exec(arr[x, y][4])
    elif button == "16":
        exec(arr[x, y][3])
    elif button == "19":
        exec(arr[x, y][5])
    elif button == "17":
        exec(arr[x, y][6])
    button = ""
    if x == 0 and y == 0 and gotoFlag == False:
        nexus.read_altAz(arr)
        radec = nexus.get_radec()
        if nexus.is_aligned() == True:
            tick = "T"
        else:
            tick = "N"
        ra = coordinates.hh2dms(radec[0])
        dec = coordinates.dd2dms(radec[1])
        handpad.display('Nexus live     '+tick,' RA:  '+ra, 'Dec: '+dec)
        time.sleep(0.2)
    else:
        time.sleep(0.1)


import statistics

from ParadoxTrading.Indicator.IndicatorAbstract import IndicatorAbstract
from ParadoxTrading.Utils import DataStruct

class AdaBBands(IndicatorAbstract):
    def __init__(
            self, _period: int, _use_key: str,
            _init_n: int = 20, _min_n: int = 20, _max_n: int = 60,
            _rate: float = 2.0, _idx_key: str = 'time'
    ):
        super().__init__()

        self.use_key = _use_key
        self.idx_key = _idx_key
        self.keys = [self.idx_key, 'upband', 'midband', 'downband']

        self.data = DataStruct(
            self.keys, self.idx_key
        )

        self.period = _period
        self.rate = _rate
        self.buf = []

        self.prev_std = None

        self.dynamic_n = float(_init_n)
        self.min_n = _min_n
        self.max_n = _max_n

    def _addOne(self, _data_struct: DataStruct):
        index_value = _data_struct.index()[0]
        self.buf.append(_data_struct.getColumn(self.use_key)[0])

        if len(self.data) > self.period:
            const_std = statistics.pstdev(self.buf[-self.period:])
            self.dynamic_n *= const_std / self.prev_std
            self.dynamic_n = max(self.min_n, self.dynamic_n)
            self.dynamic_n = min(self.max_n, self.dynamic_n)
            tmp_n = int(round(self.dynamic_n))

            mean = statistics.mean(self.buf[-tmp_n:])
            std = statistics.pstdev(self.buf[-tmp_n:])

            self.data.addRow(
                [index_value, mean + self.rate * std,
                 mean, mean - self.rate * std],
                self.keys
            )

            self.prev_std = const_std
        else:
            if len(self.data) == self.period:
                self.prev_std = statistics.pstdev(self.buf)

            self.data.addRow(
                [index_value, None, None, None],
                self.keys
            )


#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import os
import argparse
import subprocess
from glob import glob

def translatefolder(src, trg, **kw):
    python = kw.get("python", "python3")
    translate = kw.get("translate", "./translate/translate.py")
    port = int(kw.get("port", 3035))
    host = kw.get("host", "127.0.0.1")

    # create directories
    if not os.path.exists(trg):
        os.makedirs(trg)

    # collect files
    domains, problems = [], []
    for f in os.listdir(src):
        if "domain" in f and f.endswith(".pddl"):
            domains.append(os.path.join(src, f))
        elif "problem" in f and f.endswith(".pddl"):
            problems.append(os.path.join(src, f))
    domains.sort()
    problems.sort()

    # assign agents
    agents = []
    for i in range(len(domains)):
        agents.append("tcp://{}:{}".format(host, str(port+i)))

    # create command
    tmpl = ("{} {} {} {} --agent-url " + " --agent-url ".join(agents) +
            " --agent-id {} --output {} --json")
    cmd = ""
    for i, d in enumerate(domains):
        s = tmpl.format(python, translate, d, problems[i], i,
                os.path.join(trg,str(i)+'.json')) + ' & '
        print(s)
        cmd += s
    cmd = cmd[:-2]

    os.system(cmd)

def translateall(src='benchmarks/factored/', trg='benchmarks/compiled/', **kw):
    files_src = glob(src + "*/*/")
    files_trg = [os.path.join(trg, *f.split('/')[2:]) for f in files_src]

    port = 3035
    shift = 100
    errors = []
    for s, t in zip(files_src, files_trg):
        try:
            print("translating " + s + " to " + t + " port: " + str(port))
            translatefolder(s, t, port=port)
        except Exception as e:
            errors += [e]
        port += shift
    for i, error in enumerate(errors):
        print("ERR %d: %s: %s" % (i, type(error), error))

def on_translate(*args, **kw):
    if kw['all']:
        translateall(**kw)
    else:
        translatefolder(**kw)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Run GOA planner')
    parser.add_argument('src', help='path to folder containing src task')
    parser.add_argument('trg', help='destination path')
    parser.add_argument(
        '--port',
        default=3035,
        help='the port (default: 3035)'
    )
    parser.add_argument(
        '--all',
        help='translate all domains of given folder',
        action='store_true'
    )
    parser.set_defaults(func=on_translate)

    args, rest = parser.parse_known_args()
    args.func(*rest, **vars(args))


# https://adventofcode.com/2022/day/22

from collections import defaultdict

from aoctk.data import Graph, Unbound2DGrid
from aoctk.input import get_groups

def parse(data):
    ps, (ins,) = get_groups(data)

    m = Unbound2DGrid(
        (
            (complex(j, i), c)
            for i, r in enumerate(ps)
            for j, c in enumerate(r)
            if c != " "
        )
    )
    p = map(complex, ins.replace("R", " 1j ").replace("L", " -1j ").split())

    return m, p, complex(ps[0].index(ps[0].strip()))

def solve(wrapping, data="input.txt"):
    m, p, z = parse(data)

    d = 1
    while True:
        s = next(p)
        for _ in range(int(abs(s))):
            if z + d not in m:
                w, e = wrapping(m, z, d)
                if m[w] != "#":
                    z, d = w, e
                continue
            elif m[z + d] == "#":
                break
            z += d
        try:
            d *= next(p)
        except StopIteration:
            break

    return (
        int(z.real + 1) * 4 + int(z.imag + 1) * 1000 + {1: 0, 1j: 1, -1: 2, -1j: 3}[d]
    )

def part_one(data="input.txt"):
    def wrapping(m, z, d):
        w = z
        while w - d in m:
            w -= d
        return w, d

    return solve(wrapping, data)

def part_two(data="input.txt"):
    m, _, _ = parse(data)

    # Determine the face size
    w, h = (_.hi + 1 for _ in m.bounds())
    l = max(w, h) - min(w, h)

    class Faces(Graph):
        def adj(self, n):
            return {
                (n + l * d, d)
                for d in (1j ** k for k in range(4))
                if n + l * d in self.data
            }

        def __iter__(self):
            return iter(self.data)

    fs = Faces(
        {
            complex(i, j)
            for i in range(0, w, l)
            for j in range(0, h, l)
            if complex(i, j) in m
        }
    )

    # Determine the wrapping rules based on how the faces are connected
    # The mapping tells for each face and each direction the destination face
    # and the direction to go in that face.
    wrs, c = defaultdict(dict), 24
    for s in fs:
        for t, d in fs.adj(s):
            wrs[s][d] = (t, d)
            c -= 1
    while c > 0:
        for s in fs:
            r = wrs[s]
            for k in (1j ** _ for _ in range(4)):
                if c <= 0:
                    break
                if k in r and k * 1j in r:
                    (t, phi), (q, psi) = r[k], r[k * 1j]
                    if phi * 1j not in wrs[t]:
                        wrs[t][phi * 1j] = (q, psi * 1j)
                        c -= 1
                    if -psi * 1j not in wrs[q]:
                        wrs[q][-psi * 1j] = (t, -phi * 1j)
                        c -= 1

    def wrapping(m, z, d):
        a = complex(z.real // l, z.imag // l) * l
        b, e = wrs[a][d]
        w = (z - a) - (l - 1) * d + (1 + 1j)
        rot = e / d
        tr = (l + 1) * (1 + 1j) * (1 - rot) / 2
        w = b + w * rot + tr - (1 + 1j)
        return w, e

    return solve(wrapping, data)

def test():
    assert part_one("test.txt") == 6032
    assert part_two("test.txt") == 5031


import numpy as np

from sentinelhub import BBox, bbox_to_dimensions,CRS

class resolution_image:
    def __init__(self,bbox,resolution):
        self.bbox = bbox
        self.resolution = resolution
        self.size=None

    def run(self):
        our_bbox = list(np.round(self.bbox,2))
        our_bbox = BBox(bbox=our_bbox, crs=CRS.WGS84)
        self.size = bbox_to_dimensions(our_bbox, resolution=self.resolution)
        return self.size


import heapq
import numpy as np
import itertools

class PQueue:
    def __init__(self):
        self.pq = []                         # list of entries arranged in a heap
        self.entry_finder = {}               # mapping of tasks to entries
        self.REMOVED = '<removed-task>'      # placeholder for a removed task
        self.counter = itertools.count()     # unique sequence count

    def add_task(self, task, priority=0):
        'Add a new task or update the priority of an existing task'
        add_to_q = True
        if task in self.entry_finder:
            add_to_q = self.remove_task_if_lower_priority(task, priority)
        if add_to_q:
            count = next(self.counter)
            entry = [priority, count, task]
            self.entry_finder[task] = entry
            heapq.heappush(self.pq, entry)

    def remove_task_if_lower_priority(self, task, priority):
        'Mark an existing task as self.REMOVED.  Raise KeyError if not found.'
        entry = self.entry_finder[task]
        if entry[0] > priority:
            del self.entry_finder[task]
            entry[-1] = self.REMOVED
            return True
        else:
            return False

    def pop_task(self):
        'Remove and return the lowest priority task. Raise KeyError if empty.'
        while self.pq:
            priority, count, task = heapq.heappop(self.pq)
            if task is not self.REMOVED:
                #print(task)
                #print(self.entry_finder)
                del self.entry_finder[task]
                return task
        raise KeyError('pop from an empty priority queue')

    def empty(self):
        return len(self.entry_finder) == 0

    def qsize(self):
        return len(self.entry_finder)

def test():
    q = PQueue()
    q.add_task((tuple(np.array([1,2,3])),1),1)
    q.add_task((tuple(np.array([4,5,6])),1),0)
    q.add_task((tuple(np.array([1,2,3])),1),-1)
    print(q.pop_task())
    print(q.pop_task())
    q.add_task((tuple(np.array([1,2,3])),1),0.5)

    print(q.pop_task())


from app import app
from app import db
from app.models import booking
from flask import jsonify, request

@app.route('/get_booking', methods=['GET'])
def get_booking():
    date = request.args.get('date')
    idTable = request.args.get('idTable')

    phone = ['','','','','','','','']

    users = booking.query.all()
    for u in users:
        if u.date == date and u.table == int(idTable):
            for h in range(8):
                if (u.hour_start <= 12+h) and (12+h <= u.hour_end):
                    phone[h] = u.phone

    return jsonify({
            "schedule":{
                "table_id": idTable,
                "date": date,
                "hours":[
                {
                    "hour": "12:00",
                    "customerPhone": phone[0]
                },
                {
                    "hour": "13:00",
                    "customerPhone": phone[1]
                },
                {
                    "hour": "14:00",
                    "customerPhone": phone[2]
                },
                {
                    "hour": "15:00",
                    "customerPhone": phone[3]
                },
                {
                    "hour": "16:00",
                    "customerPhone": phone[4]
                },
                {
                    "hour": "17:00",
                    "customerPhone": phone[5]
                },
                {
                    "hour": "18:00",
                    "customerPhone": phone[6]
                },
                {
                    "hour": "19:00",
                    "customerPhone": phone[7]
                }
                ]
            }
        })

@app.route('/post_new_booking', methods=['POST'])
def post_new_booking():
    date = request.json['date']
    table = request.json['table_id']
    name = request.json['name']
    comment = request.json['comment']
    phone = request.json['phone']
    hours_start = request.json['hours_start']
    hours_end = request.json['hours_end']

    u = booking(table=table, name=name, phone=phone, info=comment, date=date, hour_start=hours_start, hour_end=hours_end)
    db.session.add(u)
    db.session.commit()

    return jsonify({"status": "OK"})


#!/usr/bin/env python3

import matplotlib.pyplot as plt
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("file", type=str, help="data file")
parser.add_argument("-R", "--rd", type=float, default=1e3, help="resistor on drain")
parser.add_argument("-D", "--diagnose", action="store_true", help="plot aux polynomial")
parser.add_argument("-I", "--init", type=float, default=10, help="iterative seed")
parser.add_argument("-G", "--gain", type=float, default=25, help="gain desired (dB)")
parser.add_argument("-P", "--plot", action="store_true", help="plot fitted polynomial")

args = parser.parse_args()

try:
    data = np.genfromtxt(args.file)
except OSError:
    print("File {0:s} does not exist".format(args.file))
    exit()

vgs_data, id_data = data[:, 0], data[:, 1]

if args.diagnose:
    vx = np.linspace(0, 10, 1000)
    vy1 = [((vgs_data - v) @ id_data -
        np.square(vgs_data - v) @ id_data * np.sum(np.power(vgs_data - v, 3)) /
        np.sum(np.power(vgs_data - v, 4)))
        for v in vx]
    #vy2 = [((vgs_data @ id_data -
    #    np.square(vgs_data - v) @ id_data * np.sum(np.power(vgs_data - v, 3)) /
    #    np.sum(np.power(vgs_data - v, 4))) / np.sum(id_data))
    #    for v in vx]
    #vy3 = [(vgs_data @ id_data - np.sum(id_data) * v +
    #    np.square(vgs_data - v) @ id_data * np.sum(np.power(vgs_data - v, 3)) /
    #    np.sum(np.power(vgs_data - v, 4)))]

    plt.plot(vx, vy1, color="r")
    #plt.plot(vx, vy2, color="g")
    #plt.plot(vx, vy3, color="b")
    plt.xlabel(r"$v_t$")
    plt.ylabel(r"$p(v_t$)")
    plt.grid()
    plt.show()
    exit()

# Biseccion
va, vt = 0, 0
vb = args.init
while not np.isclose(va, vb, rtol=10 * np.finfo(float).eps, atol=0.0):
    vt = (va + vb) / 2
    d = ((vgs_data - vt) @ id_data -
        (np.square(vgs_data - vt) @ id_data / np.sum(np.power(vgs_data - vt, 4))) *
        np.sum(np.power(vgs_data - vt, 3)))
    if d > 0:
        vb = vt
    elif d < 0:
        va = vt
    else:
        va = vb

k = id_data @ np.square(vgs_data - vt) / np.sum(np.power(vgs_data - vt, 4))
k2 = id_data @ (vgs_data - vt) / np.sum(np.power(vgs_data - vt, 3))

if not np.isclose(k, k2, rtol=10 * np.finfo(float).eps, atol=0.0):
    print("fit invalid, try a different seed estimated from aux polynomial")
    exit()

gain_target = 10 ** (args.gain / 20)
vgsq = gain_target / (2 * k * args.rd) + vt
idq = k * (vgsq - vt) ** 2

print("k = {:3.3f} mA/V^2".format(k * 1000))
print("Vt = {:2.3f} V\n".format(vt))
print("Gain = {} dB".format(args.gain))
print("Rd = {} ohm".format(args.rd))
print("Vgsq = {:3.3} V".format(vgsq))
print("Idq = {:2.4} mA".format(1000 * idq))

if args.plot:
    vgs = np.linspace(vgs_data[0], vgs_data[len(vgs_data) - 1], 1000)
    i_d = k * np.square(vgs - vt)

    plt.title(r"$K = {0:3.3f} mA/V^2, V_t = {1:2.3f}V$".format(k * 1000, vt))
    plt.xlabel(r"$v_{gs}$")
    plt.ylabel(r"$i_d$")
    plt.grid()
    plt.plot(vgs_data, id_data, marker="o", linestyle=" ")
    plt.plot(vgs, i_d, linestyle="-")
    plt.show()


from sklearn.svm import SVC

import common as c

def run(num_folds, seed, test_size, dataset_url, delimiter, _c, gamma, kernel):
    try:
        model = SVC(C=_c, gamma=gamma, kernel=kernel)
        c.run_with_classification_model(model, num_folds, seed, test_size, dataset_url, delimiter)
    except Exception as e:
        raise e