from typing import Tuple

import hypothesis.extra.numpy as hnp
import hypothesis.strategies as st
import numpy as np
import pytest
from hypothesis import example, given, settings
from numpy.testing import assert_allclose

from mygrad import mem_guard_off, no_autodiff
from mygrad.math.misc.funcs import matmul
from mygrad.nnet.activations import sigmoid, tanh
from mygrad.tensor_base import Tensor
from tests.utils.errors import does_not_raise

gru_module = pytest.importorskip("mygrad.nnet.layers.gru")
gru = gru_module.gru

@settings(deadline=None)
@example(s0=np.array([[0.0, 0.0]]), dropout=0.0, out_constant=False)
@given(
    s0=st.none()
    | hnp.arrays(shape=(1, 2), dtype=float, elements=st.just(0))
    | hnp.arrays(shape=(1, 2), dtype=float, elements=st.just(0)).map(
        lambda x: Tensor(x)
    )
    | hnp.arrays(shape=(1, 2), dtype=float, elements=st.just(0)).map(
        lambda x: Tensor(x, constant=True)
    ),
    dropout=st.floats(0, 1, exclude_max=True),
    out_constant=st.booleans(),
)
@mem_guard_off
def test_nonconstant_s0_raises(s0, dropout: float, out_constant: bool):
    T, N, C, D = 5, 1, 3, 2
    X = Tensor(np.random.rand(T, N, C))
    Wz, Wr, Wh = Tensor(np.random.rand(3, D, D))
    Uz, Ur, Uh = Tensor(np.random.rand(3, C, D))
    bz, br, bh = Tensor(np.random.rand(3, D))

    with does_not_raise() if (
        out_constant or s0 is None or isinstance(s0, np.ndarray) or s0.constant
    ) else pytest.raises(ValueError):
        gru(
            X,
            Uz,
            Wz,
            bz,
            Ur,
            Wr,
            br,
            Uh,
            Wh,
            bh,
            s0=s0,
            dropout=dropout,
            constant=out_constant,
        )

@settings(deadline=None)
@given(out_constant=st.booleans())
@mem_guard_off
def test_all_constant(out_constant: bool):
    T, N, C, D = 5, 1, 3, 2
    X = Tensor(np.random.rand(T, N, C), constant=True)
    Wz, Wr, Wh = Tensor(np.random.rand(3, D, D), constant=True)
    Uz, Ur, Uh = Tensor(np.random.rand(3, C, D), constant=True)
    bz, br, bh = Tensor(np.random.rand(3, D), constant=True)

    gru(X, Uz, Wz, bz, Ur, Wr, br, Uh, Wh, bh, constant=out_constant).backward()

    assert X.grad is None

    assert Wz.grad is None
    assert Wr.grad is None
    assert Wh.grad is None

    assert Uz.grad is None
    assert Ur.grad is None
    assert Uh.grad is None

    assert bz.grad is None
    assert br.grad is None
    assert bh.grad is None

@settings(deadline=None)
@given(
    X=hnp.arrays(
        shape=hnp.array_shapes(max_side=5, min_dims=3, max_dims=3),
        dtype=float,
        elements=st.floats(-10, 10),
    ),
    D=st.sampled_from(list(range(1, 5))),
    dropout=st.sampled_from([0, 0.45]),
    dtypes=st.tuples(*[hnp.floating_dtypes(endianness="=", sizes=(32, 64))] * 4),
    data=st.data(),
)
@pytest.mark.filterwarnings("ignore: overflow encountered in exp")
@pytest.mark.filterwarnings("ignore: overflow encountered in sig")
@mem_guard_off
def test_gru_fwd(X, D, dropout, dtypes, data: st.DataObject):
    T, N, C = X.shape

    Wz, Wr, Wh = data.draw(
        hnp.arrays(
            shape=(3, D, D),
            dtype=dtypes[0],
            elements=st.floats(-10.0, 10.0, width=dtypes[0].itemsize * 8),
        ),
        label="Wz, Wr, Wh",
    )

    Uz, Ur, Uh = data.draw(
        hnp.arrays(
            shape=(3, C, D),
            dtype=dtypes[1],
            elements=st.floats(-10.0, 10.0, width=dtypes[1].itemsize * 8),
        ),
        label="Uz, Ur, Uh",
    )

    bz, br, bh = data.draw(
        hnp.arrays(
            shape=(3, D),
            dtype=dtypes[2],
            elements=st.floats(-10.0, 10.0, width=dtypes[2].itemsize * 8),
        ),
        label="bz, br, bh",
    )

    V = data.draw(
        hnp.arrays(shape=(D, C), dtype=float, elements=st.floats(-10.0, 10.0)),
        label="V",
    )

    s0 = np.zeros((N, D), dtype=dtypes[3])

    X = Tensor(X)
    X2 = X.__copy__()

    Wz = Tensor(Wz)
    Wz2 = Wz.__copy__()

    Uz = Tensor(Uz)
    Uz2 = Uz.__copy__()

    bz = Tensor(bz)
    bz2 = bz.__copy__()

    Wr = Tensor(Wr)
    Wr2 = Wr.__copy__()

    Ur = Tensor(Ur)
    Ur2 = Ur.__copy__()

    br = Tensor(br)
    br2 = br.__copy__()

    Wh = Tensor(Wh)
    Wh2 = Wh.__copy__()

    Uh = Tensor(Uh)
    Uh2 = Uh.__copy__()

    bh = Tensor(bh)
    bh2 = bh.__copy__()

    V = Tensor(V)
    V2 = V.__copy__()

    s0 = Tensor(s0)
    s2 = s0.__copy__()

    s = gru(X, Uz, Wz, bz, Ur, Wr, br, Uh, Wh, bh, dropout=dropout, constant=True)
    o = matmul(s[1:], V)
    ls = o.sum()

    assert s.constant is True

    if dropout:
        for d in [
            s.creator._dropUr,
            s.creator._dropUz,
            s.creator._dropUh,
            s.creator._dropWr,
            s.creator._dropWz,
            s.creator._dropWh,
        ]:
            assert np.all(np.logical_or(d == 1 / (1 - dropout), d == 0))

    stt = s2
    all_s = [s0.data]
    ls2 = 0
    if dropout:
        Wz2d = s.creator._dropWz * Wz2
        Wr2d = s.creator._dropWr * Wr2
        Wh2d = s.creator._dropWh * Wh2
    else:
        Wz2d = Wz2
        Wr2d = Wr2
        Wh2d = Wh2

    with no_autodiff:
        for n, x in enumerate(X2):
            if not dropout:
                z = sigmoid(matmul(x, Uz2) + matmul(stt, Wz2d) + bz2)
                r = sigmoid(matmul(x, Ur2) + matmul(stt, Wr2d) + br2)
                h = tanh(matmul(x, Uh2) + matmul((r * stt), Wh2d) + bh2)
            else:
                z = sigmoid(
                    (s.creator._dropUz[0] * matmul(x, Uz2)) + matmul(stt, Wz2d) + bz2
                )
                r = sigmoid(
                    (s.creator._dropUr[0] * matmul(x, Ur2)) + matmul(stt, Wr2d) + br2
                )
                h = tanh(
                    (s.creator._dropUh[0] * matmul(x, Uh2))
                    + matmul((r * stt), Wh2d)
                    + bh2
                )

            stt = (1 - z) * h + z * stt
            all_s.append(stt)
            o = matmul(stt, V2)
            ls2 += o.sum()

    tolerances = dict(atol=1e-5, rtol=1e-5)
    rec_s_dat = np.stack([i.data for i in all_s])

    assert_allclose(ls.data, ls2.data, **tolerances)

    assert_allclose(rec_s_dat, s.data, **tolerances)

    assert_allclose(Wz.data, Wz2.data, **tolerances)
    assert_allclose(Wr.data, Wr2.data, **tolerances)
    assert_allclose(Wh.data, Wh2.data, **tolerances)

    assert_allclose(Uz.data, Uz2.data, **tolerances)
    assert_allclose(Ur.data, Ur2.data, **tolerances)
    assert_allclose(Uh.data, Uh2.data, **tolerances)

    assert_allclose(bz.data, bz2.data, **tolerances)
    assert_allclose(br.data, br2.data, **tolerances)
    assert_allclose(bh.data, bh2.data, **tolerances)

    assert_allclose(V.data, V2.data, **tolerances)

    assert_allclose(X.data, X2.data, **tolerances)

    ls.clear_graph()
    ls2.clear_graph()

    for x in [s, Wz, Wr, Wh, bz, br, bh, X, Uz, Ur, Uh, V]:
        assert not x._ops

