import json
import os
import re
import sys
import time
import uuid
import http.client
import logging
import cherrypy
import threading

import requests
from lxml import etree
from queue import Queue
from enum import Enum
from cherrypy import _cpnative_server

from .utils import load_xml, XMLPath, Setting, cherrypy_publish, SETTING_DIR

logger = logging.getLogger("Protocol")
logger.setLevel(logging.INFO)

SERVICE_STATE_OBSERVED = {
    "AVTransport": ['TransportState',
                    'TransportStatus',
                    'CurrentMediaDuration',
                    'CurrentTrackDuration',
                    'CurrentTrack',
                    'NumberOfTracks'],
    "RenderingControl": ['Volume', 'Mute'],
    "ConnectionManager": ['A_ARG_TYPE_Direction',
                          'SinkProtocolInfo',
                          'CurrentConnectionIDs']
}

class Protocol:
    def __init__(self):
        self._handler = None

    @property
    def handler(self):
        if self._handler is None:
            self._handler = Handler()
        return self._handler

    def start(self):
        pass

    def stop(self):
        pass

    def reload(self):
        self.stop()
        self.start()

    def methods(self):
        return list(filter(lambda m: m.startswith('set_state_') and callable(getattr(self, m)), dir(self)))

    @property
    def renderer(self):
        renderers = cherrypy.engine.publish('get_renderer')
        if len(renderers) == 0:
            logger.error("Unable to find an available renderer.")
            return None
        return renderers.pop()

    # The following methods are called by the renderer to set the playback status within the protocol,
    # which will be passed to the client (generally the mobile phone)

    def set_state_position(self, data: str):
        """
        :param data: string, eg: 00:00:00
        :return:
        """
        pass

    def set_state_duration(self, data: str):
        """
        :param data: string, eg: 00:00:00
        :return:
        """
        pass

    def set_state_pause(self):
        """
        :return:
        """
        pass

    def set_state_play(self):
        """
        :return:
        """
        pass

    def set_state_stop(self):
        """
        :return:
        """
        pass

    def set_state_eof(self):
        """
        :return:
        """
        pass

    def set_state_transport(self, data: str):
        """
        :param data: string in [PLAYING, PAUSED_PLAYBACK, STOPPED, NO_MEDIA_PRESENT]
        :return:
        """
        pass

    def set_state_transport_error(self):
        """
        :return:
        """
        pass

    def set_state_mute(self, data: bool):
        """
        :param data: bool
        :return:
        """
        pass

    def set_state_volume(self, data: int):
        """
        :param data: int 0-100
        :return:
        """
        pass

    def set_state_speed(self, data: str):
        pass

    def set_state_display_subtitle(self, data: bool):
        """ set custom subtitle file path
        :param data: bool, whether display the subtitle
        :return:
        """
        pass

    def set_state_url(self, data: str):
        pass

    def set_state(self, state_name, state_value):
        pass

    def get_state(self, state_name):
        return ''

    def get_state_title(self) -> str:
        """
        :return: string, eg: demo
        """
        return ''

    def get_state_url(self) -> str:
        """
        :return: string, eg: http://10.10.10.10/demo.mp4
        """
        return ''

    def get_state_position(self) -> str:
        """
        :return: string, eg: 00:00:00
        """
        return '00:00:00'

    def get_state_duration(self) -> str:
        """
        :return: string, eg: 00:00:00
        """
        return '00:00:00'

    def get_state_volume(self) -> int:
        """
        :return: int, range from 0 to 100
        """
        return 80

    def get_state_mute(self) -> bool:
        """
        :return: bool
        """
        return False

    def get_state_transport_state(self) -> str:
        """
        :return: string in [PLAYING, PAUSED_PLAYBACK, STOPPED, NO_MEDIA_PRESENT]
        """
        return 'STOPPED'

    def get_state_transport_status(self) -> str:
        """
        :return: string in [OK, ERROR_OCCURRED]
        """
        return 'OK'

    def get_state_speed(self) -> str:
        return '1'

    def get_state_display_subtitle(self) -> bool:
        return True

class ObserveClient:
    def __init__(self, service, url, timeout=1800):
        self.url = url
        self.service = service
        self.startTime = int(time.time())
        self.sid = "uuid:{}".format(uuid.uuid4())
        self.timeout = timeout
        self.seq = 0
        self.host = re.findall(r"//([0-9:.]*)", url)[0]
        self.path = re.findall(r"//[0-9:.]*(.*)$", url)[0]
        print("-----------------------------", self.host)
        self.error = 0

    def is_timeout(self):
        return int(time.time()) - self.startTime > self.timeout

    def update(self, timeout=1800):
        self.startTime = int(time.time())
        self.timeout = timeout

    def send_event_callback(self, data):
        """Sending event data to client
        """
        headers = {"NT": "upnp:event",
                   "NTS": "upnp:propchange",
                   "CONTENT-TYPE": 'text/xml; charset="utf-8"',
                   "SERVER": Setting.get_server_info(),
                   "SID": self.sid,
                   "SEQ": self.seq,
                   "TIMEOUT": "Second-{}".format(self.timeout)
                   }
        namespace = 'urn:schemas-upnp-org:event-1-0'
        root = etree.Element(etree.QName(namespace, 'propertyset'),
                             nsmap={'e': namespace})
        if self.service == 'ConnectionManager':
            for i in data:
                prop = etree.SubElement(
                    root, '{urn:schemas-upnp-org:event-1-0}property')
                item = etree.SubElement(prop, i)
                item.text = str(data[i])
        else:
            prop = etree.SubElement(
                root, '{urn:schemas-upnp-org:event-1-0}property')
            last_change = etree.SubElement(prop, 'LastChange')
            event = etree.Element('Event')
            event.attrib['xmlns'] = 'urn:schemas-upnp-org:metadata-1-0/AVT/'
            instance_id = etree.SubElement(event, 'InstanceID')
            instance_id.set('val', '0')
            for i in data:
                p = etree.SubElement(instance_id, i)
                p.set('val', str(data[i]))
            last_change.text = etree.tostring(event, encoding="UTF-8").decode()
        data = etree.tostring(root, encoding="UTF-8")
        logger.debug("Prop Change---------")
        logger.debug(data)
        conn = http.client.HTTPConnection(self.host, timeout=5)
        conn.request("NOTIFY", self.path, data, headers)
        conn.close()
        self.seq = self.seq + 1

class DataType(Enum):
    boolean = 'boolean'
    i2 = 'i2'
    ui2 = 'ui2'
    i4 = 'i4'
    ui4 = 'ui4'
    string = 'string'

class StateVariable:
    """The state of render
    """

    def __init__(self, name, send_events, datatype, service):
        self.name = name
        self.sendEvents = True if send_events == 'yes' else False
        self.datatype = DataType(datatype)
        self.minimum = None
        self.maximum = None
        self.allowedValueList = None
        self.value = '' if self.datatype == DataType.string else 0
        self.service = service

    def set_value(self, value):
        self.value = value

    def set_allowed_value_list(self, values):
        self.allowedValueList = values
        if 'NOT_IMPLEMENTED' in values:
            self.value = 'NOT_IMPLEMENTED'

    def set_allowed_value_range(self, minimum, maximum):
        self.minimum = minimum
        self.maximum = maximum

class Argument:
    def __init__(self, name, state, value=None):
        self.name = name
        self.state = state
        self.value = value

class Action:
    """Operations supported by render.

    Parameters
    ----------
    name : string
        The name of the operation.
    input : list<Argument>
        A set of state values.
    output : list<Argument>
        A set of state values.

    """

    def __init__(self, name, input, output):
        self.name = name
        self.input = input
        self.output = output

class Service:
    service_map = {}

    @classmethod
    def get(cls, name):
        return cls.service_map.get(name, Service(name))

    @classmethod
    def build(cls, name, ns, actions):
        cls.service_map[name] = Service(name, ns, actions)

    def __init__(self, name, namespace='', actions={}):
        self.name = name
        self.namespace = namespace
        self.actions = actions

