# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import fnmatch
import os
import pickle
import sys
from abc import ABCMeta, abstractmethod
from collections import defaultdict

import mozpack.path as mozpath
import six
from manifestparser import TestManifest, combine_fields
from mozbuild.base import MozbuildObject
from mozbuild.testing import REFTEST_FLAVORS, TEST_MANIFESTS
from mozbuild.util import OrderedDefaultDict
from mozpack.files import FileFinder

here = os.path.abspath(os.path.dirname(__file__))

MOCHITEST_CHUNK_BY_DIR = 4
MOCHITEST_TOTAL_CHUNKS = 5

def WebglSuite(name):
    return {
        "aliases": (name,),
        "build_flavor": "mochitest",
        "mach_command": "mochitest",
        "kwargs": {"flavor": "plain", "subsuite": name, "test_paths": None},
        "task_regex": [
            "mochitest-" + name + "($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    }

TEST_SUITES = {
    "cppunittest": {
        "aliases": ("cpp",),
        "mach_command": "cppunittest",
        "kwargs": {"test_files": None},
    },
    "crashtest": {
        "aliases": ("c", "rc"),
        "build_flavor": "crashtest",
        "mach_command": "crashtest",
        "kwargs": {"test_file": None},
        "task_regex": ["crashtest($|.*(-1|[^0-9])$)", "test-verify($|.*(-1|[^0-9])$)"],
    },
    "crashtest-qr": {
        "aliases": ("c", "rc"),
        "build_flavor": "crashtest",
        "mach_command": "crashtest",
        "kwargs": {"test_file": None},
        "task_regex": [
            "crashtest-qr($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "firefox-ui-functional": {
        "aliases": ("fxfn",),
        "mach_command": "firefox-ui-functional",
        "kwargs": {},
    },
    "firefox-ui-update": {
        "aliases": ("fxup",),
        "mach_command": "firefox-ui-update",
        "kwargs": {},
    },
    "marionette": {
        "aliases": ("mn",),
        "mach_command": "marionette-test",
        "kwargs": {"tests": None},
        "task_regex": ["marionette($|.*(-1|[^0-9])$)"],
    },
    "mochitest-a11y": {
        "aliases": ("a11y", "ally"),
        "build_flavor": "a11y",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "a11y",
            "test_paths": None,
            "e10s": False,
            "enable_fission": False,
        },
        "task_regex": [
            "mochitest-a11y($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-browser-chrome": {
        "aliases": ("bc", "browser"),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {"flavor": "browser-chrome", "test_paths": None},
        "task_regex": [
            "mochitest-browser-chrome($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-browser-chrome-screenshots": {
        "aliases": ("ss", "screenshots-chrome"),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "browser-chrome",
            "subsuite": "screenshots",
            "test_paths": None,
        },
        "task_regex": ["browser-screenshots($|.*(-1|[^0-9])$)"],
    },
    "mochitest-chrome": {
        "aliases": ("mc",),
        "build_flavor": "chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "chrome",
            "test_paths": None,
            "e10s": False,
            "enable_fission": False,
        },
        "task_regex": [
            "mochitest-chrome($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-chrome-gpu": {
        "aliases": ("gpu",),
        "build_flavor": "chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "chrome",
            "subsuite": "gpu",
            "test_paths": None,
            "e10s": False,
            "enable_fission": False,
        },
        "task_regex": [
            "mochitest-gpu($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-devtools-chrome": {
        "aliases": ("dt", "devtools"),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "browser-chrome",
            "subsuite": "devtools",
            "test_paths": None,
        },
        "task_regex": [
            "mochitest-devtools-chrome($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-browser-a11y": {
        "aliases": ("ba", "browser-a11y"),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "browser-chrome",
            "subsuite": "a11y",
            "test_paths": None,
        },
        "task_regex": [
            "mochitest-browser-a11y($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-media": {
        "aliases": ("mpm", "plain-media"),
        "build_flavor": "mochitest",
        "mach_command": "mochitest",
        "kwargs": {"flavor": "plain", "subsuite": "media", "test_paths": None},
        "task_regex": [
            "mochitest-media($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-browser-media": {
        "aliases": ("bmda", "browser-mda"),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "browser-chrome",
            "subsuite": "media-bc",
            "test_paths": None,
        },
        "task_regex": [
            "mochitest-browser-media($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-plain": {
        "aliases": (
            "mp",
            "plain",
        ),
        "build_flavor": "mochitest",
        "mach_command": "mochitest",
        "kwargs": {"flavor": "plain", "test_paths": None},
        "task_regex": [
            "mochitest-plain($|.*(-1|[^0-9])$)",  # noqa
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-plain-gpu": {
        "aliases": ("gpu",),
        "build_flavor": "mochitest",
        "mach_command": "mochitest",
        "kwargs": {"flavor": "plain", "subsuite": "gpu", "test_paths": None},
        "task_regex": [
            "mochitest-gpu($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-remote": {
        "aliases": ("remote",),
        "build_flavor": "browser-chrome",
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "browser-chrome",
            "subsuite": "remote",
            "test_paths": None,
        },
        "task_regex": [
            "mochitest-remote($|.*(-1|[^0-9])$)",
            "test-verify($|.*(-1|[^0-9])$)",
        ],
    },
    "mochitest-webgl1-core": WebglSuite("webgl1-core"),
    "mochitest-webgl1-ext": WebglSuite("webgl1-ext"),
    "mochitest-webgl2-core": WebglSuite("webgl2-core"),
    "mochitest-webgl2-ext": WebglSuite("webgl2-ext"),
    "mochitest-webgl2-deqp": WebglSuite("webgl2-deqp"),
    "mochitest-webgpu": WebglSuite("webgpu"),
    "puppeteer": {
        "aliases": ("remote/test/puppeteer",),
        "mach_command": "puppeteer-test",
        "kwargs": {"headless": False},
    },
    "python": {
        "build_flavor": "python",
        "mach_command": "python-test",
        "kwargs": {"tests": None},
    },
    "telemetry-tests-client": {
        "aliases": ("ttc",),
        "build_flavor": "telemetry-tests-client",
        "mach_command": "telemetry-tests-client",
        "kwargs": {},
        "task_regex": ["telemetry-tests-client($|.*(-1|[^0-9])$)"],
    },
    "reftest": {
        "aliases": ("rr",),
        "build_flavor": "reftest",
        "mach_command": "reftest",
        "kwargs": {"tests": None},
        "task_regex": [
            "(opt|debug)(-geckoview)?-reftest($|.*(-1|[^0-9])$)",
            "test-verify-gpu($|.*(-1|[^0-9])$)",
        ],
    },
    "reftest-qr": {
        "aliases": ("rr",),
        "build_flavor": "reftest",
        "mach_command": "reftest",
        "kwargs": {"tests": None},
        "task_regex": [
            "(opt|debug)(-geckoview)?-reftest-qr($|.*(-1|[^0-9])$)",
            "test-verify-gpu($|.*(-1|[^0-9])$)",
        ],
    },
    "robocop": {
        "mach_command": "robocop",
        "kwargs": {"test_paths": None},
        "task_regex": ["robocop($|.*(-1|[^0-9])$)"],
    },
    "web-platform-tests": {
        "aliases": ("wpt",),
        "mach_command": "web-platform-tests",
        "build_flavor": "web-platform-tests",
        "kwargs": {"subsuite": "testharness"},
        "task_regex": [
            "web-platform-tests(?!-crashtest|-reftest|-wdspec|-print)"
            "($|.*(-1|[^0-9])$)",
            "test-verify-wpt",
        ],
    },
    "web-platform-tests-crashtest": {
        "aliases": ("wpt",),
        "mach_command": "web-platform-tests",
        "build_flavor": "web-platform-tests",
        "kwargs": {"subsuite": "crashtest"},
        "task_regex": [
            "web-platform-tests-crashtest($|.*(-1|[^0-9])$)",
            "test-verify-wpt",
        ],
    },
    "web-platform-tests-print-reftest": {
        "aliases": ("wpt",),
        "mach_command": "web-platform-tests",
        "kwargs": {"subsuite": "print-reftest"},
        "task_regex": [
            "web-platform-tests-print-reftest($|.*(-1|[^0-9])$)",
            "test-verify-wpt",
        ],
    },
    "web-platform-tests-reftest": {
        "aliases": ("wpt",),
        "mach_command": "web-platform-tests",
        "build_flavor": "web-platform-tests",
        "kwargs": {"subsuite": "reftest"},
        "task_regex": [
            "web-platform-tests-reftest($|.*(-1|[^0-9])$)",
            "test-verify-wpt",
        ],
    },
    "web-platform-tests-wdspec": {
        "aliases": ("wpt",),
        "mach_command": "web-platform-tests",
        "build_flavor": "web-platform-tests",
        "kwargs": {"subsuite": "wdspec"},
        "task_regex": [
            "web-platform-tests-wdspec($|.*(-1|[^0-9])$)",
            "test-verify-wpt",
        ],
    },
    "valgrind": {
        "aliases": ("v",),
        "mach_command": "valgrind-test",
        "kwargs": {},
    },
    "xpcshell": {
        "aliases": ("x",),
        "build_flavor": "xpcshell",
        "mach_command": "xpcshell-test",
        "kwargs": {"test_file": "all"},
        "task_regex": ["xpcshell($|.*(-1|[^0-9])$)", "test-verify($|.*(-1|[^0-9])$)"],
    },
    "xpcshell-msix": {
        "aliases": ("x",),
        "build_flavor": "xpcshell",
        "mach_command": "xpcshell-test",
        "kwargs": {"test_file": "all"},
        "task_regex": ["xpcshell($|.*(-1|[^0-9])$)", "test-verify($|.*(-1|[^0-9])$)"],
    },
}
"""Definitions of all test suites and the metadata needed to run and process
them. Each test suite definition can contain the following keys.

Arguments:
    aliases (tuple): A tuple containing shorthands used to refer to this suite.
    build_flavor (str): The flavor assigned to this suite by the build system
                        in `mozbuild.testing.TEST_MANIFESTS` (or similar).
    mach_command (str): Name of the mach command used to run this suite.
    kwargs (dict): Arguments needed to pass into the mach command.
    task_regex (list): A list of regexes used to filter task labels that run
                       this suite.
"""

for i in range(1, MOCHITEST_TOTAL_CHUNKS + 1):
    TEST_SUITES["mochitest-%d" % i] = {
        "aliases": ("m%d" % i,),
        "mach_command": "mochitest",
        "kwargs": {
            "flavor": "mochitest",
            "subsuite": "default",
            "chunk_by_dir": MOCHITEST_CHUNK_BY_DIR,
            "total_chunks": MOCHITEST_TOTAL_CHUNKS,
            "this_chunk": i,
            "test_paths": None,
        },
    }

WPT_TYPES = set()
for suite, data in TEST_SUITES.items():
    if suite.startswith("web-platform-tests"):
        WPT_TYPES.add(data["kwargs"]["subsuite"])

_test_flavors = {
    "a11y": "mochitest-a11y",
    "browser-chrome": "mochitest-browser-chrome",
    "chrome": "mochitest-chrome",
    "crashtest": "crashtest",
    "firefox-ui-functional": "firefox-ui-functional",
    "firefox-ui-update": "firefox-ui-update",
    "marionette": "marionette",
    "mochitest": "mochitest-plain",
    "puppeteer": "puppeteer",
    "python": "python",
    "reftest": "reftest",
    "telemetry-tests-client": "telemetry-tests-client",
    "web-platform-tests": "web-platform-tests",
    "xpcshell": "xpcshell",
}

_test_subsuites = {
    ("browser-chrome", "a11y"): "mochitest-browser-a11y",
    ("browser-chrome", "devtools"): "mochitest-devtools-chrome",
    ("browser-chrome", "media"): "mochitest-browser-media",
    ("browser-chrome", "remote"): "mochitest-remote",
    ("browser-chrome", "screenshots"): "mochitest-browser-chrome-screenshots",
    ("chrome", "gpu"): "mochitest-chrome-gpu",
    ("mochitest", "gpu"): "mochitest-plain-gpu",
    ("mochitest", "media"): "mochitest-media",
    ("mochitest", "robocop"): "robocop",
    ("mochitest", "webgl1-core"): "mochitest-webgl1-core",
    ("mochitest", "webgl1-ext"): "mochitest-webgl1-ext",
    ("mochitest", "webgl2-core"): "mochitest-webgl2-core",
    ("mochitest", "webgl2-ext"): "mochitest-webgl2-ext",
    ("mochitest", "webgl2-deqp"): "mochitest-webgl2-deqp",
    ("mochitest", "webgpu"): "mochitest-webgpu",
    ("web-platform-tests", "testharness"): "web-platform-tests",
    ("web-platform-tests", "crashtest"): "web-platform-tests-crashtest",
    ("web-platform-tests", "print-reftest"): "web-platform-tests-print-reftest",
    ("web-platform-tests", "reftest"): "web-platform-tests-reftest",
    ("web-platform-tests", "wdspec"): "web-platform-tests-wdspec",
}

def get_suite_definition(flavor, subsuite=None, strict=False):
    """Return a suite definition given a flavor and optional subsuite.

    If strict is True, a subsuite must have its own entry in TEST_SUITES.
    Otherwise, the entry for 'flavor' will be returned with the 'subsuite'
    keyword arg set.

    With or without strict mode, an empty dict will be returned if no
    matching suite definition was found.
    """
    if not subsuite:
        suite_name = _test_flavors.get(flavor)
        return suite_name, TEST_SUITES.get(suite_name, {}).copy()

    suite_name = _test_subsuites.get((flavor, subsuite))
    if suite_name or strict:
        return suite_name, TEST_SUITES.get(suite_name, {}).copy()

    suite_name = _test_flavors.get(flavor)
    if suite_name not in TEST_SUITES:
        return suite_name, {}

    suite = TEST_SUITES[suite_name].copy()
    suite.setdefault("kwargs", {})
    suite["kwargs"]["subsuite"] = subsuite
    return suite_name, suite

def rewrite_test_base(test, new_base):
    """Rewrite paths in a test to be under a new base path.

    This is useful for running tests from a separate location from where they
    were defined.
    """
    test["here"] = mozpath.join(new_base, test["dir_relpath"])
    test["path"] = mozpath.join(new_base, test["file_relpath"])
    return test

@six.add_metaclass(ABCMeta)
class TestLoader(MozbuildObject):
    @abstractmethod
    def __call__(self):
        """Generate test metadata."""

class BuildBackendLoader(TestLoader):
    def __call__(self):
        """Loads the test metadata generated by the TestManifest build backend.

        The data is stored in two files:

            - <objdir>/all-tests.pkl
            - <objdir>/test-defaults.pkl

        The 'all-tests.pkl' file is a mapping of source path to test objects. The
        'test-defaults.pkl' file maps manifests to their DEFAULT configuration.
        These manifest defaults will be merged into the test configuration of the
        contained tests.
        """
        # If installing tests is going to result in re-generating the build
        # backend, we need to do this here, so that the updated contents of
        # all-tests.pkl make it to the set of tests to run.
        if self.backend_out_of_date(
            mozpath.join(self.topobjdir, "backend.TestManifestBackend")
        ):
            print("Test configuration changed. Regenerating backend.")
            from mozbuild.gen_test_backend import gen_test_backend

            gen_test_backend()

        all_tests = os.path.join(self.topobjdir, "all-tests.pkl")
        test_defaults = os.path.join(self.topobjdir, "test-defaults.pkl")

        with open(all_tests, "rb") as fh:
            test_data = pickle.load(fh)

        with open(test_defaults, "rb") as fh:
            defaults = pickle.load(fh)

        # The keys in defaults use platform-specific path separators.
        # self.topsrcdir was normalized to use /, revert back to \ if needed.
        topsrcdir = os.path.normpath(self.topsrcdir)

        for path, tests in six.iteritems(test_data):
            for metadata in tests:
                defaults_manifests = [metadata["manifest"]]

                ancestor_manifest = metadata.get("ancestor_manifest")
                if ancestor_manifest:
                    # The (ancestor manifest, included manifest) tuple
                    # contains the defaults of the included manifest, so
                    # use it instead of [metadata['manifest']].
                    ancestor_manifest = os.path.join(topsrcdir, ancestor_manifest)
                    defaults_manifests[0] = (ancestor_manifest, metadata["manifest"])
                    defaults_manifests.append(ancestor_manifest)

                for manifest in defaults_manifests:
                    manifest_defaults = defaults.get(manifest)
                    if manifest_defaults:
                        metadata = combine_fields(manifest_defaults, metadata)

                yield metadata

class TestManifestLoader(TestLoader):
    def __init__(self, *args, **kwargs):
        super(TestManifestLoader, self).__init__(*args, **kwargs)
        self.finder = FileFinder(self.topsrcdir)
        self.reader = self.mozbuild_reader(config_mode="empty")
        self.variables = {
            "{}_MANIFESTS".format(k): v[0] for k, v in six.iteritems(TEST_MANIFESTS)
        }
        self.variables.update(
            {"{}_MANIFESTS".format(f.upper()): f for f in REFTEST_FLAVORS}
        )

    def _load_manifestparser_manifest(self, mpath):
        mp = TestManifest(
            manifests=[mpath],
            strict=True,
            rootdir=self.topsrcdir,
            finder=self.finder,
            handle_defaults=True,
        )
        return (test for test in mp.tests)

    def _load_reftest_manifest(self, mpath):
        import reftest

        manifest = reftest.ReftestManifest(finder=self.finder)
        manifest.load(mpath)

        for test in sorted(manifest.tests, key=lambda x: x.get("path")):
            test["manifest_relpath"] = test["manifest"][len(self.topsrcdir) + 1 :]
            yield test

    def __call__(self):
        for path, name, key, value in self.reader.find_variables_from_ast(
            self.variables
        ):
            mpath = os.path.join(self.topsrcdir, os.path.dirname(path), value)
            flavor = self.variables[name]

            if name.rsplit("_", 1)[0].lower() in REFTEST_FLAVORS:
                tests = self._load_reftest_manifest(mpath)
            else:
                tests = self._load_manifestparser_manifest(mpath)

            for test in tests:
                path = mozpath.normpath(test["path"])
                assert mozpath.basedir(path, [self.topsrcdir])
                relpath = path[len(self.topsrcdir) + 1 :]

                # Add these keys for compatibility with the build backend loader.
                test["flavor"] = flavor
                test["file_relpath"] = relpath
                test["srcdir_relpath"] = relpath
                test["dir_relpath"] = mozpath.dirname(relpath)

                yield test

class TestResolver(MozbuildObject):
    """Helper to resolve tests from the current environment to test files."""

    test_rewrites = {
        "a11y": "_tests/testing/mochitest/a11y",
        "browser-chrome": "_tests/testing/mochitest/browser",
        "chrome": "_tests/testing/mochitest/chrome",
        "mochitest": "_tests/testing/mochitest/tests",
        "xpcshell": "_tests/xpcshell",
    }

    def __init__(self, *args, **kwargs):
        loader_cls = kwargs.pop("loader_cls", BuildBackendLoader)
        super(TestResolver, self).__init__(*args, **kwargs)

        self.load_tests = self._spawn(loader_cls)
        self._tests = []
        self._reset_state()

        # These suites aren't registered in moz.build so require special handling.
        self._puppeteer_loaded = False
        self._tests_loaded = False
        self._wpt_loaded = False

    def _reset_state(self):
        self._tests_by_path = OrderedDefaultDict(list)
        self._tests_by_flavor = defaultdict(set)
        self._tests_by_manifest = defaultdict(list)
        self._test_dirs = set()

    @property
    def tests(self):
        if not self._tests_loaded:
            self._reset_state()
            for test in self.load_tests():
                self._tests.append(test)
            self._tests_loaded = True
        return self._tests

    @property
    def tests_by_path(self):
        if not self._tests_by_path:
            for test in self.tests:
                self._tests_by_path[test["file_relpath"]].append(test)
        return self._tests_by_path

    @property
    def tests_by_flavor(self):
        if not self._tests_by_flavor:
            for test in self.tests:
                self._tests_by_flavor[test["flavor"]].add(test["file_relpath"])
        return self._tests_by_flavor

    @property
    def tests_by_manifest(self):
        if not self._tests_by_manifest:
            for test in self.tests:
                if test["flavor"] == "web-platform-tests":
                    # Use test ids instead of paths for WPT.
                    self._tests_by_manifest[test["manifest"]].append(test["name"])
                else:
                    relpath = mozpath.relpath(
                        test["path"], mozpath.dirname(test["manifest"])
                    )
                    self._tests_by_manifest[test["manifest_relpath"]].append(relpath)
        return self._tests_by_manifest

    @property
    def test_dirs(self):
        if not self._test_dirs:
            for test in self.tests:
                self._test_dirs.add(test["dir_relpath"])
        return self._test_dirs

    def _resolve(
        self, paths=None, flavor="", subsuite=None, under_path=None, tags=None
    ):
        """Given parameters, resolve them to produce an appropriate list of tests.

        Args:
            paths (list):
                By default, set to None. If provided as a list of paths, then
                this method will attempt to load the appropriate set of tests
                that live in this path.

            flavor (string):
                By default, an empty string. If provided as a string, then this
                method will attempt to load tests that belong to this flavor.
                Additional filtering also takes the flavor into consideration.

            subsuite (string):
                By default, set to None. If provided as a string, then this value
                is used to perform filtering of a candidate set of tests.
        """
        if tags:
            tags = set(tags)

        def fltr(tests):
            """Filters tests based on several criteria.

            Args:
                tests (list):
                    List of tests that belong to the same candidate path.

            Returns:
                test (dict):
                    If the test survived the filtering process, it is returned
                    as a valid test.
            """
            for test in tests:
                if flavor:
                    if flavor == "devtools" and test.get("flavor") != "browser-chrome":
                        continue
                    if flavor != "devtools" and test.get("flavor") != flavor:
                        continue

                if subsuite and test.get("subsuite", "undefined") != subsuite:
                    continue

                if tags and not (tags & set(test.get("tags", "").split())):
                    continue

                if under_path and not test["file_relpath"].startswith(under_path):
                    continue

                # Make a copy so modifications don't change the source.
                yield dict(test)

        paths = paths or []
        paths = [mozpath.normpath(p) for p in paths]
        if not paths:
            paths = [None]

        if flavor in ("", "puppeteer", None) and (
            any(self.is_puppeteer_path(p) for p in paths) or paths == [None]
        ):
            self.add_puppeteer_manifest_data()

        if flavor in ("", "web-platform-tests", None) and (
            any(self.is_wpt_path(p) for p in paths) or paths == [None]
        ):
            self.add_wpt_manifest_data()

        candidate_paths = set()

        for path in sorted(paths):
            if path is None:
                candidate_paths |= set(self.tests_by_path.keys())
                continue

            if "*" in path:
                candidate_paths |= {
                    p for p in self.tests_by_path if mozpath.match(p, path)
                }
                continue

            # If the path is a directory, or the path is a prefix of a directory
            # containing tests, pull in all tests in that directory.
            if path in self.test_dirs or any(
                p.startswith(path) for p in self.tests_by_path
            ):
                candidate_paths |= {p for p in self.tests_by_path if p.startswith(path)}
                continue

            # If the path is a manifest, add all tests defined in that manifest.
            if any(path.endswith(e) for e in (".ini", ".list")):
                key = "manifest" if os.path.isabs(path) else "manifest_relpath"
                candidate_paths |= {
                    t["file_relpath"]
                    for t in self.tests
                    if mozpath.normpath(t[key]) == path
                }
                continue

            # If it's a test file, add just that file.
            candidate_paths |= {p for p in self.tests_by_path if path in p}

        for p in sorted(candidate_paths):
            tests = self.tests_by_path[p]
            for test in fltr(tests):
                yield test

    def is_puppeteer_path(self, path):
        if path is None:
            return True
        return mozpath.match(path, "remote/test/puppeteer/test/**")

    def add_puppeteer_manifest_data(self):
        if self._puppeteer_loaded:
            return

        self._reset_state()

        test_path = os.path.join(self.topsrcdir, "remote", "test", "puppeteer", "test")
        for root, dirs, paths in os.walk(test_path):
            for filename in fnmatch.filter(paths, "*.spec.js"):
                path = os.path.join(root, filename)
                self._tests.append(
                    {
                        "path": os.path.abspath(path),
                        "flavor": "puppeteer",
                        "here": os.path.dirname(path),
                        "manifest": None,
                        "name": path,
                        "file_relpath": path,
                        "head": "",
                        "support-files": "",
                        "subsuite": "puppeteer",
                        "dir_relpath": os.path.dirname(path),
                        "srcdir_relpath": path,
                    }
                )

        self._puppeteer_loaded = True

    def is_wpt_path(self, path):
        """Checks if path forms part of the known web-platform-test paths.

        Args:
            path (str or None):
                Path to check against the list of known web-platform-test paths.

        Returns:
            Boolean value. True if path is part of web-platform-tests path, or
            path is None. False otherwise.
        """
        if path is None:
            return True
        if mozpath.match(path, "testing/web-platform/tests/**"):
            return True
        if mozpath.match(path, "testing/web-platform/mozilla/tests/**"):
            return True
        return False

    def get_wpt_group(self, test, depth=3):
        """Given a test object set the group (aka manifest) that it belongs to.

        If a custom value for `depth` is provided, it will override the default
        value of 3 path components.

        Args:
            test (dict): Test object for the particular suite and subsuite.
            depth (int, optional): Custom number of path elements.

        Returns:
            str: The group the given test belongs to.
        """
        # This takes into account that for mozilla-specific WPT tests, the path
        # contains an extra '/_mozilla' prefix that must be accounted for.
        if test["name"].startswith("/_mozilla"):
            depth = depth + 1

        # Webdriver tests are nested in "classic" and "bidi" folders. Increase
        # the depth to avoid grouping all classic or bidi tests in one chunk.
        if test["name"].startswith(("/webdriver", "/_mozilla/webdriver")):
            depth = depth + 1

        group = os.path.dirname(test["name"])
        while group.count("/") > depth:
            group = os.path.dirname(group)
        return group

    def add_wpt_manifest_data(self):
        """Adds manifest data for web-platform-tests into the list of available tests.

        Upon invocation, this method will download from firefox-ci the most recent
        version of the web-platform-tests manifests.

        Once manifest is downloaded, this method will add details about each test
        into the list of available tests.
        """
        if self._wpt_loaded:
            return

        self._reset_state()

        wpt_path = os.path.join(self.topsrcdir, "testing", "web-platform")
        sys.path = [wpt_path] + sys.path

        import logging

        import manifestupdate

        logger = logging.getLogger("manifestupdate")
        logger.disabled = True

        manifests = manifestupdate.run(
            self.topsrcdir,
            self.topobjdir,
            rebuild=False,
            download=True,
            config_path=None,
            rewrite_config=True,
            update=True,
            logger=logger,
        )
        if not manifests:
            print("Loading wpt manifest failed")
            return

        for manifest, data in six.iteritems(manifests):
            tests_root = data[
                "tests_path"
            ]  # full path on disk until web-platform tests directory

            for test_type, path, tests in manifest:
                full_path = mozpath.join(tests_root, path)
                src_path = mozpath.relpath(full_path, self.topsrcdir)
                if test_type not in WPT_TYPES:
                    continue

                full_path = mozpath.join(tests_root, path)  # absolute path on disk
                src_path = mozpath.relpath(full_path, self.topsrcdir)

                for test in tests:
                    testobj = {
                        "head": "",
                        "support-files": "",
                        "path": full_path,
                        "flavor": "web-platform-tests",
                        "subsuite": test_type,
                        "here": mozpath.dirname(path),
                        "name": test.id,
                        "file_relpath": src_path,
                        "srcdir_relpath": src_path,
                        "dir_relpath": mozpath.dirname(src_path),
                    }
                    group = self.get_wpt_group(testobj)
                    testobj["manifest"] = group

                    test_root = "tests"
                    if group.startswith("/_mozilla"):
                        test_root = os.path.join("mozilla", "tests")
                        group = group[len("/_mozilla") :]

                    group = group.lstrip("/")
                    testobj["manifest_relpath"] = os.path.join(
                        wpt_path, test_root, group
                    )
                    self._tests.append(testobj)

        self._wpt_loaded = True

    def resolve_tests(self, cwd=None, **kwargs):
        """Resolve tests from an identifier.

        This is a generator of dicts describing each test. All arguments are
        optional.

        Paths in returned tests are automatically translated to the paths in
        the _tests directory under the object directory.

        Args:
            cwd (str):
                If specified, we will limit our results to tests under this
                directory. The directory should be defined as an absolute path
                under topsrcdir or topobjdir.

            paths (list):
                An iterable of values to use to identify tests to run. If an
                entry is a known test file, tests associated with that file are
                returned (there may be multiple configurations for a single
                file). If an entry is a directory, or a prefix of a directory
                containing tests, all tests in that directory are returned. If
                the string appears in a known test file, that test file is
                considered. If the path contains a wildcard pattern, tests
                matching that pattern are returned.

            under_path (str):
                If specified, will be used to filter out tests that aren't in
                the specified path prefix relative to topsrcdir or the test's
                installed dir.

            flavor (str):
                If specified, will be used to filter returned tests to only be
                the flavor specified. A flavor is something like ``xpcshell``.

            subsuite (str):
                If specified will be used to filter returned tests to only be
                in the subsuite specified. To filter only tests that *don't*
                have any subsuite, pass the string 'undefined'.

            tags (list):
                If specified, will be used to filter out tests that don't contain
                a matching tag.
        """
        if cwd:
            norm_cwd = mozpath.normpath(cwd)
            norm_srcdir = mozpath.normpath(self.topsrcdir)
            norm_objdir = mozpath.normpath(self.topobjdir)

            reldir = None

            if norm_cwd.startswith(norm_objdir):
                reldir = norm_cwd[len(norm_objdir) + 1 :]
            elif norm_cwd.startswith(norm_srcdir):
                reldir = norm_cwd[len(norm_srcdir) + 1 :]

            kwargs["under_path"] = reldir

        rewrite_base = None
        for test in self._resolve(**kwargs):
            rewrite_base = self.test_rewrites.get(test["flavor"], None)

            if rewrite_base:
                rewrite_base = os.path.join(
                    self.topobjdir, os.path.normpath(rewrite_base)
                )
                yield rewrite_test_base(test, rewrite_base)
            else:
                yield test

    def resolve_metadata(self, what):
        """Resolve tests based on the given metadata. If not specified, metadata
        from outgoing files will be used instead.
        """
        # Parse arguments and assemble a test "plan."
        run_suites = set()
        run_tests = []

        for entry in what:
            # If the path matches the name or alias of an entire suite, run
            # the entire suite.
            if entry in TEST_SUITES:
                run_suites.add(entry)
                continue
            suitefound = False
            for suite, v in six.iteritems(TEST_SUITES):
                if entry.lower() in v.get("aliases", []):
                    run_suites.add(suite)
                    suitefound = True
            if suitefound:
                continue

            # Now look for file/directory matches in the TestResolver.
            relpath = self._wrap_path_argument(entry).relpath()
            tests = list(self.resolve_tests(paths=[relpath]))
            run_tests.extend(tests)

            if not tests:
                print("UNKNOWN TEST: %s" % entry, file=sys.stderr)

        return run_suites, run_tests


# coding: utf-8
import os
import sys

STATICS_VERSIONING = 20 # If this one changes page caching has to changed else the url stays cached.
PAGE_CACHING_MASTER_VERSION = "%s:%s" % (STATICS_VERSIONING, 27) # Increase it when some html from a cached paged has changed before pushing code to life.
PRODUCT_NAME = ''
DOMAIN = ''
WEB_DOMAIN = 'www.%s' % DOMAIN
EMAIL_SENDER_NAME = u'%s \u30b7' % PRODUCT_NAME # \u30b7 -> utf-8 smiley.
EMAIL_SENDER = "@%s" % DOMAIN
EMAIL_SENDER_FULL = '%s <%s>' % (EMAIL_SENDER_NAME, EMAIL_SENDER)
EMAIL_SUBJECT_PREFIX = ''
SESSION_SECRET_KEY = ''
DEVELOPMENT = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')
GOOGLE_ANALYTICS_ID = ''
BITLY_USERNAME = ''
BITLY_APIKEY = ''
SENGRID_USERNAME = ''
SENGRID_API_KEY = '*'


import torch
import torch.nn as nn

## step.1 Channel Attention
class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=8):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)

        self.fc1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)
        self.relu1 = nn.ReLU(inplace=True)
        self.fc2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)

        # self.mlp = nn.Sequential(
        #     nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False),
        #     nn.ReLU(inplace=True),
        #     nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)
        # )

        self.sigmod = nn.Sigmoid()

    def forward(self, x):
        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))  # (N, 64, H, W) -> (N, 64, 1, 1) -> (N, 8, 1, 1) -> (N, 64, 1, 1)
        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))

        out = avg_out + max_out

        return self.sigmod(out)

## step.2 Spatial Attention
class SpatialAttention(nn.Module):
    def __init__(self, kennel_size=7):
        super(SpatialAttention, self).__init__()

        assert kennel_size in (3,7), "kennel size must be 3 or 7"
        padding = 3 if kennel_size == 7 else 1

        self.conv1 = nn.Conv2d(2, 1, kennel_size, padding=padding, bias=False)
        self.sigmod = nn.Sigmoid()

    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)

        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv1(x)

        return self.sigmod(x)

## step.3 Basic Network
class BasicNetwork(nn.Module):
    def __init__(self, in_planes=64):
        super(BasicNetwork, self).__init__()
        self.CA = ChannelAttention(in_planes)
        self.SA = SpatialAttention()

    def forward(self, x):
        out = self.CA(x) * x # channel attention
        out = self.SA(out) * out # spatial attention

        return out

if __name__ == '__main__':
    cbam = BasicNetwork() # create model
    input = torch.zeros((4, 64, 640, 480)) # input tensor
    cbam.eval() # eval()
    output = cbam(input)
    print('s')


#!/usr/bin/env python3

import argparse
import json
import sys
import requests
from es2json import esgenerator, isint, litter, eprint

lookup_table_wdProperty = {"http://viaf.org": {"property": "P214",
                                               "delim": "/"},
                           "https://d-nb.info/gnd": {"property": "P227",
                                                     "delim": "/"},
                           "http://isni.org": {"property": "P213",
                                               "delim": "/"},
                           "http://id.loc.gov": {"property": "P244",
                                                 "delim": "/"},
                           "https://deutsche-digitale-bibliothek.de": {"property": "P4948",
                                                                       "delim": "/"},
                           "http://catalogue.bnf.fr/ark": {"property": "P268",
                                                           "delim": "/cb"},
                           "http://geonames.org": {"property": "P1566",
                                                   "delim": "/"},
                           "http://filmportal.de/person": {"property": "P2639",
                                                           "delim": "/"},
                           "http://orcid.org": {"property": "P496",
                                                "delim": "/"},
                           "http://swb.bsz-bw.de/DB=2.1/PPNSET?PPN=": {"property": "P1044",
                                                                       "delim": "="}
                           }

def get_wdid(_ids, rec):
    """
    gets an list of sameAs Links, e.g. ['https://d-nb.info/gnd/118827545', 'http://swb.bsz-bw.de/DB=2.1/PPNSET?PPN=035143010', 'http://catalogue.bnf.fr/ark:/12148/cb119027159', 'http://id.loc.gov/rwo/agents/n50002729', 'http://isni.org/isni/0000000120960218', 'http://viaf.org/viaf/44298691']
    """
    if not isinstance(_ids, list):
        return None
    changed = False
    url = "https://query.wikidata.org/bigdata/namespace/wdq/sparql"
    # Define header according to wikidata's User-Agent policy
    # see: https://meta.wikimedia.org/wiki/User-Agent_policy
    headers = {
            'User-Agent': 'efre-lod-enrich-wikidata-bot/0.1 '
                          '(https://github.com/slub/esmarc) '
                          'python-requests/2.22'
            }

    or_mapping = []
    for _id in _ids:
        for key, value in lookup_table_wdProperty.items():
            if _id.startswith(key):
                or_mapping.append("?item wdt:{Property} \"{value}\"".format(
                    Property=value["property"], value=_id.split(value["delim"])[-1]))
                break

    if or_mapping:
        # BUILD an SPARQL OR Query with an UNION Operator.
        # Still builds an normal query without UNION when or_mapping List only contains one element
        query = '''SELECT DISTINCT ?item \nWHERE {{\n\t{{ {UNION} }}\n}}'''.format(
            UNION="} UNION\n\t\t {".join(or_mapping))
        data = requests.get(url, headers=headers, params={'query': query, 'format': 'json'})
        if data.ok and len(data.json().get("results").get("bindings")) > 0:
            for item in data.json().get("results").get("bindings"):
                rec["sameAs"] = litter(
                    rec["sameAs"], {"@id": item.get("item").get("value"),
                                    "publisher": {
                        "@id": "https://www.wikidata.org/wiki/Q2013",
                        "abbr": "WIKIDATA",
                        "preferredName": "Wikidata"},
                        "isBasedOn": {
                            "@type": "Dataset",
                            "@id": item.get("item").get("value")}})
                changed = True
        elif not data.ok:
            eprint("wikidata: Connection Error {status}: \'{message}\'"
                   .format(status=data.status_code, message=data.content)
                   )
    if changed:
        return rec

def run():
    parser = argparse.ArgumentParser(description='enrich ES by WD!')
    parser.add_argument('-host', type=str, default="127.0.0.1",
                        help='hostname or IP-Address of the ElasticSearch-node to use, default is localhost.')
    parser.add_argument('-port', type=int, default=9200,
                        help='Port of the ElasticSearch-node to use, default is 9200.')
    parser.add_argument('-index', type=str,
                        help='ElasticSearch Search Index to use')
    parser.add_argument('-type', type=str,
                        help='ElasticSearch Search Index Type to use')
    parser.add_argument(
        "-id", type=str, help="retrieve single document (optional)")
    parser.add_argument('-stdin', action="store_true",
                        help="get data from stdin")
    parser.add_argument('-pipeline', action="store_true",
                        help="output every record (even if not enriched) to put this script into a pipeline")
    # no, i don't steal the syntax from esbulk...
    parser.add_argument(
        '-server', type=str, help="use http://host:port/index/type/id?pretty. overwrites host/port/index/id/pretty")
    args = parser.parse_args()
    if args.server:
        slashsplit = args.server.split("/")
        args.host = slashsplit[2].rsplit(":")[0]
        if isint(args.server.split(":")[2].rsplit("/")[0]):
            args.port = args.server.split(":")[2].split("/")[0]
        args.index = args.server.split("/")[3]
        if len(slashsplit) > 4:
            args.type = slashsplit[4]
        if len(slashsplit) > 5:
            if "?pretty" in args.server:
                args.pretty = True
                args.id = slashsplit[5].rsplit("?")[0]
            else:
                args.id = slashsplit[5]
    if args.stdin:
        for line in sys.stdin:
            rec = json.loads(line)
            record = None
            if (rec and isinstance(rec.get("sameAs"), list)
                    and "wikidata.org" not in str(rec["sameAs"])):
                record = get_wdid([x["@id"] for x in rec["sameAs"]], rec)
                if record:
                    rec = record
            if (record or args.pipeline) and rec:
                print(json.dumps(rec, indent=None))
    else:
        body = {"query": {"bool": {"filter": {"bool": {"should": [], "must_not": [
                   {"match": {"sameAs.publisher.abbr.keyword": "WIKIDATA"}}
               ]}}}}}
        for key in lookup_table_wdProperty:
            body["query"]["bool"]["filter"]["bool"]["should"].append(
                {"prefix": {"sameAs.@id.keyword": key}})
        for rec in esgenerator(host=args.host, port=args.port, index=args.index, type=args.type, id=args.id, headless=True, body=body):
            record = None
            if rec.get("sameAs") and isinstance(rec.get("sameAs"), list):
                record = get_wdid([x["@id"] for x in rec["sameAs"]], rec)
                if record:
                    rec = record
            if record or args.pipeline:
                print(json.dumps(rec, indent=None))

if __name__ == "__main__":
    run()


import numpy as np
import random
import argparse
from keras.models import model_from_json, Model
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.optimizers import Adam
import tensorflow as tf
import json

from ReplayBuffer import ReplayBuffer
from ActorNetwork import ActorNetwork
from CriticNetwork import CriticNetwork
from OU import OU
import timeit

from ControlInput import ControlInput
from ControlOutput import ControlOutput
import time #added for code timers

OU = OU()       #Ornstein-Uhlenbeck Process

class AiControlModule():

    BUFFER_SIZE = 100000
    BATCH_SIZE = 1200
    GAMMA = 0.99
    TAU = 0.001     #Target Network HyperParameters
    LRA = 0.0001    #Learning rate for Actor
    LRC = 0.001     #Lerning rate for Critic

    np.random.seed(1337)

    EXPLORE = 100000.
    epsilon = 1 # used for reducing exploration rate over time

    current_state = None
    reward = 0

    def __init__(self, train: bool):
        self._train_indicator = train

        #Tensorflow GPU optimization
        print("Starting TensorFlow")
        config = tf.ConfigProto()
        #config.gpu_options.allow_growth = True
        print("Get TensorFlow Session")
        sess = tf.Session(config=config)
        from keras import backend as K
        print("Starting session")
        K.set_session(sess)

        print("Initializing networks")
        self.actor = ActorNetwork(sess, ControlInput.state_dim, ControlOutput.action_dim, self.BATCH_SIZE, self.TAU, self.LRA)
        self.critic = CriticNetwork(sess, ControlInput.state_dim, ControlOutput.action_dim, self.BATCH_SIZE, self.TAU, self.LRC)
        self.buff = ReplayBuffer(self.BUFFER_SIZE)    #Create replay buffer

        #Now load the weight
        print("Now we load the weight")
        try:
            self.actor.model.load_weights("actormodel.h5")
            self.critic.model.load_weights("criticmodel.h5")
            self.actor.target_model.load_weights("actormodel.h5")
            self.critic.target_model.load_weights("criticmodel.h5")
            print("Weight load successfully")
        except:
            print("Cannot find the weight")

    def initialize_run(self, run: int, control_input: ControlInput):
        self.current_state = np.hstack(control_input.get_states_array())
        self.total_reward = 0.0

    def get_action(self, elapsed_time: float) -> ControlOutput:

        action = np.zeros([1, ControlOutput.action_dim])
        action_noise = np.zeros([1, ControlOutput.action_dim])

        original_action = self.actor.model.predict(self.current_state.reshape(1, self.current_state.shape[0]))

        # Gradually decrease epsilon from 1 to 0 over EXPLORE iterations to reduce exploration rate over time
        self.epsilon -= 1.0 / self.EXPLORE

        # OU function call
        # mu represents the mean value should be 0 as both wheels and sliders vary -1...1
        # theta was defined to have any average speed of reversal to mean
        # sigma volatility is low for wheels (to discourarge sudden acceleration) but high for sliders to encourage exploration
        action_noise[0][0] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][0],  0.0 , 0.50, 0.30)
        action_noise[0][1] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][1],  0.0 , 0.50, 0.30)
        action_noise[0][2] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][2],  0.0 , 0.50, 0.30)
        action_noise[0][3] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][3],  0.0 , 0.50, 0.30)
        action_noise[0][4] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][4],  0.0 , 0.50, 0.30)
        action_noise[0][5] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][5],  0.0 , 0.50, 0.30)
        action_noise[0][6] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][6],  0.0 , 0.50, 0.80)
        action_noise[0][7] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][7],  0.0 , 0.50, 0.80)
        action_noise[0][8] = self._train_indicator * max(self.epsilon, 0) * OU.function(original_action[0][8],  0.0 , 0.50, 0.80)

        action[0][0] = original_action[0][0] + action_noise[0][0]
        action[0][1] = original_action[0][1] + action_noise[0][1]
        action[0][2] = original_action[0][2] + action_noise[0][2]
        action[0][3] = original_action[0][3] + action_noise[0][3]
        action[0][4] = original_action[0][4] + action_noise[0][4]
        action[0][5] = original_action[0][5] + action_noise[0][5]
        action[0][6] = original_action[0][6] + action_noise[0][6]
        action[0][7] = original_action[0][7] + action_noise[0][7]
        action[0][8] = original_action[0][8] + action_noise[0][8]

        output = ControlOutput()
        output.set_actions_array(action)
        return output

    def update_run_results(self, run: int, elapsed_time:float, new_control_state: ControlInput, control_action: ControlOutput, reward: float, terminated: bool):
        #print("updating run results...")
        action = control_action.get_actions_array()
        new_state = np.hstack(new_control_state.get_states_array())
        # previous observation, actions, reward, current observation and whether terminated to buffer
        self.buff.add(self.current_state, action[0], reward, new_state, terminated)      #Add replay buffer
        # set the current state to the new state
        self.current_state = new_state
        # get a random batch of experiences from the buffer, this is a fairly small number
        batch = self.buff.getBatch(self.BATCH_SIZE)
        states = np.asarray([e[0] for e in batch])
        actions = np.asarray([e[1] for e in batch])
        rewards = np.asarray([e[2] for e in batch])
        new_states = np.asarray([e[3] for e in batch])
        dones = np.asarray([e[4] for e in batch])
        # actions from the batch again, this just seeoms to be a cheap trick to initialize array
        corrected_rewards = np.asarray([e[1] for e in batch])

        # get the q values (or rewards) for the batch from the target critic network
        target_q_values = self.critic.target_model.predict([new_states, self.actor.target_model.predict(new_states)])
        for k in range(len(batch)):
            if dones[k]:
                corrected_rewards[k] = rewards[k]
            else:
                # update the corrected_rewards array with the predicted rewards
                # not clear to me why we're adding rewards here rather than some kind of ponderation
                corrected_rewards[k] = rewards[k] + self.GAMMA*target_q_values[k]
        loss = 0
        if (self._train_indicator):
            # train the actual critic model using the updated rewards from the critic target
            # returns the loss = the global error of the critic training, ideally this should
            # be as small as possible
            loss += self.critic.model.train_on_batch([states,actions], corrected_rewards)

            # ask the current actor method for the actions he'd predict for the states
            action_for_grad = self.actor.model.predict(states)

            # get the gradients from the critic
            grads = self.critic.gradients(states, action_for_grad)

            # train the actor using the critic gradients
            self.actor.train(states, grads)

            # train the actor and critic target networks
            self.actor.target_train()

            self.critic.target_train()

        # update the total reward, this isn't actually used for anything per se
        self.total_reward += reward

        #print("Run", run, "Action", action, "Reward", reward, "Loss", loss)

    def finalize_run(self, run: int):
        if np.mod(run, 3) == 0 :
            if (self._train_indicator):
                print("Now we save model")
                self.actor.model.save_weights("actormodel.h5", overwrite=True)
                with open("actormodel.json", "w") as outfile:
                    json.dump(self.actor.model.to_json(), outfile)

                self.critic.model.save_weights("criticmodel.h5", overwrite=True)
                with open("criticmodel.json", "w") as outfile:
                    json.dump(self.critic.model.to_json(), outfile)

        print("TOTAL REWARD @ " + str(run) +"-th Run  : Reward " + str(self.total_reward))
        print("")


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Universal Buzzer to midi
# Doc : http://github.com/pigetArduino/ubuzzer
# Author : Rémi Sarrailh (madnerd.org)
# Licence : MIT