# There is an occasional overflow in the oracle sigmoid
# that is acceptable - reducing the input domain to ameliorate this
# would potentially mask real numerical issues
@settings(deadline=None)
@given(
    data=st.data(),
    X=hnp.arrays(
        shape=hnp.array_shapes(max_side=5, min_dims=3, max_dims=3),
        dtype=float,
        elements=st.floats(-10, 10),
    ),
    D=st.sampled_from(list(range(1, 5))),
    bp_lim=st.booleans(),
    dropout=st.sampled_from([0, 0.45]),
    U_constants=st.tuples(*[st.booleans()] * 3),
    W_constants=st.tuples(*[st.booleans()] * 3),
    b_constants=st.tuples(*[st.booleans()] * 3),
    X_constant=st.booleans(),
    V_constant=st.booleans(),
    dtypes=st.tuples(*[hnp.floating_dtypes(endianness="=", sizes=(32, 64))] * 4),
)
@pytest.mark.filterwarnings("ignore: overflow encountered in exp")
@pytest.mark.filterwarnings("ignore: overflow encountered in sig")
def test_gru_backward(
    data: st.DataObject,
    X: np.ndarray,
    D: int,
    bp_lim: bool,
    dropout: bool,
    U_constants: Tuple[bool, bool, bool],
    W_constants: Tuple[bool, bool, bool],
    b_constants: Tuple[bool, bool, bool],
    X_constant: bool,
    V_constant: bool,
    dtypes: Tuple[int, int, int, int],
):
    tolerances = dict(atol=1e-5, rtol=1e-5)
    T, N, C = X.shape

    Wz, Wr, Wh = data.draw(
        hnp.arrays(
            shape=(3, D, D),
            dtype=dtypes[0],
            elements=st.floats(-10.0, 10.0, width=dtypes[0].itemsize * 8),
        ),
        label="Wz, Wr, Wh",
    )

    Uz, Ur, Uh = data.draw(
        hnp.arrays(
            shape=(3, C, D),
            dtype=dtypes[1],
            elements=st.floats(-10.0, 10.0, width=dtypes[1].itemsize * 8),
        ),
        label="Uz, Ur, Uh",
    )

    bz, br, bh = data.draw(
        hnp.arrays(
            shape=(3, D),
            dtype=dtypes[2],
            elements=st.floats(-10.0, 10.0, width=dtypes[2].itemsize * 8),
        ),
        label="bz, br, bh",
    )

    V = data.draw(
        hnp.arrays(shape=(D, C), dtype=float, elements=st.floats(-10.0, 10.0)),
        label="V",
    )

    s0 = np.zeros((N, D), dtype=dtypes[3])

    X = Tensor(X, constant=X_constant)
    X2 = X.__copy__()

    Wz = Tensor(Wz, constant=W_constants[0])
    Wz2 = Wz.__copy__()

    Uz = Tensor(Uz, constant=U_constants[0])
    Uz2 = Uz.__copy__()

    bz = Tensor(bz, constant=b_constants[0])
    bz2 = bz.__copy__()

    Wr = Tensor(Wr, constant=W_constants[1])
    Wr2 = Wr.__copy__()

    Ur = Tensor(Ur, constant=U_constants[1])
    Ur2 = Ur.__copy__()

    br = Tensor(br, constant=b_constants[1])
    br2 = br.__copy__()

    Wh = Tensor(Wh, constant=W_constants[2])
    Wh2 = Wh.__copy__()

    Uh = Tensor(Uh, constant=U_constants[2])
    Uh2 = Uh.__copy__()

    bh = Tensor(bh, constant=b_constants[2])
    bh2 = bh.__copy__()

    V = Tensor(V, constant=V_constant)
    V2 = V.__copy__()

    s0 = Tensor(s0)
    s2 = s0.__copy__()

    # bp_lim = len(X) - 1 should behave the same as no bp-lim
    s = gru(
        X,
        Uz,
        Wz,
        bz,
        Ur,
        Wr,
        br,
        Uh,
        Wh,
        bh,
        dropout=dropout,
        constant=False,
        bp_lim=len(X) - 1 if bp_lim else None,
    )
    o = matmul(s[1:], V)
    ls = o.sum()

    stt = s2
    all_s = [s0.data]
    ls2 = 0
    if dropout:
        Wz2d = s.creator._dropWz * Wz2
        Wr2d = s.creator._dropWr * Wr2
        Wh2d = s.creator._dropWh * Wh2
    else:
        Wz2d = Wz2
        Wr2d = Wr2
        Wh2d = Wh2
    for n, x in enumerate(X2):
        if not dropout:
            z = sigmoid(matmul(x, Uz2) + matmul(stt, Wz2d) + bz2)
            r = sigmoid(matmul(x, Ur2) + matmul(stt, Wr2d) + br2)
            h = tanh(matmul(x, Uh2) + matmul((r * stt), Wh2d) + bh2)
        else:
            z = sigmoid(
                (s.creator._dropUz[0] * matmul(x, Uz2)) + matmul(stt, Wz2d) + bz2
            )
            r = sigmoid(
                (s.creator._dropUr[0] * matmul(x, Ur2)) + matmul(stt, Wr2d) + br2
            )
            h = tanh(
                (s.creator._dropUh[0] * matmul(x, Uh2)) + matmul((r * stt), Wh2d) + bh2
            )
        stt = (1 - z) * h + z * stt
        all_s.append(stt)
        o = matmul(stt, V2)
        ls2 += o.sum()

    ls.backward()
    ls2.backward()

    rec_s_grad = np.stack([i.grad for i in all_s[1:]])

    if not s.constant:
        assert_allclose(rec_s_grad, s.grad, **tolerances)
    else:
        assert s.grad is None

    if not Wz.constant:
        assert_allclose(Wz.grad, Wz2.grad, **tolerances)
    else:
        assert Wz.grad is None

    if not Wr.constant:
        assert_allclose(Wr.grad, Wr2.grad, **tolerances)
    else:
        assert Wr.grad is None

    if not Wh.constant:
        assert_allclose(Wh.grad, Wh2.grad, **tolerances)
    else:
        assert Wh.grad is None

    if not Uz.constant:
        assert_allclose(Uz.grad, Uz2.grad, **tolerances)
    else:
        assert Uz.grad is None

    if not Ur.constant:
        assert_allclose(Ur.grad, Ur2.grad, **tolerances)
    else:
        assert Ur.grad is None

    if not Uh.constant:
        assert_allclose(Uh.grad, Uh2.grad, **tolerances)
    else:
        assert Uh.grad is None

    if not bz.constant:
        assert_allclose(bz.grad, bz2.grad, **tolerances)
    else:
        assert bz.grad is None

    if not br.constant:
        assert_allclose(br.grad, br2.grad, **tolerances)
    else:
        assert br.grad is None

    if not bh.constant:
        assert_allclose(bh.grad, bh2.grad, **tolerances)
    else:
        assert bh.grad is None

    if not V.constant:
        assert_allclose(V.grad, V2.grad, **tolerances)
    else:
        assert V.grad is None

    if not X.constant:
        assert_allclose(X.grad, X2.grad, **tolerances)
    else:
        assert X.grad is None

    for x in [s, Wz, Wr, Wh, bz, br, bh, X, Uz, Ur, Uh, V]:
        assert not x._ops


import logging
from datetime import datetime, timezone

def unixtime_to_yyyymmdd(unix_seconds: int | float) -> tuple[str, str, str]:
    """Converts Unix time in seconds to zero-padded year, month, day values in UTC."""
    dt = datetime.fromtimestamp(unix_seconds, timezone.utc)
    year, month, day = dt.strftime("%Y-%m-%d").split("-")
    return year, month, day

def log_job_status(job_name: str, success_flag: bool) -> str:
    """Logs and returns the logged message based on a job's success/failure status."""
    if success_flag:
        message = f"Successfully ingested all {job_name} data!"
        logging.info(message)
    else:
        message = f"Failed to ingest all {job_name} data."
        logging.error(message)
    return message


import pdb

def test(sln, ls, answer):
    print('ls = %s, answer = %s' % (ls, answer))

    head = sln.ls_to_ll(ls)
    out = sln.deleteDuplicates(head)
    out_ls = sln.ll_to_ls(out)

    assert out_ls == answer, out_ls

def run(sln):
    test(sln, [1, 2, 3, 3, 4, 4, 5], [1, 2, 5])
    test(sln, [1, 1, 1, 2, 3], [2, 3])


"""
owtf.config.config
~~~~~~~~~~~~~~~~~~

The Configuration object parses all configuration files, loads them into
memory, derives some settings and provides framework modules with a central
repository to get info.
"""

import os
import re
import logging
import socket
from copy import deepcopy
try: #PY3
    from urllib.parse import urlparse
except ImportError:  #PY2
     from urlparse import urlparse
from collections import defaultdict

from owtf.dependency_management.dependency_resolver import BaseComponent
from owtf.dependency_management.interfaces import ConfigInterface
from owtf.lib.exceptions import PluginAbortException, DBIntegrityException, UnresolvableTargetException
from owtf.lib.general import cprint
from owtf.managers import target as target_manager
from owtf.utils import is_internal_ip, directory_access, FileOperations

REPLACEMENT_DELIMITER = "@@@"
REPLACEMENT_DELIMITER_LENGTH = len(REPLACEMENT_DELIMITER)
CONFIG_TYPES = ['string', 'other']

