import logging
import re
from collections import namedtuple
from urllib.parse import urljoin

from scrapy import Request, Spider, signals
from scrapy.utils.request import request_fingerprint
from warcio.warcwriter import WARCWriter

from .utils import resource_matches_base_url, write_warc_request_response

Resource = namedtuple("Resource", ["name", "type", "link_type", "content"])
REGEXP_CSS_URL = re.compile(r"""url\(['"]?(.*?)['"]?\)""")

Extractor = namedtuple("Extractor", ["name", "type", "link_type", "xpath"])
EXTRACTORS = [
    # Media (images, video etc.)
    Extractor(name="media", type="link", link_type="dependency", xpath="//img/@src"),
    Extractor(name="media", type="link", link_type="dependency", xpath="//audio/@src"),
    Extractor(name="media", type="link", link_type="dependency", xpath="//video/@src"),
    Extractor(name="media", type="link", link_type="dependency", xpath="//source/@src"),
    Extractor(name="media", type="link", link_type="dependency", xpath="//embed/@src"),
    Extractor(
        name="media", type="link", link_type="dependency", xpath="//object/@data"
    ),
    # CSS
    Extractor(
        name="css",
        type="link",
        link_type="dependency",
        xpath="//link[@rel = 'stylesheet']/@href",
    ),
    Extractor(name="css", type="code", link_type="dependency", xpath="//style/text()"),
    Extractor(name="css", type="code", link_type="dependency", xpath="//*/@style"),
    # JavaScript
    Extractor(name="js", type="link", link_type="dependency", xpath="//script/@src"),
    Extractor(name="js", type="code", link_type="dependency", xpath="//script/text()"),
    # TODO: add "javascript:XXX" on //a/@href etc.
    # TODO: add inline JS (onload, onchange, onclick etc.)
    # Internal/external links and iframes
    # TODO: iframe sources must be considered as if they were the same as the
    # current page being archived (same depth, get all dependencies etc.).
    Extractor(name="other", type="link", link_type="anchor", xpath="//iframe/@src"),
    Extractor(name="other", type="link", link_type="anchor", xpath="//a/@href"),
    Extractor(name="other", type="link", link_type="anchor", xpath="//area/@href"),
    Extractor(
        name="other",
        type="link",
        link_type="anchor",
        xpath="//link[not(@rel = 'stylesheet')]/@href",
    ),
    # TODO: link rel=icon should be considered a dependency (what about other
    # link rel=xxx?)
    # TODO: add all other "//link/@href"
]

def extract_resources(response):
    for extractor in EXTRACTORS:
        for content in response.xpath(extractor.xpath).extract():
            yield Resource(
                name=extractor.name,
                type=extractor.type,
                link_type=extractor.link_type,
                content=content,
            )

class CrauSpider(Spider):

    name = "crawler-spider"
    custom_settings = {
        "CONCURRENT_REQUESTS": 256,
        "CONCURRENT_REQUESTS_PER_DOMAIN": 16,
        "DNSCACHE_ENABLED": True,
        "DNSCACHE_SIZE": 500000,
        "DNS_TIMEOUT": 5,
        "DOWNLOAD_MAXSIZE": 5 * 1024 * 1024,
        "DOWNLOAD_TIMEOUT": 15,
        "REACTOR_THREADPOOL_MAXSIZE": 40,
        "REDIRECT_ENABLED": False,
        "SCHEDULER_PRIORITY_QUEUE": "scrapy.pqueues.DownloaderAwarePriorityQueue",
        "SPIDER_MIDDLEWARES_BASE": {
            "scrapy.spidermiddlewares.httperror.HttpErrorMiddleware": 50,
            "scrapy.spidermiddlewares.offsite.OffsiteMiddleware": 500,
            "scrapy.spidermiddlewares.referer.RefererMiddleware": 700,
            "scrapy.spidermiddlewares.urllength.UrlLengthMiddleware": 800,
        },
    }

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super().from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        return spider

    def __init__(self, warc_filename, urls, max_depth=1, allowed_uris=None):
        super().__init__()
        self.max_depth = int(max_depth)
        self.warc_filename = warc_filename
        self.urls = urls
        self._request_history = set()
        self.warc_fobj = None
        self.warc_writer = None
        self.allowed_uris = allowed_uris if allowed_uris else []

    def spider_closed(self, spider):
        if self.warc_fobj is not None:
            self.warc_fobj.close()

    def make_request(self, request_class=Request, *args, **kwargs):
        """Method to create requests and implements a custom dedup filter"""

        kwargs["dont_filter"] = kwargs.get("dont_filter", True)
        kwargs["errback"] = kwargs.get("errback", self.parse_request_error)

        meta = kwargs.get("meta", {})
        meta["handle_httpstatus_all"] = meta.get("handle_httpstatus_all", True)
        meta["dont_redirect"] = meta.get("dont_redirect", True)
        kwargs["meta"] = meta

        request = request_class(*args, **kwargs)
        if "#" in request.url:
            request = request.replace(url=request.url[: request.url.find("#")])

        # This `if` filters duplicated requests - we don't use scrapy's dedup
        # filter because it has a bug, which filters out requests in undesired
        # cases <https://github.com/scrapy/scrapy/issues/1225>.
        # TODO: check if this dedup filter does not have the same problem
        # scrapy have (the problem is related to canonicalize request url).
        request_hash = request_fingerprint(request)
        # TODO: may move this in-memory set to a temp file since the number of
        # requests can be pretty large.
        if request_hash in self._request_history:
            return None
        else:
            self._request_history.add(request_hash)
            return request

    def write_warc(self, response):
        # TODO: transform this method into `write_response` so we can have
        # other response writers than WARC (CSV, for example - would be great
        # if we can add specific parsers to save HTML's title and text into
        # CSV, for example).
        write_warc_request_response(self.warc_writer, response)

    def start_requests(self):
        """Start requests with depth = 0

        depth will be 0 for all primary URLs and all requisites (CSS, Images
        and JS) of these URLs. For links found on these URLs, depth will be
        incremented, and so on.
        """
        self.warc_fobj = open(self.warc_filename, mode="wb")
        self.warc_writer = WARCWriter(self.warc_fobj, gzip=True)

        for url in self.urls:
            yield self.make_request(
                url=url, meta={"depth": 0, "main_url": url}, callback=self.parse
            )

    def parse(self, response):
        main_url = response.request.url
        # TODO: what if response.request.url != response.url?
        current_depth = response.request.meta["depth"]
        next_depth = current_depth + 1

        content_type = response.headers.get("Content-Type", b"").decode(
            "ascii"
        )  # TODO: decode properly
        if content_type and content_type.split(";")[0].lower() != "text/html":
            logging.debug(
                f"[{current_depth}] Content-Type not found for {main_url}, parsing as media"
            )
            yield self.parse_media(response)
            return

        logging.debug(f"[{current_depth}] Saving HTML {response.request.url}")
        self.write_warc(response)

        redirect_url = None
        if 300 <= response.status <= 399 and "Location" in response.headers:
            redirect_url = urljoin(
                response.request.url,
                response.headers["Location"].decode("ascii"),  # TODO: decode properly
            )

        for resource in extract_resources(response):
            if resource.type == "link":
                # TODO: handle "//" URLs correctly
                absolute_url = urljoin(main_url, resource.content)
                depth = None
                if resource.link_type == "dependency":
                    depth = current_depth
                elif resource.link_type == "anchor":
                    depth = next_depth
                for request in self.collect_link(
                    main_url, resource.name, absolute_url, depth
                ):
                    if request is None or (
                        redirect_url is not None and redirect_url == request.url
                    ):
                        continue
                    elif (
                        self.allowed_uris
                        and resource.link_type == "anchor"
                        and not resource_matches_base_url(
                            absolute_url, self.allowed_uris
                        )
                    ):
                        logging.info(f"Different domain. Skipping {absolute_url}.")
                        continue
                    yield request

            elif resource.type == "code":
                for request in self.collect_code(
                    main_url, resource.name, resource.content, current_depth
                ):
                    if request is None:
                        continue
                    yield request

        if redirect_url is not None:
            # TODO: how to deal with redirect loops?
            logging.debug(f"[{current_depth}] Redirecting to {redirect_url}")
            yield self.make_request(
                url=redirect_url,
                meta={"depth": current_depth, "main_url": main_url},
                callback=self.parse,
            )

    def parse_request_error(self, failure):
        pass
        # TODO: should we do something with this failure?

    def parse_css(self, response):
        meta = response.request.meta

        for request in self.collect_code(
            response.request.url, "css", response.body, meta["depth"]
        ):
            if request is None:
                continue
            yield request

        logging.debug(f"Saving CSS {response.request.url}")
        self.write_warc(response)

    def parse_js(self, response):
        meta = response.request.meta

        for request in self.collect_code(
            response.request.url, "js", response.body, meta["depth"]
        ):
            if request is None:
                continue
            yield request

        logging.debug(f"Saving JS {response.request.url}")
        self.write_warc(response)

    def parse_media(self, response):
        logging.debug(f"Saving MEDIA {response.request.url}")
        self.write_warc(response)

    def collect_link(self, main_url, link_type, url, depth):
        if depth > self.max_depth:
            logging.debug(
                f"[{depth}] IGNORING (depth exceeded) get link {link_type} {url}"
            )
            return []
        elif not url.startswith("http"):
            logging.debug(f"[{depth}] IGNORING (not HTTP) get link {link_type} {url}")
            return []

        if link_type == "media":
            return [
                self.make_request(
                    url=url,
                    callback=self.parse_media,
                    meta={"depth": depth, "main_url": main_url},
                )
            ]
        elif link_type == "css":
            return [
                self.make_request(
                    url=url,
                    callback=self.parse_css,
                    meta={"depth": depth, "main_url": main_url},
                )
            ]
        elif link_type == "js":
            return [
                self.make_request(
                    url=url,
                    callback=self.parse_js,
                    meta={"depth": depth, "main_url": main_url},
                )
            ]
        elif link_type == "other":
            return [
                self.make_request(
                    url=url,
                    callback=self.parse,
                    meta={"depth": depth, "main_url": main_url},
                )
            ]
        else:
            return [
                self.make_request(
                    url=url,
                    callback=self.parse,
                    meta={"depth": depth, "main_url": main_url},
                )
            ]

    def collect_code(self, main_url, code_type, code, depth):
        if depth > self.max_depth:
            logging.debug(
                f"[{depth}] IGNORING (depth exceeded) getting dependencies for {code_type}"
            )
            return []
        elif code_type == "css":
            if isinstance(code, bytes):
                code = code.decode("utf-8")  # TODO: decode properly
            requests = []
            for result in REGEXP_CSS_URL.findall(code):
                url = urljoin(main_url, result)
                if url.startswith("data:"):
                    continue
                requests.append(
                    self.make_request(
                        url=url,
                        callback=self.parse_media,
                        meta={"depth": depth, "main_url": main_url},
                    )
                )
            return requests
        elif code_type == "js":
            # TODO: extract other references from JS code
            return []
        else:
            logging.info(f"[{depth}] [TODO] PARSE CODE {code_type} {code}")
            return []
            # TODO: change