# Arduino communication is completely managed by arduino module
# If connection is lost it will try to reconnect

import rtmidi2
from tkinter import *
import time
from threading import Thread
from functools import partial
import os
from lib import USB

# Change device_name to detect another device
# Device name CH340 is arduino nano clone
# Device type is sent to the arduino and it should answer return_string
# Baudrate : Should be 9600 or 115200
device_name = "CH340"
device_type = "UBuzzer"
device_return_string = "OK"
device_baudrate = 115200

# Bootstrap color for ui
bg_grey = "#f3f3f3"

######################
# Universal Buzzer   #
######################

global lastnote,last_time
lastnote = 0
last_time = 0

midi_to_hz = {
11:31,
12:33,
13:35,
14:37,
15:39,
16:41,
17:44,
18:46,
19:49,
20:52,
21:55,
22:58,
23:62,
24:65,
25:69,
26:73,
27:78,
28:82,
29:87,
30:93,
31:98,
32:104,
33:110,
34:117,
35:123,
36:131,
37:139,
38:147,
39:156,
40:165,
41:175,
42:185,
43:196,
44:208,
45:220,
46:233,
47:247,
48:262,
49:277,
50:294,
51:311,
52:330,
53:349,
54:370,
55:392,
56:415,
57:440,
58:466,
59:494,
60:523,
61:554,
62:587,
63:622,
64:659,
65:698,
66:740,
67:784,
68:831,
69:880,
70:932,
71:988,
72:1047,
73:1109,
74:1175,
75:1245,
76:1319,
77:1397,
78:1480,
79:1568,
80:1661,
81:1760,
82:1865,
83:1976,
84:2093,
85:2217,
86:2349,
87:2489,
88:2637,
89:2794,
90:2960,
91:3136,
92:3322,
93:3520,
94:3729,
95:3951,
96:4186,
97:4435,
98:4699,
98:4978
}