class Config(BaseComponent, ConfigInterface):

    COMPONENT_NAME = "config"

    root_dir = None
    owtf_pid = None
    config_path = os.path.expanduser(os.path.join("~", '.owtf', 'conf', 'framework.cfg'))
    profiles = {
        "GENERAL_PROFILE": None,
        "RESOURCES_PROFILE": None,
        "WEB_PLUGIN_ORDER_PROFILE": None,
        "NET_PLUGIN_ORDER_PROFILE": None,
        "MAPPING_PROFILE": None
    }
    target = None

    def __init__(self, root_dir, owtf_pid):
        """Initialize everything.

        :param root_dir: The root directory for owtf
        :type root_dir: `str`
        :param owtf_pid: The pid of the owtf parent process
        :type owtf_pid: `int`
        """
        self.register_in_service_locator()
        self.root_dir = root_dir
        self.owtf_pid = owtf_pid
        self.resource = None
        self.error_handler = None
        self.target = None
        self.config = None
        self.db_plugin = None
        self.worklist_manager = None
        self.initialize_attributes()
        # key can consist alphabets, numbers, hyphen & underscore.
        self.search_regex = re.compile('%s([a-zA-Z0-9-_]*?)%s' % (REPLACEMENT_DELIMITER, REPLACEMENT_DELIMITER))
        # Available profiles = g -> General configuration, n -> Network plugin
        # order, w -> Web plugin order, r -> Resources file
        self.initialize_attributes()
        self.load_config_from_file(self.framework_config_file_path())

    def init(self):
        """Initialize the option resources."""
        self.resource = self.get_component("resource")
        self.error_handler = self.get_component("error_handler")
        self.target = self.get_component("target")
        self.db_plugin = self.get_component("db_plugin")
        self.worklist_manager = self.get_component("worklist_manager")

    def initialize_attributes(self):
        """Initializes the attributes for the config dictionary

        :return: None
        :rtype: None
        """
        self.config = defaultdict(list)  # General configuration information.
        for type in CONFIG_TYPES:
            self.config[type] = {}

    def select_user_or_default_config_path(self, file_path, default_path=""):
        """If user config files are present return the passed file path, else the default config file path

        :param file_path: Path of config file to locate
        :param default_path: Default path of this file relative to "@@@root_dir@@@/configuration/" excluding filename
        :return: Absolute path of the file if found else default path
        """
        file_path = os.path.expanduser(file_path)
        if os.path.isfile(file_path):
            return file_path
        path = os.path.join(self.get_val("CONFIG_DIR"), default_path, os.path.basename(file_path))
        return path

    def framework_config_file_path(self):
        """Returns the full path to the configuration file in ~/.owtf or fallback to package specific file

        :return: path of the existing configuration file
        :rtype: `str`
        """
        if os.path.isfile(self.config_path):
            return self.config_path
        path = os.path.join(self.root_dir, 'data', 'conf', os.path.basename(self.config_path))
        return path

    def load_config_from_file(self, config_path):
        """Load the configuration into a global dictionary.

        :param config_path: The configuration file path
        :type config_path: `str`
        :return: None
        :rtype: None
        """
        cprint("Loading config from: %s.." % config_path)
        config_file = FileOperations.open(config_path, 'r')
        self.set_val('FRAMEWORK_DIR', self.root_dir)  # Needed Later.
        for line in config_file:
            try:
                key = line.split(':')[0]
                if key[0] == '#':  # Ignore comment lines.
                    continue
                value = line.replace("%s: " % key, "").strip()
                self.set_val(key,
                         self.multi_replace(value, {'FRAMEWORK_DIR': self.root_dir, 'OWTF_PID': str(self.owtf_pid)}))
            except ValueError:
                self.error_handler.abort_framework("Problem in config file: %s -> Cannot parse line: %s" % (
                    config_path, line))

    def str2bool(self, string):
        """ Converts a string to a boolean

        :param string: String to convert
        :type string: `str`
        :return: Boolean equivalent
        :rtype: `bool`
        """
        return (not(string in ['False', 'false', 0, '0']))

    def process_phase1(self, options):
        """Process the options from the CLI.

        :param dict options: Options coming from the CLI.

        """
        # Backup the raw CLI options in case they are needed later.
        self.cli_options = deepcopy(options)
        self.load_profiles(options['Profiles'])

    def process_phase2(self, options):
        """Process the options for phase 2

        :param options: Options coming from the CLI.
        :type options: `dict`
        :return: None
        :rtype: None
        """
        target_urls = self.load_targets(options)
        self.load_works(target_urls, options)

    def load_works(self, target_urls, options):
        """Select the proper plugins to run against the target URLs.

        :param list target_urls: the target URLs
        :param dict options: the options from the CLI.

        """
        for target_url in target_urls:
            if target_url:
                self.load_work(target_url, options)

    def load_work(self, target_url, options):
        """Select the proper plugins to run against the target URL.

        .. note::

            If plugin group is not specified and several targets are fed, OWTF
            will run the WEB plugins for targets that are URLs and the NET
            plugins for the ones that are IP addresses.

        :param str target_url: the target URL
        :param dict options: the options from the CLI.
        """
        target = self.target.get_target_config_dicts({'target_url': target_url})
        group = options['PluginGroup']
        if options['OnlyPlugins'] is None:
            # If the plugin group option is the default one (not specified by the user).
            if group is None:
                group = 'web'  # Default to web plugins.
                # Run net plugins if target does not start with http (see #375).
                if not target_url.startswith(('http://', 'https://')):
                    group = 'network'
            filter_data = {'type': options['PluginType'], 'group': group}
        else:
            filter_data = {"code": options.get("OnlyPlugins"), "type": options.get("PluginType")}
        plugins = self.db_plugin.get_all(filter_data)
        if not plugins:
            logging.error("No plugin found matching type '%s' and group '%s' for target '%s'!" %
                          (options['PluginType'], group, target))
        self.worklist_manager.add_work(target, plugins, force_overwrite=options["Force_Overwrite"])

    def get_profile_path(self, profile_name):
        """ Get the path to the named profile

        :param profile_name: Name of the profile
        :type profile_name: `str`
        :return: Path where the profile is defined
        :rtype: `str`
        """
        return self.profiles.get(profile_name, None)

    def load_profiles(self, profiles):
        """ Load profiles from default config directory

        :param profiles: Dictionary of paths to profiles
        :type profiles: `dict`
        :return: None
        :rtype: None
        """
        # This prevents python from blowing up when the Key does not exist :)
        self.profiles = defaultdict(list)

        # Now override with User-provided profiles, if present.
        self.profiles["GENERAL_PROFILE"] = profiles.get('g', None) or self.get_val("DEFAULT_GENERAL_PROFILE")
        # Resources profile
        self.profiles["RESOURCES_PROFILE"] = profiles.get('r', None) or \
            self.get_val("DEFAULT_RESOURCES_PROFILE")
        # web plugin order
        self.profiles["WEB_PLUGIN_ORDER_PROFILE"] = profiles.get('w', None) or \
            self.get_val("DEFAULT_WEB_PLUGIN_ORDER_PROFILE")
        # network plugin order
        self.profiles["NET_PLUGIN_ORDER_PROFILE"] = profiles.get('n', None) or \
            self.get_val("DEFAULT_NET_PLUGIN_ORDER_PROFILE")
        # mapping
        self.profiles["MAPPING_PROFILE"] = profiles.get('m', None) or self.get_val("DEFAULT_MAPPING_PROFILE")

    def load_targets(self, options):
        """Load targets into the DB

        :param options: User supplied arguments
        :type options: `dict`
        :return: Added targets
        :rtype: `list`
        """
        scope = options['Scope']
        if options['PluginGroup'] == 'auxiliary':
            scope = self.get_aux_target(options)
        added_targets = []
        for target in scope:
            try:
                self.target.add_target(target)
                added_targets.append(target)
            except DBIntegrityException:
                logging.warning("%s already exists in DB" % target)
                added_targets.append(target)
            except UnresolvableTargetException as e:
                logging.error("%s" % e.parameter)
        return added_targets

    def get_aux_target(self, options):
        """This function returns the target for auxiliary plugins from the parameters provided

        :param options: User supplied arguments
        :type options: `dict`
        :return: List of targets for aux plugins
        :rtype: `list`
        """
        # targets can be given by different params depending on the aux plugin we are running
        # so "target_params" is a list of possible parameters by which user can give target
        target_params = ['RHOST', 'TARGET', 'SMB_HOST', 'BASE_URL', 'SMTP_HOST']
        plugin_params = self.get_component("plugin_params")
        targets = None
        if plugin_params.process_args():
            for param in target_params:
                if param in plugin_params.args:
                    targets = plugin_params.args[param]
                    break  # it will capture only the first one matched
            repeat_delim = ','
            if targets is None:
                logging.error("Aux target not found! See your plugin accepted parameters in ./plugins/ folder")
                return []
            if 'REPEAT_DELIM' in plugin_params.args:
                repeat_delim = plugin_params.args['REPEAT_DELIM']
            return targets.split(repeat_delim)
        else:
            return []

    def multi_replace(self, text, replace_dict):
        """Recursive multiple replacement function

        :param text: Text to replace
        :type text: `str`
        :param replace_dict: The parameter dict to be replaced with
        :type replace_dict: `dict`
        :return: The modified text after replacement
        :rtype: `str`
        """
        new_text = text
        for key in self.search_regex.findall(new_text):
            # Check if key exists in the replace dict ;)
            if replace_dict.get(key, None):
                # A recursive call to remove all level occurences of place
                # holders.
                new_text = new_text.replace(REPLACEMENT_DELIMITER + key + REPLACEMENT_DELIMITER,
                                            self.multi_replace(replace_dict[key], replace_dict))
        new_text = os.path.expanduser(new_text)
        return new_text

    def load_proxy_config(self, options):
        """Load proxy related configuration

        :param options: User supplied arguments
        :type options: `dict`
        :return: None
        :rtype: None
        """
        if options['InboundProxy']:
            if len(options['InboundProxy']) == 1:
                options['InboundProxy'] = [self.get_val('INBOUND_PROXY_IP'), options['InboundProxy'][0]]
        else:
            options['InboundProxy'] = [self.get_val('INBOUND_PROXY_IP'), self.get_val('INBOUND_PROXY_PORT')]
        self.set_val('INBOUND_PROXY_IP', options['InboundProxy'][0])
        self.set_val('INBOUND_PROXY_PORT', options['InboundProxy'][1])
        self.set_val('INBOUND_PROXY', ':'.join(options['InboundProxy']))
        self.set_val('PROXY', ':'.join(options['InboundProxy']))

    def get_resources(self, resource_type):
        """Replace the resources placeholders with the relevant config.

        :param resource_type: Type of resource to get
        :type resource_type: `str`
        :return: Fetched resource
        :rtype: `str`
        """
        return self.resource.get_resources(resource_type)

    def get_resource_list(self, resource_type_list):
        """Fetch the resource list

        :param resource_type_list: Type of resource list
        :type resource_type_list: `str`
        :return: Resource list
        :rtype: `list`
        """
        return self.resource.get_resource_list(resource_type_list)

    def get_raw_resources(self, resource_type):
        """Fetch the raw resource

        :param resource_type_list: Type of resource list
        :type resource_type_list: `str`
        :return: Resource
        :rtype: `str`
        """
        return self.resource[resource_type]

    def derive_config_from_url(self, target_URL):
        """Automatically find target information based on target name.

        .note::
            If target does not start with 'http' or 'https', then it is considered as a network target.

            + target host
            + target port
            + target url
            + target path
            + etc.

        :param target_URL: Target url supplied
        :type target_URL: `str`
        :return: Target config dictionary
        :rtype: `dict`
        """
        target_config = dict(target_manager.TARGET_CONFIG)
        target_config['target_url'] = target_URL
        try:
            parsed_url = urlparse(target_URL)
            if not parsed_url.hostname and not parsed_url.path:  # No hostname and no path, urlparse failed.
                raise ValueError
        except ValueError:  # Occurs sometimes when parsing invalid IPv6 host for instance
            raise UnresolvableTargetException("Invalid hostname '%s'" % str(target_URL))

        host = parsed_url.hostname
        if not host:  # Happens when target is an IP (e.g. 127.0.0.1)
            host = parsed_url.path  # Use the path as host (e.g. 127.0.0.1 => host = '' and path = '127.0.0.1')
            host_path = host
        else:
            host_path = parsed_url.hostname + parsed_url.path

        url_scheme = parsed_url.scheme
        protocol = parsed_url.scheme
        if parsed_url.port is None:  # Port is blank: Derive from scheme (default port set to 80).
            try:
                host, port = host.rsplit(':')
            except ValueError:  # Raised when target doesn't contain the port (e.g. google.fr)
                port = '80'
                if 'https' == url_scheme:
                    port = '443'
        else:  # Port found by urlparse.
            port = str(parsed_url.port)

        # Needed for google resource search.
        target_config['host_path'] = host_path
        # Some tools need this!
        target_config['url_scheme'] = url_scheme
        # Some tools need this!
        target_config['port_number'] = port
        # Set the top URL.
        target_config['host_name'] = host

        host_ip = self.get_ip_from_hostname(host)
        host_ips = self.get_ips_from_hostname(host)
        target_config['host_ip'] = host_ip
        target_config['alternative_ips'] = host_ips

        ip_url = target_config['target_url'].replace(host, host_ip)
        target_config['ip_url'] = ip_url
        target_config['top_domain'] = target_config['host_name']

        hostname_chunks = target_config['host_name'].split('.')
        if target_config['target_url'].startswith(('http', 'https')):  # target considered as hostname (web plugins)
            if not target_config['host_name'] in target_config['alternative_ips']:
                target_config['top_domain'] = '.'.join(hostname_chunks[1:])
            # Set the top URL (get "example.com" from "www.example.com").
            target_config['top_url'] = "%s://%s:%s" % (protocol, host, port)
        else:  # target considered as IP (net plugins)
            target_config['top_domain'] = ''
            target_config['top_url'] = ''
        return target_config

    def hostname_is_ip(self, hostname, ip):
        """Test if the hostname is an IP.

        :param str hostname: the hostname of the target.
        :param str ip: the IP (v4 or v6) of the target.

        :return: ``True`` if the hostname is an IP, ``False`` otherwise.
        :rtype: :class:`bool`

        """
        return hostname == ip

    def get_ip_from_hostname(self, hostname):
        """Get IP from the hostname

        :param hostname: Target hostname
        :type hostname: `str`
        :return: IP address of the target hostname
        :rtype: `str`
        """
        ip = ''
        # IP validation based on @marcwickenden's pull request, thanks!
        for sck in [socket.AF_INET, socket.AF_INET6]:
            try:
                socket.inet_pton(sck, hostname)
                ip = hostname
                break
            except socket.error:
                continue
        if not ip:
            try:
                ip = socket.gethostbyname(hostname)
            except socket.gaierror:
                raise UnresolvableTargetException("Unable to resolve: '%s'" % hostname)

        ipchunks = ip.strip().split("\n")
        alternative_ips = []
        if len(ipchunks) > 1:
            ip = ipchunks[0]
            cprint("%s has several IP addresses: (%s).Choosing first: %s" % (hostname, "".join(ipchunks)[0:-3], ip))
            alternative_ips = ipchunks[1:]
        self.set_val('alternative_ips', alternative_ips)
        ip = ip.strip()
        self.set_val('INTERNAL_IP', is_internal_ip(ip))
        logging.info("The IP address for %s is: '%s'" % (hostname, ip))
        return ip

    def get_ips_from_hostname(self, hostname):
        """Get IPs from the hostname

        :param hostname: Target hostname
        :type hostname: `str`
        :return: IP addresses of the target hostname as a list
        :rtype: `list`
        """
        ip = ''
        # IP validation based on @marcwickenden's pull request, thanks!
        for sck in [socket.AF_INET, socket.AF_INET6]:
            try:
                socket.inet_pton(sck, hostname)
                ip = hostname
                break
            except socket.error:
                continue
        if not ip:
            try:
                ip = socket.gethostbyname(hostname)
            except socket.gaierror:
                raise UnresolvableTargetException("Unable to resolve: '%s'" % hostname)

        ipchunks = ip.strip().split("\n")
        return ipchunks

    def is_set(self, key):
        """Checks if the key is set in the config dict

        :param key: Key to check
        :type key: `str`
        :return: True if present, else False
        :rtype: `bool`
        """
        key = self.pad_key(key)
        config = self.get_config_dict()
        for type in CONFIG_TYPES:
            if key in config[type]:
                return True
        return False

    def get_key_val(self, key):
        """Gets the right config for target / general.

        :param key: The key
        :type key: `str`
        :return: Value for the key
        """
        config = self.get_config_dict()
        for type in CONFIG_TYPES:
            if key in config[type]:
                return config[type][key]

    def pad_key(self, key):
        """Add delimiters.

        :param key: Key to pad
        :type key: `str`
        :return: Padded key string
        :rtype: `str`
        """
        return REPLACEMENT_DELIMITER + key + REPLACEMENT_DELIMITER

    def strip_key(self, key):
        """Replaces key with empty space

        :param key: Key to clear
        :type key: `str`
        :return: Empty key
        :rtype: `str`
        """
        return key.replace(REPLACEMENT_DELIMITER, '')

    def get_val(self, key):
        """Transparently gets config info from target or General.

        :param key: Key
        :type key: `str`
        :return: The value for the key
        """
        try:
            key = self.pad_key(key)
            return self.get_key_val(key)
        except KeyError:
            message = "The configuration item: %s does not exist!" % key
            self.error_handler.add(message)
            # Raise plugin-level exception to move on to next plugin.
            raise PluginAbortException(message)

    def get_logs_dir(self):
        """
        Get log directory by checking if abs or relative path is provided in
        config file
        """
        logs_dir = self.get_val("LOGS_DIR")
        # Check access for logs dir parent directory because logs dir may not be created.
        if os.path.isabs(logs_dir) and directory_access(os.path.dirname(logs_dir), "w+"):
            return logs_dir
        else:
            return os.path.join(self.get_output_dir(), logs_dir)

    def get_log_path(self, process_name):
        """Get the log file path based on the process name

        :param process_name: Process name
        :type process_name: `str`
        :return: Path to the specific log file
        :rtype: `str`
        """
        log_file_name = "%s.log" % process_name
        return os.path.join(self.get_logs_dir(), log_file_name)

    def get_as_list(self, key_list):
        """Get values for keys in a list

        :param key_list: List of keys
        :type key_list: `list`
        :return: List of corresponding values
        :rtype: `list`
        """
        value_list = []
        for key in key_list:
            value_list.append(self.get_val(key))
        return value_list

    def get_header_list(self, key):
        """Get list from a string of values for a key

        :param key: Key
        :type key: `str`
        :return: List of values
        :rtype: `list`
        """
        return self.get_val(key).split(',')

    def set_general_val(self, type, key, value):
        """ Set value for a key in any config file

        :param type: Type of config file, framework or general.cfg
        :type type: `str`
        :param key: The key
        :type key: `str`
        :param value: Value to be set
        :type value:
        :return: None
        :rtype: None
        """
        self.config[type][key] = value

    def set_val(self, key, value):
        """set config items in target-specific or General config."""
        # Store config in "replacement mode", that way we can multiple-replace
        # the config on resources, etc.
        key = REPLACEMENT_DELIMITER + key + REPLACEMENT_DELIMITER
        type = 'other'
        # Only when value is a string, store in replacements config.
        if isinstance(value, str):
            type = 'string'
        return self.set_general_val(type, key, value)

    def get_framework_config_dict(self):
        return self.get_config_dict()['string']

    def get_replacement_dict(self):
        """Returns a dictionary with framework directory path

        :return:
        :rtype:
        """
        return {"FRAMEWORK_DIR": self.root_dir}

    def __getitem__(self, key):
        return self.get_val(key)

    def __setitem__(self, key, value):
        return self.set_val(key, value)

    def get_config_dict(self):
        """Get the global config dictionary

        :return: None
        :rtype: None
        """
        return self.config

    def show(self):
        """Print all keys and values from configuration dictionary

        :return: None
        :rtype: None
        """
        logging.info("Configuration settings: ")
        for k, v in list(self.get_config_dict().items()):
            logging.info("%s => %s" % (str(k), str(v)))

    def get_output_dir(self):
        """Gets the output directory for the session

        :return: The path to the output directory
        :rtype: `str`
        """
        output_dir = os.path.expanduser(self.get_val("OUTPUT_PATH"))
        if not os.path.isabs(output_dir) and directory_access(os.getcwd(), "w+"):
            return output_dir
        else:
            # The output_dir may not be created yet, so check its parent.
            if directory_access(os.path.dirname(output_dir), "w+"):
                return output_dir
        return os.path.expanduser(os.path.join(self.get_val("SETTINGS_DIR"), output_dir))

    def get_output_dir_target(self):
        """Returns the output directory for the targets

        :return: Path to output directory
        :rtype: `str`
        """
        return os.path.join(self.get_output_dir(), self.get_val("TARGETS_DIR"))

    def get_dir_worker_logs(self):
        """Returns the output directory for the worker logs

        :return: Path to output directory for the worker logs
        :rtype: `str`
        """
        return os.path.join(self.get_output_dir(), self.get_val("WORKER_LOG_DIR"))

    def cleanup_target_dirs(self, target_url):
        """Cleanup the directories for the specific target

        :return: None
        :rtype: None
        """
        return FileOperations.rm_tree(self.get_target_dir(target_url))

    def get_target_dir(self, target_url):
        """Gets the specific directory for a target in the target output directory

        :param target_url: Target URL for which directory path is needed
        :type target_url: `str`
        :return: Path to the target URL specific directory
        :rtype: `str`
        """
        clean_target_url = target_url.replace("/", "_").replace(":", "").replace("#", "")
        return os.path.join(self.get_output_dir_target(), clean_target_url)

    def create_output_dir_target(self, target_url):
        """Creates output directories for the target URL

        :param target_url: The target URL
        :type target_url: `str`
        :return: None
        :rtype: None
        """
        FileOperations.create_missing_dirs(self.get_target_dir(target_url))