"""Define the Separable Covariance Function

Author:
    Ilias Bilionis

Date:
    11/20/2012

"""

__all__ = ['SeparableCovarianceFunction']

import numpy as np
import itertools as iter
from . import CovarianceFunction

class SeparableCovarianceFunction(CovarianceFunction):

    """A Separable Covariance Function."""

    # A tuple of covariance functions
    _cov = None

    @property
    def cov(self):
        """Return covariance."""
        return self._cov

    @cov.setter
    def cov(self, value):
        """Set the covariance functions."""
        if not isinstance(value, tuple):
            raise TypeError('value must be a tuple.')
        for c in value:
            if not isinstance(c, CovarianceFunction):
                raise TypeError(
                    'value is not a tuple of covariance functions.')
        self._cov = value

    def __init__(self, cov=None, name='SeparableCovarianceFunction'):
        """Initialize the object.

        Keyword Arguments:
        cov     ---     A tuple of covariance functions

        """
        super(SeparableCovarianceFunction, self).__init__(name=name)
        if cov is not None:
            self.cov = cov

    def _check_if_tuple(self, x, var_name):
        """Check if x is a tuple of the right length"""
        if not isinstance(x, tuple):
            raise TypeError(var_name +
                    ' must be a tuple.')
        if not len(x) == len(self.cov):
            raise TypeError(var_name +
                    ' must have the same number of components as the number'
                    + ' of covariance functions.')

    def __call__(self, hyp, x1, x2=None, A=None):
        """Evaluate the covariance function."""
        self._check_if_tuple(hyp, 'hyp')
        self._check_if_tuple(x1, 'x1')
        if x2 is None:
            x2 = ()
            for _ in xrange(len(self.cov)):
                x2 += (None, )
        else:
            self._check_if_tuple(x2, 'x2')
        if A is None:
            A = ()
            for c, chyp, cx1, cx2 in iter.izip(self.cov, hyp, x1, x2):
                A += (c(chyp, cx1, cx2), )
            return A
        else:
            self._check_if_tuple(A, 'A')
            for c, chyp, cx1, cx2, cA in iter.izip(self.cov, hyp, x1, x2, A):
                c(chyp, cx1, cx2, cA)

    def __str__(self):
        """Return a string representation of the object."""
        s = super(SeparableCovarianceFunction, self).__str__()
        for c in self.cov:
            s += '\n' + str(c)
        return s


from itertools import groupby
from typing import List, Tuple

from hwt.hdl.statements.assignmentContainer import HdlAssignmentContainer
from hwt.hdl.operator import Operator, isConst
from hwt.hdl.operatorDefs import AllOps
from hwt.serializer.utils import RtlSignal_sort_key
from hwtGraph.elk.containers.constants import PortType, PortSide
from hwtGraph.elk.containers.lNode import LNode

class InterfaceSplitInfo(tuple):
    pass

def extractSplitsAsSingleNode(root: LNode, sliceParts: List[Tuple[slice, HdlAssignmentContainer, LNode]], toL: dict):
        # replace multiple index nodes with a larger slice node
    sliceParts.sort(key=lambda x: x[0].start)
    n = toL[sliceParts[0][1]]
    p = n.west[0]
    if not p.incomingEdges:
        # was already replaced
        return

    srcPorts = p.incomingEdges[0].srcs
    assert len(srcPorts) == 1
    srcPort = srcPorts[0]

    dstPortsOnInputNet = list(p.incomingEdges[0].dsts)
    sliceNode = root.addNode(
        name="SLICE", cls="Operator",
        originObj=InterfaceSplitInfo(x[1] for x in sliceParts))
    inputPort = sliceNode.addPort(
        "", PortType.INPUT, PortSide.WEST)

    # create new sliceNode
    for sliceRange, _, oldAssigNode in sliceParts:
        # create a new port on main slice node which will be used instead of this operator
        if sliceRange.start - sliceRange.stop == 1:
            portName = f"[{sliceRange.stop:d}]"
        else:
            portName = f"[{sliceRange.start:d}:{sliceRange.stop:d}]"
        outPort = sliceNode.addPort(
            portName, PortType.OUTPUT, PortSide.EAST)

        # disconnect and replace the index and assignment node itself
        assert root is oldAssigNode.parent
        dstPortsOnInputNet.remove(oldAssigNode.west[0])
        for e in list(oldAssigNode.west[0].incomingEdges):
            e.remove()

        dstPorts = []
        # this assignment of slice is directly in the root
        for e in list(oldAssigNode.east[0].outgoingEdges):
            for _dst in e.dsts:
                dstPorts.append((_dst, e.originObj))
            e.remove()

        oldAssigNode.parent.children.remove(oldAssigNode)
        # remove index value node (we know that it is constant,
        # from original select)
        _e = oldAssigNode.west[1].incomingEdges[0]
        _e.removeTarget(oldAssigNode.west[1])
        assert len(_e.srcs) == 1
        indexValNodeP = _e.srcs[0]
        if not _e.dsts:
            _e.remove()

        if not indexValNodeP.outgoingEdges:
            root.children.remove(indexValNodeP.parentNode)

        root.addHyperEdge([outPort],
                          [dst[0] for dst in dstPorts],
                          originObj=dstPorts[0][1])

    dstPortsOnInputNet.append(inputPort)
    root.addHyperEdge([srcPort, ], dstPortsOnInputNet,
                      name=e.name, originObj=e.originObj)

def extractSplits(root: LNode):
    """
    convert group of indexed assignments witch are splitting signal to Split node

    a = sig[0]
    b = sig[1]
    to
    a, b = sig

    :param toL: dictionary {hdl object: layout object}
    """
    toL = root._node2lnode
    signals = sorted(root.originObj._ctx.signals, key=RtlSignal_sort_key)

    # search from "sig" side (look at doc string)
    for s in signals:
        if len(s.drivers) == 1 and len(s.endpoints) > 1:
            sliceParts = []
            for ep in s.endpoints:
                if isinstance(ep, HdlAssignmentContainer) and not ep.indexes and ep.src.hidden:
                    op = ep.src.origin
                else:
                    op = ep

                if isinstance(op, Operator)\
                        and op.operator == AllOps.INDEX\
                        and op.operands[0] is s:
                    index = op.operands[1]
                    if isConst(index):
                        sliceRange = index.staticEval().to_py()
                        if isinstance(sliceRange, int):
                            sliceRange = slice(sliceRange + 1, sliceRange)

                        if ep not in toL:
                            continue
                        sliceParts.append((sliceRange, ep, toL[ep]))

            for _root, _sliceParts in groupby(sliceParts, lambda x: x[2].parent):
                # the slices may be spoted in some sub node, in that case we need to extract it only in this sub node
                _sliceParts = list(_sliceParts)
                if _sliceParts:
                    extractSplitsAsSingleNode(_root, _sliceParts, toL)


import argparse
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sys

from statsmodels.tsa.seasonal import seasonal_decompose

def parse_opt() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument('--house', type=str, default='3', help='house id')
    parser.add_argument('--plot_type', type=str, default='normal',
                        help='possible values: normal, histogram, box-plot, pearson, violin, decompose')
    parser.add_argument('--interval', type=str, default='month', help='show the seasonality on specific interval')
    parser.add_argument('--show_plot', default=True, action='store_true', help='flag for showing the plot or not')
    parser.add_argument('--save_plot', default=True, action='store_true', help='flag of storing the plot or not')
    return parser.parse_args()

def box_plot_seasonality(df: pd.DataFrame, args: argparse.Namespace) -> None:
    interval = args.interval
    if interval == 'month':
        df['month'] = df.index.month
    elif interval == 'week':
        df['week'] = df.index.day_of_week + 1
    else:
        df['hour'] = df.index.hour + 1

    fig, ax = plt.subplots(figsize=(7, 3.5))
    df.boxplot(column='IMPORT_KW', by=interval, ax=ax, )
    df.groupby(interval)['IMPORT_KW'].median().plot(style='o-', linewidth=0.8, ax=ax)
    ax.set_ylabel('Consumption')
    ax.set_title('Consumption distribution by {}'.format(interval))
    fig.suptitle('')
    if args.show_plot:
        plt.show()
    if args.save_plot:
        fig.savefig(r'../plots/time_series_analysis/consumption_distribution_by_{}.png'.format(interval))
        plt.close()