#####################
# GUI Functions     #
#####################
# We use a callback when we quit the application so
# we can correctly close the arduino connection
def quit_callback():
	try:
		usb.close()
	except:
		print("Arduino was not gracefully closed")
	root.destroy()

# This function generate buttons and commands with arguments
# We need to use partial to programatically create the commands

# GUI

# Create interface
root = Tk()
root.title(device_type) #Title
root.geometry("210x50")
root.configure(background=bg_grey) #Background color
root.iconbitmap('ubuzzer.ico') #Icon

# Callback when application is closed
root.protocol("WM_DELETE_WINDOW", quit_callback)

#################
# Buttons Frame #
#################
frame_commands = Frame(root)
frame_commands.grid(row=0)

def midi_callback(message, time_stamp):
    global lastnote,last_time
    note = message[1]
    velocity = message[2]

    if velocity != 0:
        print("ON:  "+str(note) + " " + str(time_stamp))
        midi.config(text=str(note))
        lastnote = note #Send tone
        last_time = time_stamp
        usb.write(str(midi_to_hz[note]))
    if velocity == 0:
        if lastnote == note:
            usb.write("OFF")
            print("OFF: "+str(note) + " " + str(time_stamp))
        else:
            print("DIS OFF: "+str(note) + " " + str(time_stamp) + "  " + str(last_time))