import pygame

BLACK = (0,0,0)
WHITE = (255,255,255)
BLUE = (0,0,255)
GREEN = (0,255,0)
RED = (255,0,0)
PURPLE = (255,0,255)
PERSO = (255,215,0)

class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, colour):
        super().__init__()
        self.image = pygame.Surface([width, height])
        self.image.fill(colour)
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

class Player(pygame.sprite.Sprite):
    def __init__(self,pp_x,pp_y):
        super().__init__()
        move_ppx = 0
        move_ppy = 0
    def changespeed(self,pp_x,pp_y):
        self.move_ppx += pp_x
        self.move_ppy += pp_y
    def move(self, walls):
        self.pp_x += self.move_ppx
        block_hit_list = pygame.sprite.spritecollide(self, walls, False)
        for block in block_hit_list:
            if self.move_ppx > 0:
                self.right = block.left
            else:
                self.left = block.right
        self.pp_y += self.move_ppx
        block_hit_list = pygame.sprite.spritecollide(self, walls, False)
        for block in block_hit_list:
            if self.move__ppy > 0:
                self.bottom = block.top
            else:
                self.top = block.bottom
# Parent class

class Room(object):
    wall_list = None
    enemy_sprites = None
    def __init__(self):
        self.wall_list = pygame.sprite.Group()
        self.enemy_sprites = pygame.sprite.Group()

# Levels
class Room1(Room):
    def __init__(self):
        super().__init__()
        walls = [[0, 0, 20, 250, WHITE],
                 [0, 350, 20, 250, WHITE],
                 [780, 0, 20, 250, WHITE],
                 [780, 350, 20, 250, WHITE],
                 [20, 0, 760, 20, WHITE],
                 [20, 580, 760, 20, WHITE],
                 [390, 50, 20, 500, BLUE]
                 ]
        for item in walls:
            wall = Wall(item[0], item[1], item[2], item[3], item[4])
            self.wall_list.add(wall)

    def __init__(self):
        super().__init__()
        walls = [[0, 0, 20, 250, PURPLE],
                 [0, 350, 20, 250, PURPLE],
                 [780, 0, 20, 250, PURPLE],
                 [780, 350, 20, 250, PURPLE],
                 [20, 0, 760, 20, PURPLE],
                 [20, 580, 760, 20, PURPLE]
                 ]
        for item in walls:
            wall = Wall(item[0], item[1], item[2], item[3], item[4])
            self.wall_list.add(wall)
        for x in range(100, 400, 100):
            for y in range(30, 451, 300):
                wall = Wall(x, y, 20, 200, RED)
                self.wall_list.add(wall)
        for x in range(400, 800, 100):
            for y in range(100, 480, 270):
                wall = Wall(x, y, 20, 200, RED)
                self.wall_list.add(wall)
        for x in range(150, 700, 100):
            wall = Wall(x, 200, 20, 200, WHITE)
            self.wall_list.add(wall)

def main():
    pygame.init()
    print("Welcome to the Maze Runner ! Please install python and pygame first.")
    print("Contact me on ladevweb@yahoo.com")
    screen = pygame.display.set_mode((800,600))
    pygame.display.set_caption('Maze Runner')
    bg = pygame.image.load("./sprites/bg.jpg").convert()
    screen.blit(bg, (0,0))
    #player = Player(50, 50)
#player2
    pp_x = 150
    pp_y = 200
    img = pygame.image.load("./sprites/sprite.png")
    player = Player(pp_x,pp_y) #attributes are about first sprite position
    screen.blit(img,(pp_x,pp_y))
##
    movingsprites = pygame.sprite.Group()
    movingsprites.add(player)
    rooms = []
    room = Room1()
    rooms.append(room)
    '''
    room = Room2()
    rooms.append(room)
    room = Room3()
    rooms.append(room)
    '''
    current_room_no = 0
    current_room = rooms[current_room_no]
    clock = pygame.time.Clock()
    done = False
# user entry
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    player.changespeed(-5, 0)
                if event.key == pygame.K_RIGHT:
                    player.changespeed(5, 0)
                if event.key == pygame.K_UP:
                    player.changespeed(0, -5)
                if event.key == pygame.K_DOWN:
                    player.changespeed(0, 5)
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT:
                    player.changespeed(5, 0)
                if event.key == pygame.K_RIGHT:
                    player.changespeed(-5, 0)
                if event.key == pygame.K_UP:
                    player.changespeed(0, 5)
                if event.key == pygame.K_DOWN:
                    player.changespeed(0, -5)