class DLNAProtocol(Protocol):

    def __init__(self):
        super(DLNAProtocol, self).__init__()
        self.running = False
        self.state_list = {}
        self.action_list = {}
        self.event_thread = None
        self.event_subscribes = {}  # subscribe devices
        self.state_queue = Queue()  # states needed be send to subscribe devices
        self.removed_device_queue = Queue()  # devices needed be removed
        self.append_device_queue = Queue()  # devices needed be added
        self.init_services()  # create services handle function from xml file
        self.init_state()  # set default value

    @property
    def handler(self):
        if self._handler is None:
            self._handler = DLNAHandler()
        return self._handler

    def init_state(self):
        self.set_state('CurrentPlayMode', 'NORMAL')
        self.set_state('TransportPlaySpeed', 1)
        self.set_state('TransportStatus', 'OK')
        self.set_state('RelativeCounterPosition', 2147483647)
        self.set_state('AbsoluteCounterPosition', 2147483647)
        self.set_state('A_ARG_TYPE_Direction', 'Output')
        self.set_state('CurrentConnectionIDs', '0')
        self.set_state('PlaybackStorageMedium', 'None')
        self.set_state('SinkProtocolInfo', load_xml(XMLPath.PROTOCOL_INFO.value).strip())

    def init_services(self, description=XMLPath.DESCRIPTION.value):
        """
        :param description: dlna description xml file
        :return:
        """
        desc = etree.parse(description).getroot()
        for service_type in desc.iter('{urn:schemas-upnp-org:device-1-0}serviceType'):
            # service_type:  urn:schemas-upnp-org:service:ConnectionManager:1
            namespace = service_type.text
            service = service_type.text.split(":")[3]
            self.build_action(namespace, service, etree.parse(
                XMLPath.BASE_PATH.value + f"/xml/{service}.xml").getroot())

    def build_action(self, namespace, service, xml):
        """
        :param namespace: eg: urn:schemas-upnp-org:service:ConnectionManager:1
        :param service:  eg: ConnectionManager
        :param xml: xml content of service
        :return:
        """
        """Build action and variable list from xml file
        """
        ns = '{urn:schemas-upnp-org:service-1-0}'
        # get state variable from xml file
        for state_variable in xml.iter(ns + 'stateVariable'):
            name = state_variable.find(ns + "name").text

            data = StateVariable(name,
                                 state_variable.attrib['sendEvents'],
                                 state_variable.find(ns + "dataType").text,
                                 service)
            default_value = state_variable.find(ns + "defaultValue")
            if default_value is not None:
                data.set_value(default_value.text)
            allowed_value_list = state_variable.find(ns + "allowedValueList")
            if allowed_value_list is not None:
                values = [
                    value.text
                    for value in allowed_value_list.findall(ns + "allowedValue")
                ]
                data.set_allowed_value_list(values)

            allowed_value_range = state_variable.find(ns + "allowedValueRange")
            if allowed_value_range is not None:
                data.set_allowed_value_range(
                    int(allowed_value_range.find(ns + "minimum").text),
                    int(allowed_value_range.find(ns + "maximum").text))
            self.state_list[name] = data

        # get action from xml file
        actions = {}
        for action in xml.iter(ns + 'action'):
            name = action.find(ns + "name").text
            input = []
            output = []
            argument_list = action.find(ns + "argumentList")
            if argument_list is not None:
                for argument in argument_list.findall(ns + 'argument'):
                    data = Argument(
                        argument.find(ns + "name").text,
                        argument.find(ns + "relatedStateVariable").text)
                    if argument.find(ns + "direction").text == 'in':
                        input.append(data)
                    else:
                        output.append(data)
            actions[name] = Action(name, input, output)
        # self.action_list[service] = actions
        Service.build(service, namespace, actions)

    def add_subscribe(self, service, url, timeout=1800):
        """Add a DLNA client to subscribe list
        """
        logger.error("SUBSCRIBE: " + url)
        for client in self.event_subscribes:
            if self.event_subscribes[client].url == url and \
                    self.event_subscribes[client].service == service:
                s = self.event_subscribes[client]
                s.update(timeout)
                logger.error("SUBSCRIBE UPDATE")
                return {
                    "SID": s.sid,
                    "TIMEOUT": "Second-{}".format(s.timeout)
                }
        logger.error("SUBSCRIBE ADD")
        client = ObserveClient(service, url, timeout)
        self.append_device_queue.put(client)
        threading.Thread(target=self.send_init_event,
                         kwargs={
                             'service': service,
                             'client': client
                         }).start()
        return {
            "SID": client.sid,
            "TIMEOUT": "Second-{}".format(client.timeout)
        }

    def send_init_event(self, service, client):
        """When there is a client subscription,
        the first event callback will send all the state values of the service.
        """
        data = {}
        for state in SERVICE_STATE_OBSERVED[service]:
            data[state] = self.state_list[state].value
        try:
            client.send_event_callback(data)
        except Exception as e:
            logger.error(str(e))

    def remove_subscribe(self, sid):
        """Remove a DLNA client from subscribe list
        """
        if sid in self.event_subscribes:
            self.removed_device_queue.put(sid)
        return 200

    def renew_subscribe(self, sid, timeout=1800):
        """Renew a DLNA client in subcribe list
        """
        if sid in self.event_subscribes:
            self.event_subscribes[sid].update(timeout)
            return 200
        return 412

    def send_states_to_clients(self, state_change_list):
        """Sending the states in the stateChangeList to the clients which subscribe to them.
        :param state_change_list:
        :return:
        """
        if not bool(state_change_list):
            return
        # remove offline clients
        while not self.removed_device_queue.empty():
            sid = self.removed_device_queue.get()
            logger.info("Remove client: {}".format(sid))
            del self.event_subscribes[sid]
            self.removed_device_queue.task_done()
        # add clients
        while not self.append_device_queue.empty():
            client = self.append_device_queue.get()
            self.event_subscribes[client.sid] = client
            self.append_device_queue.task_done()
        # send stateChangeList to client
        for sid in self.event_subscribes:
            client = self.event_subscribes[sid]
            if client.is_timeout():
                self.remove_subscribe(client.sid)
                continue
            try:
                # Only send state which within the service
                state = {}
                for name in state_change_list:
                    if self.state_list[name].service == client.service:
                        state[name] = state_change_list[name]
                if len(state) == 0:
                    continue
                client.send_event_callback(state)

            except Exception as e:
                logger.error("send event error: " + str(e))
                client.error = client.error + 1
                if client.error > 10:
                    logger.debug("remove " + client.sid)
                    self.remove_subscribe(client.sid)

    def event(self):
        """DLNA Event thread
        If a DLNA client subscribes to the dlna event,
        it will automatically send the event to the client when the renderer state changes.
        """
        while self.running:
            if not self.state_queue.empty():
                state = {}
                while not self.state_queue.empty():
                    k, v = self.state_queue.get()
                    state[k] = v
                    self.state_queue.task_done()
                self.send_states_to_clients(state)
            time.sleep(1)

    def call(self, rawbody):
        """Processing requests from DLNA clients
        The request from the client is passed into this method
        through the DLNAHandler(macast.py -> class DLNAHandler).
        If the Render class implements the corresponding action method,
        the method will be called automatically.
        Otherwise, the corresponding state variable will be returned
        according to the **action return value** described in the XML file.
        :param rawbody: soap request from dlna client
        :return:
        """
        root = etree.fromstring(rawbody)[0][0]
        param = {}
        for node in root:
            param[node.tag] = node.text
        action = root.tag.split('}')[1]
        service = root.tag.split(":")[3]
        method = "{}_{}".format(service, action)
        if method not in [
            'AVTransport_GetPositionInfo',
            'AVTransport_GetTransportInfo',
            'RenderingControl_GetVolume'
        ]:
            logger.info("{} {}".format(method, param))
        res = {}
        service_type = Service.get(service)
        if hasattr(self, method):
            data = {}
            # input = self.action_list[service][action].input
            input = service_type.actions[action].input
            for arg in input:
                data[arg.name] = Argument(
                    arg.name, arg.state,
                    param[arg.name] if arg.name in param else None)
                if arg.name in param:
                    self.set_state(arg.state, param[arg.name])
            res = getattr(self, method)(data)
        else:
            # output = self.action_list[service][action].output
            output = service_type.actions[action].output
            for arg in output:
                res[arg.name] = self.state_list[arg.state].value
        if method not in ['ConnectionManager_GetProtocolInfo', 'AVTransport_GetPositionInfo']:
            logger.info("{}res: {}".format("*" * 20, res))
        else:
            logger.info("{}res: {}".format("*" * 20, method))

        # build response xml
        ns = 'http://schemas.xmlsoap.org/soap/envelope/'
        encoding = 'http://schemas.xmlsoap.org/soap/encoding/'
        root = etree.Element(etree.QName(ns, 'Envelope'), nsmap={'s': ns})
        root.attrib[f'{{{ns}}}encodingStyle'] = encoding
        body = etree.SubElement(root, etree.QName(ns, 'Body'), nsmap={'s': ns})
        # namespace = 'urn:schemas-upnp-org:service:{}:1'.format(service)
        response = etree.SubElement(body,
                                    etree.QName(
                                        service_type.namespace, '{}Response'.format(action)),
                                    nsmap={'u': service_type.namespace})
        for key in res:
            prop = etree.SubElement(response, key)
            prop.text = str(res[key])
        return etree.tostring(root, encoding="UTF-8", xml_declaration=False)

    def set_state(self, name: str, value) -> None:
        """Set DLNA state which defined by xml file
        :param name: state name
        :param value: state value
        :return:
        """
        # update states which will send to DLNA Client
        if name in SERVICE_STATE_OBSERVED['AVTransport'] or \
                name in SERVICE_STATE_OBSERVED['RenderingControl']:
            logger.debug("setState: {} {}".format(name, value))
            # When some states change, the DLNA client needs to be notified immediately
            # We put this kind of state into state_queue, waiting to be sent to client.
            self.state_queue.put((name, value))
        # update other states
        if self.state_list[name].value != value:
            self.state_list[name].value = value

    def get_state(self, name: str):
        """Get DLNA state, The type of state is described by XML file
        :param name: DLNA state name
        :return: int/string/bool
        """
        return self.state_list[name].value

    def start(self):
        """Start render thread
        """
        if self.running:
            return

        self.running = True
        self.event_thread = threading.Thread(target=self.event, daemon=True)
        self.event_thread.start()
        self.set_state_stop()

    def stop(self):
        """Stop render thread
        """
        self.running = False

    # The following method names are defined by the XML file

    def RenderingControl_SetVolume(self, data):
        volume = data['DesiredVolume']
        self.renderer.set_media_volume(volume.value)
        return {}

    def RenderingControl_SetMute(self, data):
        mute = data['DesiredMute']
        if mute.value == 0 or mute.value == '0':
            mute = False
        else:
            mute = True
        self.renderer.set_media_mute(mute)
        return {}

    def AVTransport_SetAVTransportURI(self, data):
        uri = data['CurrentURI'].value
        logger.info(uri)
        self.set_state_url(uri)
        self.renderer.set_media_url(uri)
        title = Setting.get_friendly_name()
        try:
            meta = etree.fromstring(data['CurrentURIMetaData'].value.encode())
            title_xml = meta.find('.//{{{}}}title'.format(meta.nsmap['dc']))
            if title_xml is not None and title_xml.text is not None:
                title = title_xml.text
            metadata = etree.tostring(meta, encoding="UTF-8", xml_declaration=False)
        except Exception as e:
            logger.error(str(e))
            logger.error(data['CurrentURIMetaData'].value)
            self.set_state('CurrentTrackMetaData', data['CurrentURIMetaData'].value)
        else:
            self.set_state('CurrentTrackMetaData', metadata.decode())
        self.renderer.set_media_title(title)
        self.renderer.set_media_resume()
        self.set_state('CurrentTrackTitle', title)
        self.set_state('CurrentTrackURI', uri)
        self.set_state('RelativeTimePosition', '00:00:00')
        self.set_state('AbsoluteTimePosition', '00:00:00')
        self.set_state('TransportState', 'PAUSED_PLAYBACK')
        self.set_state('TransportStatus', 'OK')
        return {}

    def AVTransport_Play(self, data):
        self.renderer.set_media_resume()
        self.set_state('TransportState', 'PLAYING')
        self.set_state('TransportStatus', 'OK')
        return {}

    def AVTransport_Pause(self, data):
        self.renderer.set_media_pause()
        self.set_state('TransportState', 'PAUSED_PLAYBACK')
        return {}

    def AVTransport_Seek(self, data):
        target = data['Target']
        self.renderer.set_media_position(target.value)
        self.set_state('RelativeTimePosition', target.value)
        self.set_state('AbsoluteTimePosition', target.value)
        return {}

    def AVTransport_Stop(self, data):
        self.renderer.set_media_stop()
        self.set_state('TransportState', 'STOPPED')
        return {}

    # The following methods are usually used to update the states of
    # DLNA Renderer according to the status obtained from the player.
    # So, when your player state changes, call the following methods.
    # For example, when you click the pause button of the player,
    # call "self.protocol.set_state_pause()" from renderer
    # Then, the DLNA client (such as your mobile phone) will
    # automatically get this information and update it to the front-end.

    def set_state_position(self, data: str):
        """
        :param data: string, eg: 00:00:00
        :return:
        """
        self.set_state('RelativeTimePosition', data)
        self.set_state('AbsoluteTimePosition', data)

    def set_state_duration(self, data: str):
        """
        :param data: string, eg: 00:00:00
        :return:
        """
        self.set_state('CurrentTrackDuration', data)
        self.set_state('CurrentMediaDuration', data)

    def set_state_pause(self):
        self.set_state_transport('PAUSED_PLAYBACK')

    def set_state_play(self):
        self.set_state_transport('PLAYING')

    def set_state_stop(self):
        self.set_state_transport('STOPPED')

    def set_state_eof(self):
        self.set_state_transport('NO_MEDIA_PRESENT')

    def set_state_transport(self, data: str):
        """
        :param data: string in [PLAYING, PAUSED_PLAYBACK, STOPPED, NO_MEDIA_PRESENT]
        :return:
        """
        self.set_state('TransportState', data)
        self.set_state('TransportStatus', 'OK')

    def set_state_transport_error(self):
        """
        :return:
        """
        self.set_state('TransportState', 'STOPPED')
        self.set_state('TransportStatus', 'ERROR_OCCURRED')

    def set_state_mute(self, data: bool):
        """
        :param data: bool
        :return:
        """
        self.set_state('Mute', data)

    def set_state_volume(self, data: int):
        """
        :param data: int, range from 0 to 100
        :return:
        """
        self.set_state('Volume', data)

    def set_state_speed(self, data: str):
        self.set_state('TransportPlaySpeed', data)

    def set_state_display_subtitle(self, data: bool):
        self.set_state('DisplayCurrentSubtitle', data)

    def set_state_url(self, data: str):
        self.set_state('CurrentTrackURI', data)

    # When you are implementing another protocol similar to DLNA,
    # you can get the status of DLNA renderer by calling the following methods.
    # Using DLNA protocol usually does not need to pay attention to these methods,
    # because the state of renderer will be read automatically when using DLNA protocol.

    def get_state_title(self) -> str:
        """
        :return: string, eg: demo
        """
        return self.get_state('CurrentTrackTitle')

    def get_state_url(self) -> str:
        """
        :return: string, eg: http://10.10.10.10/demo.mp4
        """
        return self.get_state('CurrentTrackURI')

    def get_state_position(self) -> str:
        """
        :return: string, eg: 00:00:00
        """
        return self.get_state('RelativeTimePosition')

    def get_state_duration(self) -> str:
        """
        :return: string, eg: 00:00:00
        """
        return self.get_state('CurrentMediaDuration')

    def get_state_volume(self) -> int:
        """
        :return: int, range from 0 to 100
        """
        return self.get_state('Volume')

    def get_state_mute(self) -> bool:
        """
        :return: bool
        """
        return self.get_state('Mute')

    def get_state_transport_state(self) -> str:
        """
        :return: string in [PLAYING, PAUSED_PLAYBACK, STOPPED, NO_MEDIA_PRESENT]
        """
        return self.get_state('TransportState')

    def get_state_transport_status(self) -> str:
        """
        :return: string in [OK, ERROR_OCCURRED]
        """
        return self.get_state('TransportStatus')

    def get_state_speed(self) -> str:
        return self.get_state('TransportPlaySpeed')

    def get_state_display_subtitle(self) -> bool:
        return bool(self.get_state('DisplayCurrentSubtitle'))