def midi_out_callback(message,time_stamp):
    print(message)

def check_midi():
    midi_in = rtmidi2.MidiInMulti()
    curr_ports = []
    prev_ports = []
    first_loop = True

    while True:
        curr_ports = rtmidi2.get_in_ports()
        if(len(prev_ports) != len(curr_ports)):
            midi_in.close_ports()
            prev_ports = []
            for port in curr_ports:
                if port not in prev_ports and 'Midi Through' not in port and (len(prev_ports) != len(curr_ports)):
                    midi_in.open_ports(port)
                    midi_in.callback = midi_callback
                    if first_loop:
                        print('Opened MIDI port: ' + port)
                    else:
                        print('Reopening MIDI port: ' + port)
        prev_ports = curr_ports
        first_loop = False
        time.sleep(0.2)

MidiThread = Thread(target=check_midi)
MidiThread.daemon = True
MidiThread.start()

#################
# Status Frame  #
#################

frame_status = Frame(root)
frame_status.grid(row=2)
status = Label(frame_status,fg="red",text="Searching...")
status.grid()
midi = Label(frame_status,fg="blue",text="Midi")
midi.grid()

# Search arduino as soon as the gui is created
# We use a thread or the gui will be blocked by the function
# We passed the status label object, you can remove this if you don't want to
usb = USB.Device(device_name,device_type,device_return_string,device_baudrate,status)