#walls and pieces
        player.move(current_room.wall_list)

        if player.rect.ppx < -15:
            if current_room_no == 0:
                current_room_no = 2
                current_room = rooms[current_room_no]
                player.rect.ppx = 790
            elif current_room_no == 2:
                current_room_no = 1
                current_room = rooms[current_room_no]
                player.rect.ppx = 790
            else:
                current_room_no = 0
                current_room = rooms[current_room_no]
                player.rect.ppx = 790

        if player.rect.ppx > 801:
            if current_room_no == 0:
                current_room_no = 1
                current_room = rooms[current_room_no]
                player.rect.ppx = 0
            elif current_room_no == 1:
                current_room_no = 2
                current_room = rooms[current_room_no]
                player.rect.ppx = 0
            else:
                current_room_no = 0
                current_room = rooms[current_room_no]
                player.rect.ppx = 0
    # renonciation clause
        rect = bg.get_rect()
        screen.fill(BLACK)
        screen.blit(bg, rect)
        pygame.draw.rect(screen, RED, rect, 1)
        movingsprites.draw(screen)
        current_room.wall_list.draw(screen)
        pygame.display.flip()
        clock.tick(60)
    pygame.quit()
    quit()

if __name__ == "__main__":
    main()


import cv2
import numpy as np
import sys
sys.path.append("/home/fyp/darknet")
import darknet as dn
import darknet_images as dni

def depth_cone_detect(depthimg, net, name):
  image_board = depthimg
  name = [name]
  image_board, detections = dni.image_detection_(image_board, net, name, 0.5)

  return detections

def cone_detect(image, mask, net, class_colors, name):
  name = [name]
  image_for = image
  new_image = cv2.bitwise_and(image_for,image_for, mask=mask)
  image_for, detections = dni.image_detection_(new_image, net, name, class_colors, 0.5)

  return detections, new_image

# def cone_detect(detected_both, image, mask, net, class_colors, name):
#     name = [name]
#     image_for = image
#     new_image = cv2.bitwise_and(image_for,image_for, mask=mask)
#     image_for, detections = dni.image_detection_(new_image, net, name, class_colors, 0.5)
#     # detected = image_for
#     # yolo_cones_center = []
#     # for label, confidence, bbox in detections:
#     #   left, top, right, bottom = dn.bbox2points_(bbox)
#     #   area = (right-left)*(bottom-top)
#     #   if area > 600:# and confidence > 0.6:
#     #     cv2.rectangle(detected, (left, top), (right, bottom), (255,0,100), 1)
#     #     cv2.putText(detected, "{} [{:.2f}]".format(label, float(confidence)),
#     #                 (left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
#     #                 (255,0,100), 2)
#     #     #draw on the resized original image
#     #     cv2.rectangle(detected_both, (left, top), (right, bottom), (255,0,100), 1)
#     #     cv2.putText(detected_both, "{} [{:.2f}]".format(label, float(confidence)),
#     #                 (left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
#     #                 (255,0,100), 1)

#     #     #get the centers of the bbox
#     #     centerx = int((left + right)/2)
#     #     centery = int((top + bottom)/2)
#     #     yolo_cones_center.append([centerx,centery])
#     #     cv2.drawMarker(detected, (centerx, centery), class_colors, cv2.MARKER_CROSS, 10,1,1 )

#     #     #draw on the resized original image
#     #     cv2.drawMarker(detected_both, (centerx, centery), class_colors, cv2.MARKER_CROSS, 10,1,1 )

#     # return detected_both, detected, yolo_cones_center, detections
#     return detections

def cone_connect(detected, detected_both, yolo_cones_center):
    yolo_cones_center = sorted(yolo_cones_center, key=lambda k:[k[1], k[0]], reverse=True)
    yolo_cones_center = yolo_cones_center[:3]
    yolo_slopes = []
    for i in range(len(yolo_cones_center)):
      if i != len(yolo_cones_center)-1:
        if yolo_cones_center[i][1] > yolo_cones_center[i+1][1]:

          cv2.line(detected, (yolo_cones_center[i][0],yolo_cones_center[i][1]) , (yolo_cones_center[i+1][0], yolo_cones_center[i+1][1]), (255,0,0), 1)

          #draw on the resized original image
          cv2.line(detected_both, (yolo_cones_center[i][0],yolo_cones_center[i][1]) , (yolo_cones_center[i+1][0], yolo_cones_center[i+1][1]), (255,0,0), 1)

          #get the slopes between yellow cones
          xdiff = (yolo_cones_center[i][0]) - (yolo_cones_center[i+1][0])
          ydiff = (yolo_cones_center[i][1]) - (yolo_cones_center[i+1][1])
          if xdiff != 0:
            sl = round(np.true_divide(ydiff, xdiff, out=None), 5)
          else:
            sl = 999
          yolo_slopes.append(sl)

    return detected_both, detected, yolo_slopes


# test_ioa_exclusions.py
# This class tests the ioa_exclusions service class
import os
import sys

# Authentication via test_authorization.py
from tests import test_authorization as Authorization
# Import our sibling src folder into the path
sys.path.append(os.path.abspath('src'))
# Classes to test - manually imported from sibling folder
from falconpy.ioa_exclusions import IOA_Exclusions as FalconIOAE

auth = Authorization.TestAuthorization()
auth.getConfig()
falcon = FalconIOAE(creds={"client_id": auth.config["falcon_client_id"],
                           "client_secret": auth.config["falcon_client_secret"]
                           })
AllowedResponses = [200, 429]  # Adding rate-limiting as an allowed response for now

class TestIOAExclusions:
    def serviceIOAE_ListExclusions(self):
        returned = False
        if falcon.queryIOAExclusionsV1(limit=1, offset=2, pizza="IsDelicious")["status_code"] in AllowedResponses:
            returned = True

        return returned

    def serviceIOAE_GenerateErrors(self):
        falcon.base_url = "nowhere"
        errorChecks = True
        commandList = [
            ["getIOAExclusionsV1", "ids='12345678'"],
            ["createIOAExclusionsV1", "body={}"],
            ["updateIOAExclusionsV1", "body={}"],
            ["deleteIOAExclusionsV1", "ids='12345678'"]
        ]
        for cmd in commandList:
            if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500:
                errorChecks = False

        return errorChecks

    def test_Find(self):
        assert self.serviceIOAE_ListExclusions() is True

    def test_Errors(self):
        assert self.serviceIOAE_GenerateErrors() is True


from pathlib import Path
homek = str(Path.home())+"\\desktop\\nkeys.txt"
homev = str(Path.home())+"\\desktop\\nvalues.txt"
from time import sleep
try:
    with open(homek,"r+") as f:
        pass
except FileNotFoundError:
    with open(homek,"w") as f:
        pass
try:
    with open(homev,"r+") as f:
        pass
except FileNotFoundError:
    with open(homev,"w") as f:
        pass
sifre="zxcasdqwe123"
sayac = 0
while True:
    gsifre=input("Veritabanı erişimi için şifre gereklidir:(çıkış için q) ")
    if gsifre == "q":
        quit()
    sayac += 1
    if sayac == 4:
        print("Çok fazla şifre denemesi lütfen 60sn boyunca bekleyin.")
        for i in range(60):
            sleep(1)
            print("Kalan süre: {}".format(60-i))

    if gsifre==sifre:
        break
    else:
        print("Şifre yanlış. tekrar deneyiniz.(kalan hak{})".format(3-sayac))

with open(homek,"r",encoding="utf-8")as f:
    keyler=f.read()
    keyler=keyler.split(",")

with open(homev,"r",encoding="utf-8") as f:
    degerler=f.read()
    degerler=degerler.split(":")

liste=[]
print(liste)
while True:
    choose=input("Veri okuma için -> 0 \n Veri girişi için -> 1: \n")
    if choose == "q":
        quit()
    if choose == "0":
        with open(homek,"r",encoding="utf-8") as f:
            keyler=f.read()
            keyler=keyler.split(",")
        with open(homev,"r",encoding="utf-8")as f:
            degerler=f.read()
            degerler=degerler.split(":")
        while True:
            kisi=input("Kişi ismi(key): ")
            if kisi == "q":
                break
            if kisi in keyler:
                indexkisi=keyler.index(kisi)
                degerlerindex=degerler[indexkisi].split(",")
                print(kisi," Bilgiler: ")
                for i in range(len(degerlerindex)):
                    print(degerlerindex[i])
                print("\n"*4)
            else:
                print("aradığınız kişi veritabanımızda yok!")

    elif choose == "1":
        while True:
            gkey=input("Kişinin ismi: ")
            if gkey=="q":
                break
            for i in range(10):
                gne=input("Ne kaydedilecek? ")
                if gne == "q":
                    break
                göz=input("Kaydedilecek şeyin özelliği: ")
                liste.append(gne+"--->"+göz+",")
            with open(homek,"a+",encoding="utf-8") as f:
                f.write(gkey+",")
            with open (homev,"a+",encoding="utf-8") as f:
                for i in liste:
                    f.write(i)
                f.write(":")

    else:
        print("Lütfen tanımladığımız bir şeyi giriniz: ")


result_list = []
number_of_testCase = int(input("Enter the number of test case: "))
for _ in range(number_of_testCase):
    alpha_list = []
    favrit_word = set()
    def check():
        for i in range(len(alpha_list)):
            fov_word = alpha_list[i]
            my_word = 'vika'
            for x in range(len(fov_word)):
                if fov_word[x] == my_word[x]:
                    favrit_word.add(fov_word[x])

    size = list(map(int, input('Enter the size of Carpet: ').split()))
    for y in range(0, size[0]):
        alpha_list.append(input("Enter the word: "))
    check()
    for i in range(number_of_testCase):
        if len(favrit_word) == 4:
            result_list.append("Yes")
        else:
            result_list.append("No")

print(*result_list)


"""
http://pythontutor.ru/lessons/lists/problems/swap_neighbours/
Переставьте соседние элементы списка (A[0] c A[1], A[2] c A[3] и т. д.).
Если элементов нечетное число, то последний элемент остается на своем месте.
"""

lst = input().split()

for i in range(0, len(lst) - 1, 2):
    lst[i], lst[i + 1] = lst[i + 1], lst[i]

for el in lst:
    print(el, end=' ')


import random

imena = ['Karlo', 'Ana-Marija', 'Antonio', 'Marko', 'Matea', 'Vice', 'Sara', 'Ivana', 'Ante', 'Ivan Entoni', 'Tonka', 'Antonio',
'Mateo', 'Mateo', 'Josip', 'Marko', 'Tino', 'Azer', 'Tomislava', 'Katarina', 'Karlo', 'David', 'Ivan', 'Petar', 'Marija',
'Antonio', 'Mario', 'Josip', 'Leonardo', 'Antonio', 'Renato', 'Matej', 'Matej', 'Jozo Matej', 'Petar', 'Ivan', 'Stjepan',
'Petar', 'Dražen', 'Zvonimir', 'Marin', 'Antonio', 'Stipe', 'Ana', 'Mate', 'Miroslav', 'Karlo', 'Marino', 'Mija', 'Kristijan',
'Ante', 'Ana', 'Iva', 'Mladen', 'Ivan', 'Frano', 'Mate', 'Mateo', 'Harun']

imena_br = {}
for ime in imena:
    if ime in imena_br:
        imena_br[ime] += 1
    else:
        imena_br[ime] = 1

print(imena_br)

ocjene = {}
for ime in imena:
    ocjene[ime] = random.randint(1,5)

for ime in ocjene:
    print(ime + ": " + str(ocjene[ime]))


# Extract_CSV_Delimited.py