@cherrypy.expose
class Handler:

    def __init__(self):
        self.setting_page = load_xml(XMLPath.SETTING_PAGE.value).encode()
        self.__downloading = False

    @property
    def protocol(self) -> Protocol:
        protocols = cherrypy.engine.publish('get_protocol')
        if len(protocols) == 0:
            logger.error("Unable to find an available protocol.")
            return Protocol()
        return protocols.pop()

    def reload(self):
        cherrypy.server.httpserver = _cpnative_server.CPHTTPServer(cherrypy.server)

    def __download_plugin(self, path, url):
        try:
            with open(path, 'wb') as f:
                f.write(requests.get(url).content)
        except Exception as e:
            logger.error(f"download plugin error: {e}")
        finally:
            self.__downloading = False
            Setting.restart()
            # cherrypy.engine.restart()

    def GET(self, param=None, *args, **kwargs):
        if not Setting.is_service_running():
            raise cherrypy.HTTPError(503, 'Server restarting')
        if param == 'api':
            cherrypy.response.headers['Content-Type'] = 'application/json;charset:utf-8'
            query = kwargs.get('query', '')
            res = {
                'api?query=log': 'get logs of macast',
                'api?query=settings': 'get settings of macast',
            }
            if query == 'log':
                log_path = os.path.join(SETTING_DIR, 'macast.log')
                data = ''
                try:
                    with open(log_path, 'r', encoding='utf-8') as f:
                        data = f.read()
                except:
                    pass
                res = {"logs": data}
            elif query == 'launch-param':
                res = Setting.setting
            elif query == 'plugin-info':
                info = cherrypy_publish('get_plugin_info', [])
                res = {
                    'platform': sys.platform,
                    'version': Setting.version,
                    'plugins': info
                }
            return json.dumps(res, indent=4).encode()
        if param is not None:
            raise cherrypy.HTTPRedirect('/')
        cherrypy.response.headers['Content-Type'] = 'text/html'
        # return self.setting_page
        return load_xml(XMLPath.SETTING_PAGE.value).encode()

    def POST(self, *args, **kwargs):
        cherrypy.response.headers['Content-Type'] = 'application/json;charset:utf-8'
        res = {'code': 0, 'message': 'success'}
        if kwargs.get('save-launch-param', None) is not None:
            setting = kwargs.get('save-launch-param', None)
            try:
                setting = json.loads(setting)
            except Exception as e:
                res['code'] = 1
                res['message'] = 'json format error'
            else:
                Setting.setting = setting
                Setting.save()
                Setting.restart()
                # cherrypy.engine.restart()
        elif kwargs.get('install-plugin', None) is not None:
            plugin = kwargs.get('install-plugin', None)
            if self.__downloading:
                cherrypy.engine.publish('app_notify', 'ERROR', 'Downloading other plugin now')
                res['code'] = 1
                res['message'] = 'Downloading other plugin now'
            else:
                cherrypy.engine.publish('app_notify', 'INFO', 'installing plugin...')
                self.__downloading = True
                try:
                    plugin = json.loads(plugin)
                    url = plugin.get('url', '')
                    plugin_name = url.split('/')[-1]
                    local_path = os.path.join(SETTING_DIR, plugin.get('type', 'renderer'), plugin_name)
                    threading.Thread(target=self.__download_plugin(local_path, url),
                                     daemon=True).start()
                except Exception as e:
                    res['code'] = 1
                    res['message'] = 'json format error'
        else:
            logger.info(kwargs)

        return json.dumps(res, indent=4).encode()

@cherrypy.expose
class DLNAHandler(Handler):
    """Receiving requests from DLNA client
    and communicating with the RenderPlugin thread
    see also: plugin.py -> class RenderPlugin
    """

    def __init__(self):
        super(DLNAHandler, self).__init__()
        self.description = None
        self.reload()

    def reload(self):
        super(DLNAHandler, self).reload()
        self.build_description()

    @property
    def protocol(self) -> DLNAProtocol:
        protocols = cherrypy.engine.publish('get_protocol')
        if len(protocols) == 0:
            logger.error("Unable to find an available protocol.")
            return DLNAProtocol()
        return protocols.pop()

    def build_description(self):
        self.description = load_xml(XMLPath.DESCRIPTION.value).format(
            friendly_name=Setting.get_friendly_name(),
            manufacturer="xfangfang",
            manufacturer_url="https://github.com/xfangfang",
            model_description="AVTransport Media Renderer",
            model_name="Macast",
            model_url="https://xfangfang.github.io/Macast",
            model_number=Setting.get_version(),
            uuid=Setting.get_usn(),
            serial_num=1024,
            header_extra="",
            service_extra=""
        ).encode()

    def GET(self, param=None, *args, **kwargs):
        if param == 'description.xml':
            return self.description
        return super(DLNAHandler, self).GET(param, *args, **kwargs)

    def POST(self, service=None, param=None, *args, **kwargs):
        length = cherrypy.request.headers['Content-Length']
        rawbody = cherrypy.request.body.read(int(length))
        logger.debug('RAW: {}'.format(rawbody))
        if param == 'action':
            res = self.protocol.call(rawbody)
            cherrypy.response.headers['EXT'] = ''
            logger.debug('RES: {}'.format(res))
            return res
        return super(DLNAHandler, self).POST(service, param, *args, **kwargs)

    def SUBSCRIBE(self, service="", param=""):
        """DLNA/UPNP event subscribe
        """
        if param == 'event':
            SID = cherrypy.request.headers.get('SID')
            CALLBACK = cherrypy.request.headers.get('CALLBACK')
            TIMEOUT = cherrypy.request.headers.get('TIMEOUT')
            TIMEOUT = TIMEOUT if TIMEOUT is not None else 'Second-1800'
            TIMEOUT = int(TIMEOUT.split('-')[-1])
            if SID:
                logger.error("RENEW SUBSCRIBE:!!!!!!!" + service)
                res = self.protocol.renew_subscribe(SID, TIMEOUT)
                if res != 200:
                    logger.error("RENEW SUBSCRIBE: cannot find such sid.")
                    raise cherrypy.HTTPError(status=res)
                cherrypy.response.headers['SID'] = SID
                cherrypy.response.headers['TIMEOUT'] = TIMEOUT
            elif CALLBACK:
                logger.error("ADD SUBSCRIBE:!!!!!!!" + service)
                suburl = re.findall("<(.*?)>", CALLBACK)[0]
                res = self.protocol.add_subscribe(service, suburl, TIMEOUT)
                cherrypy.response.headers['SID'] = res['SID']
                cherrypy.response.headers['TIMEOUT'] = res['TIMEOUT']
            else:
                logger.error("SUBSCRIBE: cannot find sid and callback.")
                raise cherrypy.HTTPError(status=412)
        return b''

    def UNSUBSCRIBE(self, service, param):
        """DLNA/UPNP event unsubscribe
        """
        if param == 'event':
            SID = cherrypy.request.headers.get('SID')
            if SID:
                logger.error("REMOVE SUBSCRIBE:!!!!!!!" + service)
                res = self.protocol.remove_subscribe(SID)
                if res != 200:
                    raise cherrypy.HTTPError(status=res)
                return b''
        logger.error("UNSUBSCRIBE: error 412.")
        raise cherrypy.HTTPError(status=412)


from discord.ext import commands