# Start application (if something bad happens close arduino connection)
try:
	root.mainloop()
except:
	print("Application was forced to stop")
	try:
		#If something go wrong we try to close the serial connection correctly
		usb.close()
	except:
		print("Arduino Not gracefully closed")


import discord
from datetime import datetime

from hooks.hook_interface import HookInterface, HooksManager
import utilities.regex as regex

@HooksManager.add_hook_handler('on_message_edit')
class OnMessageEditHook(HookInterface):

    def __init__(self, hook, before, after: discord.Message):
        super(OnMessageEditHook, self).__init__(hook)
        self._before = before
        self._after = after
        self._before_filter = hook['before'] if 'before' in hook else None
        self._after_filter = hook['after'] if 'after' in hook else None
        self._namespace = {
            "author": str(after.author),
            "before content": before.content if isinstance(before, discord.Message) else 'UNKNOWN',
            "before attachments": before.attachments if before else None,
            "created at": after.created_at,
            "after content": after.content,
            "after attachments": after.attachments,
            "edited at": after.edited_at,
            'jump url': after.jump_url,
            'author mention': after.author.mention,
            'message id': after.id
        }

    def _calculate_filter(self, filters, message):
        for f_name, args in filters.items():
            if f_name in HooksManager.FILTERS[self.__class__.__name__]:
                if type(args) is not list:
                    args = [args]
                yield HooksManager.FILTERS[self.__class__.__name__][f_name](self, message, *args[0:-1]) ^ args[-1]

    def _filter(self):
        if self._before_filter:
            if self._before:
                before_result = self._calculate_filter(self._before_filter, self._before)
            else:
                before_result = (False,)
        else:
            before_result = (True, )
        if self._after_filter:
            after_result = self._calculate_filter(self._after_filter, self._after)
        else:
            after_result = (True,)

        return all(after_result) and all(before_result)

    @HooksManager.add_filter('contains')
    def contains(self, message: discord.Message, list_of_strings):
        """
        function logic here
        :param discord.Message message:
        :param list[str] list_of_strings:
        :return bool: True if filter is ok otherwise False
        """
        for s in list_of_strings:
            if s in message.content:
                return True
        return False

    @HooksManager.add_filter('roles')
    def has_role(self, message: discord.Message, list_of_roles):
        """

        :param discord.Message message:
        :param list[str] list_of_roles:
        :return bool:
        """
        return any(map(lambda r: str(r.id) in list_of_roles, message.author.roles))

    @HooksManager.add_filter('attachments')
    def has_attachments(self, message):
        return len(message.attachments) > 0 or regex.website_image_regex.findall(self._message.content)

    @HooksManager.add_filter('channels')
    def in_channel(self, message: discord.Message, list_of_channel_ids):
        """

        :param discord.Message message:
        :param list[str] list_of_channel_ids:
        :return bool:
        """
        return str(message.channel.id) in list_of_channel_ids

    @HooksManager.add_filter('author')
    def author(self, message: discord.Message, author_id):
        """
        :param discord.Message message:
        :param list[str] author_id:
        :return bool:
        """
        return str(message.author.id) in author_id

    @HooksManager.add_filter('bot')
    def is_bot(self, message: discord.Message):
        """
        :param discord.Message message:
        :return bool:
        """
        return self._after.author.bot

    @HooksManager.add_action('write_embed')
    async def write_embed(self, channel, embed, footer=None, image=None, thumbnail=None, fields=None):
        """
        :param str channel:
        :param dict embed:
        :param dict footer:
        :param str image:
        :param str thumbnail:
        :param list[dict] fields:
        :return:
        """
        channel = discord.utils.find(lambda c: str(c.id) == channel, self._after.guild.text_channels)
        if channel is None:
            return

        for field, value in embed.copy().items():
            embed[field] = value.format(**self._namespace)

        if 'timestamp' in embed:
            embed['timestamp'] = datetime.strptime(embed['timestamp'], '%Y-%m-%d %H:%M:%S.%f')

        embed = discord.Embed(**embed)
        if footer:
            embed.set_footer(**footer)
        if image:
            embed.set_image(url=image)
        if thumbnail:
            embed.set_thumbnail(url=thumbnail)
        if fields:
            for field in fields:
                embed.add_field(**field)

        await channel.send(embed=embed)

    @HooksManager.add_action('delete_message')
    async def delete_message(self, delay):
        await self._after.delete(delay=delay)

    @HooksManager.add_action('give_roles')
    async def give_roles(self, list_of_role_ids):
        """

        :param list[str] list_of_role_ids:
        :return:
        """
        roles = list(filter(lambda r: r.id in list_of_role_ids and r not in self._after.author.roles, self._after.guild.roles))
        if roles:
            await self._after.author.add_roles(roles)

    @HooksManager.add_action('remove_roles')
    async def give_roles(self, list_of_role_ids):
        """

        :param list[str] list_of_role_ids:
        :return:
        """
        roles = list(filter(lambda r: r.id in list_of_role_ids and r not in self._after.author.roles, self._after.guild.roles))
        if roles:
            await self._after.author.remove_roles(roles)