dir = '/Volumes/C/projects/SMART Plan Systemwide STOPS/AC_MDTEXIST#MDTNOB#MDTBLD_STOPSY2015Results'
txt_dir = "txt_extract"
csv_dir = "csv_dir"
test_file = "Table     2.04.txt"
test_csv_file = "Table     2.04.csv"

# Second Method to extract table contents based on delimiter
table_rows = []
found_header = 0

import os, csv, pandas as pd

def write_table_to_csv(data, csv_file_name):
    with open(csv_file_name, 'w') as csvfile:
        writer = csv.writer(csvfile)
        for row in data:
            writer.writerow(row)

dir_file = os.path.join(dir, txt_dir, test_file)
csv_file_name = os.path.join(dir, csv_dir, test_csv_file)

# Extract table text contents to csv
with open (dir_file, 'rt') as in_file:
    # get rows
    for line in in_file:

        # check header separator (start of table)
        header_separator = "======"
        row_elements = []

        # get table header (fieldnames)
        if line.find(header_separator, len(header_separator)) != -1 and found_header == 0:
            fieldNames = prev_line.split(" ")
            if len(fieldNames) > 1: # at least 3 columns
                found_header = 1
                for e in fieldNames:
                    e_value = e.strip()
                    if len(e_value) > 0 and e_value != ":" :
                        row_elements.append(e_value)
                table_rows.append(row_elements)

        # get table contents
        if line.find(header_separator, len(header_separator)) == -1 and found_header == 1:
            elements = line.split(" ")
            if len(elements) > 1: # at least 3 columns
                for e in elements:
                    e_value = e.strip()
                    if len(e_value) > 0 and e_value != ":" :
                        row_elements.append(e_value)
                table_rows.append(row_elements)

        # store previous line (to get header)
        prev_line = line

    write_table_to_csv(table_rows, csv_file_name)
    print("Finished Converting " + test_file + " to " + test_csv_file)

    # fix header column issue with pandas (read csv file and use index to get colnames and replace rownames and save to same csv file)
    # df = pd.read_csv(csv_file_name, skiprows = 1,
    # rownames = list(df.index)
    # colnames = list(df)
    # # df.columns = df.index
    # # col1 = df['1-South_:']
    # print(colnames)
    # print(rownames)
    # print(df.shape)
    # # print(col1)


import discord
from discord.ext import commands

class Admin(commands.Cog):

    def __init__(self, bot):
        self.bot = bot

    @commands.command(name="kick")
    @commands.has_permissions(kick_members=True)
    async def kick(self, ctx, member : discord.Member, *, reason=None):
        try:
            await member.kick(reason=reason)
            embed = discord.Embed(color=discord.Colour.dark_orange(), title="", description="")
            embed.add_field(name="Kicked:",

                value=f"""
                **{member}** has been kicked.
                Reason: **{reason}**
                """, inline=True)

            await ctx.reply(embed=embed)

        except discord.Forbidden:
            await ctx.send(f'You do not have the proper permissions to kick.')
        except discord.HTTPException:
            await ctx.send(f'Kicking failed.')

    @commands.command(name="ban")
    @commands.has_permissions(administrator=True)
    async def ban(self, ctx, member : discord.Member, *, reason=None):
        try:
            await member.ban(reason=reason)
            embed = discord.Embed(color=discord.Colour.dark_red(), title="", description="")
            embed.add_field(name="Banned:",

                value=f"""
                **{member}** has been **banned** from the server.
                Reason: **{reason}**
                """, inline=True)

            await ctx.reply(embed=embed)

        except discord.Forbidden:
            await ctx.send(f'You do not have the proper permissions to ban.')
        except discord.NotFound:
            await ctx.send(f'{member} not found!')
        except discord.HTTPException:
            await ctx.send('Banning Failed.')

    @commands.command(name="unban")
    @commands.has_permissions(administrator=True)
    async def unban(self, ctx, *, member: discord.User, reason=None):
        try:
            await ctx.guild.unban(member)
            embed = discord.Embed(color=discord.Colour.dark_red(), title="", description="")
            embed.add_field(name="Unbanned:",

                value=f"""
                **{member}** has been **unbanned** from the server.
                Reason: **{reason}**
                """, inline=True)

            await ctx.reply(embed=embed)

        except discord.NotFound:
            await ctx.send(f'{member} not found!')
        except discord.Forbidden:
            await ctx.send(f'Do not have proper permission to unban!')
        except discord.HTTPException:
            await ctx.send(f'Unbanning failed.')

    @commands.command(name="clear")
    @commands.has_permissions(administrator=True)
    async def clear(self, ctx, amount=1):
        if amount > 100:
            user = ctx.author.name
            await ctx.send(f"{user}, you cannot clear that amount!")
        else:
            await ctx.channel.purge(limit=amount + 1)

async def setup(bot):
    await bot.add_cog(Admin(bot))


import csv
from math import floor
from os.path import splitext, exists

import os

from Implementation.ClassicMethods.Expert import Expert
from Implementation.AbstractDiscretisation import Discretization
from Implementation.Constants import CLASS_SEPARATOR, DEBUG_MODE
from Implementation.DataRow import DataRow
from Implementation.Entity import Entity
from typing import Dict, List ,Set
from copy import deepcopy, copy

from Implementation.TD4C.TD4C import TD4C
from dateutil import parser

supported_extensions = [".txt",".csv"]
entities: Dict[int,Entity] = {}