class Talk(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(name= "best", help="Avoid arguments about who is the best girl")
    async def best_girl(self, ctx):
        answer = "They're all the best "

        await ctx.send (answer)

    @commands.command(name= "members", help="Members of group")
    async def members_group(self, ctx):
        answer = f"The members are Ayaka Takamura, Kyoka Moriya, Mayu Iizuka, Manatsu Murakami, Nene Hieda, Satsuki Miyahara, Yuna Ogata and Yurina Uchiyama."

        await ctx.send (answer)

    @commands.command(name= "rule", help="The rule that must always be followed")
    async def rule(self, ctx):
        answer = "Idols are for giving love, not for thinking lewd things!"
        await ctx.send (answer)

def setup(bot):
    bot.add_cog(Talk(bot))


from airflow.hooks.postgres_hook import PostgresHook
from airflow.contrib.hooks.aws_hook import AwsHook
from airflow.models import BaseOperator
from airflow.utils.decorators import apply_defaults

class StageToRedshiftOperator(BaseOperator):
    ui_color = '#358140'
    template_fields = ("s3_file_path",) # for templating the path to include month and year of execution
    copy_sql="""
    COPY {} FROM '{}'
    ACCESS_KEY_ID '{}'
    SECRET_ACCESS_KEY '{}'
    FORMAT AS json '{}'
    COMPUPDATE OFF
    STATUPDATE OFF;
    """
    @apply_defaults
    def __init__(self,
                 redshift_conn_id="",
                 table="",
                 s3_file_path="",
                 s3_con_id="", # Dummy AWS connection in order to user IAM role instead of the key and secret key
                 json_load_type="auto",
                 *args, **kwargs):

        super(StageToRedshiftOperator, self).__init__(*args, **kwargs)
        # Map params here
        # Example:
        self.redshift_conn_id = redshift_conn_id
        self.table = table
        self.s3_file_path = s3_file_path
        self.s3_con_id = s3_con_id
        self.json_load_type = json_load_type

    def execute(self, context):
        #self.log.info('StageToRedshiftOperator not implemented yet')
        aws_hook = AwsHook(self.s3_con_id)
        credentials = aws_hook.get_credentials()
        redshift = PostgresHook(postgres_conn_id=self.redshift_conn_id)
        self.log.info("Clearing data from destination Redshift table")
        redshift.run("DELETE FROM {}".format(self.table))

        self.log.info("Copying data from S3 to Redshift")
        formatted_sql = StageToRedshiftOperator.copy_sql.format(
            self.table,
            self.s3_file_path,
            credentials.access_key,
            credentials.secret_key,
            self.json_load_type
        )
        redshift.run(formatted_sql)


import bitly_api
from django.core.mail import EmailMultiAlternatives
from django.http import HttpResponse
from django.template import Context
from django.template.loader import get_template
from django.utils.encoding import smart_str
import csv

__author__ = 'student'
"""
Utility class that provides some common functionality to one or more views
"""

from core.models import Communication, CommsAudit, Newsletter, Audience

def twitter_link(path, token):
    """
    Usage:
        * Pass the function the full path (url) of the request
        * Pass the access token, https://bitly.com/a/oauth_apps
    :param path: full path of the request to be shortened
    :param token: API access token from registered developer account
    :return: shortened URL
    """
    c = bitly_api.Connection(access_token=token)
    d = c.shorten(path)
    return d['url']

def get_stats():
    """
    Compile the statistics of the website, used on the
    landing page
    :return: dictionary of relevant stats
    """
    total_comm = 0
    not_admin_checked = 0
    ncl_value = 0
    comm_objs = Communication.objects.all().order_by('-created_on')

    for i in comm_objs:
        # Count the total objects
        total_comm += 1

        # If admin_checked is false
        if not i.admin_checked:
            # Increment that counter
            not_admin_checked += 1

        # Sum total value awarded to Newcastle Uni
        ncl_value += i.value_awarded_to_ncl

    audit_objs = CommsAudit.objects.all()
    audited = audit_objs.count()
    unaudited = total_comm - audited

    audience_objs = Audience.objects.all()

    d = {}
    # Sum all of the audited articles that have a shared
    # audience
    for x in audit_objs:
        for y in audience_objs:
            # If the object is stored in both audit_objs and audience_objs
            if x.audience.pk == y.pk:
                # If it's not already stored in the dictionary (d)
                if not str(y.name) in d:
                    # Create entry in dictionary and set value to 1
                    # (must have an object set for that audience)
                    d[str(y.name)] = 1
                # Else, the audience isn't already stored in the dictionary
                else:
                    # Increment the value for that audience
                    d[str(y.name)] += 1

    total_newsletter = Newsletter.objects.all().count()

    # Build a dictionary of statistics gather above
    stats = {
        "total_comm": total_comm,
        "not_admin_checked": not_admin_checked,
        "ncl_value": ncl_value,
        "audited": audited,
        "unaudited": unaudited,
        "comm_objs": comm_objs,
        "total_newsletter": total_newsletter,
        "audit_objs": audit_objs,
        "d": d,
        "audience_objs": audience_objs
    }

    return stats

def send_mail_confirm(communication_instance):
    """
    Send an email confirmation of a new communication
    :param communication_instance: instance of the communication form
    :return: fail_silently will catch errors
    """
    created_by = communication_instance.created_by
    created_on = communication_instance.created_on
    subject = "Comminication Added - %s" % communication_instance.pk
    to_list = ['j.carlton@ncl.ac.uk']
    from_email = 'j.carlton@ncl.ac.uk'

    plain_txt = get_template('core/email/new_communication.txt')
    html = get_template('core/email/new_communication.html')

    d = Context({
        "created_by": created_by,
        "created_on": created_on
    })

    txt_content = plain_txt.render(d)
    html_content = html.render(d)
    msg = EmailMultiAlternatives(subject, txt_content, from_email, to_list)
    msg.attach_alternative(html_content, "text/html")
    msg.send(fail_silently=False)

def audited_article_to_csv(queryset):
    """
    Turn a set of audited articles into a csv
    file
    :param queryset: set of audited articles
    :return: HttpResponse containing csv file
    """
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="exported_audited_articles.csv"'

    writer = csv.writer(response)

    writer.writerow([
        smart_str(u'ID'),
        smart_str(u'Short Desc'),
        smart_str(u'Full Desc'),
        smart_str(u'BH Number'),
        smart_str(u'Value'),
        smart_str(u'Value to NCL'),
        smart_str(u'Start Date'),
        smart_str(u'Duration'),
        smart_str(u'External'),
        smart_str(u'Source'),
        smart_str(u'Level'),
        smart_str(u'Audience'),
    ])

    for obj in queryset:
        writer.writerow([
            smart_str(obj.sent.pk),
            smart_str(obj.sent.short_desc),
            smart_str(obj.sent.full_desc),
            smart_str(obj.sent.bh_number),
            smart_str(obj.sent.value_of_award),
            smart_str(obj.sent.value_awarded_to_ncl),
            smart_str(obj.sent.project_start_date),
            smart_str(obj.sent.duration),
            smart_str(obj.sent.external),
            smart_str(obj.sent.source),
            smart_str(obj.sent.level),
            smart_str(obj.audience)
        ])
    return response


import torch
from tqdm.notebook import tqdm
import numpy as np

def flatten(l):
    return [item for sublist in l for item in sublist]

def remove_tech_tokens(mystr, tokens_to_remove=['<eos>', '<sos>', '<unk>', '<pad>']):
    return [x for x in mystr if x not in tokens_to_remove]

def get_text(x, TRG_vocab):
    text = [TRG_vocab.itos[token] for token in x]
    try:
        end_idx = text.index('<eos>')
        text = text[:end_idx]
    except ValueError:
        pass
    text = remove_tech_tokens(text)
    if len(text) < 1:
        text = []
    return text

def generate_translation(model, iterator, TRG_vocab):
    model.eval()
    original_text = []
    generated_text = []
    model.eval()
    with torch.no_grad():

        for i, batch in tqdm(enumerate(iterator)):

            src = batch.src
            trg = batch.trg

            output = model(src, trg, 0) #turn off teacher forcing

            #trg = [trg sent len, batch size]
            #output = [trg sent len, batch size, output dim]

            output = output.argmax(dim=-1)

            original_text.extend([get_text(x, TRG_vocab) for x in trg.cpu().numpy().T])
            generated_text.extend([get_text(x, TRG_vocab) for x in output[1:].detach().cpu().numpy().T])
    return (original_text, generated_text)

def emb_sentence(sent, dicts):
    emb = dicts[0]
    no_emb = dicts[1]
    vocab = dicts[2]
    result = [(emb[(vocab.itos[idx])]) if (vocab.itos[idx] in emb.vocab.keys()) else no_emb[vocab.itos[idx]] for idx in sent]
    #print(result[0])
    return np.array(result)

def generate_translation_2(model, iterator, TRG_vocab, embedding_pretrained = False, dicts = None):
    model.eval()
    original_text = []
    generated_text = []
    model.eval()
    with torch.no_grad():

        for i, batch in tqdm.tqdm(enumerate(iterator)):

            src = batch.src
            trg = batch.trg

            device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
            if embedding_pretrained == True:
                sentences = src.cpu().numpy()[:]
                src = [emb_sentence(x, dicts) for x in sentences]
                src = torch.from_numpy(np.array(src)).to(device)
                src = src.float()

            output, _ = model(src, trg[:, :-1])
            trg_pred = output.argmax(dim=2).cpu().numpy()
            orig =  trg.cpu().numpy()
            for orig_txt, gen_txt in zip(orig, trg_pred):
                original_text.append(get_text(orig_txt, TRG_vocab))
                generated_text.append(get_text(gen_txt, TRG_vocab))

    return (original_text, generated_text)


from flask import Flask , request , url_for , redirect , session , render_template , g
from flask.json import jsonify
from flask.wrappers import Request
import sqlite3
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'Thisissecret!'

def connect_db():
    sql = sqlite3.connect("data.db")
    sql.row_factory = sqlite3.Row
    return sql
def get_db():
    if not hasattr(g,'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db
@app.teardown_appcontext
def close_db(error):
    if hasattr(g,'sqlite_db'):
        g.sqlite_db.close()

@app.route('/viewresults')
def viewresults():
    db = get_db()
    cur = db.execute("select * from users")
    results =  cur.fetchall()
    return f"
This id is {results[0]['id']} , name is {results[0]['name']}, the location is {results[0]['location']}</1>"

@app.route('/')
def index():
    session.pop('name',None)
    return "
ยินดีต้อนรับครับ ขอเกรด A นะครับ</1>"

@app.route('/home' ,methods = ['POST','GET'],defaults={'name': 'Test Default'})

@app.route('/home/<string:name>' ,methods = ['POST','GET'])
def home(name):
    session['name'] = name
    db = get_db()
    cur = db.execute("select * from users")
    results = cur.fetchall()

    return render_template('home.html' , name2=name ,display=False
    ,mylist=['one','two','three'],mylist_of_dict = [{'name' : 'noraphat'},{'name':'somjai'}],results=results), 200

@app.route('/json')
def json():
    if 'name' in session:
        name  = session['name']
    else:
        name = 'Not Value in Session'
    return jsonify({'key':'velue','listkey':[1,2,3] , 'name': name})

@app.route('/query')
def query():
    name = request.args.get('name')
    location = request.args.get('location')
    return f"
Hi {name} . You are from {location} You are on the query page
"

@app.route('/theform',methods = ['POST','GET'])
def theform():
    if request.method == 'GET':
        return render_template('form.html'), 200
    else:
        name = request.form['name']
        location = request.form['location']

        db = get_db()
        db.execute("insert into users(name,location) values(?,?)",[name,location])
        db.commit()

        return redirect(url_for('home',name=name))

@app.route('/process',methods=['POST'])
def process():
    name = request.form['name']
    location = request.form['location']
    return f"
Hi {name} . You are from {location} You Have summitted the form sucfully!!!
"

@app.route('/processjson',methods=['POST'])
def processjson():
    data = request.get_json()
    name = data['name']
    location = data['location']
    randomlist = data['randomlist']
    return jsonify({'result':'Success!','name': name , 'location' : location, 'randomkey_in_list':randomlist[0]})

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


#!/usr/bin/env python3
"""write an async routine called wait_n"""
import asyncio
from typing import List
wait_random = __import__('0-basic_async_syntax').wait_random

async def wait_n(n: int, max_delay: int) -> List[float]:
    """calls wait_random and spawns it n times asynchronously"""
    tasks = [asyncio.create_task(wait_random(max_delay)) for _ in range(n)]
    time_list = []
    for task in asyncio.as_completed(tasks):
        time: float = await task
        time_list.append(time)
    return time_list


import pygame
from pygame.rect import Rect
from pygame.gfxdraw import pie
from math import pi, sqrt
import numpy as np
from Constants.constants import *
# remove after
import matplotlib.pyplot as plt

class Scenario(object):
    def __init__(self, simulation, window, mapParameters, cars, initial):
        self.simulation = simulation
        self.window = window
        self.mapParameters = mapParameters
        self.cars = cars
        self.collision_array = None
        self.initial = initial
        self.cost_array = None
        self.n_players = simulation.number_players

    def  drawBackgroundImage(self):
        fundo = pygame.image.load('./Img/star.png')
        fundo = pygame.transform.scale(fundo, (SCREEN_WIDTH, SCREEN_HEIGHT))
        pista = pygame.image.load('./Img/pista.png')
        pista = pygame.transform.scale(pista, (SCREEN_WIDTH -200, SCREEN_HEIGHT))

        sensorPoint = pygame.image.load("./Img/luzAzul.png")
        sensorPoint = pygame.transform.scale(sensorPoint, (SENSOR_HEIGHT, SENSOR_HEIGHT))

        if self.initial == False:
            self.window.blit(fundo, (0,0))
        self.window.blit(pista, (200,0))

        # cars
        for i in range(self.n_players):
            self.cars[i] = pygame.transform.scale(self.cars[i], (CARS_HEIGHT, CARS_WIDTH))
            car_rotate = pygame.transform.rotate(self.cars[i], round(-self.simulation.player[i].pose.rotation * RAD2DEGREE)%360)
            burntCar = pygame.image.load("./Img/carroQueimado.png")
            burntCar = pygame.transform.scale(burntCar, (CARS_HEIGHT, CARS_WIDTH))
            x = M2PIX * self.simulation.player[i].pose.position.x
            y = M2PIX * self.simulation.player[i].pose.position.y
            # print(x, y)
            if self.initial == False:
                collide = self.simulation.player[i].bumper_state
                if collide == False:
                    if i == 0:
                        self.drawSensors(self.simulation.player[i].sensors, (x,y), sensorPoint)
                    self.window.blit(car_rotate, (x-car_rotate.get_rect().center[0], y-car_rotate.get_rect().center[1]))
                else:
                    # explosion = []
                    # if self.simulation.player[i].animationFrame != 45:
                    #     for j in range(1, 45):
                    #         explosion.append(pygame.image.load("./Img/explosion/exp (" + str(j) + ").png"))
                    #         explosion[j-1] = pygame.transform.scale(explosion[j-1], (200, 200))
                    burntCar = pygame.transform.rotate(burntCar, round(-self.simulation.player[i].pose.rotation * RAD2DEGREE)%360)
                    self.window.blit(burntCar, (x-burntCar.get_rect().center[0], y-burntCar.get_rect().center[1]))
                    # if self.simulation.player[i].animationFrame < 45:
                    #     # self.window.blit(explosion[self.simulation.player[i].animationFrame - 1], (x-100, y-100))
                    #     self.simulation.player[i].animationFrame += 1

        self.drawScore()
        windowScale = pygame.transform.scale(pygame.display.get_surface(), (SCREEN_WIDTH * self.mapParameters[0], SCREEN_HEIGHT * self.mapParameters[0]))
        self.window.fill((0,0,0))
        self.window.blit(windowScale, self.mapParameters[1])

    def drawSensors(self, sensors, centerPos, sensorPoint):
        if self.simulation.player[0].controllable != False:
            for i in range(N_SENSORS):
                pygame.draw.line(self.window, COLOR_SENSOR, sensors[i].distance()[0], centerPos, 1)
                center = sensors[i].distance()[0]
                self.window.blit(sensorPoint, (center[0] - SENSOR_HEIGHT/2, center[1] - SENSOR_HEIGHT/2))

    def drawScore(self):

        font = pygame.font.SysFont('Comic Sans MS', 30)
        generation = "Geração: " + str(self.simulation.generation)
        textsurface = font.render(generation, False, (255, 255, 255))
        self.window.blit(textsurface, (20,200))
        distance = "Melhor distância: "
        textsurface = font.render(distance, False, (255, 255, 255))
        self.window.blit(textsurface, (15,240))
        distance = str(self.simulation.better_distance * M2PIX) + " pix"
        textsurface = font.render(distance, False, (255, 255, 255))
        self.window.blit(textsurface, (100,265))

        if self.simulation.better_distance >= (INITIAL_DISTANCE - 2) * PIX2M:
            conclusion = "Eu aprendi a dirigir, Jony!"
            textsurface = font.render(conclusion, False, (255, 255, 255))
            self.window.blit(textsurface, (15,300))

    def matrixCollision(self):
        pxarray = pygame.PixelArray(self.window)
        array = np.array(pxarray, dtype="int32")
        for i in range(SCREEN_WIDTH):
            for j in range(SCREEN_HEIGHT):
                if array[i,j] < self.window.map_rgb((110,110,110)):
                    array[i, j] = 0
                elif  array[i,j] >= self.window.map_rgb((118,118,118)):
                    array[i, j] = 0
                else:
                    array[i,j] = 1
        # plt.matshow(array)
        # plt.show()
        self.collision_array = array
        self.cost_function()
        self.initial = False
        return array

    def cost_function(self):
        array = np.copy(self.collision_array)
        nodeArray = np.empty((SCREEN_WIDTH, SCREEN_HEIGHT), dtype=Node)

        # preparing array
        for i in range(SCREEN_WIDTH):
            for j in range(SCREEN_HEIGHT):
                if array[i,j] == 0:
                    nodeArray[i, j] = Node(i,j,-1)
                else:
                    nodeArray[i, j] = Node(i,j,-2)

        # queue of pixels
        queue = []
        # set zero for finish line
        initialPoint = FINISH_LINE[0]
        finishPoint = FINISH_LINE[1]
        for i in range(initialPoint[0], finishPoint[0] + 1):
            nodeArray[i, initialPoint[1]].setCost(0)
            queue.append(nodeArray[i, initialPoint[1]])

        while len(queue) != 0:
            node = queue.pop(0)
            # print(type(node.neighbor))
            for nodes in node.neighbor:
                if nodeArray[nodes].cost == -2:
                    queue.append(nodeArray[nodes])
                    nodeArray[nodes].setCost(node.cost + 1)

        for i in range(SCREEN_WIDTH):
            for j in range(SCREEN_HEIGHT):
                array[i, j] = nodeArray[i,j].cost

        self.cost_array = array
        # plt.matshow(array)
        # plt.show()
        self.simulation.resetTime()

class Node(object):

    def __init__(self, i, j, cost):

        self.i = i
        self.j = j
        self.cost = cost
        self.neighbor = self.getNeighbor()

    def setCost(self, cost):

        self.cost = cost

    def getNeighbor(self):
        neighbor = []
        for di in range(-1,2):
            for dj in range(-1,2):
                if self.is_index_valid(self.i+di, self.j+dj) and (di != 0 or dj != 0):
                    neighbor.append((self.i+di, self.j+dj))

        return neighbor

    def is_index_valid(self, i, j):
        return 0 <= i < SCREEN_WIDTH and 0 <= j < SCREEN_HEIGHT


from decimal import Decimal
from django.db.models import F, Sum
from django.conf import settings
from django.views.generic import ListView, DetailView, View
from ..models import *

class Cart(object):
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)

        if not cart:
            cart = self.session[settings.CART_SESSION_ID] = {}

        self.cart = cart

    def __iter__(self):
        for p in self.cart.keys():
            self.cart[str(p)]['product'] = Product.objects.get(pk=p)

        for item in self.cart.values():
            item['total_price'] = item['product'].price * item['quantity']

            yield item

    def __len__(self):
        return sum(item['quantity'] for item in self.cart.values())

    def add(self, product_id, quantity=1, update_quantity=False):
        product_id = str(product_id)

        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 1, 'id': product_id}

        if update_quantity:
            self.cart[product_id]['quantity'] += int(quantity)

            if self.cart[product_id]['quantity'] == 0:
                self.remove(product_id)

        self.save()

    def remove(self, product_id):
        if product_id in self.cart:
            del self.cart[product_id]
            self.save()

    def save(self):
        self.session[settings.CART_SESSION_ID] = self.cart
        self.session.modified = True

    def clear(self):
        del self.session[settings.CART_SESSION_ID]
        self.session.modified = True

    def get_total_cost(self):
        for p in self.cart.keys():
            self.cart[str(p)]['product'] = Product.objects.get(pk=p)

        return sum(item['quantity'] * item['product'].price for item in self.cart.values())