##Packages######################################
import numpy as np
import string
import pandas  as  pd
import datetime
import pymongo
import json
import requests
from dateutil import parser
import pyelasticsearch
from pyelasticsearch import ElasticSearch
from elasticsearch import Elasticsearch
###################################################

es = Elasticsearch("http://127.0.0.1:9300")    #### Initializing  ElasticSearch instance  with localhost  at port  9300

##############################################################################

############################# Mapping  of  data  to be inserted into elastic search############
######  There  will  be 3  sensors in our  database(index)  "sensor" ,  sensor1, sensor2, sensor3  as  type(tables)
#####   Each sensor  have  3  pairs  of values  - "sensor_value" , "created"(date_format) , "sensor_descr" (description about the sensor)
####    Below  we  defined  the  datatypes  of the above variables  using mapping .
'''
PUT provider2
{
    "mappings": {
        "sensor1": {
            "properties": {

                "sensor_value": {
                    "type": "long"
                },

                "created": {
                    "type": "date",
                    "format": "yyyy-MM-dd HH:mm:ss"
                },

                "sensor_descr": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                }
            }
        }
    }
}

'''

##########################################################################
###############Define  Data to  be inserted  into  3 sensors

def provider_value_insert(provider_name,sensor_1,sensor_2,sensor_3):
    from datetime import datetime, timedelta
    import datetime

    ##### Took 3 dates   , present  ,  previous  , and  day  before  previous  for all  the  three  sensors
    #### removed  microsecound

    todays_date= datetime.datetime.now().replace(microsecond=0)
    yesterdays_date=todays_date.replace(microsecond=0)- timedelta(days=1)
    day_before_yesterday_date=todays_date.replace(microsecond=0)- timedelta(days=2)

    sensor1=pd.DataFrame({"sensor_value":[100,101,102],"created":[todays_date,yesterdays_date,day_before_yesterday_date],"sensor_descr":["first_freq","secnd_freq","third_freq"]})
    sensor2=pd.DataFrame({"sensor_value":[200,201,202],"created":[todays_date,yesterdays_date,day_before_yesterday_date],"sensor_descr":["forth_freq","fifth_freq","sixth_freq"]})
    sensor3=pd.DataFrame({"sensor_value":[300,301,302],"created":[todays_date,yesterdays_date,day_before_yesterday_date],"sensor_descr":["seventh_freq","eight_freq","nine_freq"]})

    ###   Convert all  dataframe   to json  format
    SENSOR1_JSON = sensor1.to_dict(orient='records')
    SENSOR2_JSON = sensor2.to_dict(orient='records')
    SENSOR3_JSON = sensor3.to_dict(orient='records')
    ########################################UPDATE SENSOR1 SENSOR2 SENSOR3 TABLES  ###############################

    def myconverter(o):
        if isinstance(o, datetime.datetime):
            return o.__str__()

    #####################################SENSOR1  UPDATE
    extended_dat = []
    for i in range(sensor1.__len__()):  ###  converting  dict  to  strings
        extended_dat.append(json.dumps(SENSOR1_JSON[i], default=myconverter))

    for item in range(SENSOR1_JSON.__len__()):  ####  dumping  all  data  into  elastic search  .
        req = requests.post('http://localhost:9200/'+provider_name+'/'+sensor_1+'/', data=extended_dat[item])
        print(req.text)

    #####################################SENSOR2  UPDATE
    extended_dat = []
    for i in range(sensor1.__len__()):  ###  converting  dict  to  strings
        extended_dat.append(json.dumps(SENSOR2_JSON[i], default=myconverter))

    for item in range(SENSOR1_JSON.__len__()):  ####  dumping  all  data  into  elastic search  .
        req = requests.post('http://localhost:9200/'+provider_name+'/'+sensor_2+'/', data=extended_dat[item])
        print(req.text)

    #####################################SENSOR3  UPDATE
    extended_dat = []
    for i in range(sensor3.__len__()):  ###  converting  dict  to  strings
        extended_dat.append(json.dumps(SENSOR3_JSON[i], default=myconverter))

    for item in range(SENSOR3_JSON.__len__()):  ####  dumping  all  data  into  elastic search  .
        req = requests.post('http://localhost:9200/'+provider_name+'/'+sensor_3+'/', data=extended_dat[item])
        print(req.text)

######################################### DATA UPDATE  FINISHED ########################

provider_value_insert("provider1","sen1","sen2","sen3")  #### Provider 1

provider_value_insert("provider2","sen4","sen5","sen6")  ###  Provider 2

provider_value_insert("provider3","sen7","sen8","sen9")  ###  Provider 3


from dataclasses import dataclass

@dataclass
class Club:
    """
    This class contains the domain model for a club.
    """

    id: int
    name: str
    total_players: int
    avg_age: float
    total_foreigners: int
    avg_market_value: str
    market_value: str

    def __init__(self, **kwargs):
        self.id = kwargs.get("id")
        self.name = kwargs.get("name")
        self.total_players = kwargs.get("total_players")
        self.avg_age = kwargs.get("avg_age")
        self.total_foreigners = kwargs.get("total_foreigners")
        self.avg_market_value = kwargs.get("avg_market_value")
        self.market_value = kwargs.get("market_value")

    def __repr__(self):
        attribute_value_pairs = [
            f"id={self.id}",
            f"name='{self.name}'",
            f"total_players={self.total_players}",
            f"avg_age={self.avg_age}",
            f"total_foreigners={self.total_foreigners}",
            f"avg_market_value='{self.avg_market_value}'",
            f"market_value='{self.market_value}'",
        ]

        return f"Club({', '.join(attribute_value_pairs)})"