def consumption_on_holidays(df: pd.DataFrame, args: argparse.Namespace) -> None:
    df = df.assign(HOLIDAY=df.HOLIDAY.astype(str))
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(7, 3.5))
    sns.violinplot(
        x='IMPORT_KW',
        y='HOLIDAY',
        data=df,
        palette='tab10',
        ax=ax
    )
    ax.set_title('Distribution of consumption between holidays and non-holidays')
    ax.set_xlabel('Demand')
    ax.set_ylabel('Holiday')
    if args.show_plot:
        plt.show()
    if args.save_plot:
        fig.savefig(r'../plots/time_series_analysis/consumption_on_holidays.png')
        plt.close()

def correlation_check(df: pd.DataFrame, args: argparse.Namespace) -> None:
    """
    Plots a Pearson Correlation Heatmap.
    ---
    Args:
        df (pd.DataFrame): dataframe to plot
        args (argparse.Namespace): resolving input arguments

    Returns: None
    """
    # Figure
    fig, ax = plt.subplots(figsize=(16, 12), facecolor='w')
    correlations_df = df.corr(method='pearson', min_periods=1)
    sns.heatmap(correlations_df, cmap="Blues", annot=True, linewidth=.1)

    # Labels
    ax.set_title("Pearson Correlation Heatmap", fontsize=15, pad=10)
    ax.set_facecolor(color='white')
    if args.show_plot:
        plt.show()
    if args.save_plot:
        fig.savefig(r'../plots/time_series_analysis/pearson_correlation_heatmap.png')
        plt.close()

def decompose_series(df: pd.DataFrame) -> None:
    """
    This function decomposes the time series
    into trend, seasonality and residuals.
    ---
    Args:
        df (pd.DataFrame): Dataframe that contains the timeseries data

    Returns: None
    """
    df = df.resample('D').sum()
    # Decomposition
    decomposition = seasonal_decompose(df['IMPORT_KW'])
    decomposition.plot()

    plt.tight_layout()
    plt.show()

def histogram(df: pd.DataFrame):
    df.hist(bins=50, column='IMPORT_KW')
    plt.show()

def plot_house_data(df: pd.DataFrame, args: argparse.Namespace) -> None:
    house_df = df.resample('D').sum()
    house_df.reset_index(inplace=True)
    house_df.plot.line(x='timestamp', y=['IMPORT_KW'], title='Consumption')
    # Add legend
    plt.legend()
    # Auto space
    plt.tight_layout()
    # Display plot
    if args.show_plot:
        plt.show()
    # if args.save_plot:
    #     plt.savefig(r'plots/aggregated_train.png')
    #     plt.close()

def main():
    # Load input arguments
    args = parse_opt()
    df = pd.read_csv(r'../../data/house_data_cleaned/house{}.csv'.format(args.house), parse_dates=['timestamp'],
                     index_col='timestamp')
    df.drop(columns=['EXPORT_KW', 'PV_KW', 'BATTERY_KW', 'IX'], inplace=True)
    plot_type = args.plot_type
    if plot_type == 'normal':
        plot_house_data(df, args)
    elif plot_type == 'histogram':
        histogram(df)
    elif plot_type == 'box-plot':
        box_plot_seasonality(df, args)
    elif plot_type == 'pearson':
        correlation_check(df, args)
    elif plot_type == 'violin':
        consumption_on_holidays(df, args)
    elif plot_type == 'decompose':
        decompose_series(df)
    else:
        print('Unknown plot type')

if __name__ == '__main__':
    sys.exit(main())


from openvino.inference_engine import IENetwork, IECore
import numpy as np
import sys
import os
import cv2

class InferenceModel:
    def __init__(self, device='MYRIAD'):
        #self.ie = IECore()
        self.device = device

    def create_exec_infer_model(self, model_dir, labels, num_requests=2):

        model_xml = os.path.join(model_dir, 'frozen_inference_graph.xml')
        model_bin = os.path.join(model_dir, 'frozen_inference_graph.bin')
        exported_model = os.path.join(model_dir, 'exported_model')

        assert os.path.isfile(model_bin)
        assert os.path.isfile(model_xml)

        ie = IECore()
        net = IENetwork(model=model_xml, weights=model_bin)

        # return ExecInferModel()

        img_info_input_blob = None
        feed_dict = {}
        for blob_name in net.inputs:
            if len(net.inputs[blob_name].shape) == 4:
                input_blob = blob_name
            elif len(net.inputs[blob_name].shape) == 2:
                img_info_input_blob = blob_name
            else:
                raise RuntimeError("Unsupported {}D input layer '{}'. Only 2D and 4D input layers are supported"
                                   .format(len(net.inputs[blob_name].shape), blob_name))

        assert len(
            net.outputs) == 1, "Demo supports only single output topologies"
        out_blob = next(iter(net.outputs))

        if os.path.isfile(exported_model):  # found exported mode
            print('found model to import')
            exec_net = ie.import_network(
                model_file=exported_model, device_name=self.device)
        else:
            print('creating exec model')
            exec_net = ie.load_network(
                network=net, num_requests=num_requests, device_name=self.device)
            exec_net.export(exported_model)

        n, c, h, w = net.inputs[input_blob].shape
        if img_info_input_blob:
            feed_dict[img_info_input_blob] = [h, w, 1]

        del net
        del ie

        return ExecInferModel(exec_net, input_blob, out_blob, feed_dict, n, c, h, w, num_requests, labels)

class ExecInferModel:
    def __init__(self, exec_net, input_blob, out_blob, feed_dict, n, c, h, w, num_requests, labels):
        self.exec_net = exec_net
        self.labels = labels
        self.input_blob = input_blob
        self.out_blob = out_blob
        self.feed_dict = feed_dict
        self.n = n
        self.c = c
        self.h = h
        self.w = w
        self.num_requests = num_requests
        self.current_frames = {}
        self.detected_objects = {}

    def infer_image(self, image, threshhold=0.7):
        height, width = image.shape[:2]
        in_frame = cv2.resize(image, (self.w, self.h))
        in_frame = in_frame.transpose((2, 0, 1))
        in_frame = in_frame.reshape(
            (self.n, self.c, self.h, self.w))

        self.feed_dict[self.input_blob] = in_frame
        self.exec_net.start_async(
            request_id=0, inputs=self.feed_dict)

        if self.exec_net.requests[0].wait(-1) == 0:
            res = self.exec_net.requests[0].outputs[self.out_blob]

            for obj in res[0][0]:
                if obj[2] > threshhold:
                    xmin = int(obj[3] * width)
                    ymin = int(obj[4] * height)
                    xmax = int(obj[5] * width)
                    ymax = int(obj[6] * height)

                    class_id = int(obj[1])
                    color = (0, 255, 255)
                    cv2.rectangle(image, (xmin, ymin),
                                  (xmax, ymax), color, 2)

                    if self.labels:
                        det_label = self.labels[class_id-1]
                    else:
                        det_label = 'class id ' + str(class_id)
                    cv2.putText(image, det_label + ' ' + str(round(obj[2] * 100, 1)) + ' %', (xmin, ymin - 7),
                                cv2.FONT_HERSHEY_COMPLEX, 0.6, color, 1)
        return image


import time

import flask
import json
import base64
import pandas as pd

from io import StringIO
from flask import Response, request
from Algorithm.SVM_Wavelet import train_model, make_prediction
from flask_cors import CORS

application = flask.Flask(__name__)
CORS(application)

trained = False

@application.route("/trainModel", methods=["POST"])
def train():
    if request.json is None:
        # Expect application/json request
        response = Response("Empty request", status=415)
    else:
        try:
            request_content = json.loads(request.data)
            message = request_content

            print("Training - JSON content ", message)

            data = message['data']
            csv_decoded = base64.b64decode(data).decode('utf-8')
            df = pd.read_csv(StringIO(csv_decoded, newline=''), delimiter=',')

            closing_prices = df['closing_price'].values.tolist()
            dates = df['dates'].values.tolist()

            #print("Closing prices: ", closing_prices)
            #print("Dates: ", dates)
            y_pred, y_test, dates_p = train_model(closing_prices=closing_prices, dates=dates)
            global trained
            trained = True
            service_response = {'Predicted_values': y_pred.tolist(), 'Real_values': y_test, 'Dates': dates_p}
            #response = Response("Trained", 200)
            response = Response(json.dumps(service_response, default=str).encode('UTF-8'), 200)
        except Exception as ex:
            print(ex)
            response = Response("Error processing", 500)

    return response

@application.route("/predict", methods=["POST"])
def predict():
    global trained
    if request.json is None:
        # Expect application/json request
        response = Response("Empty request", status=415)
    else:
        try:
            if trained:
                request_content = json.loads(request.data)
                message = request_content
                days_to_predict = message["days_to_predict"]
                print("Predict - JSON content ", message)

                y_pred, _dates = make_prediction(prediction_days=days_to_predict)
                #y_pred = sc_y.inverse_transform(y_pred.reshape(1, -1)).ravel()
                print("Prediction: ", y_pred)
                print("Dates: ", _dates)
                service_response = {'Predicted_values': y_pred.tolist(), 'Dates': _dates.tolist()}
                response = Response(json.dumps(service_response, default=str).encode('UTF-8'), 200)
            else:
                response = Response("Call the training model method first", 405)
        except Exception as ex:
            print(ex)
            response = Response("Error processing", 500)

    return response

if __name__ == "__main__":
    application.run(host="0.0.0.0", threaded=True)


# import gdkeji
import caizhengbu
# import fagaiwei
# import gdshangwu
# import guowuyuan
# import kejibu
import xlwt
import os

#创建文件夹
def mkdir(path):
    folder = os.path.exists(path)
    if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
        os.makedirs(path)  # makedirs 创建文件时如果路径不存在会创建这个路径
        print("---  new folder...  ---")
        print("---  OK  ---")

    else:
        print("---  There is this folder!  ---")

if __name__ == '__main__':
    #创建文件夹调用
    file = "/home/260199/政府政策公告信息/超链接"
    mkdir(file)  # 调用函数

    workbook = xlwt.Workbook()
    caizhengbu.main(workbook)
    workbook.save("/home/260199/政府政策公告信息/政府政策公告.xlsx")