class CartMixin(View):

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            customer = Customer.objects.filter(user=request.user).first()
            if not customer:
                customer = Customer.objects.create(
                    user=request.user
                )
            cart = Cart.objects.filter(owner=customer, in_order=False).first()
            if not cart:
                cart = Cart.objects.create(owner=customer)
        else:
            cart = Cart.objects.filter(for_anonymous_user=True).first()
            if not cart:
                cart = Cart.objects.create(for_anonymous_user=True)
        self.cart = cart
        return super().dispatch(request, *args, **kwargs)


import json
import math
from time import perf_counter
import boto3
from fastapi import FastAPI
from pydantic import BaseModel
import requests
import pandas as pd
from datetime import datetime, time
from datetime import timedelta
import random as rnd

app = FastAPI()
server_url = "http://100.22.18.163"
max_cache_records = 1000000
default_cache_minutes = 10
volume_attach_threshold = 100000

class QueryInput(BaseModel):
    # device_id: str
    # start_time: str
    # end_time: str
    s_date_time: str
    e_date_time: str
    android_id: str

@app.post("/query_s3_all")
def query_s3_all(data: QueryInput):
    s_date_time_input = data.s_date_time
    e_date_time_input = data.e_date_time
    android_id = data.android_id
    s_date_time = datetime.strptime(s_date_time_input, "%Y-%m-%d %H:%M:%S")
    e_date_time = datetime.strptime(e_date_time_input, "%Y-%m-%d %H:%M:%S")
    now = datetime.now()
    date_time_now = now.strftime("%Y-%m-%d %H:%M:%S")
    now = datetime.strptime(date_time_now, "%Y-%m-%d %H:%M:%S")

    today = datetime.today()
    offset = (today.weekday() - 3) % 7
    last_thursday = today - timedelta(days=offset)
    last_thursday = datetime.combine(last_thursday, time()) # set to 00:00:00
    print(last_thursday)

    last_thursday = last_thursday - timedelta(days=7)  # prev of prev, because older than one week is for the end time of an interval
    print(last_thursday)

    now = str(now).replace(" ", "T")
    if e_date_time_input > now:
        e_date_time_input = now
    # sql = "Select * from S3Object s WHERE s._1 >= '" + s_date_time_input + "' AND s._1 < '" + e_date_time_input + "' AND s._2 = '" + android_id + "'"

    # determine EC2 or S3

    ec2 = 0
    s3 = 0
    s3_key_list = []

    if s_date_time >= e_date_time:
        pass
    elif last_thursday <= s_date_time:
        ec2 = 1
    elif last_thursday >= e_date_time:
        s3 = 1
    else:
        ec2 = 1
        s3 = 1

    if ec2 == 1 and s3 == 0:
        res = 0.023/30/24/3600
    else:
        res = perform_query(android_id, s_date_time_input, e_date_time_input, last_thursday)

    return res

def perform_query(android_id, s_date_time_input, e_date_time_input, last_thursday):
    time_interval_in_cache_url = server_url + ":3000/rpc/time_interval_in_cache"
    time_interval_in_cache_obj = {
        "device_id": android_id,
        "start_c": s_date_time_input,
        "end_c": e_date_time_input
    }
    time_interval_in_cache = requests.post(time_interval_in_cache_url, json=time_interval_in_cache_obj)
    cache_start_time = time_interval_in_cache.json()[0]["start_time"]
    cache_end_time = time_interval_in_cache.json()[0]["end_time"]
    last_thursday = str(last_thursday).replace(" ", "T")
    if cache_start_time <= last_thursday and cache_end_time >= e_date_time_input: # all in cache:
        res = 0.023/30/24/3600
    elif cache_start_time > last_thursday and cache_end_time >= e_date_time_input: # ec2 + s3 + cache
        ec2_res = 0.023/30/24/3600/2
        s3_res = 0.0067/2
        res = ec2_res + s3_res
    elif cache_start_time <= last_thursday and cache_end_time < e_date_time_input: # ec2 + cache + s3
        ec2_res = 0.023/30/24/3600/2
        s3_res = 0.0067/2
        res = ec2_res + s3_res
    else: # ec2 + s3 + cache + s3
        ec2_res = 0.023/30/24/3600/3
        s3_res_1 = 0.0067/3
        s3_res_2 = 0.0067/3
        res = ec2_res + s3_res_1 + s3_res_2

    return res

def query_app_usage_by_time_s3(android_id, s_date_time_input, e_date_time_input):
    cache_metadata_url = server_url + ':3000/cache_metadata'

    pk_now = datetime.now() + timedelta(hours=8) # Peking
    date_time_now = pk_now.strftime("%Y-%m-%d %H:%M:%S")
    pk_now = datetime.strptime(date_time_now, "%Y-%m-%d %H:%M:%S")
    print(str(pk_now).replace(" ", "T"))

    cache_metadata_obj = {
        "android_id": android_id,
        "start_time": s_date_time_input,
        "end_time": e_date_time_input,
        "num_records": 100,
        "upload_time": str(pk_now).replace(" ", "T"),
        "evict_time": calculate_eviction_time(e_date_time_input)
    }
    cache_metadata = requests.post(cache_metadata_url, json = cache_metadata_obj)

    remove_cache_metadata_duplicate_url = server_url + ":3000/rpc/remove_cache_metadata_duplicate"
    remove_cache_metadata_duplicate_obj = {
        "device_id": android_id
    }
    remove_cache_metadata_duplicate = requests.post(remove_cache_metadata_duplicate_url, json=remove_cache_metadata_duplicate_obj)

def calculate_eviction_time(e_date_time_input):
    e_date_time = datetime.strptime(e_date_time_input.replace("T", " "), "%Y-%m-%d %H:%M:%S")
    now = datetime.now()
    date_time_now = now.strftime("%Y-%m-%d %H:%M:%S")
    now = datetime.strptime(date_time_now, "%Y-%m-%d %H:%M:%S")
    base = 1737 # in seconds
    r = rnd.random()
    res = base # deterministic
    # res = base * math.log((math.e - 1) * r + 1) # probabalistic
    eviction_time = now + timedelta(seconds=res)
    print(eviction_time)
    return eviction_time