from time import sleep
import io
import base64
from hashlib import md5

from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from scipy import misc

"""
Known bugs:
when the rover gets in a strange position and loses,
after the restart the game restarts automatically again and it causes a timeout
*Could* be fixed in the executor by using the distance between the wheels instead of the x value
to determine the wheels and check if the x-difference is negative
"""

URL = "https://d29zfk7accxxr5.cloudfront.net/games/game-142/data/index.html"

class Game():

    def __init__(self, driver):
        driver = driver.casefold()

        if driver == 'phantomjs':
            # --disk-cache=true allows to keep a cache
            self.driver = webdriver.PhantomJS(
                service_args=['--disk-cache=true'])

        elif driver in ['chrome', 'chrome-headless', 'chromium', 'chromium-headless']:
            # TODO: find option to use custom profile with cache
            chrome_options = ChromeOptions()
            chrome_options.add_argument("--disable-gpu")  # most important line
            chrome_options.add_argument("--disable-extensions")
            if len(driver.split('-')) == 2:
                chrome_options.add_argument("--headless")
            if driver.split('-')[0] == 'chromium':
                chrome_options.binary_location = '/Applications/Chromium.app/Contents/MacOS/Chromium'
            self.driver = webdriver.Chrome(chrome_options=chrome_options)

        elif driver == 'firefox':
            # not working, disable gpu?
            self.driver = webdriver.Firefox()

        self.driver.get(URL)

        # hash of starting screen
        magic = '2979145a2e1a7685c995a8e097276cd1'
        while self.screen_hash() != magic:
            sleep(.1)
            # print(self.screen_hash())

        self._lastcontrols = [0, 0]

        self.driver.switch_to_active_element().send_keys('r')
        self.driver.execute_script('gamee.score = 0')

    def screen(self, file=None):
        """
        Does a screenshot

        returns the screen
        """
        data = self.driver.execute_script(
            "return document.getElementById('canvas').toDataURL()")[22:]
        data = base64.b64decode(data)
        img = misc.imread(io.BytesIO(data))
        misc.imsave('/tmp/mars.png', img)
        return img

    def screen_hash(self):
        """
        return hash of screen
        """
        return md5(bytes(self.screen())).digest().hex()

    def restart(self):
        self.driver.execute_script('gamee.onRestart()')
        self.driver.execute_script('gamee.score = 0')

    def pause(self):
        self.driver.execute_script('gamee.onPause()')

    def mute(self):
        self.driver.execute_script('gamee.onMute()')

    def resume(self):
        self.driver.execute_script('gamee.onResume()')

    def score(self):
        return self.driver.execute_script('return gamee.score')

    def over(self):
        return self.screen_hash() == '3f0371f975116bb1165834d64c4c67b0'

    def control(self, updown, leftright):
        controls = ['keyup', 'keydown']
        command = """
        gamee.controller.trigger("%s", {button : "left"});
        gamee.controller.trigger("%s", {button : "right"});
        gamee.controller.trigger("%s", {button : "down"});
        gamee.controller.trigger("%s", {button : "up"});
        """
        params = (controls[leftright == -1],
                  controls[leftright == 1],
                  controls[updown == -1],
                  controls[updown == 1])
        self.driver.execute_script(command % params)
        self._lastcontrols = [updown, leftright]


import sqlite3
import pprint
from books_publishers import book
from books_publishers import publisher

def execute_query(db_name, query, entry):
    connection = sqlite3.connect(db_name)
    connection_cursor = connection.cursor()
    connection_cursor.execute(query, entry)
    connection.commit()
    connection.close()

def create_table(db_name, query):
    connection = sqlite3.connect(db_name)
    connection_cursor = connection.cursor()
    connection_cursor.execute(query)
    connection.commit()
    connection.close()

def select_data(db_name, query, entry=None):
    if entry is None:
        entry = []
    connection = sqlite3.connect(db_name)
    connection_cursor = connection.cursor()
    connection_cursor.execute(query, entry)
    connection.commit()
    rows = []
    for row in connection_cursor.execute(query, entry):
        rows.append(row)
    pp = pprint.PrettyPrinter()
    pp.pprint(rows)
    connection.close()

db_books = "books.db"
books_table_query = """CREATE TABLE IF NOT EXISTS books (
                                                        book_id integer PRIMARY KEY,
                                                        book_title text,
                                                        author text,
                                                        publish_date date,
                                                        publisher text,
                                                        selling_price numeric
                                                        )"""
publishers_table_query = """CREATE TABLE IF NOT EXISTS publishers (
                                                        publishers_id integer PRIMARY KEY,
                                                        publisher_name text,
                                                        book_title text,
                                                        author text,
                                                        printed_quantity integer,
                                                        printing_price numeric
                                                        )"""

books_publishers_query = """CREATE TABLE IF NOT EXISTS books_publishers(
                                                                book_id int,
                                                                publisher_id int,
                                                                FOREIGN KEY (book_id) REFERENCES books(book_id),
                                                                FOREIGN KEY (publisher_id) REFERENCES publishers(publishers_id)
                                                                )"""

# Insert
def insert_book(book):
    insert_query = """INSERT INTO books (book_title, author, publish_date, publisher, selling_price)
                      VALUES(?, ?, ?, ?, ?)"""
    book = [book.book_title, book.author, book.date, book.publisher, book.selling_price]
    execute_query(db_books, insert_query, book)

def insert_publisher(publisher):
    insert_query = """INSERT INTO publishers (publisher_name, book_title, author, printed_quantity, printing_price)
                      VALUES(?, ?, ?, ?, ?)"""
    publisher = [publisher.publisher_name, publisher.book_title, publisher.author, publisher.printed_quantity,
                 publisher.printing_price]
    execute_query(db_books, insert_query, publisher)

def insert_books_publishers(book_title, publisher_name):
    insert_books_publishers_query = """INSERT INTO books_publishers (book_id, publisher_id)
                                        SELECT(SELECT book_id FROM books WHERE book_title=?),
                                        (SELECT publishers_id FROM publishers WHERE publisher_name=?)"""
    param = (book_title, publisher_name)
    execute_query(db_books, insert_books_publishers_query, param)

# Search
def get_from_books(search_string):
    select_query = """SELECT * FROM books WHERE book_title OR
                                                author OR
                                                publish_date OR
                                                publisher OR
                                                selling_price LIKE ?"""
    title = ['%' + search_string + '%']
    select_data(db_books, select_query, title)

def get_from_publishers(search_string):
    select_query = """SELECT * FROM publishers WHERE publisher_name OR
                                                     book_title OR
                                                     author OR
                                                     printed_quantity OR
                                                     printing_price LIKE ?"""
    title = ['%' + search_string + '%']
    select_data(db_books, select_query, title)

def get_books_publishers():
    select_query = """SELECT * FROM books_publishers """
    select_data(db_books, select_query)

# Update Book methods
def update_book_title(new_value, book_id):
    update_query = """UPDATE books SET book_title = ? WHERE id = ?"""
    update_data = [new_value, book_id]
    execute_query(db_books, update_query, update_data)

def update_book_publisher(new_value, book_id):
    update_query = """UPDATE books SET publisher = ? WHERE id = ?"""
    update_data = [new_value, book_id]
    execute_query(db_books, update_query, update_data)

def update_book_author(new_value, book_id):
    update_query = """UPDATE books SET author = ? WHERE id = ?"""
    update_data = [new_value, book_id]
    execute_query(db_books, update_query, update_data)

def update_book_publish_date(new_value, book_id):
    update_query = """UPDATE books SET publish_date = ? WHERE id = ?"""
    update_data = [new_value, book_id]
    execute_query(db_books, update_query, update_data)

def update_book_selling_price(new_value, book_id):
    update_query = """UPDATE books SET selling_price = ? WHERE id = ?"""
    update_data = [new_value, book_id]
    execute_query(db_books, update_query, update_data)

# Update Publisher methods
def update_publisher_name(new_value, publisher_id):
    update_query = """UPDATE publishers SET publisher_name = ? WHERE id = ?"""
    update_data = [new_value, publisher_id]
    execute_query(db_books, update_query, update_data)

def update_publisher_book_title(new_value, publisher_id):
    update_query = """UPDATE publishers SET book_title = ? WHERE id = ?"""
    update_data = [new_value, publisher_id]
    execute_query(db_books, update_query, update_data)

def update_publisher_author(new_value, publisher_id):
    update_query = """UPDATE publishers SET author = ? WHERE id = ?"""
    update_data = [new_value, publisher_id]
    execute_query(db_books, update_query, update_data)

def update_publisher_printed_quantity(new_value, publisher_id):
    update_query = """UPDATE publishers SET printed_quantity = ? WHERE id = ?"""
    update_data = [new_value, publisher_id]
    execute_query(db_books, update_query, update_data)

def update_publisher_printing_price(new_value, publisher_id):
    update_query = """UPDATE publishers SET printing_price = ? WHERE id = ?"""
    update_data = [new_value, publisher_id]
    execute_query(db_books, update_query, update_data)

# Delete
def delete_book_by_id(book_id):
    delete_query = """DELETE FROM books WHERE id = ?"""
    entry_id = [book_id]
    execute_query(db_books, delete_query, entry_id)

def delete_publisher_by_id(publisher_id):
    delete_query = """DELETE FROM publishers WHERE id = ?"""
    entry_id = [publisher_id]
    execute_query(db_books, delete_query, entry_id)

def get_quantity_price():
    select_query = """SELECT (publishers.printed_quantity * SUM(books.selling_price - publishers.printing_price)) AS rez
                        FROM books
                        INNER JOIN publishers ON books.book_title = publishers.book_title"""
    select_data(db_books, select_query)

create_table(db_books, books_table_query)
create_table(db_books, publishers_table_query)
create_table(db_books, books_publishers_query)
#insert_book('Zigmas po dangum', 'Janionis', 1998, 'Alma Litera', 25)
#insert_publisher('Alma litera', 'Zigmas po dangum', 'Janionis', 100, 10)
# get_from_books('Zigm')
# get_from_publishers('Alm')
# get_quantity_price()
book = book.book(0, "knygos pavadinimas", "Autorius", 2019, "Alma litera", 31)
insert_book(book)

publisher = publisher.publisher(0, "Vaga", "Pavadinimas", "Janionis Julius", 1234, 3)
insert_publisher(publisher)
insert_books_publishers('knygos pavadinimas', 'Vaga')
select_data(db_books, "SELECT * FROM books")
select_data(db_books, "SELECT * FROM publishers")
get_books_publishers()