from flask import Flask, render_template, Response
import cv2

app = Flask(__name__)

# Load the pre-trained Haar Cascade face detection model
face_cascade = cv2.CascadeClassifier(
    cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# OpenCV video capture object
cap = cv2.VideoCapture(0)

# Define route for homepage
@app.route('/')
def index():
    return render_template('index.html')

# Define route for video feed
@app.route('/video_feed')
def video_feed():
    def gen():
        while True:
            # Read a frame from the video stream
            success, frame = cap.read()

            # If a frame was successfully read, detect faces in the frame and draw rectangles around them
            if success:
                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1,
                                                      minNeighbors=5)
                for (x, y, w, h) in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

                # Encode the frame as a jpeg image and yield it
                ret, jpeg = cv2.imencode('.jpg', frame)
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + jpeg.tobytes() + b'\r\n')
            else:
                break

    # Use the Response class to stream video frames back to the web app
    return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(debug=True)


"""buggy URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from pushers import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.rolls, name='rolls'),
    url(r'^login$', views.login_view, name='login'),
    # Roll day urls
    url(r'^rolls/create_roll_day$', views.create_roll_day, name='create_roll_day'),
    url(r'^rolls/(?P<r_id>[0-9]+)/edit_active_pushers$', views.edit_active_pushers, name='edit_active_pushers'),
    url(r'^rolls/(?P<r_id>[0-9]+)/activate_pusher/(?P<p_id>[0-9]+)$', views.activate_pusher, name='activate_pusher'),
    url(r'^rolls/(?P<r_id>[0-9]+)/deactivate_pusher/(?P<p_id>[0-9]+)$', views.deactivate_pusher, name='deactivate_pusher'),

    # Roll urls
    url(r'^rolls/(?P<r_id>[0-9]+)/create_roll$', views.create_roll, name='create_roll'),
    url(r'^rolls/edit_roll/(?P<r_id>[0-9]+)$', views.edit_roll, name='edit_roll'),

    # Pusher urls
    url(r'^pushers$', views.pushers, name='pushers'),
    url(r'^create_pusher$', views.create_pusher, name='create_pusher'),
    url(r'^delete_pusher/(?P<p_id>[0-9]+)$', views.delete_pusher, name='delete_pusher'),

    # Buggy urls
    url(r'^buggies$', views.buggies, name='buggies'),
    url(r'^create_buggy$', views.create_buggy, name='create_buggy'),
    url(r'^delete_buggy/(?P<b_id>[0-9]+)$', views.delete_buggy, name='delete_buggy'),
]


import random
import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in

import pygame
import myparameters
import pygame_menu
from pygame.locals import (
    RLEACCEL,
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    K_SPACE,
    KEYDOWN,
    QUIT,
)

SCREEN_HEIGHT = myparameters.SCREEN_HEIGHT
SCREEN_WIDTH = myparameters.SCREEN_WIDTH
PLAY_HEIGHT = myparameters.PLAY_HEIGHT
PLAY_WIDTH = myparameters.PLAY_WIDTH

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.tag = 'player'
        self.surf = pygame.Surface((64, 64))
        self.surf.fill((255, 255, 255))
        self.surf = pygame.image.load("asset/player_up.png").convert()
        self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.rect = self.surf.get_rect(center=(PLAY_WIDTH/2 , PLAY_HEIGHT/2))
        self.level_up_sound = pygame.mixer.Sound("asset/chime_up.wav")
        self.direction = 1
        self.speed = 5
        self.Strength=5
        self.Agility=5
        self.Vigor=5
        self.Intellect=5
        self.Wisdom=5
        self.HP = 50
        self.max_HP = 10*self.Vigor
        self.Mana = 50
        self.max_Mana = 10 * self.Wisdom
        self.STR_exp = 0
        self.STR_exp_required = 100*self.Strength
        self.AGI_exp = 0
        self.AGI_exp_required = 100 * self.Agility
        self.VIG_exp = 0
        self.VIG_exp_required = 100 * self.Vigor
        self.INT_exp = 0
        self.INT_exp_required = 100 * self.Intellect
        self.WIS_exp = 0
        self.WIS_exp_required = 100 * self.Wisdom
        self.move_x = 0
        self.move_y = 0
        self.equiped_weapon = 'Iron Sword'
        self.equiped_armor = 'Leather Armor'
        self.equiped_fire = 'firebolt'
        self.equiped_lighting = 'lightingbolt'
        self.equiped_ice = 'iceball'
        self.defense = 0
        self.equiped_armor_defense = 5
        self.current_weapon_cooldown = 333
        self.regen_counter =0
    def regen(self):
        if self.regen_counter>=120:
            if self.Mana< self.max_Mana:
                self.Mana += round(self.max_Mana*0.02)
            if self.HP < self.max_HP:
                self.HP += round(self.max_HP * 0.01+0.01)
            self.regen_counter=0
        self.regen_counter += 1
    def update(self, pressed_keys,slow_factor):
        if pressed_keys[K_UP] and pressed_keys[K_LEFT] == False and pressed_keys[K_RIGHT] == False:
            self.direction = 1  # up
            if self.direction == 1:
                self.move_y = -self.speed+slow_factor
                #self.rect.move_ip(0, -self.speed+slow_factor)
            self.surf = pygame.image.load("asset/player_up.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if pressed_keys[K_DOWN] and pressed_keys[K_LEFT] == False and pressed_keys[K_RIGHT] == False:
            self.direction = 2  # down
            if self.direction == 2:
                self.move_y =  +self.speed-slow_factor
                #self.rect.move_ip(0, self.speed-slow_factor)
            self.surf = pygame.image.load("asset/player_down.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if pressed_keys[K_LEFT] and pressed_keys[K_UP] == False and pressed_keys[K_DOWN] == False:
            self.direction = 3  # left
            if self.direction == 3:
                self.move_x =  -self.speed+slow_factor
                #self.rect.move_ip(-self.speed+slow_factor, 0)
            self.surf = pygame.image.load("asset/player_left.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if pressed_keys[K_RIGHT] and pressed_keys[K_UP] == False and pressed_keys[K_DOWN] == False:
            self.direction = 4  # right
            if self.direction == 4:
                self.move_x = + self.speed - slow_factor
                #self.rect.move_ip(self.speed-slow_factor, 0)
            self.surf = pygame.image.load("asset/player_right.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > PLAY_WIDTH:
            self.rect.right = PLAY_WIDTH
        if self.rect.top <= 0:
            self.rect.top = 0
        if self.rect.bottom >= PLAY_HEIGHT:
            self.rect.bottom = PLAY_HEIGHT

class Tile(pygame.sprite.Sprite):
    def __init__(self, chosen_tile, x, y):
        super(Tile, self).__init__()
        self.surf = pygame.Surface((32, 32))
        self.rect = self.surf.get_rect(topleft=(x, y))
        self.surf.blit(chosen_tile, (0,0))

class Tileset:
    def __init__(self, file_path):
        super(Tileset, self).__init__()
        self.surf = pygame.Surface((32, 32))
        self.tiles = []
        self.image = pygame.image.load(file_path)
        self.rect = self.image.get_rect()
        self.load()

    def load(self):
        for x in range(0, self.rect.right, 32):
            for y in range(0, self.rect.bottom, 32):
                tile = pygame.Surface((32,32))
                tile.blit(self.image, (0,0), (y, x, 32,32))
                self.tiles.append(tile)

class Tilemap:
    def __init__(self, rel_path ,tileset_path, map_id, all_sprites, ob_tiles, slow_tiles , new_map_tiles,prev_map_tiles):
        super(Tilemap, self).__init__()
        abs_file_path = os.path.join(script_dir, rel_path)
        with open(abs_file_path) as f:
            map_input = [[int(num) for num in line.split(',')] for line in f]
        self.size = (len(map_input[0])*32, len(map_input)*32)
        self.surf = pygame.Surface(self.size)
        self.surf.fill((50,60,70))
        self.rect = self.surf.get_rect()
        self.map = map_input
        self.map_id=map_id
        self.tileset=Tileset(tileset_path)
        self.tiles=self.tileset.tiles
        for i in range(len(self.map)):
            for j in range(len(self.map[0])):
                new_tile = Tile(self.tiles[self.map[i][j]], j * 32, i * 32)
                #screen.blit(new_tile.surf, (j * 32 , i * 32))
                self.surf.blit(new_tile.surf, (j * 32, i * 32))
                if map_id == 'Tomb_entrance':
                    if self.map[i][j] <=1 or self.map[i][j] >=3 and self.map[i][j]<=13 :  # brick tile
                        ob_tiles.add(new_tile)
                        all_sprites.add(new_tile)
                    if self.map[i][j] == 14 or self.map[i][j] == 15:
                        new_map_tiles.add(new_tile)
                        all_sprites.add(new_tile)
                if map_id == 'Tomb_L1' or map_id == 'Tomb_L2' or map_id == 'Tomb_L3' or map_id == 'Tomb_L4':
                    if self.map[i][j] >=3:  # brick tile
                        ob_tiles.add(new_tile)
                        all_sprites.add(new_tile)
                    if self.map[i][j] == 1:
                        prev_map_tiles.add(new_tile)
                        all_sprites.add(new_tile)
                    if self.map[i][j] == 2:
                        new_map_tiles.add(new_tile)
                        all_sprites.add(new_tile)

                elif self.map[i][j] == 1:  # grass tile
                    slow_tiles.add(new_tile)
                    all_sprites.add(new_tile)

"""
Enemy
"""

class Skeleton(pygame.sprite.Sprite):
    def __init__(self,enemy_type, map_size):
        super(Skeleton, self).__init__()
        self.enemy_kill_sound= pygame.mixer.Sound("asset/floop2_x.wav")
        if enemy_type=='skeleton_normal':
            self.tag = 'skeleton_normal'
            self.speed = 3
            self.Strength = 5
            self.Agility = 2
            self.Vigor = 2
            self.Intellect = 0
            self.Wisdom = 0
            self.HP = 50
            self.max_HP = 50
            self.defense = 5
            self.direction = 2  # 1up 2down 3left 4right
            self.exp_points = 100
            self.img_x=40
            self.img_y=40
            self.img_surf = pygame.image.load(f"asset/{self.tag}_down.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if enemy_type=='skeleton_archer':
            self.tag = 'skeleton_archer'
            self.speed = 3
            self.Strength = 5
            self.Agility = 2
            self.Vigor = 2
            self.Intellect = 0
            self.Wisdom = 0
            self.HP = 75
            self.max_HP = 75
            self.defense = 5
            self.direction = 2  # 1up 2down 3left 4right
            self.exp_points = 200
            self.img_x=40
            self.img_y=40
            self.img_surf = pygame.image.load(f"asset/{self.tag}_down.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if enemy_type=='skeleton_warrior':
            self.tag = 'skeleton_warrior'
            self.speed = 5
            self.Strength = 5
            self.Agility = 2
            self.Vigor = 5
            self.Intellect = 0
            self.Wisdom = 0
            self.HP = 300
            self.max_HP = 300
            self.defense = 15
            self.direction = 2  # 1up 2down 3left 4right
            self.exp_points = 500
            self.img_x=60
            self.img_y=60
            self.img_surf = pygame.image.load(f"asset/{self.tag}_down.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if enemy_type=='skeleton_mage':
            self.tag = 'skeleton_mage'
            self.speed = 4
            self.Strength = 5
            self.Agility = 2
            self.Vigor = 3
            self.Intellect = 5
            self.Wisdom = 0
            self.HP = 200
            self.max_HP = 200
            self.defense = 10
            self.direction = 2  # 1up 2down 3left 4right
            self.exp_points = 400
            self.img_x=40
            self.img_y=40
            self.img_surf = pygame.image.load(f"asset/{self.tag}_down.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if enemy_type=='skeleton_boss':
            self.tag = 'skeleton_boss'
            self.speed = 3
            self.Strength = 50
            self.Agility = 20
            self.Vigor = 20
            self.Intellect = 0
            self.Wisdom = 0
            self.HP = 3000
            self.max_HP = 3000
            self.defense = 15
            self.direction = 2  # 1up 2down 3left 4right
            self.exp_points = 1500
            self.img_x=120
            self.img_y=120
            self.img_surf = pygame.image.load("asset/skeleton_boss_down.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.steps = 0
        self.max_step = random.randint(200,400)
        self.img_surf = pygame.Surface((self.img_x, self.img_y))
        #self.img_surf.fill((255, 255, 255))
        self.surf=pygame.Surface((self.img_x, self.img_y+10))
        self.HP_bar=Floating_bar(self.img_x)
        self.surf.blit(self.img_surf, (0,0))
        self.surf.blit(self.HP_bar.surf, (0,self.img_y+5))
        self.rect = self.img_surf.get_rect(
            center=(
                random.randint(40, map_size[0] - 40),
                random.randint(40, map_size[1] - 40),
            )
        )

    def enemy_fire(entity, enemy_bullets, all_sprites):
        if entity.tag == 'skeleton_archer':
            x = (entity.rect.left + entity.rect.right) / 2
            y = (entity.rect.top + entity.rect.bottom) / 2
            new_enemy_bullet = Bullet(x, y, entity.direction, entity.tag)
            enemy_bullets.add(new_enemy_bullet)
            all_sprites.add(new_enemy_bullet)
        if entity.tag == 'skeleton_mage':
            x = (entity.rect.left + entity.rect.right) / 2
            y = (entity.rect.top + entity.rect.bottom) / 2
            new_enemy_bullet = Bullet(x, y, entity.direction, entity.tag)
            enemy_bullets.add(new_enemy_bullet)
            all_sprites.add(new_enemy_bullet)

    def update(self, dir_int, player, collide = False):
        x_dist = abs(self.rect.centerx - player.rect.centerx)
        y_dist = abs(self.rect.centery - player.rect.centery)
        if collide == True and x_dist>y_dist:
            x_dist=0  # change direction when hit wall
        if collide == True and y_dist>x_dist:
            y_dist=0

        if self.rect.centerx>player.rect.centerx and x_dist>y_dist:
            dir_int=3
        elif self.rect.centerx<player.rect.centerx and x_dist>y_dist:
            dir_int=4
        elif self.rect.centery>player.rect.centery:
            dir_int=1
        elif self.rect.centery<player.rect.centery:
            dir_int=2
        if self.steps < self.max_step:
            if self.direction == 1:
                self.rect.move_ip(0, -self.speed)
            if self.direction == 2:
                self.rect.move_ip(0, self.speed)
            if self.direction == 3:
                self.rect.move_ip(-self.speed, 0)
            if self.direction == 4:
                self.rect.move_ip(self.speed, 0)
            self.steps = self.steps + self.speed

        elif self.steps >= self.max_step:
            self.direction = dir_int
            if self.direction == 0:
                self.rect.move_ip(0, 0)
            if self.direction == 1:
                self.rect.move_ip(0, -self.speed)
            if self.direction == 2:
                self.rect.move_ip(0, self.speed)
            if self.direction == 3:
                self.rect.move_ip(-self.speed, 0)
            if self.direction == 4:
                self.rect.move_ip(self.speed, 0)
            self.steps = 0

        if self.direction == 2:
            self.img_surf = pygame.image.load(f'asset/{self.tag}_down.png').convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if self.direction == 1:
            self.img_surf = pygame.image.load(f"asset/{self.tag}_up.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if self.direction == 4:
            self.img_surf = pygame.image.load(f"asset/{self.tag}_right.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        if self.direction == 3:
            self.img_surf = pygame.image.load(f"asset/{self.tag}_left.png").convert()
            self.img_surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.surf.blit(self.img_surf, (0, 0))
        self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.surf.blit(self.HP_bar.surf, (0,self.img_y+5))
        self.HP_bar.update(self)
"""
weapon
"""

class Sword(pygame.sprite.Sprite):
    def __init__(self, x, y, direction,user_size, sword_name):
        super(Sword, self).__init__()
        if direction == 1:
            self.surf = pygame.Surface((64, 10))
            self.surf = pygame.image.load("asset/sword_light_up.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 2:
            self.surf = pygame.Surface((64, 10))
            self.surf = pygame.image.load("asset/sword_light_down.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 3 :
            self.surf = pygame.Surface((10, 64))
            self.surf = pygame.image.load("asset/sword_light_left.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 4 :
            self.surf = pygame.Surface((10, 64))
            self.surf = pygame.image.load("asset/sowrd_light_right.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if direction == 1:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2, y - user_size[1]/2 -25))
        if direction == 2:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2, y + user_size[1]/2 + 15))
        if direction == 3:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2 - 25, y - user_size[1]/2))
        if direction == 4:
            self.rect = self.surf.get_rect(topleft=(x + user_size[0]/2 + 15, y - user_size[1]/2))
        self.lifecycle = 5
        self.life_counter=0
        self.direction = direction
        self.shoot_sound= pygame.mixer.Sound("asset/swing.flac")
        self.collide_sound = pygame.mixer.Sound("asset/swing.flac")
        if sword_name == 'Iron Sword':
            self.min_attack = 3
            self.max_attack = 6
            self.tag = 'Iron Sword'
        if sword_name == 'Steel Sword':
            self.min_attack = 8
            self.max_attack = 12
            self.tag = 'Steel Sword'

    def update(self):
        self.life_counter += 1
        if self.life_counter>=self.lifecycle:
            self.kill()

class Greatsword(pygame.sprite.Sprite):
    def __init__(self, x, y, direction,user_size, sword_name):
        super(Greatsword, self).__init__()
        if direction == 1:
            self.surf = pygame.Surface((96, 32))
            self.surf = pygame.image.load("asset/greatsword_light_up.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 2:
            self.surf = pygame.Surface((96, 32))
            self.surf = pygame.image.load("asset/greatsword_light_down.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 3 :
            self.surf = pygame.Surface((32, 96))
            self.surf = pygame.image.load("asset/greatsword_light_left.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 4 :
            self.surf = pygame.Surface((32, 96))
            self.surf = pygame.image.load("asset/greatsword_light_right.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if direction == 1:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2, y - user_size[1]/2 -35))
        if direction == 2:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2, y + user_size[1]/2 + 25))
        if direction == 3:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0]/2 - 35, y - user_size[1]/2))
        if direction == 4:
            self.rect = self.surf.get_rect(topleft=(x + user_size[0]/2 + 25, y - user_size[1]/2))
        self.lifecycle = 5
        self.life_counter=0
        self.direction = direction
        self.shoot_sound= pygame.mixer.Sound("asset/swing.flac")
        self.collide_sound = pygame.mixer.Sound("asset/swing.flac")
        if sword_name == 'Claymore':
            self.min_attack = 12
            self.max_attack = 20
            self.defense =0
            self.tag = 'Claymore'

class Spear(pygame.sprite.Sprite):
    def __init__(self, x, y, direction, user_size, sword_name):
        super(Spear, self).__init__()
        if direction == 1:
            self.surf = pygame.Surface((16, 96))
            self.surf = pygame.image.load("asset/spear_light_up.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 2:
            self.surf = pygame.Surface((16, 96))
            self.surf = pygame.image.load("asset/spear_light_down.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 3:
            self.surf = pygame.Surface((96, 16))
            self.surf = pygame.image.load("asset/spear_light_left.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if direction == 4:
            self.surf = pygame.Surface((96, 16))
            self.surf = pygame.image.load("asset/spear_light_right.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)

        if direction == 1:
            self.rect = self.surf.get_rect(topleft=(x - 8, y - user_size[1] / 2 - 106))
        if direction == 2:
            self.rect = self.surf.get_rect(topleft=(x - 8, y + user_size[1] / 2 + 10))
        if direction == 3:
            self.rect = self.surf.get_rect(topleft=(x - user_size[0] / 2 - 106, y - 8))
        if direction == 4:
            self.rect = self.surf.get_rect(topleft=(x + user_size[0] / 2 + 10, y - 8))
        self.lifecycle = 5
        self.life_counter = 0
        self.direction = direction
        self.shoot_sound = pygame.mixer.Sound("asset/swing.flac")
        self.collide_sound = pygame.mixer.Sound("asset/swing.flac")
        if sword_name == 'Iron Spear':
            self.min_attack = 16
            self.max_attack = 24
            self.defense = 0
            self.tag = 'Iron Spear'

    def update(self):
        self.life_counter += 1
        if self.life_counter>=self.lifecycle:
            self.kill()

class Bar(pygame.sprite.Sprite):
    def __init__(self, bar_type, screen):
        super(Bar, self).__init__()
        self.surf = pygame.Surface((150, 10))
        if bar_type == 'HP':
            self.bar_len=150
            self.surf = pygame.Surface((self.bar_len, 10))
            self.surf.fill((255,0,0))
        if bar_type == 'Mana':
            self.bar_len = 150
            self.surf = pygame.Surface((self.bar_len, 10))
            self.surf.fill((0,0,255))
        if bar_type == 'STR' or bar_type == 'AGI' or bar_type == 'AGI' or bar_type == 'VIG' or bar_type == 'INT' or bar_type == 'WIS':
            self.bar_len = 50
            self.surf = pygame.Surface((100, 10))
            self.surf.fill((0, 255, 255))

        self.tag=bar_type

        #fill border
        self.surf.fill((255, 255, 255), (0, 0, self.bar_len, 1))
        self.surf.fill((255, 255, 255), (0, 9, self.bar_len, 1))
        self.surf.fill((255, 255, 255), (0, 0, 1, 10))
        self.surf.fill((255, 255, 255), (self.bar_len-1, 0, 1, 10))

        #blit to screen
        if bar_type == 'HP':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-180, 40))
        if bar_type == 'Mana':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-180, 80))
        if bar_type == 'STR':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 105))
        if bar_type == 'AGI':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 135))
        if bar_type == 'VIG':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 165))
        if bar_type == 'INT':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 195))
        if bar_type == 'WIS':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 225))

    def update(self, player, screen):
        self.surf.fill((0, 0, 0))
        if self.tag == 'HP':
            x=round(player.HP/player.max_HP*self.bar_len)
            self.surf.fill((255, 0, 0), (0,0,x,10))
        if self.tag == 'Mana':
            x=round(player.Mana/player.max_Mana*self.bar_len)
            self.surf.fill((0, 0, 255), (0,0,x,10))
        if self.tag == 'STR':
            x=round(player.STR_exp/player.STR_exp_required*self.bar_len)
            self.surf.fill((0, 255, 255), (0,0,x,10))
        if self.tag == 'AGI':
            x=round(player.AGI_exp/player.AGI_exp_required*self.bar_len)
            self.surf.fill((0, 255, 255), (0,0,x,10))
        if self.tag == 'VIG':
            x=round(player.VIG_exp/player.VIG_exp_required*self.bar_len)
            self.surf.fill((0, 255, 255), (0,0,x,10))
        if self.tag == 'INT':
            x=round(player.INT_exp/player.INT_exp_required*self.bar_len)
            self.surf.fill((0, 255, 255), (0,0,x,10))
        if self.tag == 'WIS':
            x=round(player.WIS_exp/player.WIS_exp_required*self.bar_len)
            self.surf.fill((0, 255, 255), (0,0,x,10))
        # fill border
        self.surf.fill((255, 255, 255), (0, 0, self.bar_len, 1))
        self.surf.fill((255, 255, 255), (0, 9, self.bar_len, 1))
        self.surf.fill((255, 255, 255), (0, 0, 1, 10))
        self.surf.fill((255, 255, 255), (self.bar_len-1, 0, 1, 10))
        if self.tag == 'HP':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-180, 40))
        if self.tag == 'Mana':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-180, 80))
        if self.tag == 'STR':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 105))
        if self.tag == 'AGI':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 135))
        if self.tag == 'VIG':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 165))
        if self.tag == 'INT':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 195))
        if self.tag == 'WIS':
            screen.blit(self.surf, (myparameters.SCREEN_WIDTH-100, 225))

class Floating_bar(pygame.sprite.Sprite):
    def __init__(self, width):
        super(Floating_bar, self).__init__()
        self.surf = pygame.Surface((width, 6))
        self.surf.fill((255,0,0))
        self.width=width
        #fill border
        self.surf.fill((255, 255, 255), (0, 0, self.width, 1))
        self.surf.fill((255, 255, 255), (0, 4 , self.width, 1))
        self.surf.fill((255, 255, 255), (0, 0, 1, 6))
        self.surf.fill((255, 255, 255), (self.width-1, 0, 1, 6))

        #blit to screen
        #screen.blit(self.surf, entity.rect.leftbottom)

    def update(self, entity):
        self.surf.fill((0, 0, 0))
        x=round(entity.HP/entity.max_HP*self.width)
        self.surf.fill((255, 0, 0), (0,0,x,6))
        # fill border
        self.surf.fill((255, 255, 255), (0, 0, self.width, 1))
        self.surf.fill((255, 255, 255), (0, 4, self.width, 1))
        self.surf.fill((255, 255, 255), (0, 0, 1, 6))
        self.surf.fill((255, 255, 255), (self.width - 1, 0, 1, 6))
        #screen.blit(self.surf, screen.blit(self.surf, entity.rect.leftbottom))

class Dmg_txt(pygame.sprite.Sprite):
    def __init__(self, content, x, y, screen):
        super(Dmg_txt, self).__init__()
        font = pygame.font.Font('asset/Roboto-Black.ttf', 18)
        self.text = font.render(content, True, (255, 0, 0), (0, 0, 0))
        self.text.set_colorkey((0, 0, 0), RLEACCEL)
        self.rect=self.text.get_rect(center=(x, y))
        screen.blit(self.text, self.rect)
        self.timer = 0

    def update(self,screen):
        self.rect.move_ip(0,-1)
        if self.timer <= 30:
            screen.blit(self.text, self.rect)
        else:
            self.kill()
        self.timer +=1

"""
bullet
"""

class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, direction, bullet_type):
        super(Bullet, self).__init__()
        self.surf = pygame.Surface((1, 1))
        if bullet_type=='firebolt':
            self.surf = pygame.Surface((20, 20))
            self.surf = pygame.image.load("asset/firebolt.png").convert()
            self.tag = bullet_type
            self.speed = 20
            self.Mana_cost = 5
            self.mgk_dmg_fctr=5
            self.mgk_base_dmg = 25
        if bullet_type=='fireball':
            self.surf = pygame.Surface((40, 40))
            self.surf = pygame.image.load("asset/weapon_icon.png").convert()
            self.tag = bullet_type
            self.speed = 20
            self.Mana_cost = 20
            self.mgk_dmg_fctr=20
            self.mgk_base_dmg = 20
        if bullet_type=='lightingbolt':
            if direction == 1 or direction ==2:
                self.surf = pygame.Surface((30, 60))
                self.surf = pygame.image.load("asset/lightingbolt_down.png").convert()
            if direction == 3 or direction ==4:
                self.surf = pygame.Surface((60, 30))
                self.surf = pygame.image.load("asset/lightingbolt_left.png").convert()
            self.tag = bullet_type
            self.speed = 30
            self.Mana_cost = 10
            self.mgk_dmg_fctr = 1
            self.mgk_base_dmg = 10
            self.travel_distance = 0
            self.max_distance = 300
        if bullet_type=='iceball':
            self.surf = pygame.Surface((60, 60))
            self.surf = pygame.image.load("asset/iceball.png").convert()
            self.tag = bullet_type
            self.speed = 10
            self.Mana_cost = 8
            self.mgk_dmg_fctr=2
            self.mgk_base_dmg = 5
            self.lifecycle=10
        if bullet_type=='skeleton_archer':
            if direction == 1 :
                self.surf = pygame.Surface((10, 20))
                self.surf = pygame.image.load("asset/arrow_up.png").convert()
            if direction == 2 :
                self.surf = pygame.Surface((10, 20))
                self.surf = pygame.image.load("asset/arrow_down.png").convert()
            if direction == 3:
                self.surf = pygame.Surface((20, 10))
                self.surf = pygame.image.load("asset/arrow_left.png").convert()
            if direction == 4:
                self.surf = pygame.Surface((20, 10))
                self.surf = pygame.image.load("asset/arrow_right.png").convert()
            self.tag = bullet_type
            self.speed = 10
            self.attack = 15
        if bullet_type=='skeleton_mage':
            self.surf = pygame.Surface((20, 20))
            self.surf = pygame.image.load("asset/firebolt.png").convert()
            self.tag = bullet_type
            self.speed = 15
            self.attack = 30
        #self.surf.fill((0, 0, 0))
        self.surf.set_colorkey((0,0,0),RLEACCEL)
        self.rect = self.surf.get_rect( center=(x,y,))
        self.bullet_direction = direction
        self.collide_sound = pygame.mixer.Sound("asset/explosion_x.wav")

    def update(self):
        if self.tag == 'iceball':
            self.rect.move_ip(random.randint(-self.speed, self.speed), random.randint(-self.speed, self.speed))
        elif self.bullet_direction == 1:
            self.rect.move_ip(0, -self.speed)
        elif self.bullet_direction == 2:
            self.rect.move_ip(0, self.speed)
        elif self.bullet_direction == 3:
            self.rect.move_ip(-self.speed, 0)
        elif self.bullet_direction == 4:
            self.rect.move_ip(self.speed, 0)
        elif self.rect.right > PLAY_WIDTH or self.rect.right < 0 or self.rect.top < 0 or self.rect.top > PLAY_HEIGHT:
            self.kill()

        if self.tag == 'lightingbolt':
            self.travel_distance += self.speed
            if self.travel_distance >= self.max_distance:
                self.kill()

"""
drop
"""
class Treasurebox(pygame.sprite.Sprite):
    def __init__(self, bonusbox_id, x, y):
        super(Treasurebox, self).__init__()
        self.tag=bonusbox_id
        if bonusbox_id == 0:
            self.surf = pygame.image.load("asset/treasurebox.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if bonusbox_id == 1:
            self.surf = pygame.image.load("asset/treasurebox.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        if bonusbox_id == 2:
            self.surf = pygame.image.load("asset/treasurebox.png").convert()
            self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.rect = self.surf.get_rect(center=(x, y))
        self.bonus_sound = pygame.mixer.Sound("asset/chime.wav")

def enemy_drop(entity, treasureboxes, all_sprites):
    x = (entity.rect.left + entity.rect.right) / 2
    y = (entity.rect.top + entity.rect.bottom) / 2
    if entity.tag == 'skeleton_normal' or entity.tag == 'skeleton_archer':
        new_treasurebox=Treasurebox(0,x,y)
        treasureboxes.add(new_treasurebox)
        all_sprites.add(new_treasurebox)
    if entity.tag == 'skeleton_archer' :
        new_treasurebox=Treasurebox(1,x,y)
        treasureboxes.add(new_treasurebox)
        all_sprites.add(new_treasurebox)
    if entity.tag == 'skeleton_warrior' or entity.tag == 'skeleton_mage':
        new_treasurebox=Treasurebox(2,x,y)
        treasureboxes.add(new_treasurebox)
        all_sprites.add(new_treasurebox)

def loot_treasurebox(treasurebox):
    seed = random.randint(1, 100)
    if treasurebox.tag == 0:
        gold=random.randint(2, 10)
        myparameters.item_inventory['Gold'] += gold
        #notification(f'Gold +{gold}')
        if seed<=2:
            myparameters.weapon_inventory['Steel Sword'] = True
            notification(f'Got Steel Sword')
        if seed>90:
            myparameters.item_inventory['HP Potion'] += 1
            notification(f'Got HP Potion')
        if seed>80 and seed<=90:
            myparameters.item_inventory['Mana Potion'] += 1
            notification(f'Got Mana Potion')
    if treasurebox.tag == 1:
        gold=random.randint(5, 15)
        myparameters.item_inventory['Gold'] += gold
        #notification(f'Gold +{gold}')
        if seed<=5:
            myparameters.weapon_inventory['Steel Sword'] = True
            notification(f'Got Steel Sword')
        if seed>5 and seed<=10:
            myparameters.weapon_inventory['Iron Spear'] = True
            notification(f'Got Iron Spear')
        if seed>85:
            myparameters.item_inventory['HP Potion'] += 1
            notification(f'Got HP Potion')
        if seed>70 and seed<=85:
            myparameters.item_inventory['Mana Potion'] += 1
            notification(f'Got Mana Potion')
    if treasurebox.tag == 2:
        gold=random.randint(10, 30)
        myparameters.item_inventory['Gold'] += gold
        #notification(f'Gold +{gold}')
        if seed<=5:
            myparameters.weapon_inventory['Iron Armor'] = True
            notification(f'Got Iron Armor')
        if seed>5 and seed <=10:
            myparameters.weapon_inventory['Claymore'] = True
            notification(f'Got Claymore')
        if seed>85:
            myparameters.item_inventory['HP Potion'] += 1
            notification(f'Got HP Potion')
        if seed>70 and seed<=85:
            myparameters.item_inventory['Mana Potion'] += 1
            notification(f'Got Mana Potion')
    myparameters.item_inventory['HP Potion'] = min(myparameters.item_inventory['HP Potion'], 9)
    myparameters.item_inventory['Mana Potion'] = min (myparameters.item_inventory['Mana Potion'], 9)
"""
functions
"""

def calc_dmg(attacker, attacker_weapon, defenser, atk_type):
    if atk_type == 'Iron Sword' or atk_type == 'Steel Sword' or atk_type == 'Elven Sword':
        dmg=attacker.Strength/2+attacker.Agility/2 \
            +random.randint(attacker_weapon.min_attack,attacker_weapon.max_attack)\
            -defenser.defense
    elif atk_type == 'Claymore' or atk_type == 'Iron Spear':
        dmg=attacker.Strength+random.randint(attacker_weapon.min_attack,attacker_weapon.max_attack)\
            -defenser.defense
    elif atk_type == 'skeleton_archer' :
        dmg=attacker.attack-defenser.defense-defenser.equiped_armor_defense
    elif atk_type == 'skeleton_mage' :
        dmg=attacker.attack

    elif atk_type == 'firebolt' or atk_type == 'lightingbolt' or atk_type == 'iceball' or atk_type== 'skeleton_mage':
        dmg = attacker.Intellect * attacker_weapon.mgk_dmg_fctr + attacker_weapon.mgk_base_dmg

    return round(max(dmg, 1))

def calc_dmg_col(attacker,  defenser):
    dmg= (attacker.Vigor*5 - defenser.defense - defenser.equiped_armor_defense)
    print(defenser.equiped_armor_defense)
    return round(max(dmg, 1))

def calc_exp_gain(attacker, defenser, exp_type, kill_y_n,level_up_sound, dmg=0, mana_used=0):
    if exp_type == 'Iron Sword' or exp_type == 'Steel Sword':
        if kill_y_n == False:
            attacker.STR_exp = attacker.STR_exp + defenser.exp_points/20
            attacker.AGI_exp = attacker.AGI_exp + defenser.exp_points / 20
        if kill_y_n == True:
            attacker.STR_exp = attacker.STR_exp + defenser.exp_points/2
            attacker.AGI_exp = attacker.AGI_exp + defenser.exp_points / 2
        if attacker.STR_exp>=attacker.STR_exp_required:
            level_up_sound.play()
            attacker.Strength += 1
            attacker.STR_exp = 0
            attacker.STR_exp_required = attacker.Strength*100
        if attacker.AGI_exp>=attacker.AGI_exp_required:
            level_up_sound.play()
            attacker.Agility += 1
            attacker.AGI_exp = 0
            attacker.AGI_exp_required = attacker.Agility*100
    if exp_type == 'firebolt' or exp_type == 'lightingbolt' or exp_type == 'iceball':
        if kill_y_n == False:
            attacker.INT_exp = attacker.INT_exp + defenser.exp_points/10
        if kill_y_n == True:
            attacker.INT_exp = attacker.INT_exp + defenser.exp_points
        if attacker.INT_exp>=attacker.INT_exp_required:
            level_up_sound.play()
            attacker.Intellect += 1
            attacker.INT_exp = 0
            attacker.INT_exp_required = attacker.Intellect*100
    if exp_type == 'VIG':
        attacker.VIG_exp = attacker.VIG_exp + dmg*20
        if attacker.VIG_exp>=attacker.VIG_exp_required:
            level_up_sound.play()
            attacker.Vigor += 1
            attacker.VIG_exp = 0
            attacker.VIG_exp_required = attacker.Vigor*100
            attacker.max_HP=attacker.Vigor*10
            attacker.defense += 1
    if exp_type == 'WIS':
        attacker.WIS_exp = attacker.WIS_exp + mana_used*20
        if attacker.WIS_exp>=attacker.WIS_exp_required:
            level_up_sound.play()
            attacker.Wisdom += 1
            attacker.WIS_exp = 0
            attacker.WIS_exp_required = attacker.Wisdom*100
            attacker.max_Mana = attacker.Wisdom*10

def display_text(font_file, font_size, content,x, y, screen):
    font = pygame.font.Font(font_file, font_size)
    text = font.render(content, True, (255, 255, 255), (0, 0, 0))
    textRect = text.get_rect()
    textRect.topleft = (x, y)
    screen.blit(text, textRect)

class Icon(pygame.sprite.Sprite):
    def __init__(self, icon_file,x, y, screen):
        super(Icon, self).__init__()
        self.surf = pygame.Surface((32, 32))
        self.surf = pygame.image.load(icon_file).convert()
        self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.rect=self.surf.get_rect(topleft = (x, y))
        screen.blit(self.surf, self.rect)

def move_ob(sprite, direction, speed, ob_tiles):
    if direction == 1:
        sprite.rect.move_ip(0, speed)
    if direction == 2:
        sprite.rect.move_ip(0, -speed)
    if direction == 3:
        sprite.rect.move_ip(speed, 0)
    if direction == 4:
        sprite.rect.move_ip(-speed, 0)
    if pygame.sprite.spritecollideany(sprite, ob_tiles):
        if direction == 1:
            sprite.rect.move_ip(0, -speed)
        if direction == 2:
            sprite.rect.move_ip(0, speed)
        if direction == 3:
            sprite.rect.move_ip(-speed, 0)
        if direction == 4:
            sprite.rect.move_ip(speed, 0)

def hit_bounce(sprite, direction, speed, ob_tiles):
    if direction == 1:
        sprite.rect.move_ip(0, -speed)
    if direction == 2:
        sprite.rect.move_ip(0, speed)
    if direction == 3:
        sprite.rect.move_ip(-speed, 0)
    if direction == 4:
        sprite.rect.move_ip(speed, 0)
    if pygame.sprite.spritecollideany(sprite, ob_tiles):
        if direction == 1:
            sprite.rect.move_ip(0, speed)
        if direction == 2:
            sprite.rect.move_ip(0, -speed)
        if direction == 3:
            sprite.rect.move_ip(speed, 0)
        if direction == 4:
            sprite.rect.move_ip(-speed, 0)

def paused(pause, screen):
    screen.fill((0,0,0))
    display_text('asset/Roboto-Black.ttf', 18, "PAUSED", 400, 400, screen)
    while pause:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                print("keydown",event.type, KEYDOWN)
                if event.key == pygame.K_p:
                    print("K_p", event.key, pygame.K_p)
                    pause = False
                    print(pause)

            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # gameDisplay.fill(white)

        #button("Continue", 150, 450, 100, 50, green, bright_green, unpause)
        #button("Quit", 550, 450, 100, 50, red, bright_red, quitgame)

        pygame.display.update()
        #pygame.time.clock.tick(15)

def notification(message):
    myparameters.notifications.append(message)

def use_potion(player,potion_type):
    if potion_type == 'HP Potion':
        if myparameters.item_inventory['HP Potion'] >0:
            player.HP = min(player.HP +round(player.max_HP*0.6), player.max_HP)
            myparameters.item_inventory['HP Potion'] -= 1
    if potion_type == 'Mana Potion':
        if myparameters.item_inventory['Mana Potion'] > 0:
            player.Mana = min(player.Mana + round(player.max_Mana*0.6), player.max_Mana)
            myparameters.item_inventory['Mana Potion'] -= 1

def load_new_map(map_path, tileset_path , map_id,all_sprites, ob_tiles, slow_tiles,new_map_tiles,prev_map_tiles):
    all_sprites.empty()
    ob_tiles.empty()

    tilemap = Tilemap( map_path,tileset_path,map_id, all_sprites, ob_tiles, slow_tiles, new_map_tiles, prev_map_tiles)
    return tilemap

def respawn_enemy(tilemap, enemy_id,cnt, enemies, all_sprites, ob_tiles):
    while cnt>0:
        new_enemy = Skeleton(enemy_id, tilemap.size)
        if pygame.sprite.spritecollideany(new_enemy, ob_tiles):
            new_enemy.kill()
        else:
            enemies.add(new_enemy)
            all_sprites.add(new_enemy)
            cnt -= 1


# pylint: disable=missing-docstring
from unittest.mock import Mock

import pytest

from peltak.core.hooks import HooksRegister

def test_is_called_when_subscribed():
    fake_handler = Mock()
    register = HooksRegister()

    register('fake-hook')(fake_handler)
    register.call('fake-hook')

    fake_handler.assert_called_once_with()

def test_is_not_called_after_unsubscribed():
    conf = {}
    fake_handler = Mock()
    register = HooksRegister()

    register('fake-hook')(fake_handler)
    register.remove('fake-hook', fake_handler)
    register.call('fake-hook', conf)

    fake_handler.assert_not_called()

def test_passes_arguments_to_the_hooks():
    param = {'name': 'hello'}
    fake_handler = Mock()
    register = HooksRegister()

    register('fake-hook')(fake_handler)
    register.call('fake-hook', param, 1)

    fake_handler.assert_called_once_with(param, 1)

def test_can_register_hooks_with_decorator():
    fake_fn = Mock()
    register = HooksRegister()

    @register('fake-hook')
    def post_conf_load():       # pylint: disable=unused-variable
        fake_fn()

    register.call('fake-hook')

    fake_fn.assert_called_once_with()

def test_registering_with_empty_name_raises_ValueError():
    fake_handler = Mock()
    register = HooksRegister()

    with pytest.raises(ValueError):
        register('')(fake_handler)

def test_calling_a_hook_with_empty_name_raises_ValueError():
    register = HooksRegister()

    with pytest.raises(ValueError):
        register.call('')

def test_trying_to_remove_unregistered_hook_raises_ValueError():
    fake_handler1 = Mock()
    fake_handler2 = Mock()
    register = HooksRegister()

    with pytest.raises(ValueError):
        register.remove('fake-hook', fake_handler1)

    register('fake-hook')(fake_handler2)

    with pytest.raises(ValueError):
        register.remove('fake-hook', fake_handler1)

def test_registering_hook_twice_raises_ValueError():
    fake_handler = Mock()
    register = HooksRegister()

    register('fake-hook')(fake_handler)

    with pytest.raises(ValueError):
        register('fake-hook')(fake_handler)


from bs4 import BeautifulSoup
import requests

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def get_movies_titles(website_link, count_tables):
    """
    Getting Titles of all the
    """
    r = requests.get(website_link)
    soup = BeautifulSoup(r.content, features="html.parser")

    # finding the tables for orbital and suborbital flights
    tables = soup.findAll('table', attrs={
        'class': ['wikitable', 'collapsible', 'mw-collapsible',
                    'mw-made-collapsible']})

    all_movies = []
    for table in tables[0:count_tables]:
        title_cells = table.find_all("th", attrs={'scope':"row"})
        for cell in title_cells:
            cell_link = cell.findAll('a')[0]
            all_movies.append(cell_link.get('title'))

    return all_movies

def get_imdb_link(movie_title, driver):
    """
    Scraping DuckDuckGo to get imdb page of a movie by its title
    movie_title (str) - title of the movie
    driver - Chrome driver for selenium

    """
    # searching the query
    query = movie_title + " imdb"
    # html_page = requests.get("https://duckduckgo.com/?q="+query)
    driver.get("https://duckduckgo.com/?q="+query)

    soup = BeautifulSoup(driver.page_source, 'html.parser')
    link_class = "eVNpHGjtxRBq_gLOfGDr"
    link_div_elems = soup.find_all("a", {"class": link_class})

    return link_div_elems[0]['href']

def get_movies_locations(all_movies, movie_locations):
    """
    Getting Filming Locations of the list of movies
    all_movies (list: str) - list of titles of movies to search for
    movie_locations (dict) - list of locations (str) for each movie title (str), store here
    """
    driver_location = '/home/sayyor/Desktop/selfStudy/race-charts/drivers/chromedriver'

    # setting up the driver
    ser = Service(driver_location)
    op = webdriver.ChromeOptions()
    driver = webdriver.Chrome(service=ser, options=op)

    for movie_title in all_movies:
        # search for the movie title
        page_link = get_imdb_link(movie_title, driver)

        # go to the locations page
        page_link = page_link.split("/")
        page_link = page_link[:-1] # removing unnecessary part
        page_link = "/".join(page_link)+'/locations' # going to the filming locations page
        html_page = requests.get(page_link)
        soup = BeautifulSoup(html_page.content, 'html.parser')

        url_links = soup.find_all("a", {"itemprop": "url"})
        print(url_links[0])
        movie_locations[movie_title] = [url_link.encode_contents().decode("utf-8").replace("\n", "") for url_link in url_links]

    driver.quit()
    return movie_locations


'''
clic.db.book: Fetch/store book dicts to DB
******************************************
'''
import psycopg2
import psycopg2.extras

from clic.db.lookup import rclass_id_lookup
from clic.tokenizer import types_from_string

def put_book(cur, book):
    """
    Import a book object:

    * name: The shortname of the book
    * content: The full book string, as per instructions in the corpora repository
    * An entry for each rclass, e.g. "chapter.text": See /schema/10-rclass.sql. A list of...
      - off_start: Character offset for start of this region
      - off_end: Character offset for end of this region, non-inclusive
      - rvalue: rvalue, e.g. chapter number (see /schema/10-rclass.sql)

    The book contents / regions will be imported into the database, and any
    "chapter.text" region will be tokenised.
    """
    rclass = rclass_id_lookup(cur)

    # Insert book / update content, get ID for other updates
    cur.execute("""
        SELECT book_id, token_tbl, region_tbl FROM book_import_init(%(name)s, %(content)s)
    """, dict(
        name=book['name'],
        content=book['content'],
    ))
    (book_id, token_tbl, region_tbl) = cur.fetchone()

    # Replace regions with new values
    for rclass_name in book.keys():
        if '.' not in rclass_name:
            continue  # Not an rclass
        rclass_id = rclass[rclass_name]
        psycopg2.extras.execute_values(cur, """
            INSERT INTO """ + region_tbl + """ (book_id, crange, rclass_id, rvalue) VALUES %s
        """, ((
            book_id,
            psycopg2.extras.NumericRange(off_start, off_end),
            rclass_id,
            rvalues[0] if len(rvalues) > 0 else None,
        ) for off_start, off_end, *rvalues in book[rclass_name]))

    # Tokenise each chapter text region and add it to the database
    psycopg2.extras.execute_values(cur, """
        INSERT INTO """ + token_tbl + """ (book_id, crange, ttype) VALUES %s
    """, ((
        book_id,
        psycopg2.extras.NumericRange(off_start, off_end),
        ttype,
    ) for ttype, off_start, off_end in types_from_string(
        book['content'],
        offset=0
    )))

    # Finalise token import, let DB update metadata, indexes
    cur.execute("""
        SELECT * FROM book_import_finalise(%(book_id)s)
    """, dict(
        book_id=book_id,
    ))

def get_book(cur, book_id_name, content=False, regions=False):
    """Get book from DB, specifying what details are required"""
    out = dict()

    # Initial fetch from main table
    cur.execute("".join([
        "SELECT book_id, name",
        ", content" if content else ", NULL AS content",
        " FROM book WHERE",
        " book_id = %s" if isinstance(book_id_name, int) else " name = %s",
    ]), (book_id_name,))
    (out['id'], out['name'], out['content'],) = cur.fetchone()
    if not content:
        del out['content']

    if regions:
        cur.execute("""
            SELECT (SELECT name FROM rclass WHERE rclass_id = r.rclass_id) rclass_name
                 , r.crange
                 , r.rvalue
              FROM region r
             WHERE r.book_id = %(book_id)s
          ORDER BY r.crange
        """, dict(
            book_id=out['id'],
        ))

        for rclass_name, crange, rvalue in cur:
            if rclass_name not in out:
                out[rclass_name] = []
            out[rclass_name].append((crange.lower, crange.upper, rvalue))

    return out