def extract_from_file(file_path, file_extension, class_separator, add_class_information_to_timestamps) -> bool:
    with open(file_path) as f:
        try:
            line_number = 0
            l = f.readline()
            for line in f:
                dr = DataRow.get_data_from_row(line)
                eid = dr.get_entity_id()
                if eid in entities:
                    e = entities[eid]
                else:
                    e = Entity(eid, 0, class_separator)
                    entities[eid] = e
                e.add_time_stamp(dr.get_temporal_property_id(),dr.get_time_stamp())
                line_number += 1
                if line_number % 100000 == 0:
                    print("%s/%s" %(line_number//100000,97000000//100000))
            p2e, c2e, p2t = Entity.get_maps()
            # holy loops batman
            if add_class_information_to_timestamps:
                for c in c2e:
                    es = c2e[c]
                    for e in es:
                        ps = e.properties
                        e.entity_class = c
                        for p in ps:
                            for t in ps[p]:
                                t.ts_class = c
        except:
            return False
    return True

"""
def format_timestamps_to_int(file_path,entities_path):
    with open(file_path) as f, open(file_path + "t", 'w') as w:
        max_time =
        for line in f:
            time = line.rstrip().split(',')[2]
"""

def format_timestamps_to_int(file_path, entities_path):
    pass

def partition_file_to_properties(file_path,entities_path):
    folder = file_path.split("\\")[:-1]
    partitions_path = "\\".join(folder) + "\\partitions"
    property_to_file = {}
    class_to_entity_count = {}
    line_count = 0
    if DEBUG_MODE or not exists(partitions_path):
        print("No partitions found, creating partitions...")
        e_file = None
        if not exists(entities_path):
            e_file = open(entities_path, 'w', newline='')
        with open(file_path) as f:
            entities = set()
            if not exists(partitions_path):
                os.makedirs(partitions_path)
            f.readline()
            for line in f:
                if line_count%1000000 == 0:
                    print("Wrote %s lines..." % line_count)
                line_count += 1
                if line_count == 1:
                    try:
                        time = int(line.rstrip().split(',')[2])
                    except:
                        format_timestamps_to_int(file_path, entities_path)
                        return
                dr = DataRow.get_data_from_row(line)
                if dr.entity_id not in entities:
                    entities.add(dr.entity_id)
                pid = dr.get_temporal_property_id()
                if pid == CLASS_SEPARATOR:
                    c = floor(dr.get_time_stamp().value)
                    if c in class_to_entity_count:
                        class_to_entity_count[c] += 1
                    else:
                        class_to_entity_count[c] = 1
                if pid not in property_to_file:
                    property_to_file[pid] = open(partitions_path + "\\property%s.csv" % pid, 'w')
                property_to_file[pid].write(line)
            if e_file is not None:
                entity_csv = csv.writer(e_file)
                entity_csv.writerow(["id","name"])
                for e in entities:
                    entity_csv.writerow([str(e),"Entity%s" % e])
                e_file.close()
        for pid in property_to_file:
            property_to_file[pid].close()
        with open(partitions_path + "\\properties.csv", 'w', newline='') as f, open(partitions_path + "\\class_to_entity_count.csv", 'w', newline='') as c:
            input = csv.writer(f)
            class_input = csv.writer(c)
            lst = list(property_to_file.keys())
            if CLASS_SEPARATOR in lst:
                lst.remove(CLASS_SEPARATOR)
            input.writerow(lst)
            classed_entities = 0
            for c in class_to_entity_count:
                classed_entities += class_to_entity_count[c]
                class_input.writerow([c,class_to_entity_count[c]])
            non_classed_entities = len(entities) - classed_entities
            if non_classed_entities != 0:
                class_input.writerow([-10000,non_classed_entities])
    else:
        print("Partitions found. Continuing...")

def receive_file(file_path, class_separator, class_information):
    file_extension = splitext(file_path)[1]
    if file_extension not in supported_extensions:
        raise Exception("File extension not supported")
    if not extract_from_file(file_path, file_extension, class_separator, class_information):
        raise Exception("File format incorrect")

def get_maps_from_file(path, entities_path, class_seperator, class_information=False):
    return partition_file_to_properties(path, entities_path)
    #receive_file(path, class_seperator, class_information)
    #return Entity.get_maps()
    #return None, None, None

if __name__ == "__main__":
    pass


import json
import logging
import os
from json.decoder import JSONDecodeError

import urllib3
from django.core.management import BaseCommand
from tqdm import tqdm

from ifbcat_api.model.tool.tool import Tool

logger = logging.getLogger(__name__)

class Command(BaseCommand):
    http = None

    def crawl_tools(self, limit, collection_id):
        # clean tool table
        # Tool.objects.all().delete()
        # ToolType.objects.all().delete()
        # OperatingSystem.objects.all().delete()
        # ToolCredit.objects.all().delete()
        # Collection.objects.all().delete()

        try:
            resp = self.get_from_biotools(collection_id=collection_id, page=1)
            count = int(resp['count'])
            print(f"{count} available BioTools entries for collection {collection_id}")

            page = 1
            has_next_page = True
            progress_bar = tqdm()
            while has_next_page and (limit == -1 or progress_bar.n < limit):
                try:
                    entry = self.get_from_biotools(collection_id=collection_id, page=page)
                except JSONDecodeError as e:
                    logging.error("Json decode error")
                    break

                has_next_page = entry['next'] is not None
                for tool in entry['list']:
                    logger.debug("https://bio.tools/api/" + tool['biotoolsID'] + "?format=jsonld ")
                    tool_entry = Tool.objects.filter(biotoolsID__iexact=tool['biotoolsID']).first()
                    if tool_entry is None:
                        tool_entry = Tool.objects.filter(name__iexact=tool['name']).first()
                        if tool_entry is not None and (tool_entry.biotoolsID is None or tool_entry.biotoolsID == ""):
                            tool_entry.biotoolsID = tool['biotoolsID']
                            tool_entry.save()
                            tool_entry.update_information_from_json(tool)
                    if tool_entry is None:
                        tool_entry = Tool.objects.create(
                            name=tool['biotoolsID'],
                        )
                        tool_entry.biotoolsID = tool['biotoolsID']
                        tool_entry.update_information_from_json(tool)

                    progress_bar.update()
                page += 1
        except urllib3.exceptions.HTTPError as e:
            logger.error("Connection error")
            logger.error(e)

    def get_from_biotools(self, collection_id, page):
        key = None
        cache_dir = os.environ.get('CACHE_DIR', None)
        if cache_dir is not None:
            os.makedirs(cache_dir, exist_ok=True)
            cache_dir = os.path.join(cache_dir, 'biotools')
            key = f'{collection_id}.{page}.json'
            try:
                with open(os.path.join(cache_dir, key)) as f:
                    response = json.load(f)
                return response
            except FileNotFoundError:
                pass

        if self.http is None:
            self.http = urllib3.PoolManager()
        req = self.http.request(
            'GET', f'https://bio.tools/api/tool/?collectionID={collection_id}&page={page}&format=json'
        )
        response = json.loads(req.data.decode('utf-8'))

        if key is not None:
            with open(os.path.join(cache_dir, key), 'w') as f:
                json.dump(response, f)
        return response

    def add_arguments(self, parser):
        """
        Arguments for the command line load_biotools
        """
        parser.add_argument(
            '-l', '--limit', help='Number of tools to import (-1 to retrieve all)', type=int, default=-1
        )
        parser.add_argument(
            '-c',
            '--collection_id',
            help='Number of tools to import (-1 to retrieve all)',
            type=str,
            default='elixir-fr-sdp-2019',
        )

    def handle(self, *args, **options):
        """
        Call the function to import data
        """
        self.crawl_tools(limit=options['limit'], collection_id=options['collection_id'])


from ctypes import *
from threading import Thread
from time import sleep

import matplotlib.pyplot as plt
import numpy

# import matplotlib
# matplotlib.rcParams['interactive'] == True

# print(plt.get_backend())

ret_spi_transfer = 0

MAX = 512

so_file = "./main.so"
c_lib = CDLL(so_file)

# https://stackoverflow.com/questions/54888242/passing-nested-ctypes-structure-with-array-to-c-library-function-not-as-expected

class SPI_CONFIG(Structure):
    _fields_ = [("freq", c_uint32),
                ("time_delay", c_float),
                ("mode", c_uint8),
                ("is_msb_First", c_bool),
                ("bits_per_word", c_uint8)]

class SPI_PINS(Structure):
    _fields_ = [("cs", c_int),
                ("clk", c_int),
                ("mosi", c_int),
                ("miso", c_int),
                ("time_ns", c_uint64)]

SPI_PINS_MAX = SPI_PINS * MAX

class CBFIFO(Structure):
    _fields_ = [("spi_pins_status", SPI_PINS_MAX),
                ("head", c_int),
                ("tail", c_int),
                ("count", c_int)]

    def __init__(self, data):
        self.spi_pins_status = SPI_PINS_MAX()
        self.head = 0
        self.tail = 0
        self.count = 0
        for i in range(len(data)):
            self.spi_pins_status[i].cs = data[i][0]
            self.spi_pins_status[i].clk = data[i][1]
            self.spi_pins_status[i].mosi = data[i][2]
            self.spi_pins_status[i].miso = data[i][3]
            self.spi_pins_status[i].time_ns = data[i][4]
            self.count = 0

# def circular_buffer():
#     class CBFIFO(Structure):
#         _fields_ = [("spi_pins_status", SPI_PINS * MAX),
#                     ("head", c_int),
#                     ("tail", c_int),
#                     ("count", c_int)]
#     return CBFIFO
# reference: https://www.digitalocean.com/community/tutorials/calling-c-functions-from-python
sleep(1)

cs_list = []
clk_list = []
mosi_list = []
miso_list = []
time_stamps_list = []

# function to create threads

# cbfifo_gen_c = c_uint64 * 8
# cbfifo_gen = CBFIFO(SPI_PINS(0, 0, 0, 0, 0), 0, 0, 0)

spi_pins_list = [[-1 for i in range(5)] for j in range(MAX)]
cbfifo_gen_c = CBFIFO(spi_pins_list)

c_lib.cbfifo_init(cbfifo_gen_c)

def get_spi_from_c():
    global ret_spi_transfer

    print("Getting parameters")
    c_lib.get_spi.restype = POINTER(SPI_PINS)
    while True:
        ret_spi_transfer = c_lib.get_spi(cbfifo_gen_c)
        if ret_spi_transfer:
            cs_list.append(ret_spi_transfer.contents.cs)
            clk_list.append(ret_spi_transfer.contents.clk)
            mosi_list.append(ret_spi_transfer.contents.mosi)
            miso_list.append(ret_spi_transfer.contents.miso)
            time_stamps_list.append(ret_spi_transfer.contents.time_ns)
            sleep(0.1)
        else:
            print("No more SPI transfer")
            break

spi_data_c = c_uint64 * 8
spi_data = spi_data_c(0xA5, 0xB0, 3, 4, 5, 6, 7, 8)

if __name__ == "__main__":
    mode = input("Enter required SPI mode (i.e, 0,1,2,3): ")
    print(mode)
    msb_first = input("MSB first? (enter True/False): ")
    print(msb_first)
    bits_per_word = input("Enter required bits per word (i.e., 8,16,32,64): ")
    print(bits_per_word)
    spi_config = SPI_CONFIG(500, 2000000, int(
        mode), msb_first, int(bits_per_word))
    c_lib.config_set(spi_config)
    sleep(1)
    c_lib.init_spi()

    print("Starting SPI generator")

# get number of elements in cbfifo from c_lib
    c_lib.cbfifo_count.restype = c_int
    cbfifo_count = c_lib.cbfifo_count(cbfifo_gen_c)
    print("cbfifo_count: ", cbfifo_count)

    ret_spi_transfer = c_lib.spi_transfer(spi_data, 1)
    print("SPI transfer finished...exiting")

    # get number of elements in cbfifo from c_lib
    c_lib.cbfifo_count.restype = c_int
    cbfifo_count = c_lib.cbfifo_count(cbfifo_gen_c)
    print("cbfifo_count: ", cbfifo_count)

    get_spi_from_c()

    # print("cs_list: ", cs_list)
    # print("clk_list: ", clk_list)
    # print("mosi_list: ", mosi_list)
    # print("miso_list: ", miso_list)
    # print("time_stamps_list: ", time_stamps_list)

    # modified timestamp starts from 0
    time_stamps_list = [x - time_stamps_list[0] for x in time_stamps_list]

    cs = numpy.array(cs_list)
    clk = numpy.array(clk_list)
    mosi = numpy.array(mosi_list)
    miso = numpy.array(miso_list)
    timestamp = numpy.array(time_stamps_list)

    # print cs, clk, mosi, miso, timestamp
    print("cs: ", cs)
    print("clk: ", clk)
    print("mosi: ", mosi)
    print("miso: ", miso)
    print("timestamp: ", timestamp)

    plt.plot([1, 2, 3])

    plt.show()
    # plt.show(block=True)

    # # plot the data in dfferent colors
    # plt.plot(timestamp, cs, color='r', label='cs')
    # plt.plot(timestamp, clk, color='g', label='clk')
    # plt.plot(timestamp, mosi, color='b', label='mosi')
    # plt.plot(timestamp, miso, color='y', label='miso')
    # plt.legend(loc='upper left')
    # plt.xlabel('Time (ns)')
    # plt.ylabel('SPI pins status')
    # plt.title('SPI pins status vs Time')
    # plt.show()

    print("Exiting")

    print("done")


from flask import *
from app import app
from service.CustomerService import CustomerService
from service.UserService import UserService
from service.TableBookingService import TableBookingService
from service.CategoryService import CategoryService
from service.EmailService import EmailBTH

ALLOWED_EXTENSIONS = {'jpg', 'jpeg','png'}

import json
import base64

userService = UserService()
bookingService = TableBookingService()
customerService = CustomerService()
catService = CategoryService()

emailbth = EmailBTH()

@app.route('/adminpanel')
def adminPanel():
    if(session.get("email") is not None and session['user_type'] == 'Admin'):

        resultAllCustomers = viewAllCustomers()
        resultAllBookings = viewAllBookings()
        return render_template('admin_panel.html',custData=resultAllCustomers, bookingData= resultAllBookings)
    else:
        return render_template('index.html')

def viewAllCustomers():

    resultAllCustomers = userService.allCustomers()
    # customer_json_string = json.dumps(resultAllCustomers)

    session["allusers"] = resultAllCustomers

    return resultAllCustomers

def viewAllBookings():

    resultAllBookings = bookingService.getAllBookings()
    #booking_json_string = json.dumps(resultAllBookings)

    session["allbookings"] = resultAllBookings
    print(resultAllBookings)

    return resultAllBookings

@app.route('/changecustomerstatus', methods=['POST'])
def changeCustomerStatus():

    if (session.get("email") is not None and session['user_type'] == 'Admin'):
        postData = request.form
        print(postData)

        result = customerService.updateUserStatus(postData)
        print(result)

        return "1"

    else:
        return render_template('index.html')

@app.route('/cancel_or_process_order', methods=['POST'])
def cancelOrder():

    if (session.get("email") is not None and session['user_type'] == 'Admin'):
        print("cancel_or_process_order")
        postData = request.form
        print(postData)
        purpose = postData.get("o_purpose")
        print(purpose)

        id = postData.get("o_id")
        print(id)

        result = emailbth.sendEmail(postData)
        print(result)
        bookingService.processBookingOrder(result, id)

        return "1"
    else:
        return render_template('index.html')

@app.route('/addNewCategory', methods=['POST'])
def newCategory():
    if (session.get("email") is not None and session['user_type'] == 'Admin'):
        print("cateeeee")
        postData = request.form
        print(postData)

        result = catService.saveFoodCategory(postData)
        print(result)
        return str(result)
    else:
        return render_template('index.html')

@app.route('/addMenu', methods=['POST', 'GET'])
def addMenuItem():
    if (session.get("email") is not None and session['user_type'] == 'Admin'):

        print("Menu Item")
        postData = request.form
        img_file = request.files['file']
        encr_img = base64.b64encode(img_file.read())

        if 'file' not in request.files:
            flash('No File Part in Request')
            return redirect(url_for('adminPanel'))

        if img_file.filename == '':
            flash('There is no selected Image')
            return redirect(url_for('adminPanel'))

        if img_file and checkFileExtension(img_file.filename):
            catService.saveMenuItem(postData, encr_img)
            flash('Menu Item Added Successfully...!')
            return redirect(url_for('adminPanel'))
        else:
            flash('Wrong File Selection...!')
            return redirect(url_for('adminPanel'))

def checkFileExtension(fileName):
    print("extension")
    return '.' in fileName and \
           fileName.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/allCategories',methods=['POST'])
def allCategories():
    if (session.get("email") is not None and session['user_type'] == 'Admin'):
        resultSet = catService.getAllCtegories()
        session['Categories'] = resultSet
        print(resultSet)
        return "None"
    else:
        return render_template('index.html')


import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as tm
from src.different.examStartVal import ExamStartVal
from src.app.genAlg import GenAlg

TITLE = 'Aplikacja szukająca min.glo za pomocą alg.genetycznego'
TITLE_APP = 'Aplikacja'
TITLE_ENTRY = 'Liczba epok'
TITLE_SIZE_POPU = 'Rozmiar populacji'
TITLE_LEN_BIT = 'Rozmiar cechy'
TITLE_FUN_OPT = 'Funkcja do opt'
TITLE_SELECT = 'Funkcja selekcji'
TITLE_CROSS = 'Funkcja krzyzowania'
TITLE_MUTABLE = 'Funkcja mutacji'
TITLE_CROSS_PROP = 'Procent krzyzowania'
TITLE_SELECT_PROP = 'Procent selekcji'
TITLE_MUTABLE_PROP = 'Procent mutacji'
TITLE_INVER_PROP = 'Procent inwersji'
TITLE_ELIT = 'Strategia elitarna'
TITLE_SET_X = 'Zakres dla X'
TITLE_SET_Y = 'Zakres dla Y'
TITLE_BUTTON = 'Start'
SIZE_WIN = '540x330+400+100'
COLUMN_1 = 10
COLUMN_2 = 270
ROW_1 = 50
ROW_2 = 80
ROW_3 = 110
ROW_4 = 140
ROW_5 = 170
ROW_6 = 200
ROW_7 = 230
MARGIN_2_ENTRY = 195
MARGIN_FROM = 95
MARGIN_TO = 170
FIRST = 0
SECOND = 1
THIRD = 2
WIDTH_ENTRY = 19
WIDTH_SET = 7
WIDTH_COMBOX = 16
WIDTH_BUTTON = 10
MARGIN_ROW = 120
FONT_TITLE = ('Arial', 12)
FONT_BUTTON = ('Arial', 10)
STATIC = 'readonly'
FROM = 'od'
TO = 'do'
NO = False
TWO_BIT = 2
NULL = ''
X_MIN, X_MAX = 0, 1
Y_MIN, Y_MAX = 2, 3
BUT_X, BUT_Y = 220, 290
TITLE_X, TITLE_Y = 70, 10
TITLE_ERROR = 'Bład danych'
CLICK_SELECT = '<<ComboboxSelected>>'
VALUES = 'values'
OPT_FUN = (
    'ACKLEY', 'BEALE', 'BUKIN', 'DROP-WAVE',
    'GOLDSTEIN-PRICE', 'MCCORMICK', 'SCHAFFER 2',
    'HOLDER TAB'
)
OPT_SELECT = (
    'Koła ruletki', 'Najlepsi', 'Selekcja turniejowa'
)
OPT_CROSS = (
    'Jedno punktowe', 'Dwu punktowe',
    'Trzy punktowa', 'Jednorodne'
)
OPT_MUTABLE = (
    'Brzegowa', 'Jedno punktowa', 'Dwu punktowa',
    'Jednorodne'
)
OPT_PROC_SELECT = [
    'Proc. losowan ruletki', 'Proc. najlepszych',
    'Roz. grupy w turnieju'
]

class Gui:
    """ Klasa odpowiedzialma za wyswietlanie
    okna graficznego """

    def __init__(self):
        self.__main = tk.Tk()
        self.__epok = None
        self.__popu = None
        self.__len_bit = None
        self.__len_var = None
        self.__board = None
        self.__fun_opt = None
        self.__select = None
        self.__cross = None
        self.__mutate = None
        self.__button = None
        self.__select_prop = None
        self.__cross_prop = None
        self.__mutable_prop = None
        self.__inver_prop = None
        self.__elit = None
        self.__p_select_text = None
        self.__opt_fun = tk.StringVar()
        self.__opt_select = tk.StringVar()
        self.__p_select = tk.StringVar()
        self.__opt_cross = tk.StringVar()
        self.__opt_mutable = tk.StringVar()

        self.__set_gui()

    """ Funkcja uruchamia okno graficzne """
    def create(self) -> None:
        self.__main.mainloop()

    """ Ustawianie elementów gui """
    def __set_gui(self) -> None:
        self.__set_main()
        self.__set_title_win()
        self.__set_option_epok()
        self.__set_choise_win()
        self.__set_proc_entry()
        self.__set_select_proc()
        self.__set_entry_get_set()
        self.__set_button()

    """ Naniesienie tytułu strony na ekran """
    def __set_title_win(self) -> None:
        tk.Label(
            self.__main, text=TITLE, font=FONT_TITLE
        ).place(x=TITLE_X, y=TITLE_Y)

    """ Wyswietlanie opcji zwiazanych z epoka """
    def __set_option_epok(self) -> None:
        self.__epok = self.__put_entry(
            COLUMN_1, ROW_1, TITLE_ENTRY
        )

        self.__popu = self.__put_entry(
            COLUMN_1, ROW_2, TITLE_SIZE_POPU
        )

        self.__len_bit = self.__put_entry(
            COLUMN_1, ROW_3, TITLE_LEN_BIT
        )

        self.__elit = self.__put_entry(
            COLUMN_2, ROW_1, TITLE_ELIT
        )

    """ Wyswietlanie okien funkcji, selekcji, krzyzowania, mutacji """
    def __set_choise_win(self) -> None:
        self.__fun_opt = self.__put_combobox(
            COLUMN_1, ROW_4, TITLE_FUN_OPT,
            OPT_FUN, self.__opt_fun
        )

        self.__fun_select = self.__put_combobox(
            COLUMN_1, ROW_5, TITLE_SELECT,
            OPT_SELECT, self.__opt_select
        )

        self.__fun_select.bind(
            CLICK_SELECT, self.__set_new_title_select
        )

        self.__fun_cross = self.__put_combobox(
            COLUMN_1, ROW_6, TITLE_CROSS,
            OPT_CROSS, self.__opt_cross
        )

        self.__fun_mutable = self.__put_combobox(
            COLUMN_1, ROW_7, TITLE_MUTABLE,
            OPT_MUTABLE, self.__opt_mutable
        )

    """ Wyswietlanie okien do pobierania przedziałów """
    def __set_entry_get_set(self) -> None:
        x_min, x_max = self.__put_set_xy(
            COLUMN_2, ROW_6, TITLE_SET_X
        )

        y_min, y_max = self.__put_set_xy(
            COLUMN_2, ROW_7, TITLE_SET_Y
        )

        self.__board = [x_min, x_max, y_min, y_max]

    """ Wywoływanie okien do pobrania procentow """
    def __set_proc_entry(self) -> None:
        self.__cross_prop = self.__put_entry(
            COLUMN_2, ROW_2, TITLE_CROSS_PROP
        )

        self.__mutable_prop = self.__put_entry(
            COLUMN_2, ROW_3, TITLE_MUTABLE_PROP
        )

        self.__inver_prop = self.__put_entry(
            COLUMN_2, ROW_4, TITLE_INVER_PROP
        )

    """ Wywołanie okna procentu selekcji """
    def __set_select_proc(self) -> None:
        self.__p_select.set(OPT_PROC_SELECT[FIRST])

        tk.Label(
            self.__main, textvariable=self.__p_select
        ).place(x=COLUMN_2, y=ROW_5)

        self.__select_prop = tk.Entry(
            self.__main, width=WIDTH_ENTRY
        )

        self.__select_prop.place(
            x=COLUMN_2 + MARGIN_ROW, y=ROW_5
        )

    """ Funkcja zmienia text procentu selekcji
    po wybranie opcji selekcji """
    def __set_new_title_select(self, event) -> None:
        index_sel_opt = OPT_SELECT.index(
            self.__opt_select.get()
        )

        self.__p_select.set(
            OPT_PROC_SELECT[index_sel_opt]
        )

    """ Ustawianie okna głownego """
    def __set_main(self) -> None:
        self.__main.title(TITLE_APP)
        self.__main.geometry(SIZE_WIN)
        self.__main.resizable(width=NO, height=NO)

    """ Funkcja tworzy okno ENTRY """
    def __put_entry(self, row, col, text) -> tk:
        tk.Label(
            self.__main, text=text
        ).place(x=row, y=col)

        obj = tk.Entry(self.__main, width=WIDTH_ENTRY)
        obj.place(x=row + MARGIN_ROW, y=col)

        return obj

    """ Funkcja tworzy okno COMBOBOX """
    def __put_combobox(
            self, row, col, text, opt_fun, str_list
    ) -> tk:
        tk.Label(
            self.__main, text=text
        ).place(x=row, y=col)

        obj = ttk.Combobox(
            self.__main, textvariable=str_list,
            width=WIDTH_COMBOX, state=STATIC
        )

        obj.place(x=row + MARGIN_ROW, y=col)
        obj[VALUES] = opt_fun
        obj.current(FIRST)

        return obj

    """ Funkcja tworzy okna do pobrania przedziału """
    def __put_set_xy(self, row, col, text) -> ():
        tk.Label(
            self.__main, text=text
        ).place(x=row, y=col)

        tk.Label(
            self.__main, text=FROM
        ).place(x=row + MARGIN_FROM, y=col)

        obj_1 = tk.Entry(self.__main, width=WIDTH_SET)
        obj_1.place(x=row + MARGIN_ROW, y=col)

        tk.Label(
            self.__main, text=TO
        ).place(x=row + MARGIN_TO, y=col)

        obj_2 = tk.Entry(self.__main, width=WIDTH_SET)
        obj_2.place(x=row + MARGIN_2_ENTRY, y=col)

        return obj_1, obj_2

    """ Ustawianie przycisku uruchamiającego """
    def __set_button(self) -> None:
        self.__button = tk.Button(
            self.__main, text=TITLE_BUTTON,
            width=WIDTH_BUTTON, font=FONT_BUTTON,
            command=self.__click
        )

        self.__button.place(x=BUT_X, y=BUT_Y)

    """ Wykonuje sie w chwili nacisniecia przucisku """
    def __click(self) -> None:
        error = self.__test_var()

        if error == NULL:
            self.__run_calc()
        else:
            tm.showerror(TITLE_ERROR, error)

    """ Wywołani funkcji sprawdzajacej dane """
    def __test_var(self) -> str:
        test = ExamStartVal()

        return test.exam(
            self.__epok.get(), self.__popu.get(),
            self.__len_bit.get(),
            [
                self.__board[X_MIN].get(),
                self.__board[X_MAX].get(),
                self.__board[Y_MIN].get(),
                self.__board[Y_MAX].get()
            ],
            self.__elit.get(), self.__cross_prop.get(),
            self.__mutable_prop.get(), self.__inver_prop.get(),
            self.__select_prop.get(), self.__opt_select.get()
        )

    """ Uruchamianie algorytmu genetycznego """
    def __run_calc(self) -> None:
        app = GenAlg(
            int(self.__epok.get()), int(self.__popu.get()),
            TWO_BIT, int(self.__len_bit.get()),
            [
                float(self.__board[X_MIN].get()),
                float(self.__board[X_MAX].get()),
                float(self.__board[Y_MIN].get()),
                float(self.__board[Y_MAX].get()),
            ],
            self.__opt_fun.get(), self.__opt_select.get(),
            self.__opt_cross.get(), self.__opt_mutable.get(),
            int(self.__elit.get()), float(self.__select_prop.get()),
            float(self.__cross_prop.get()),
            float(self.__mutable_prop.get()),
            float(self.__inver_prop.get())
        )

        app.run()