import pygame
import sys

# Initialize Pygame
pygame.init()

# Set up some constants
WIDTH, HEIGHT = 800, 600
BACKGROUND_SPEED = 2

# Create the screen
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# Load the background image (add your image file path)
background = pygame.image.load("./img/dark-yellow2-road.png")

# This is to make sure the image fits in the screen. You can skip this if your image size matches the screen size
background = pygame.transform.scale(background, (WIDTH, HEIGHT))

# Initial position of the background
y = 0

# Game loop
running = True
while running:
    # Event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Move the background
    y += BACKGROUND_SPEED
    if y >= HEIGHT:
        y = 0

    # Draw the background twice to create the continuous scrolling effect
    screen.blit(background, (0, y))
    screen.blit(background, (0, y - HEIGHT))

    # Update the display
    pygame.display.flip()

# Quit Pygame
pygame.quit()
sys.exit()


from fastapi import APIRouter, Depends, File, UploadFile
from sqlalchemy.orm import Session
import shutil
import uuid
from celery import Celery

from config import BROKER_URL, RESULT_BACKEND_URL
from database import get_db
from src.db.repository import get_hash

celery = Celery(
    'worker',
    broker=BROKER_URL,
    backend=RESULT_BACKEND_URL
)

router = APIRouter()

@router.post("/")
def upload_file(file: UploadFile = File(...)):
    id = uuid.uuid4()

    try:
        with open(f'data/{id}', "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
    finally:
        file.file.close()

    celery.send_task('tasks.hash_file', kwargs={'id': id})

    return {"id": id}

@router.get("/{file_id}")
def get_file_hash(id: str, db: Session = Depends(get_db)):
    return get_hash(db, id)


import scipy.stats
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

cmap = plt.get_cmap("viridis")

def plot_gp_samples(ax, xs, ys, **kwargs):
    ax.plot(xs, ys.squeeze(), **kwargs)
    ax.set_xlabel("Font size")
    ax.set_ylabel("Reading speed (seconds per word)")

def render_gp(ax, xs, gp):

    norm = scipy.stats.norm(0, 1)
    if len(xs.shape)==1:
        xs = xs[:, None]
    y_pred, y_std = gp.predict(xs, return_std=True)

    y_pred = y_pred.squeeze()

    ax.plot(xs, y_pred, c="k")
    for contour in np.linspace(0, 0.5, 50):
        k1 = norm.ppf(contour)
        k2 = norm.ppf(1 - contour)

        upper = y_pred + y_std * k1 * 2
        lower = y_pred + y_std * k2 * 2
        ax.fill_between(xs[:,0], upper, lower, color=cmap(norm.pdf(k1)))

    ys  = gp.sample_y(xs, 20)
    plot_gp_samples(ax, xs[:,0], ys, c='w', alpha=0.1)

def pi(y_pred, y_std):

    y_pred = y_pred.squeeze()
    best = max(y_pred)
    # calculate the probability of improvement
    return scipy.stats.norm(0, 1).cdf((y_pred - best) / (y_std + 1e-7))

def ei(y_pred, y_std, xi=0):
    y_pred = y_pred.squeeze()
    norm = scipy.stats.norm(0, 1)
    best = max(y_pred)
    Z = (y_pred - best - xi) / (y_std + 1e-9)
    # calculate the expected improvement
    return norm.cdf(Z) * (y_pred - best - xi) + y_std * norm.pdf(Z)

def ei(mu, std, xi=0):
    mu = mu.squeeze()
    std = std.squeeze()
    values = np.zeros_like(mu)
    mask = std > 0
    y_opt = max(mu)
    improve = y_opt - xi - mu[mask]
    scaled = improve / std[mask]
    cdf = scipy.stats.norm.cdf(scaled)
    pdf = scipy.stats.norm.pdf(scaled)
    exploit = improve * cdf
    explore = std[mask] * pdf
    values[mask] = exploit + explore
    return -values

def lcb(y_pred, y_std, kappa=1):
    return y_pred.squeeze() - kappa * y_std.squeeze() + np.random.normal(0, 1e-6, y_pred.shape[0])

def ucb(y_pred, y_std, kappa=1):
    return y_pred.squeeze() + kappa * y_std.squeeze() + np.random.normal(0, 1e-6, y_pred.shape[0])

from skopt.learning.gaussian_process import GaussianProcessRegressor
from skopt.learning.gaussian_process.kernels import (
    RBF,
    ConstantKernel,
    WhiteKernel,
    Matern,
)

Day 1 - Bayesian Inference/examples/gp_utils.py


from django.conf import settings as s

class Settings:
    _defaults = {
        "subject": "Your order ID {order.invoice_id}",
        "from_address": "orders@example.com",
        "template_html": None,
        "template_text": None,
        "copy_address": None,
    }

    def __getattr__(self, attr):
        if attr not in self._defaults:
            raise KeyError(attr)
        return getattr(
            s, "LORIKEET_EMAIL_INVOICE_" + attr.upper(), self._defaults[attr]
        )

    @property
    def copy_address(self):
        return getattr(s, "LORIKEET_EMAIL_INVOICE_COPY_ADDRESS", None)

settings = Settings()
__all__ = ["settings"]


import solution
import utils

class TRAN(solution.SimpleWriteSolution):

    def _read(self, f):
        return utils.read_fasta(f, dna_only=True)

    def solve(self, data):
        transitions = 0
        transversions = 0

        s1, s2 = data

        for c1, c2 in zip(s1, s2):
            if c1 == c2:
                continue

            if (c1 in utils.PURINES) ^ (c2 in utils.PURINES):
                transversions += 1
            else:
                transitions += 1

        return transitions * 1. / transversions


from brownie import Vote,test_try,config,network
from scripts.helpfulscripts import getAccounts
from scripts.helpfulscripts import update_front_end
# add publish
def deploys(frontend_update=True):
    account=getAccounts()
    Vote.deploy({"from":account},publish_source=config["networks"][network.show_active()]["verified"])
    if(frontend_update):
        update_front_end()
    print("deployed")

def test():
    acc=getAccounts()
    Vote[-1].addCandidate("bjp",{"from":acc})
    Vote[-1].addCandidate("cpim",{"from":acc})
    Vote[-1].addVoter(getAccounts(index=0),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=1),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=2),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=3),{"from":acc})
    Vote[-1].startVote(120,{"from":acc})

    Vote[-1].voteCandidate(0,{"from":getAccounts(index=0)})
    Vote[-1].voteCandidate(0,{"from":getAccounts(index=1)})
    Vote[-1].voteCandidate(0,{"from":getAccounts(index=2)})
    Vote[-1].voteCandidate(1,{"from":getAccounts(index=3)})

    print("winner")

    print(Vote[-1].getCandidateArray({"from":acc}))
    print(Vote[-1].total_voters({"from":acc}))

def test2():
    acc=getAccounts()
    Vote[-1].addCandidate("bjp",{"from":acc})
    Vote[-1].addCandidate("cpim",{"from":acc})
    Vote[-1].addVoter(getAccounts(index=0),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=1),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=2),{"from":acc})
    Vote[-1].addVoter(getAccounts(index=3),{"from":acc})
    Vote[-1].startVote(600,{"from":acc})
    print("done set up")

def deploy_test():
    acc=getAccounts(index=2)
    v=test_try.deploy({"from":acc})
    print(v.win({"from":acc}))
    tx=v.Increase({"from":acc})
    tx.wait(1)
    print(v.win({"from":acc}))

def main():
    deploys()
    # test2()
    # deploy_test()


import os,sys, math
import torch
import numpy                    as np
import torchvision.transforms   as transforms

root_dir     = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

def get_data_loaders(dataset, batch_size, num_workers, model, valid = 0.0):

    image_size = 227
    train_transform   = transforms.Compose([transforms.ToTensor(),
                        transforms.Normalize(   mean=(0., 0., 0.),
                                                 std=(1./255., 1./255., 1./255.)
                                             ),
                        transforms.Normalize(   mean=(104, 116.668, 122.678),
                                                std=(1., 1., 1.)
                                            )
                        ])

    test_transform   = transforms.Compose([transforms.ToTensor(),
                        transforms.Normalize(   mean=(0., 0., 0.),
                                                 std=(1./255., 1./255., 1./255.)
                                             ),
                        transforms.Normalize(   mean=(104, 116.668, 122.678),
                                                std=(1., 1., 1.)
                                            )
                        ])

    if dataset == "pascal":
        csv_train = os.path.join(root_dir, 'data/pascal3d_train.csv')
        csv_test  = os.path.join(root_dir, 'data/pascal3d_valid.csv')

        train_set = pascal3d(csv_train, dataset_root= dataset_root, transform = train_transform, im_size = image_size)
        test_set  = pascal3d(csv_test,  dataset_root= dataset_root, transform = test_transform,  im_size = image_size)
    else:
        print("Error in load_datasets: Dataset name not defined.")

    # Generate validation dataset
    if valid > 0.0:
        valid_set   = train_set.generate_validation(valid)

    # Generate data loaders
    train_loader = torch.utils.data.DataLoader( dataset=train_set,
                                                batch_size=batch_size,
                                                shuffle=True,
                                                num_workers=num_workers,
                                                drop_last = True)

    test_loader  = torch.utils.data.DataLoader( dataset=test_set,
                                                batch_size=batch_size,
                                                num_workers=num_workers,
                                                drop_last = False)

    if valid > 0.0:
        print("Generated Validation Dataset - size : ", valid_set.num_instances)
        valid_loader = torch.utils.data.DataLoader( dataset     = valid_set,
                                                    batch_size  = batch_size,
                                                    shuffle     = False,
                                                    pin_memory  = True,
                                                    num_workers = num_workers,
                                                    drop_last = False)
    else:
        valid_loader = None

    return train_loader, valid_loader, test_loader


import sys
import math
from collections import deque
from itertools import permutations

input = sys.stdin.readline

def bfs():
    start_idx = int(input()) - 1
    dq = deque()
    dq.append(start_idx)
    visited = [False] * N

    while len(dq) != 0:
        cur_idx = dq.popleft()
        if visited[cur_idx]:
            continue
        visited[cur_idx] = True
        move_range = li[cur_idx]
        for d in [-move_range, move_range]:
            next_idx = cur_idx + d
            if 0<= next_idx < N and not visited[next_idx]:
                dq.append(next_idx)
    ans = 0
    for i in visited:
        if i:
            ans += 1
    return ans

N = int(input())
li = list(map(int, input().split()))

print(bfs())