from fastapi import Depends, Response, status
from fastapi.routing import APIRouter
from fastapi_jwt_auth import AuthJWT
from sqlalchemy.orm import Session

from src.apps.jwt.schemas import AccessTokenOutputSchema
from src.apps.user.models import User
from src.apps.user.schemas import (UserLoginInputSchema, UserOutputSchema,
                                   UserRegisterSchema, UserUpdateSchema)
from src.apps.user.services import (authenticate, delete_single_user,
                                    get_all_users, get_single_user,
                                    register_user, update_single_user)
from src.core.pagination.models import PageParams
from src.core.pagination.schemas import PagedResponseSchema, T
from src.dependencies.get_db import get_db
from src.dependencies.user import authenticate_user

router = APIRouter(prefix="/users", tags=["users"])

@router.post(
    "/register", response_model=UserOutputSchema, status_code=status.HTTP_201_CREATED
)
def create_user(
    user: UserRegisterSchema, db: Session = Depends(get_db)
) -> UserOutputSchema:
    db_user = register_user(db, user)
    return db_user

@router.post(
    "/login", status_code=status.HTTP_200_OK, response_model=AccessTokenOutputSchema
)
def login_user(
    user_login_schema: UserLoginInputSchema,
    auth_jwt: AuthJWT = Depends(),
    db: Session = Depends(get_db),
) -> AccessTokenOutputSchema:
    user = authenticate(**user_login_schema.dict(), session=db)
    user_schema = UserOutputSchema.from_orm(user)
    access_token = auth_jwt.create_access_token(
        subject=user_schema.json(), algorithm="HS256"
    )

    return AccessTokenOutputSchema(access_token=access_token)

@router.get("/me", status_code=status.HTTP_200_OK, response_model=UserOutputSchema)
def get_logged_user(
    request_user: User = Depends(authenticate_user),
) -> UserOutputSchema:
    return UserOutputSchema.from_orm(request_user)

@router.get(
    "/",
    response_model=PagedResponseSchema[T],
    dependencies=[Depends(authenticate_user)],
    status_code=status.HTTP_200_OK,
)
def get_users(
    db: Session = Depends(get_db), page_params: PageParams = Depends()
) -> PagedResponseSchema[T]:
    db_users = get_all_users(db, page_params)
    return db_users

@router.get(
    "/{user_id}",
    dependencies=[Depends(authenticate_user)],
    response_model=UserOutputSchema,
    status_code=status.HTTP_200_OK,
)
def get_user(user_id: int, db: Session = Depends(get_db)) -> UserOutputSchema:
    db_user = get_single_user(db, user_id)
    return db_user

@router.patch(
    "/{user_id}",
    dependencies=[Depends(authenticate_user)],
    response_model=UserOutputSchema,
    status_code=status.HTTP_200_OK,
)
def update_user(
    user_id: int, user: UserUpdateSchema, db: Session = Depends(get_db)
) -> UserOutputSchema:
    db_user = update_single_user(db, user, user_id)
    return db_user

@router.delete(
    "/{user_id}",
    dependencies=[Depends(authenticate_user)],
    status_code=status.HTTP_204_NO_CONTENT,
)
def delete_user(user_id: int, db: Session = Depends(get_db)) -> Response:
    delete_single_user(db, user_id)
    return Response(status_code=status.HTTP_204_NO_CONTENT)


import keras
import keras.backend as K
from keras.models import Model
from keras.preprocessing.text import Tokenizer
from keras.models import Sequential, load_model
from keras.utils import np_utils,to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras.layers import Dense, Activation, Flatten, Dropout, BatchNormalization, Embedding, Add, add, Input
from keras.layers import Conv2D, MaxPooling2D, LSTM, Conv1D
from keras import regularizers
from keras.callbacks import LearningRateScheduler
from keras.optimizers import Adam, Adadelta, SGD, RMSprop, Adagrad, Adamax, Nadam
from keras.regularizers import l2
import tensorflow as tf
import numpy as np
import os,sys
import pandas as pd
import csv
import time

def lr_schedule(epoch):
    lrate = 0.001
    if epoch > 75:
        lrate = 0.0005
    if epoch > 100:
        lrate = 0.0001
    return lrate

def readListFile(list_file):
    file_list=[]
    with open (list_file,"r") as f:
        for line in f:
            file_list.append(line.strip())
    return file_list

def loadData(datafile):
    data = []
    label = []
    with open (datafile) as f:
        csv_line=csv.reader(f,delimiter=",")
        for parts in csv_line:
            if parts[0]=="Text": continue
            data.append(parts[0])
            label.append(int(parts[1]))
    return data,label

def normalize(arr):
    mini=np.min(arr[0])
    maxi=np.max(arr[0])
    arr[0]=(arr[0]-mini)/(maxi-mini)
    mini=np.min(arr[1])
    maxi=np.max(arr[1])
    arr[1]=(arr[1]-mini)/(maxi-mini)
    mini=np.min(arr[2])
    maxi=np.max(arr[2])
    arr[2]=(arr[2]-mini)/(maxi-mini)
    return arr

def normalize_2(arr):
    mini=np.min(arr)
    maxi=np.max(arr)
    arr=arr/maxi
    return arr

def createModel(x_train):
    num_filters=1
    kernel_size=(3)
    strides=1
    inputs=Input(shape=(1000,32))
    emb=Embedding(2547,32, input_length=1000)
    #print (x.)
    #sys.exit()
    conv=Conv1D(num_filters, kernel_size=kernel_size, input_shape=(1000,32), strides=strides, padding="same", kernel_initializer="he_normal", kernel_regularizer=l2(1e-4), activation="relu")
    model=Sequential()
    model.add(emb)
    x=conv(model.layers[0].output[0])
    #x=Tensor(model.layers[0].output)
    print ("x_shape:",x.shape)
    print (type(x))
    #sys.exit()
    for _ in range (1):
        model=conv(inputs)#model.add(conv)
        print ("1st: ", model.shape)
        model=BatchNormalization()(model)#model.add(BatchNormalization())
        print ("2nd: ", model.shape)
        model=add([x,model])#model.add(add[x,model.add(Dropout(0.2))])

    print ("Here: ", model.shape)
    #print (len(x_train))
    #print(model.layers[0].output.shape)
    #print(model.layers[0].output)
    #model_layer=K.function([mods.layers[0].input,K.learning_phase()],[mods.layers[0].output])

    #sys.exit()
    #model.add()

    """
    model.add(Dense(1024))
    model.add(Dropout(0.1))
    model.add(Dense(512))
    model.add(Dropout(0.1))
    model.add(Dense(128))
    model.add(Dropout(0.1))
    model.add(Dense(64))
    model.add(Dropout(0.1))
    model.add(Dense(32))
    """
    model=Dropout(0.1)(model)#model.add(Dropout(0.1))
    model=Flatten()(model)#model.add(Flatten())
    model=Dense(10,activation="relu")(model)#model.add(Dense(10))
    model=Dense(1,activation="sigmoid")(model)#model.add(Dense(1,input_dim=10,activation="sigmoid"))

    mod=Model(inputs=inputs,outputs=model)

    return mod

def saveModel(model):
    model.save(sys.argv[0].replace(".py","")+"HW4.h5")
    model.save_weights(sys.argv[0].replace(".py","")+"HW4_weights.h5")
    return

def trainModel(model,X_train,Y_train,X_test,Y_test,epoch=1,batch_size=1):
    optim = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
    #model.compile(loss="categorical_crossentropy", optimizer=optim, metrics=["accuracy"])
    model.compile(loss="binary_crossentropy", optimizer=optim, metrics=["accuracy"])
    history=model.fit(X_train, Y_train, validation_data=(X_test,Y_test), epochs= epoch, batch_size=batch_size)
    #history=model.fit(X_train, Y_train, validation_split=0.2, epochs= epoch, batch_size=batch_size)
    saveModel(model)
    return history

def testModel(X_test,Y_test,model=None):
    if (model==None):
        model=load_model(sys.argv[0].replace(".py","")+"HW4.h5")
    result=model.predict(X_test)
    """
    for i in range(len(X_test)):
        val=model.predict(X_test[i])
        if (val<0.5): result.append([val,0,test_y[i]])
        if (val>=0.5): result.append([val,1,test_y[i]])
    """
    return model,result

def trainIt(model,train_x,train_y,test_x,test_y,epoch):
    history=trainModel(model,train_x,train_y,test_x,test_y,epoch=50)
    train_loss = history.history["loss"]
    val_loss = history.history["val_loss"]
    train_acc= history.history["acc"]
    val_acc=history.history["val_acc"]

    with open (sys.argv[0].replace(".py","")+"_train_loss.txt","w") as f:
        for loss in train_loss:
            f.write(str(loss)+"\n")

    with open (sys.argv[0].replace(".py","")+"_val_loss.txt","w") as f:
        for loss in val_loss:
            f.write(str(loss)+"\n")

    with open (sys.argv[0].replace(".py","")+"_train_acc.txt","w") as f:
        for acc in train_acc:
            f.write(str(acc)+"\n")

    with open (sys.argv[0].replace(".py","")+"_val_acc.txt","w") as f:
        for acc in val_acc:
            f.write(str(acc)+"\n")

#Read the list of training and test data
#The following loads the training data and labels into a list. Labels are one-hot encoded
training_list_file="HW5_training.csv"
test_list_file="HW5_test.csv"
train_x,train_y=loadData(training_list_file)
test_x,test_y=loadData(test_list_file)
n_train=len(train_x)
n_test=len(test_x)
total=train_x+test_x
l=[]
for x in total:
    l.append(len(x))
print (max(l))
max_len=max(l)
token_train_x=Tokenizer(num_words=1000)#.fit_on_texts(train_x)
token_train_x.fit_on_texts(train_x)
print (train_x[0])
#Tokenize training text
train_x=token_train_x.texts_to_matrix(train_x,  mode="tfidf")
#train_x=train_x.reshape(len(train_x),1,train_x.shape[1])
train_x=train_x.reshape(len(train_x),train_x.shape[1])
#train_x=train_x.reshape(len(train_x),train_x.shape[1],1)
print(train_x.shape)
#Tokenize test text
token_test_x=Tokenizer(num_words=1000)#.fit_on_texts(train_x)
token_test_x.fit_on_texts(test_x)
test_x=token_test_x.texts_to_matrix(test_x,  mode="tfidf")
#test_x=test_x.reshape(len(test_x),1,test_x.shape[1])
test_x=test_x.reshape(len(test_x),test_x.shape[1])
train_y=np.asarray(train_y)
test_y=np.asarray(test_y)

train_x=normalize(train_x)
test_x=normalize(test_x)

#Convert input to Embeddings for Conv2D
print (train_x.shape)

mods=Sequential()
mods.add(Embedding(2547,32,input_length=1000))
mods.compile(optimizer='adam',loss="binary_crossentropy",metrics=['accuracy'])
mods.fit(train_x,train_y,verbose=False,epochs=1)

model_layer=K.function([mods.layers[0].input,K.learning_phase()],[mods.layers[0].output])
print ("This is it: ",model_layer([train_x])[0].shape)
sys.exit()

"""
mods=Sequential()
mods.add(Embedding(2547,32))
model_layer=K.function([mods.layers[0].input,K.learning_phase()],[mods.layers[0].output])
print ("This is it: ",model_layer([train_x])[0].shape)
sys.exit()
"""

#Activate cuda environment

os.environ["CUDA_VISIBLE_DEVICES"] = "0"
config = tf.ConfigProto(allow_soft_placement = True)
tf.GPUOptions(per_process_gpu_memory_fraction = 0.99)
config.gpu_options.allow_growth = True
sess= tf.Session(config = config)
print (train_x.shape)
#sys.exit()
model = createModel(train_x)
model.summary()
trainIt(model,train_x,train_y,test_x,test_y,epoch=1)
sys.exit()
model,predictions=testModel(test_x,test_y)
print(predictions)
print(model.evaluate(test_x,test_y,batch_size=20))
tp_00=0
tp_11=0
fp_01=0
fp_10=0
print("Test:")
for i in range(20):
    if predictions[i]<0.5:
        print ([0,test_y[i]])
        if (test_y[i]==0): tp_00+=1
        if (test_y[i]==1): fp_10+=1
    else:
        print ([1,test_y[i]])
        if (test_y[i]==1): tp_11+=1
        if (test_y[i]==0): fp_01+=1

print ("00",tp_00)
print ("01",fp_01)
print ("10",fp_10)
print ("11",tp_11)

print ("Training:")

model,predictions=testModel(train_x,train_y)
print(predictions)
print(model.evaluate(train_x,train_y,batch_size=100))
tp_00=0
tp_11=0
fp_01=0
fp_10=0

for i in range(100):
    if predictions[i]<0.5:
        print ([0,train_y[i]])
        if (train_y[i]==0): tp_00+=1
        if (train_y[i]==1): fp_10+=1
    else:
        print ([1,train_y[i]])
        if (train_y[i]==1): tp_11+=1
        if (train_y[i]==0): fp_01+=1

print ("00",tp_00)
print ("01",fp_01)
print ("10",fp_10)
print ("11",tp_11)


import pandas as pd
from gensim.models import Word2Vec
import operator
from numpy import take
from Word2VecTrain.Word2Vec_train import check_corpus
import time
import copy
import numpy
import joblib
from itertools import islice
from Word2VecTrain.EditDistance import controlKeywords
from string import digits

Word2VecModel = Word2Vec.load('C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/models/trained_data.model.bin')
df = pd.read_csv('C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/files/product_catalog.v2.csv')
abbrev = ['lı', 'li', 'lu', 'lü', 'kg', 'gr', 'lt', 'ml', 'cm']
manufacturers = []

def lowerForTurkish(str):
    rep = [('I', 'ı'), ('İ', 'i')]
    for search, replace in rep:
        str = str.replace(search, replace)
    return str.lower()
def take(n, iterable):
    return dict(islice(iterable, n))
def readStems():
    filename =('C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/files/stems_withoutverb.txt')
    stems = dict()
    with open(filename,encoding='utf8') as fstem:
        for line in fstem:
            val = line.split()
            stems[val[0]] = val[1]
    return stems
def controlProduct(product):

    productl = lowerForTurkish(product)
    productl,manufacturers = check_corpus(productl)
    splitted = productl.split()
    withManufac = productl.split()

    for i in splitted.copy():
        if (len(i) <2) :
            splitted.remove(i)
            withManufac.remove(i)
        elif i not in Word2VecModel.wv.vocab:
            splitted.remove(i)
            if i not in manufacturers:
                withManufac.remove(i)
        elif i in abbrev:
            splitted.remove(i)
    return splitted,withManufac
def getPredictions(words):
    #enSon_model.sav
    filename = 'C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/Classification/enSon_model.sav'
    model = joblib.load(filename)
    filename = 'C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/Classification/enSon_pca.sav'
    pca = joblib.load(filename)
    result = dict()
    for i in words:
        t = numpy.array(Word2VecModel.wv[i]).reshape(1, -1)
        t = pca.transform(t)
        rslt = model.predict_proba(t)[0]
        prob_per_class_dictionary = dict(zip(model.classes_, rslt))
        prob_per_class_dictionary = dict(sorted(prob_per_class_dictionary.items(), key=operator.itemgetter(1), reverse=True))

        temp = take(20,prob_per_class_dictionary.items())
        for k in temp:
            if k in result:
                result[k]+=temp[k]*100
            else:
                result[k]=temp[k]*100

    result = dict(sorted(result.items(), key=operator.itemgetter(1),reverse=True))
    return result

def searchEngine(keys):

    fread = open('C:/Users/Lenovo/Desktop/Bitirme/SearchEngine/files/checked_product.txt', 'r',encoding='utf8')
    numbers = [s for s in keys.split() if s.isdigit()]
    checkedPro = []
    withManufactPro = []
    for sentence in fread:
        sentence = sentence.rstrip('\n')
        sp = sentence.split(',')
        checkedPro.append(sp[1].split())
        withManufactPro.append(sp[2].split())

    keyWords = controlKeywords(keys)
    keyWordsCopy = copy.deepcopy(keyWords)
    for i in keyWords:
        if i not in Word2VecModel.wv.vocab:
            keyWords.remove(i)

    stems = readStems()

    for i in keyWordsCopy:
        if i in stems:
            newWord = stems[i]
            if newWord not in keyWordsCopy and newWord in Word2VecModel.wv.vocab:
                keyWordsCopy.append(newWord)

    puanlanmis = dict()
    if len(keyWords)>0:

        ind = 0
        for product in df['ProductName']:

            checked,withManufact = checkedPro[ind],withManufactPro[ind]
            #checked, withManufact = controlProduct(product)
            #fread.write(product+','+' '.join(checked)+','+' '.join(withManufact)+'\n')
            ind+=1

            if len(checked)>0 and len(keyWords)>0:
                puanlanmis[product]=Word2VecModel.wv.n_similarity(checked,keyWords)

                # arama kelimesinin kökü ürün içinde varsa +1
                for i in keyWordsCopy:
                    if i in checked:
                        puanlanmis[product] += 2
                    elif i not in checked and i in withManufact:
                        puanlanmis[product] += 2
                # ürün adındaki kelimenin kökü arama kelimesinde varsa +1
                for i in checked:
                    if i not in keyWordsCopy and i in stems and stems[i] not in checked and stems[i] in keyWordsCopy:
                        puanlanmis[product] +=2
                for i in numbers:
                    if i in [s for s in product.split() if s.isdigit()]:
                        puanlanmis[product] += 1

    if len(puanlanmis)>0  :
        puanlanmis = dict(sorted(puanlanmis.items(), reverse=True, key=operator.itemgetter(1)))
        classResult = getPredictions(keyWords)
        print(classResult)
        if puanlanmis[list(puanlanmis.keys())[0]]>0.7 and puanlanmis[list(classResult.keys())[0]]>0.7:

            size = len(keyWords)
            factor = 1
            if len(classResult)>0:
                if classResult[list(classResult.keys())[0]] < size:
                    factor = (size)/classResult[list(classResult.keys())[0]]
                for i in classResult:
                    if i in puanlanmis:
                        puanlanmis[i] += classResult[i]*factor

        puanlanmis = dict(sorted(puanlanmis.items(), reverse=True, key=operator.itemgetter(1)))
        remove_digits = str.maketrans('', '', digits)
        if keyWords!=lowerForTurkish(keys).translate(remove_digits).split():
            return take(50, puanlanmis.items()), ' '.join(keyWords)

        return take(50,puanlanmis.items()),None

    else:
        return None,None


"""
This is a simple simulation of cross-track position error based on IMU bias instability and angle random walk.
To run, set desired IMU specs, time, and velocity in main() and run the script.

Author: Kirstin Schauble - kirstin.schauble@anellophotonics.com
"""

import numpy as np
import matplotlib.pyplot as plt

def imu_position_error(bi, arw, T, dt, velocity, incl_bi, incl_arw):
    # Initialize variables
    t = np.arange(0, T, dt)
    N = len(t)

    for j in range(len(bi)):
        for k in range(len(arw)):
            # Initialize variables
            angle_bi = np.zeros(N)
            angle_arw = np.zeros(N)
            error_bi = np.zeros(N)
            error_arw = np.zeros(N)
            error = np.zeros(N)

            # Create legend labels
            if len(bi) > 1:
                legend_label = f'BI = {bi[j]} deg/hr'
            elif len(arw) >1:
                legend_label = f'ARW = {arw[k]} deg/rt(hr)'
            else:
                # legend_label = f'BI = {bi[j]} deg/hr; ARW = {arw[k]} deg/rt(hr)'
                legend_label = f'Velocity = {velocity} mph'

            # convert velocity, BI and ARW units
            velocity_mps = velocity/2.237 # mph to m/s
            bi_rad = [x * np.pi/180 / 3600 for x in bi] # deg/hr to rad/s
            arw_rad = [x * np.pi/180 / np.sqrt(3600) for x in arw] # deg/rthr to rad/rtsec

            for i in range(1, N):
                # add error from BI
                if incl_bi:
                    angle_bi[i] = angle_bi[i-1] + bi_rad[j] * dt # rad
                    error_bi[i] = error_bi[i-1] + velocity_mps * np.tan(angle_bi[i]) * dt # m

                # add angle error from ARW
                if incl_arw:
                    angle_arw[i] = arw_rad[k] * np.sqrt(t[i]) # rad
                    error_arw[i] = t[i] * velocity_mps * np.tan(angle_arw[i]) # m

                # total error
                error[i] = error_bi[i] + error_arw[i]

            # Plot
            plt.plot(t/60, error, label=legend_label)
            plt.legend()

    return error, t

def main():
    #Specs to include in simulation
    incl_bi = True
    incl_arw = True

    #IMU specs
    bi = [0.3] # bias instability in deg/hr
    arw = [0.03] # angle rangom walk in deg/rthr

    #Other parameters
    T = 3000 # total simulation time in seconds
    velocity = 30 # mph

    dt = 1 # time step in seconds
    error, t = imu_position_error(bi, arw, T, dt, velocity, incl_bi, incl_arw)

    plt.xlabel('Time (min)')
    plt.ylabel('Cross-track Error (m)')
    plt.grid()
    plt.tight_layout()
    plt.show()

if __name__ == "__main__":
    main()


""" Общие функции для сервера и клиента"""

import sys
import json
import argparse
from .variables import PACKAGE_SIZE, ENCODING_METHOD, \
    PORT_LISTEN, ADDR_LISTEN, DEFAULT_IP
# Загружаем ошибки
from .errors import DictionaryNotReceived, SenderIndicationError, \
    NonBytesMessage, JsonEncodeError, NonStrData, PortNumberError
# Обеспечиваем доступность пути к корню проекта
import os

sys.path.append(os.path.join(os.getcwd(), '..'))
# Загружаем обработчики логов клиента и сервера
import logging
import log.server_log_config
import log.client_log_config
# Загружаем декораторы
from decorators.log_deco import debug_log

def choose_log(sender):
    """
    Вспомогательная функция.
    Принимает источник вызова функции
    и устанавливает адресацию записи логов
    :param - sender: str
    """
    if sender == 'server':
        return logging.getLogger('server')
    elif sender == 'client':
        return logging.getLogger('client')
    else:
        raise SenderIndicationError

@debug_log
def send_response(sock, message, sender):
    """
    Принимает сообщение в виде словаря, осуществляет проверку соответствия.
    Генерирует ошибку в случае несовпадения содержимого.
    Кодирует сообщение в байтовый формат.
    Отправляет сообщение.
    :param - sock: socket
    :param - message: dict
    :param - sender: str
    :return None
    """
    log_aim = choose_log(sender)
    if not isinstance(message, dict):
        log_aim.error(f'Невозможно обработать сообщение {message}')
        raise DictionaryNotReceived
    try:
        json_message = json.dumps(message)
        encoded_message = json_message.encode(ENCODING_METHOD)
    except UnicodeEncodeError:
        log_aim.error(f'Невозможно обработать сообщение {message}')
        raise JsonEncodeError
    sock.send(encoded_message)
    log_aim.info('Сообщение отправлено')
    return

@debug_log
def get_response(client, sender):
    """
    Функция принимает сообщение в байтовом формате,
    Генерирует ValueError если данные получены другом формате
    или содержат ошибку.
    Возращает сообщение в JSON-формате (словарь).

    :return response: dict - json-data.
    """

    log_aim = choose_log(sender)
    log_aim.debug(f'Ожидается сообщение от {sender}')
    encoded_response = client.recv(PACKAGE_SIZE)
    if not isinstance(encoded_response, bytes):
        log_aim.error('Ошибка обработки данных в функции get_response')
        raise NonBytesMessage
    json_response = encoded_response.decode(ENCODING_METHOD)
    if not isinstance(json_response, str):
        log_aim.error('Ошибка обработки данных в функции get_response')
        raise NonStrData
    response = json.loads(json_response)
    if not isinstance(response, dict):
        raise DictionaryNotReceived
    log_aim.info(f'Получены новые данные от {sender}.')
    return response

@debug_log
def get_port_and_address_for_use(sender):
    """
    Осуществляет парсинг коммандной строки, возвращает кортеж с
    содержащий IP-адрес и номер порта. Генерирует ошибку при
    получении ошибочных параметров.
    :return tuple: (str(ip-address), int(port number))
    """
    log_aim = choose_log(sender)
    try:
        parser = argparse.ArgumentParser(
            description='Choose and indicate IP-address and port for server '
                        'listen. In case of options -p or -a is missing '
                        'default settings will be use. Available port in range '
                        '1024-65535. Exception will be generate in case of '
                        'mistake find.'
        )
        parser.add_argument('-p')
        parser.add_argument('-a')
        args = parser.parse_args()
        addr_listen, port_listen = args.a, args.p

        # Порт не указан в параметрах
        if port_listen is None:
            port_listen = PORT_LISTEN
        if int(port_listen) < 1024 or int(port_listen) > 65535:
            raise PortNumberError

        # Адрес не указан в параметрах
        if addr_listen is None:
            if sender == 'server':
                addr_listen = ADDR_LISTEN
            else:
                addr_listen = DEFAULT_IP

    except PortNumberError:
        log_aim.error(f'Номер порта должен быть указан в диапазоне от 1024 до 65535. Указано - {port_listen}')
        sys.exit(1)
    return addr_listen, int(port_listen)


from sortedcontainers import SortedList
class Solution:
    def oddEvenJumps(self, arr: List[int]) -> int:
        '''
        odd => 跳下一個略大 => maintain bst => bisect.bisect_left
        even => 跳下一個略小 => maintain bst => (neg) bisect.bisect_left

        [10,13,12,14,15]
    odd   F  F  F  T  T
    even  F  F  F  F  T
        '''
        n = len(arr)
        dp = [[False, False] for _ in range(n)]
        bigger = SortedList()
        smaller = SortedList()

        dp[-1][0] = dp[-1][1] = True
        bigger.add((arr[-1], n-1))
        smaller.add((-arr[-1], n-1))

        for i in range(n-2, -1, -1):
            val = arr[i]
            b = bigger.bisect_left((val,))
            s = smaller.bisect_left((-val,))

            # odd
            if b < len(bigger):
                bigger_val, bigger_index = bigger[b]
                dp[i][0] = dp[bigger_index][1]

            # even
            if i > 0 and s < len(smaller):
                smaller_val, smaller_index = smaller[s]
                dp[i][1] = dp[smaller_index][0]

            bigger.add((val, i))
            smaller.add((-val, i))

        return sum([dp[i][0] for i in range(n)])


from django.shortcuts import render

# Create your views here.

from django.shortcuts import render, redirect
from .forms import RegisterForm

# Create your views here.
def register(response):
    if response.method == "POST":
        form = RegisterForm(response.POST)
        if form.is_valid():
            print("form is valid")
            form.save()

        else:
            print(response.POST)

        return redirect("login")
    else:
        form = RegisterForm()

    return render(response, "registration/register.html", {"form": form})

def home(request):
    return render(request, 'home.html')


import torch
import torch.distributed as dist
import torch.distributed.rpc as rpc
import torch.multiprocessing as mp
from torch.distributed.optim import DistributedOptimizer

import os
import random

NUM = 1000
DIM = 64

class EmbeddingPS(torch.nn.Module):
    def __init__(self, num, dim):
        super().__init__()
        self.embed = torch.nn.EmbeddingBag(num_embeddings=num,embedding_dim=dim, mode='sum')

    def forward(self, indics, offset):
        ''' '''
        return self.embed(indics, offset).cpu()

def _retrieve_embedding_parameters(emb_rref):
    param_rrefs = []
    for param in emb_rref.local_value().parameters():
        param_rrefs.append(rpc.RRef(param))
    return param_rrefs

class Model(torch.nn.Module):
    def __init__(self, embed_rref, device_id):
        super().__init__()
        self.embed_rref = embed_rref
        self.device_id = device_id

        fc = torch.nn.Linear(DIM, DIM).cuda(device_id)
        self.fc = torch.nn.parallel.DistributedDataParallel(fc, device_ids=[device_id])

    def forward(self, indics, offset):
        emb_lookup = self.emb_rref.rpc_sync().forward(indics, offset)
        return self.fc(emb_lookup.to(self.device_id))

def _worker(rref, rank):
    '''
    '''
    num_indices = random.randint(20, 50)
    indices = torch.LongTensor(num_indices).random_(0, NUM)

    offsets = []
    start = 0
    while start < num_indices:
        offsets.append(start)
        start += random.randint(1, 10)
    offsets = torch.LongTensor(offsets)

    print(rank, indices.shape, offsets.shape)

    # model = Model(rref, rank)
    output = rref.rpc_sync().forward(indices, offsets)
    print(rank, output.shape)

    params_rref = rpc.rpc_sync(to='ps', func=_retrieve_embedding_parameters, args=(rref, ))
    # params_rref.extend([dist.rpc.RRef(p) for p in model.parameters()])

    opt = dist.optim.DistributedOptimizer(torch.optim.Adam, params_rref, lr=0.01)
    # criterion = torch.nn.CrossEntropyLoss()

    for e in range(5):
        for indices, offsets in [(indices, offsets), ]:
            with dist.autograd.context() as context_id:
                output = rref.rpc_sync().forward(indices, offsets)
                # output = model(indices, offsets)
                loss = output.sum()
                dist.autograd.backward(context_id, [loss])
                opt.step(context_id)

        print(rank, e, loss.item())

def run_worker(rank, world_size, ):
    '''
    '''
    os.environ['MASTER_ADDR'] = 'localhost'
    os.environ['MASTER_PORT'] = '50000'

    rpc_backend_options = rpc.TensorPipeRpcBackendOptions()
    # rpc_backend_options.num_worker_threads = 8
    rpc_backend_options.init_method = 'tcp://localhost:50001'
    # rpc_backend_options.rpc_timeout = 2

    if rank == 3:
        '''master'''
        rpc.init_rpc('master', rank=rank, world_size=world_size, backend=rpc.BackendType.TENSORPIPE, rpc_backend_options=rpc_backend_options) # ,

        embed_rref = rpc.remote(to='ps', func=EmbeddingPS, args=(NUM, DIM), )

        _ps = []
        for trainer_rank in [0, 1]:
            trainer_name = f'trainer{trainer_rank}'
            _p = rpc.rpc_async(to=trainer_name, func=_worker, args=(embed_rref, trainer_rank))
            _ps.append(_p)

        for _p in _ps:
            _p.wait()

    elif rank in [0, 1]:
        '''ddp worker'''
        dist.init_process_group('gloo', rank=rank, world_size=2)
        rpc.init_rpc(f'trainer{rank}', rank=rank, world_size=world_size, backend=rpc.BackendType.TENSORPIPE, rpc_backend_options=rpc_backend_options)
        pass

    else:
        '''ps'''
        rpc.init_rpc('ps', rank=rank, world_size=world_size, backend=rpc.BackendType.TENSORPIPE, rpc_backend_options=rpc_backend_options)
        pass

    # dist.destroy_process_group()
    rpc.shutdown()

if __name__ == '__main__':
    '''
    '''
    world_size = 4
    mp.spawn(run_worker, args=(world_size, ), nprocs=world_size, join=True)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This modules contains the SearchBar class.
"""
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class SearchBar(Gtk.Box, Gtk.SearchBar):
    """
    This class contains methods related the SearchBar class.
    """

    # ----------------------------------------------------------------------

    def __init__(self, main_window):
        super(SearchBar, self).__init__()

        self.main_window = main_window
        self.search_entry = Gtk.SearchEntry()
        self.search_entry.connect("search-changed", self.search_changed)
        self.pack_start(self.search_entry, True, True, 0)

    # ----------------------------------------------------------------------
    def search_changed(self, data):
        """
        This method monitors if search was search_changed.
            Parameter:
            Returns:
                * **SearchBar** (:class:`SearchBar<mosaicode.GUI.searchbar>`)
        """
        self.main_window.main_control.search(
            self.search_entry.get_text().upper())
        return self.search_entry.get_text()
# ---------------------------------------------------------------------------


#!/usr/bin/python3

import inspect
import json
from models import base
from models.base import Base
from unittest.mock import patch
import unittest

class TestBase(unittest.TestCase):
    """unittest class for the Base class"""

    @classmethod
    def setUpClass(cls):
        """Importing all functions from Base class"""
        cls.base_functions = inspect.getmembers(Base, inspect.isfunction)

    def test_func_docstrings(self):
        """Tests for the existence of docstrings in all functions"""
        for func_name, func in self.base_functions:
            self.assertTrue(func.__doc__ is not None, f"Missing docstring for function: {func_name}")

    def test_to_json_string(self):
        dict1 = {"id": 9, "width": 5, "height": 6, "x": 7, "y": 8}
        dict2 = {"id": 2, "width": 2, "height": 3, "x": 4, "y": 0}
        json_str = Base.to_json_string([dict1, dict2])
        self.assertIsInstance(json_str, str)
        d = json.loads(json_str) #convert back to list objects of two dictionaries
        self.assertEqual(d, [dict1, dict2])

if __name__ == '__main__':
    unittest.main()


"""
  Name     : c12_08_uniform_dist.py
  Book     : Python for Finance (2nd ed.)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan
  Date     : 6/6/2017
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""

import scipy as sp
sp.random.seed(123345)
x=sp.random.uniform(low=1,high=100,size=10)
print(x[0:5])


#!/usr/bin/env python3
import sys
if sys.version_info[0] < 3:
    raise Exception("Must be using Python 3")

import http.server
import socketserver
import socket
import os
import sys

class NoCacheHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_my_headers()
        http.server.SimpleHTTPRequestHandler.end_headers(self)

    def send_my_headers(self):
        self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
        self.send_header("Pragma", "no-cache")
        self.send_header("Expires", "0")

    def do_GET(self):
        if '.png?' in self.path:
            self.path = self.path.split('.png?')[0]+'.png'

        http.server.SimpleHTTPRequestHandler.do_GET(self)

class RocTCPServer(socketserver.TCPServer):
    def server_bind(self):
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)

def run_server():
    Handler = NoCacheHTTPRequestHandler
    os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)),'.'))
    try:
        with RocTCPServer((IPAddr, PORT), Handler) as httpd:
            httpd.serve_forever()
    except KeyboardInterrupt:
        pass

def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(0)
    try:
        hostname = socket.gethostname()
        IPAddr = socket.gethostbyname(hostname)
        s.connect(({IPAddr}, 1))
    except Exception:
        IPAddr = '127.0.0.1'
    finally:
        return IPAddr

IPAddr = get_ip()
PORT = 8000

if len(sys.argv) > 1:
    PORT = int(sys.argv[1])
print('serving at port: {0}'.format(PORT))

try:
    run_server()
except KeyboardInterrupt:
    print("Exitting.")