from __future__ import print_function

from __future__ import absolute_import
from __future__ import division

from  simplesvg import Path, Text

from    . _math import (
    Point, sin, cos, between, pi,
    atan2, midpoint, sqrt, dist )

import attr

@attr.s(cmp=False)
class ArcDecorations(object):
    radius  = attr.ib()
    spacing = attr.ib()

    def __call__(self, ctr, leg0, leg1, bigArc=False, n=1, **kw):
        ctr, leg0, leg1 = Point.from_any(ctr, leg0, leg1)

        radius  = kw.pop( 'radius',  self.radius)
        spacing = kw.pop('spacing', self.spacing)

        dst0 = dist(ctr, leg0)
        dst1 = dist(ctr, leg1)

        p0 = between(ctr, leg0, radius/dst0)
        p1 = between(ctr, leg1, radius/dst1)

        ## ?? IVY ?? ##
        a0 = atan2(p0.y-ctr.y, p0.x-ctr.x)
        a1 = atan2(p1.y-ctr.y, p1.x-ctr.x)

        if a0>a1:
            p0,p1 = p1,p0
            a0,a1 = a1,a0

            leg0,leg1 = leg1,leg0
            dst0,dst1 = dst1,dst0

        incAngle = bigArc if a1-a0 > pi else not bigArc

        kw['fill-opacity'] = 0
        path = Path(p0, **kw)

        while n:
            path.abs.arcTo(p1, radius, radius, 0, bigArc, incAngle)

            n -= 1

            if n:
                radius += spacing

                leg0, leg1 = leg1,leg0
                dst0, dst1 = dst1,dst0

                p0 = between(ctr, leg0, radius/dst0)
                path.abs.moveTo(p0)

                p1 = between(ctr, leg1, radius/dst1)
                incAngle = not incAngle

        return path

@attr.s(cmp=False)
class CornerDecorations(object):
    """
    Draws straight lines rather than arcs. Intended to implement "right
    angle" figure annotations, but provides functionality analogous to
    the ArcDecorations class.

    "legLength" is defined as the length from the center along each leg
    to the endpoints of the decoration lying on the legs.

    "diagonal" is the distance from the center along the angle bisector
    to the vertex of the corner, somewhat analogous to an arc's radius.
    For a right angle's conventional half-square symbol this is sqrt(2)
    times legLength, which is the default."""

    legLength = attr.ib()
    diagonal  = attr.ib()
    spacing   = attr.ib(default=None)

    @diagonal.default
    def _(self):
        return self.legLength * sqrt(2)

    def __call__(self, ctr, leg0, leg1, bigArc=False, n=1, **kw):
        ctr, leg0, leg1 = Point.from_any(ctr, leg0, leg1)

        legLength = kw.pop('legLength', self.legLength)
        diagonal  = kw.pop( 'diagonal',  self.diagonal)
        spacing   = kw.pop(  'spacing',   self.spacing)

        diagonalSpacing = diagonal / legLength * spacing

        dst0 = dist(ctr, leg0)
        dst1 = dist(ctr, leg1)

        p0 = between(ctr, leg0, legLength/dst0)
        p1 = between(ctr, leg1, legLength/dst1)

        pm = midpoint( p0, p1)
        dm =     dist(ctr, pm)

        bs0, bs1 = ctr, pm

        if bigArc:
            bs0, bs1 = bs1, bs0

        pv = between(bs0, bs1, diagonal/dm)

        kw['fill-opacity'] = 0
        path = Path(p0, **kw)

        while n:

            path.abs.lineTo(pv)
            path.abs.lineTo(p1)

            n -= 1

            if n:
                legLength += spacing
                diagonal  += diagonalSpacing

                leg0, leg1 = leg1, leg0
                dst0, dst1 = dst1, dst0

                p0 = between(ctr, leg0, legLength/dst0)
                path.abs.moveTo(p0)

                p1 = between(ctr, leg1, legLength/dst1)
                pv = between(bs0,  bs1, diagonal/dm)

        return path

@attr.s(cmp=False)
class HatchDecorations(object):
    length  = attr.ib()
    spacing = attr.ib()

    def __call__(self, pt0, pt1, n=1, **kw):
        pt0, pt1 = Point.from_any(pt0, pt1)

        length  = kw.pop( 'length',  self.length)
        spacing = kw.pop('spacing', self.spacing)

        inc   = spacing / dist(pt0, pt1)
        tick0 = .5 - (n-1)/2*inc

        crossings = [between(pt0, pt1, tick0+inc*i) for i in range(n)]

        if abs(pt1.y-pt0.y)<1e-9:
            slope = None
        else:
            slope = -(pt1.x-pt0.x)/(pt1.y-pt0.y)

        # A slope and a point define a line; the point is also the
        # center of a circle, the diameter of which is the tick length.
        # The intersection defines the endpoints of the tick mark.

        pti = crossings[0]

        if slope is None:
            z   = length/2
            pt0 = Point(pti.x, pti.y-z)
            pt1 = Point(pti.x, pti.y+z)
        else:
            z   = length/2/sqrt(1+slope**2)
            pt0 = Point(pti.x-z, pti.y-slope*z)
            pt1 = Point(pti.x+z, pti.y+slope*z)

        path = Path(pt0, **kw)

        while crossings:
            path.abs.lineTo(pt1)

            crossings.pop(0)

            if crossings:
                pti = crossings[0]

                if slope is None:
                    pt0 = Point(pti.x, pti.y-z)
                    path.abs.moveTo(pt0)
                    pt1 = Point(pti.x, pti.y+z)
                else:
                    pt0 = Point(pti.x-z, pti.y-slope*z)
                    path.abs.moveTo(pt0)
                    pt1 = Point(pti.x+z, pti.y+slope*z)

        return path

class LineLabel(Text):
    # inverting the order of points is identical to inverting the rotation
    def __init__(self, pt1, pt2, text='', invert=False, **kw):
        pt1, pt2 = Point.from_any(pt1, pt2)

        if invert:
            pt1,pt2 = pt2,pt1

        midPt = midpoint(pt1, pt2)

        ## ?? IVY ?? ##
        kw.update(transform='rotate({:f} {},{})'.format(
            180/pi * atan2(pt2.y-pt1.y, pt2.x-pt1.x), *midPt))

        kw['text-anchor'] = 'middle'
        Text.__init__(self, midPt, text, **kw)

import sys

def float_out(*args):
    return ','.join(['{:.2f}'.format(arg) for arg in args])

class OhMy(str):
    def __new__(cls, s):
        return str.__new__(cls, s)

def print_(*args):
    for arg in args:
        if isinstance(arg, OhMy):
            print(arg, end='', file=sys.stderr)

        else:
            if not isinstance(arg, Point):
                arg = [arg]

            print(float_out(*arg), file=sys.stderr)

class AngleLabel(Text):
    def __init__(self, ctr, leg0, leg1, radius=None, text='', rotate=0, dx=None, dy=None, **kw):
        ctr, leg0, leg1 = Point.from_any(ctr, leg0, leg1)

        show = kw.pop('show', False)

        dst0 = dist(ctr, leg0)
        dst1 = dist(ctr, leg1)

        r  = (dst0 + dst1) / 2

        p0 = between(ctr, leg0, r/dst0)
        p1 = between(ctr, leg1, r/dst1)

        ## ?? IVY ?? ##
        a0 = atan2(p0.y-ctr.y, p0.x-ctr.x)
        a1 = atan2(p1.y-ctr.y, p1.x-ctr.x)

        a  = (a0+a1)/2 + rotate

        if show:
            print_(
                ctr,r,OhMy('\n'),
                p0,leg0,dst0,p0.y-ctr.y, p0.x-ctr.x,OhMy('\n'),
                p1,leg1,dst1,p1.y-ctr.y, p1.x-ctr.x,OhMy('\n'),
                a0/pi*180,a1/pi*180,a/pi*180 )

        ## ?? IVY ?? ##
        pt = ctr + Point(
            radius*cos(a) if dx is None else dx,
            radius*sin(a) if dy is None else dy )

        kw['text-anchor'] = 'middle'
        Text.__init__(self, pt, text, **kw)

__all__ = [i+'Decorations' for i in ('Arc', 'Hatch', 'Corner')] + [i+'Label' for i in ('Line', 'Angle')]


import glob
import os
import sys

try:
    sys.path.append(glob.glob('../carla/dist/carla-*%d.%d-%s.egg' % (
        sys.version_info.major,
        sys.version_info.minor,
        'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
except IndexError:
    pass

import carla

import random
import time
import numpy as np

# receive the velocity and receive acc
def action(vehicle,acc,angle_old,angle_new,deltat):
    # angle_loc is the angle change in transform, angle_global is the angle in world
    # obtain the vel info of actor
    current_vel = vehicle.get_velocity()
    # the coming angular velocity in deltat
    angle_vel = (angle_new-angle_old)/deltat
    indicator = np.sign(acc)
    change_vel_x = indicator*acc*np.cos(angle_new)*deltat
    change_vel_y = indicator*acc*np.sin(angle_new)*deltat
    change_vel_z = acc*0

    change_vel = carla.Vector3D(change_vel_x,change_vel_y,change_vel_z)
    new_ang_vel = carla.Vector3D(0,0,angle_vel)
    new_vel = current_vel + change_vel
    vehicle.set_angular_velocity(new_ang_vel)
    vehicle.set_velocity(new_vel)

def vehicle_info(vehicle):
    current_vel = vehicle.get_velocity()
    current_acc = vehicle.get_acceleration()

    return current_vel, current_acc

# define the actor list, containing vehivle, camera, sensor
actor_list = []
try:
    client = carla.Client('localhost', 2000)
    client.set_timeout(2.0)

    world = client.get_world()
    # get carla.BlueprintLibrary
    blueprint_library = world.get_blueprint_library()

    bp = blueprint_library.filter('model3')[0]
    print(bp)

    deltat = 0.1

    # spawn_point = random.choice(world.get_map().get_spawn_points()) # type: transform
    spawn_point = carla.Transform(carla.Location(4440,700,50),carla.Rotation(0,0,0))
    x=79.8
    y=40
    z=0
    new_point = carla.Location(79.8, 40, 0.0)
    # generate the vehicle actor
    vehicle = world.spawn_actor(bp, spawn_point)
    vehicle.set_location(new_point)
    actor_list.append(vehicle)

    ##########################################################
    deltat=0.1
    action(vehicle,5,90,-90,deltat)

    time.sleep(deltat)

    ##########################################################
    '''for i in range(3000):
        x=x+0.3
        new_point = carla.Location(x,y,z)
        vehicle.set_location(new_point)
        time.sleep(0.01)'''
    # vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=0.0))
    # # sleep for 3 seconds, then finish:
    # time.sleep(5)
    # vehicle.apply_control(carla.VehicleControl(hand_brake=True))
    # vehicle.apply_control(carla.VehicleControl(hand_brake=False))
    # vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=0.0,reverse=True))

    # sleep for 10 seconds, then finish:
    #time.sleep(1)

finally:

    print('destroying actors')
    for actor in actor_list:
        actor.destroy()
    print('done.')


# -*- coding: UTF-8 -*-

from dogwood.core.logger import Logger
from dogwood.core.base_thread import BaseThread
from dogwood.core.network.net_notify import NetNotify
from dogwood.core.network.net_def import NeTDef
from dogwood.core.gameframe.net_packet_split import NetPacketSplit, NetSplitMgr, NetSplitError
from dogwood.core.gameframe.base_client import BaseClient, ClientMgr, ClientError
from dogwood.core.base_packet import PacketError
from dogwood.core.mysql.mysql_monitor import MySqlMonitor
from dogwood.core.meta_class import Singleton, DeriveSingleton

class BaseGameMain(BaseThread, metaclass=Singleton):
    '''此类及派生类,一个工程里只能启动一个'''
    __slots__ = ('_mysql_monitor', '_client_mgr', '_net_split_mgr', '_net_dict')
    def __init__(self, event):
        real_cls_name = self.__class__.__name__
        DeriveSingleton.check_exist('BaseGameMain', real_cls_name)

        super().__init__(event)

        self._mysql_monitor = MySqlMonitor(self)         # mysql操作器
        self._client_mgr = ClientMgr()                   # 管理所有客户端连接
        self._net_split_mgr = NetSplitMgr()              # 网络粘包处理的管理器
        self._net_dict = {}                              # 网络监听进程字典

    def add_net(self, net_process):
        self._net_dict[net_process.net_id] = net_process

    def thread_init(self):              # 重载
        super().thread_init()
        self.create_db_monitor()
        self.create_game_config()

    def thread_quit(self):
        self.close_db_monitor()
        super().thread_quit()

    def create_game_config(self):
        '''子类要重载,创建自己的配置类'''
        pass

    def create_db_monitor(self):
        '''子类要重载,创建自己的数据库管理类'''
        pass

    def close_db_monitor(self):
        self._mysql_monitor.close_all()

    def fill_msg_queue(self):                               # 重载父类
        for net_proc in self._net_dict.values():
            while not net_proc.pull_msg_empty():
                msg_obj = net_proc.pull_msg()
                self._msg_queue.put(msg_obj)

    def process_msg(self, msg_obj):                     # 重载父类
        '''子类重载时,记得调用super().process_msg'''
        if type(msg_obj) is NetNotify:                      # 只处理网络消息
            if msg_obj.ope == NeTDef.CONNECT.value:             #新连接连上
                try:
                    self.create_packet_split(msg_obj.sid)           # 创建粘包处理器
                except NetSplitError as e:
                    Logger().warning(e)
                try:
                    client = self.create_client(msg_obj.sid)
                    self._client_mgr.on_net_connect(msg_obj.sid)
                except ClientError as e:
                    Logger().warning(e)
            elif msg_obj.ope == NeTDef.DISCONNECT.value:        # 连接关闭
                self._net_split_mgr.remove_split(msg_obj.sid)     # 关闭粘包处理
                try:
                    self._client_mgr.on_net_disconnect(msg_obj.sid)     # 关闭客户端
                except ClientError as e:
                    Logger().warning(e)
            elif msg_obj.ope == NeTDef.RECV.value:              # 收到网络消息
                if msg_obj.buf is None or len(msg_obj.buf) == 0:
                    Logger().warning('收到空串,{}'.format(msg_obj.sid))
                    return
                try:
                    sid, pack_list = self._net_split_mgr.deal_with_bytes(msg_obj.sid, msg_obj.buf)      #粘包处理
                    for pack in pack_list:
                        try:
                            self._client_mgr.push_net_msg(sid, pack)
                        except ClientError as e:
                            Logger().warning(e)
                except PacketError as e:
                    Logger().warning(e)
            elif msg_obj.ope == NeTDef.CLIENT_CONNECT_FAIL.value:           # 作为客户端,连远程服务器失败
                self.on_client_connect_fail(msg_obj.sid)

    def create_packet_split(self, sock_id):
        '''子类要重载，返回自己的粘包处理类'''
        split = NetPacketSplit(sock_id)
        self._net_split_mgr.add_split(sock_id, split)

    def create_client(self, sock_id):
        '''子类要重载，返回自己的客户端类'''
        client = BaseClient(self._client_mgr, sock_id)
        return client

    def process_timer(self, now_milli):
        '''子类重载,需调用super().process_timer(now_milli)'''
        super().process_timer(now_milli)
        self._mysql_monitor.run_timer(now_milli)
        self._client_mgr.run_timer(now_milli)

    def on_client_connect_fail(self, sock_id):
        '''子类选择重载,添加自己的连远程服务器失败处理,如果不存在连接远程服务器,则不需要'''
        pass

    def close_socket(self, sock_id, is_svr):
        if is_svr:
            ntif = NetNotify(sock_id, NeTDef.SERVER_CLOSE.value)
        else:
            ntif = NetNotify(sock_id, NeTDef.CLIENT_CLOSE.value)
        self._net_dict[sock_id.net_id].push_msg(ntif)

    def send_socket_msg(self, sock_id, buffer):
        ntif = NetNotify(sock_id, NeTDef.SEND.value, buffer)
        self._net_dict[sock_id.net_id].push_msg(ntif)

    @property
    def mysql_monitor(self):
        return self._mysql_monitor

    @property
    def client_mgr(self):
        return self._client_mgr


"""
Provides a super class for stages of a pipeline.
"""
from abc import ABC, abstractmethod
from typing import Tuple
import os
import pathlib
import time
import urllib.request
import zipfile

import numpy as np
from PIL import Image, ImageDraw, ImageFont

from pipeline.models.time import Time
from pipeline.stage_result import StageResult

class Stage(ABC):
    """
    A stage of a pipeline.
    """

    def __init__(self):
        self._start = 0
        self._time = 0
        self._executions = 0

        self.pipeline = None

    def _array2tuple(self, array: np.array) -> Tuple[int, int]:
        return (array[0], array[1])

    def _draw_rectangle(self, img, draw):
        draw.rectangle(((0, 0), img.size), fill="white")
        draw.rectangle(
            ((0, 0), self._array2tuple(np.array(img.size) - np.array([1, 1]))),
            outline="black",
        )

    def _get_font(self, size: int):
        pathlib.Path("./tools").mkdir(exist_ok=True)

        url = "https://github.com/floriankarsten/space-grotesk/releases/download/2.0.0/SpaceGrotesk-2.0.0.zip"
        font_archive = "tools/SpaceGrotesk.zip"
        font_path = "tools/SpaceGrotesk"

        if not os.path.exists(font_archive):
            urllib.request.urlretrieve(url, font_archive)

        if not os.path.exists(font_path):
            with zipfile.ZipFile(font_archive, "r") as archive:
                archive.extractall(font_path)

        return ImageFont.truetype(
            "tools/SpaceGrotesk/SpaceGrotesk-2.0.0/ttf/static/SpaceGrotesk-Regular.ttf",
            size,
        )

    def after_execute(self):
        """
        Executed after the execute method.
        """

        self._time += time.perf_counter() - self._start

    def before_execute(self):
        """
        Executed before the execute method.
        """

        self._start = time.perf_counter()
        self._executions += 1

    @abstractmethod
    def execute(self) -> StageResult:
        """
        When implemented in a child class, processes the provided state and returns a new state.
        """

    def before_init(self) -> None:
        """
        Called immediately after instructor is called.
        """

    def on_init(self) -> None:
        """
        Called when the application is started.  Just before the pipeline begins.
        """

    def on_destroy(self) -> None:
        """
        Called when the application is closed, just before the pipeline is destroyed.
        """

    def get_time(self) -> Time:
        """
        Calculates the average time per execution of this stage.
        """

        return Time(type(self).__name__, self._time / self._executions)

    def flowchart_image(self):
        """
        Generates a flowchart for the current stage.
        """

        name = type(self).__name__

        font = self._get_font(24)

        padding = np.array([10, 10])
        text_size = np.array(font.getsize(name))
        text_size_padding = text_size + 2 * padding

        img = Image.new("1", self._array2tuple(text_size_padding))
        draw = ImageDraw.Draw(img)

        self._draw_rectangle(img, draw)
        draw.text(self._array2tuple(padding - np.array([0, 1])), name, font=font)

        start = (0, img.size[1] / 2)
        end = (img.size[0], img.size[1] / 2)

        return (img, start, end)


"""
Un nodo è composto da:
- un oggetto che rappresenta il nodo nel grafico
- un oggetto che rappresenta il nodo nel codice
- un'interfaccia che permette di comunicare tra il nodo nel grafico e il nodo nel codice

                    nodeInterface
                    |            \
                    |             \
                nodeGraphic     nodeData

Di per se un nodo non fa niente di particolare, a parte prendere un valore in ingresso
 e restituirlo in uscita.

Il nodo può essere modificato in modo da fare qualcosa di particolare, per esempio
un nodo che somma due numeri, o un nodo che moltiplica due numeri, o un nodo che
fa una media di due numeri, etc etc.

    Per farlo si può creare una classe che eredita abstractNodeInterface, e che implementa
    il metodo calculateOutput(plugIndex).

    Inoltre è possibile cambiare il numero di Input, il numero di output, il colore del nodo,
    la dimensione del nodo, etc etc.

Basando sulle vecchie implementazioni, presenti nella cartella Nodes, copilot, creerà
AbstractNodeData, AbstractNodeGraphic, AbstractNodeInterface, in modo da semplificare
la creazione di nuovi nodi come descritto sopra.

# background-color: {self.graphicNode.proxyColorFill.name()};
"""

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class ConvertToGrayscaleThread(QThread):
    converted = pyqtSignal(QPixmap, name="converted")

    def __init__(self, filename, grayStyle):
        super().__init__()
        self.filename = filename
        self.grayStyle = grayStyle
        self.stopped = False

    def run(self):
        # Carica l'immagine e ridimensiona se necessario
        image = QImage(self.filename)
        width = image.width()
        height = image.height()
        for y in range(height):
            for x in range(width):
                r, g, b, a = image.pixelColor(x, y).getRgb()
                if self.grayStyle == "Luminosity":
                    gray = int(0.21 * r + 0.72 * g + 0.07 * b)
                elif self.grayStyle == "Average":
                    gray = (r + g + b) // 3
                elif self.grayStyle == "gOnly":
                    gray = g + g + g // 3
                elif self.grayStyle == "rOnly":
                    gray = r
                elif self.grayStyle == "bOnly":
                    gray = b
                else:
                    gray = int(0.16 * r + 0.67 * g + 0.07 * b)
                image.setPixel(x, y, qRgba(gray, gray, gray, a))
                if self.stopped:
                    return
        pixmap = QPixmap.fromImage(image)

        # Emitti il segnale con l'immagine convertita
        self.converted.emit(pixmap)

    def stopThread(self):
        self.stopped = True
        self.wait()

class SuperTxtTitle(QGraphicsTextItem):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent

    def setColor(self, color):
        self.setDefaultTextColor(color)

    def setText(self, txt):
        title = self.parent.nodeInterface.updateTxtTitleFromGraphics(txt)
        self.parent.updateTitlePosition()

    def eventFilter(self, obj, event):
        # Verifica se l'evento è una pressione del tasto Invio
        if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Return:
            # Esegue l'azione desiderata (ad esempio, imposta il nuovo valore del testo)
            self.setText(self.toPlainText().strip())
            return True
        return super().eventFilter(obj, event)

class SuperQLineEdit(QLineEdit):
    font = QFont("Arial", 7)

    def __init__(self, graphicNode, parent=None):
        super().__init__(parent)
        self.graphicNode = graphicNode
        # rounded_rec è self.rect() +0.5 per evitare che il bordo del QLineEdit sia sfasato
        rect = QRectF(self.rect().x() - 0.5, self.rect().y() - 0.5, self.rect().width() + 0.5,
                      self.rect().height() + 0.5)
        self.rounded_rect = rect.normalized()
        self.setFrame(False)
        # il problema nella qLine è che si vede il rettangolo sotto nonostante il bordo
        # per risolverlo si può usare un background-clip: border-box; che non funziona, oppure
        # si può usare un background-color: transparent; che non funziona, oppure
        # si può usare un background-color: rgba(0,0,0,0); che funziona
        self.styleZ = f"""
                            QLineEdit
                                    {{
                                        color: {self.graphicNode.proxyColorText.name()};
                                        background-color: {self.graphicNode.proxyColorFill.name()};
                                        border: 1px solid {self.graphicNode.proxyColorBorder.name()};
                                        border-radius: 2px;
                                        background-clip: border-box;
                                    }}
                            QLineEdit:hover
                                    {{
                                        border: 1px solid {self.graphicNode.proxyColorBorder.name()};
                                    }}
                        """
        self.setStyleSheet(self.styleZ)

    def updateStyle(self):
        r, g, b = self.graphicNode.proxyColorFill.red(), self.graphicNode.proxyColorFill.green(), \
            self.graphicNode.proxyColorFill.blue()
        self.styleZ = f"""
                        QLineEdit
                                {{
                                    color: {self.graphicNode.proxyColorText.name()};
                                    background-color: rgba({r}, {g}, {b}, 100);
                                    border: 1px solid {self.graphicNode.proxyColorBorder.name()};
                                    border-radius: 2px;
                                    background-clip: border-box;
                                }}
                        QLineEdit:hover
                                {{
                                    border: 1px solid {self.graphicNode.proxyColorBorder.name()};
                                }}
                                """
        self.setStyleSheet(self.styleZ)

    def focusInEvent(self, event):
        self.setStyleSheet(self.styleZ)
        super().focusInEvent(event)

    def focusOutEvent(self, event):
        self.setStyleSheet(self.styleZ)
        super().focusOutEvent(event)

class SizeGripZ(QGraphicsItem):
    def __init__(self, graphicNode, parent=None):
        super().__init__(parent)
        self.graphicNode = graphicNode
        self.setParentItem(self.graphicNode)
        # crea un rettangolo dal nodo
        self.boundingRectangle = QRectF(0, 0, 5, 5)
        self.rect = self.boundingRectangle.adjusted(1, 1, -1, -1)
        # disegna la diagonale del rettangolo dall'angolo in basso a sinistra
        # al vertice in alto a destra

        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges)
        self.setZValue(11)

    def boundingRect(self):
        return self.boundingRectangle.normalized()

    def paint(self, painter, option, widget=None):
        brush = QBrush(QColor(0, 0, 0, 40))
        pen = QPen(Qt.PenStyle.SolidLine)
        pen.setWidth(1)
        pen.setColor(QColor(70, 70, 70, 150))
        painter.setBrush(brush)
        painter.setPen(pen)
        bottom_right = self.rect.bottomRight()
        top_right = self.rect.topRight()
        bottom_left = self.rect.bottomLeft()

        delta_x = bottom_right.x() - bottom_left.x()
        delta_y = bottom_left.y() - top_right.y()

        # Disegna le tre linee parallele
        for i in range(3):
            start = QPointF(bottom_right.x() - delta_y / 3 * (i + 1), bottom_right.y() - delta_y / 3 * (i + 1))
            end = QPointF(top_right.x() - delta_y / 3 * (i + 1), top_right.y() - delta_y / 3 * (i + 1))
            painter.drawLine(QLineF(start, end))

    def itemChange(self, change, value):
        if change == QGraphicsItem.GraphicsItemChange.ItemPositionChange and self.scene():
            delta = value - self.pos()
            self.scene().parentItem().resize(delta.x(), delta.y())
        return super().itemChange(change, value)

class AbstractNodeGraphic(QGraphicsItem):
    # NodeGraphic parameter
    width: int = 50
    height: int = 100

    logo: QLabel
    logoPath: str = "C:/Users/Andrea/Desktop/pixelSmith_GraphicEditor/elements/nodeV2_1/AbstractClass/logo.png"
    isLogoVisible: bool = True
    isLogoBandW: bool = False
    proxyLogo: QGraphicsProxyWidget
    logoSize: int = 20

    txtTitle: SuperTxtTitle
    txtValue: SuperQLineEdit
    txtValueProxy: QGraphicsProxyWidget

    contextMenu: QMenu

    # NodeGraphic colors
    borderColorDefault = QColor(10, 120, 10)
    borderColorSelect = QColor(255, 70, 10)
    borderColorHover = QColor(255, 255, 10)
    colorFill = QColor(10, 180, 40)
    proxyColorText = QColor(255, 255, 255)
    proxyColorFill = QColor(0, 0, 0)
    proxyColorBorder = QColor(255, 255, 255)
    proxyColorBorderSelect = QColor(255, 255, 255)

    inPlugs: list = []
    outPlugs: list = []
    isNodeCreated: bool = False

    def __init__(self, nodeInterface, parent=None):
        super(AbstractNodeGraphic, self).__init__(parent)
        self.nodeInterface = nodeInterface
        self.contextMenu = QMenu()
        self.inPlugs = []
        self.outPlugs = []
        # set flags
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable)
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges)
        # set bounding rectangle
        self.boundingRectangle = QRectF(0, 0, self.width, self.height)
        self.setZValue(-20)
        self.isNodeCreated = True
        self.thread = None
        self.sizeGrip = SizeGripZ(self)
        self.sizeGrip.setZValue(1)

    def boundingRect(self):
        return self.boundingRectangle.normalized()

    def itemChange(self, change, value):
        if change == QGraphicsItem.GraphicsItemChange.ItemPositionHasChanged:
            for connection in self.nodeInterface.outConnections:
                connection.update()
        return QGraphicsItem.itemChange(self, change, value)

    def paint(self, painter, option, widget=None):
        if not self.isSelected():
            painter.setPen(self.borderColorDefault)
        else:
            painter.setPen(self.borderColorSelect)
        if self.nodeInterface.isDisabled:
            painter.setBrush(QColor(20, 20, 20))
        else:
            painter.setBrush(self.colorFill)
        painter.drawRoundedRect(self.boundingRectangle, 5, 5)

    def contextMenuEvent(self, event):
        self.contextMenu.exec(event.screenPos())

    # ##########################################
    #
    #                Look & Feel
    #

    def setLogo(self, filePNG):
        self.logo = QLabel()
        self.logoPath = filePNG
        self.updateLogo()
        self.proxyLogo = QGraphicsProxyWidget(self)
        self.proxyLogo.setWidget(self.logo)
        self.proxyLogo.setPos(self.width - 28, 2)

    def updateLogo(self):
        pixmap = QPixmap()
        if self.isLogoBandW:
            pixmap = self.toGrayScale()
        else:
            pixmap.load(self.logoPath, "PNG", Qt.ImageConversionFlag.AutoColor)
        self.logo.setStyleSheet("background-color: transparent;")
        self.logo.setPixmap(pixmap)
        self.logo.setMaximumSize(25, 25)
        self.logo.setScaledContents(True)

    def updateLogoPosition(self):
        self.proxyLogo.setPos(self.width - 28, 2)

    def toGrayScale(self, grayStyle="Average"):
        image = QImage(self.logoPath)
        width = image.width()
        height = image.height()
        for y in range(height):
            for x in range(width):
                r, g, b, a = image.pixelColor(x, y).getRgb()
                if grayStyle == "Average":
                    gray = (r + g + b) // 3
                elif grayStyle == "Luminosity":
                    gray = int(0.21 * r + 0.72 * g + 0.07 * b)
                elif grayStyle == "bOnly":
                    gray = b
                elif grayStyle == "gOnly":
                    gray = g + g + g // 3
                elif grayStyle == "rOnly":
                    gray = r
                else:
                    gray = int(0.16 * r + 0.67 * g + 0.07 * b)
                image.setPixel(x, y, qRgba(gray, gray, gray, a))
        return QPixmap.fromImage(image)

    def setLogoBW(self, isBW: bool):
        """
        ITA: imposta il logo in bianco e nero mantenendo la trasparenza
        ENG: set the logo in black and white maintaining the transparency
        :param isBW:
        :return:
        """
        self.isLogoBandW = isBW
        self.updateLogo()

    def setLogoVisible(self, isVisible: bool):
        self.isLogoVisible = isVisible
        self.proxyLogo.setVisible(isVisible)

    def setColorTrain(self, colorTrain: list):
        self.colorFill = colorTrain[0]
        self.borderColorDefault = colorTrain[1]
        self.borderColorSelect = colorTrain[2]
        self.borderColorHover = colorTrain[3]
        self.proxyColorText = colorTrain[4]
        self.proxyColorFill = colorTrain[5]
        self.proxyColorBorder = colorTrain[6]
        self.proxyColorBorderSelect = colorTrain[7]
        self.txtValue.updateStyle()
        self.update()

    def getColorTrain(self):
        return [self.colorFill, self.borderColorDefault, self.borderColorSelect, self.borderColorHover,
                self.proxyColorText, self.proxyColorFill, self.proxyColorBorder, self.proxyColorBorderSelect]

    def changeSize(self, width, height):
        self.width = width
        self.height = height
        self.boundingRectangle = QRectF(0, 0, self.width, self.height)
        self.updatePlugsPos()
        self.updateTitlePosition()
        self.updateTxtValuePosition()
        self.update()

    # ##########################################
    #
    #                TITLE SECTION
    #

    def createTitle(self):
        self.txtTitle = SuperTxtTitle(self)
        self.txtTitle.installEventFilter(self.txtTitle)
        self.txtTitle.setTextInteractionFlags(Qt.TextInteractionFlag.TextEditorInteraction)
        self.txtTitle.setPlainText(self.nodeInterface.title)
        self.txtTitle.setDefaultTextColor(Qt.GlobalColor.white)
        self.txtTitle.setZValue(2)
        self.updateTitlePosition()

    def updateTitle(self, title):
        self.txtTitle.setPlainText(title)
        self.updateTitlePosition()

    def updateTitlePosition(self):
        x = self.txtTitle.boundingRect().width() // 2 - self.width // 2
        self.txtTitle.setPos(-x, -30)

    # ##########################################
    #
    #                VALUE SECTION
    #

    def createTxtValue(self):
        """
        laTxtValue è la QLineEdit che viene visualizzata sul Nodo e ne visualizza il valore
        dell'input 0 del nodo, oppure il valore di output 0 del nodo.
        :return:
        """
        self.txtValue = SuperQLineEdit(self)
        self.txtValueProxy = QGraphicsProxyWidget(self)
        self.txtValueProxy.setWidget(self.txtValue)
        self.txtValueProxy.setZValue(2)
        self.txtValue.setFocus()
        self.setTextValueOnQLineEdit(self.nodeInterface.getOutputValue(0))
        self.txtValue.returnPressed.connect(self.setTxtValue)
        self.initTxtValueProperties()
        self.updateTxtValuePosition()

    def setTxtValue(self):
        """
        Questo metodo viene chiamato quando viene premuto il tasto invio sulla QLineEdit.
        Generalmente in questo caso si vuole settare il valore della QLineEdit come input
        del nodo.
        :return:
        """
        self.nodeInterface.setInputValue(0, self.txtValue.text())
        self.txtValue.clearFocus()

    def initTxtValueProperties(self):
        self.txtValue.setFont(QFont("Arial", 9))
        self.txtValue.setFixedWidth(int(self.width * 1.4))
        self.txtValue.setFixedHeight(20)
        self.txtValue.setAlignment(Qt.AlignmentFlag.AlignCenter)

    def setTextValueOnQLineEdit(self, value):
        """
        Questo metodo serve per settare il valore della QLineEdit
        dall'esterno.
        :param value:
        :return:
        """
        if not isinstance(value, str):
            value = str(value)
        self.txtValue.setText(value)

    def updateTxtValuePosition(self):
        """
        ITA:
            Questo metodo serve per aggiornare la larghezza della QLineEdit in base al testo
            che contiene. quello che può accadere in alcuni casi è che la Qline
            contenga una lista di valori, in questo caso la larghezza viene falsata da alcuni caratteri
            come le parentesi quadre e le virgole, quindi se la larghezza è maggiore
            del doppio rispetto alla larghezza del widget allora la larghezza viene ridotta.

        ENG:
            This method is used to update the width of the QLineEdit based on the text
            that contains. What happen in some cases is that the Qline
            contains a list, in this case the width is falsified by some characters
            such as square brackets and commas, so if the width is greater
        :return:
        """
        size = self.txtValue.sizeHint()
        newSize = QSize(size.width() * 2, size.height())
        self.txtValue.resize(newSize)
        if self.txtValue.width() > self.width * 2 - 40:
            self.txtValue.resize(self.width - 40, self.txtValue.height())
        x = (self.width - self.txtValue.width()) // 2
        y = self.height - (self.txtValue.height() * 1.2)
        self.txtValueProxy.setPos(x, y)

    def setTxtValueReadOnly(self, value):
        self.txtValue.setReadOnly(value)

    # ##########################################
    #
    #                PLUGS SECTION
    #

    def addPlug(self, _type, plug):
        if _type == "In":
            self.inPlugs.append(plug)
        elif _type == "Out":
            self.outPlugs.append(plug)

    def deleteInPlug(self, index):
        try:
            self.inPlugs.pop(index)
        except IndexError:
            print("warning from AbstractNodeGraphic.deleteInPlug: index out of range")

    def updatePlugsPos(self):
        self.updatePlugPosition(self.inPlugs)
        self.updatePlugPosition(self.outPlugs)

    def updatePlugPosition(self, plugReference):
        x = -8
        if "out" in plugReference[0].plugData.className.lower():
            x = self.width - 2
        if len(plugReference) == 1:
            y = self.height // 2
            plugReference[0].setPos(QPointF(x, y))
        else:
            # Quello che fa è calcolare la distanza tra i vari plug
            # in modo che siano sempre uguali
            y = (self.height - (len(plugReference) * plugReference[0].diameter * 3)) // 2
            for plug in plugReference:
                plug.setPos(QPointF(x, y))
                y += plug.diameter * 3


"""
This file runs the main training/val loop
"""
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from datasets.dataset import CelebAHQDataset, get_transforms, TO_TENSOR, NORMALIZE, MASK_CONVERT_TF, MASK_CONVERT_TF_DETAILED
from models.networks import Net, Net2, Net3, MultiScaleNet
from models.encoder_with_optim import EncoderPlusOptimNet
from options.test_options import TestOptions
import os
import json
import sys
import pprint
import torch
from utils import torch_utils
from tqdm import tqdm
import numpy as np
from PIL import Image

sys.path.append(".")
sys.path.append("..")

class Tester:
    def __init__(self,opts):
        self.opts = opts
        self.test_ds = CelebAHQDataset(dataset_root=self.opts.dataset_root, mode="test",
                                       img_transform=transforms.Compose(
                                           [TO_TENSOR, NORMALIZE]),
                                       label_transform=transforms.Compose(
                                           [ MASK_CONVERT_TF_DETAILED,TO_TENSOR]), # MASK_CONVERT_TF,
                                       fraction=self.opts.ds_frac)
        print(f"Number of test samples: {len(self.test_ds)}")

        self.test_dataloader = DataLoader(self.test_ds, batch_size=self.opts.test_batch_size,
                                          shuffle=False, num_workers=int(self.opts.test_workers), drop_last=False)

        assert self.opts.checkpoint_path is not None, "please specify the pre-trained weights!"
        self.net = Net3(self.opts).eval().to(self.opts.device)

        ckpt_dict=torch.load(self.opts.checkpoint_path)
        self.net.latent_avg = ckpt_dict['latent_avg'].to(self.opts.device) if self.opts.start_from_latent_avg else None
        self.net.load_state_dict(torch_utils.remove_module_prefix(ckpt_dict["state_dict"],prefix="module."))
        print("Load pre-trained weights.")

    # @torch.no_grad()
    # def test(self,num_imgs=20, save_dir=""):
    #     cnt = 0

    #     for batch_idx, batch in enumerate(self.test_dataloader):
    #         (img1, img2), (mask1, mask2), (mask1_vis, mask1_vis) = batch
    #         img1, img2 = img1.to(self.opts.device).float(), img2.to(
    #             self.opts.device).float()
    #         mask1 = (mask1*255).long().to(self.opts.device)
    #         mask2 = (mask2*255).long().to(self.opts.device)

    #         # [bs,1,H,W]的mask 转成one-hot格式，即[bs,#seg_cls,H,W]
    #         onehot1 = torch_utils.labelMap2OneHot(
    #             mask1, num_cls=self.opts.num_seg_cls)
    #         onehot2 = torch_utils.labelMap2OneHot(
    #             mask2, num_cls=self.opts.num_seg_cls)

    #         swap = False
    #         recon1, latent1 = self.net(img1, onehot1, return_latents=True)
    #         recon2, latent2 = self.net(img2, onehot2, return_latents=True)

    #         imgs_1 = self.parse_images(onehot1, img1, recon1)
    #         imgs_2 = self.parse_images(onehot2, img2, recon2)

    #         self.save_imgs(imgs_1, save_name="%04d" % (cnt))
    #         self.save_imgs(imgs_2, save_name="%04d" % (cnt+1))
    #         cnt += len(img1)*2

    #         if cnt>num_imgs:
    #             break

    # 补偿网络测试
    @torch.no_grad()
    def compensate_test(self,num_imgs=20, save_dir=""):
        cnt = 0
        for batch_idx, batch in enumerate(tqdm(self.test_dataloader)):

            img, recon_img, optimed_style_code, mask, mask_vis = batch

            sample_name = os.path.basename(self.test_ds.imgs[batch_idx])[:-4]

            img = img.to(self.opts.device).float()
            recon_img = recon_img.to(self.opts.device).float()
            optimed_style_code = optimed_style_code.to(self.opts.device).float()
            mask = (mask*255).long().to(self.opts.device)
            # [bs,1,H,W]的mask 转成one-hot格式，即[bs,#seg_cls,H,W]
            onehot = torch_utils.labelMap2OneHot(mask, num_cls=self.opts.num_seg_cls)

            diffMap = img - recon_img

            res_feats, base_codes, compensated_codes = self.net.get_style(img, onehot, diff_img=diffMap)

            # 1. 不用补偿style code 的重建结果
            recon_1 = self.net.gen_img(res_feats, base_codes, onehot)
            # 2. 用了补偿style code 的重建结果
            recon_2 = self.net.gen_img(res_feats, base_codes + compensated_codes, onehot)

            imgs = {
                'input_face': torch_utils.tensor2im(img[0]),
                'input_mask': torch_utils.tensor2map(onehot[0]),
                'recon_face_wo_compensation': torch_utils.tensor2im(recon_1[0]),
                'recon_face_w_compensation': torch_utils.tensor2im(recon_2[0]),
            }
            self.save_imgs(imgs, save_name=sample_name)

            cnt += len(img)

            if cnt>num_imgs:
                break

    @torch.no_grad()
    def test(self,num_imgs=20, save_dir="",begin_idx=0):
        cnt = 0
        for batch_idx, batch in enumerate(tqdm(self.test_dataloader)):

            if batch_idx < begin_idx:
                continue

            img, mask, mask_vis = batch

            sample_name = os.path.basename(self.test_ds.imgs[batch_idx])[:-4]

            img = img.to(self.opts.device).float()
            mask = (mask*255).long().to(self.opts.device)
            # [bs,1,H,W]的mask 转成one-hot格式，即[bs,#seg_cls,H,W]
            onehot = torch_utils.labelMap2OneHot(mask, num_cls=self.opts.num_seg_cls)

            recon, structure_codes_GT, latent = self.net(img, onehot, return_latents=True)

            imgs = self.parse_images(onehot, img, recon)
            self.save_imgs(imgs, save_name=sample_name)

            cnt += len(img)

            if cnt>num_imgs:
                break

    def save_imgs(self, img_data, save_name):
        # # gt 和 recon 放在一张图·
        # arr = np.hstack((
        #     np.array(img_data["input_face"]),
        #     np.array(img_data["recon_face"])
        # ))
        # Image.fromarray(arr).save(os.path.join(self.opts.save_dir, "%s.png" % save_name))

        for k, v in img_data.items():
            if k=="recon_face":
                v.save(os.path.join(self.opts.save_dir, "%s_%s.png" % (save_name, k)))

    def parse_images(self, mask, img, recon):
        cur_im_data = {
            'input_face': torch_utils.tensor2im(img[0]),
            'input_mask': torch_utils.tensor2map(mask[0]),
            'recon_face': torch_utils.tensor2im(recon[0]),
        }
        return cur_im_data

if __name__ == '__main__':
    opts = TestOptions().parse()
    os.makedirs(opts.save_dir, exist_ok=True)
    tester = Tester(opts)
    tester.test(num_imgs=2000,begin_idx=0)


#
# Name:
# Email ID:
#
def get_prices_in_range(price_list, low, high):
    # Modify the code below
    my_list = []

    for element in price_list:
    	if int(element) >= low and int(element) <= high:
    		my_list.append(element)

    return my_list


import json
import pandas as pd
import torch
from pathlib import Path
from itertools import repeat
from collections import OrderedDict
import numpy as np

def ensure_dir(dirname):
    dirname = Path(dirname)
    if not dirname.is_dir():
        dirname.mkdir(parents=True, exist_ok=False)

def read_json(fname):
    fname = Path(fname)
    with fname.open('rt') as handle:
        return json.load(handle, object_hook=OrderedDict)

def write_json(content, fname):
    fname = Path(fname)
    with fname.open('wt') as handle:
        json.dump(content, handle, indent=4, sort_keys=False)

def inf_loop(data_loader):
    """wrapper function for endless data loader."""
    for loader in repeat(data_loader):
        yield from loader

class MetricTracker:
    """Metric Tracker Class for Training and validation."""
    def __init__(self, *keys, writer=None):
        self.writer = writer
        self._data = pd.DataFrame(index=keys, columns=['total', 'counts', 'average'])
        self.reset()

    def reset(self):
        for col in self._data.columns:
            self._data[col].values[:] = 0

    def update(self, key, value, n=1):
        if self.writer is not None:
            self.writer.add_scalar(key, value)
        self._data.total[key] += value * n
        self._data.counts[key] += n
        self._data.average[key] = self._data.total[key] / self._data.counts[key]

    def avg(self, key):
        return self._data.average[key]

    def result(self):
        return dict(self._data.average)

def euclidean_dist(x, y):
    """Compute euclidean distance between two tensors

    Args:
        x: (Tensor) N x D
        y: (Tensor) M x D

    Returns:
        Euclidean distance of x and y, a float
    """
    flag = False
    if y is None:
        y = x
        flag = True
    if len(list(x.size())) == len(list(y.size())) == 1:
        return torch.pow(x - y, 2).sum()
    x_norm = (x ** 2).sum(1).view(-1, 1)
    y_t = torch.transpose(y, 0, 1)
    y_norm = (y ** 2).sum(1).view(1, -1)
    dist = x_norm + y_norm - 2.0 * torch.mm(x, y_t)
    # Ensure diagonal is zero if x=y
    if flag:
        dist = dist - torch.diag(dist.diag())
    return torch.clamp(dist, 0.0, np.inf)

def cos_sim(x, y=None, eps=1e-8):
    """Cosine Similarity calculate. Add eps for numerical stability"""
    y = x if y is None else y
    if len(list(x.size())) == len(list(y.size())) == 1:
        return torch.nn.CosineSimilarity(dim=-1, eps=eps)(x, y)
    x_n, y_n = x.norm(dim=1)[:, None], y.norm(dim=1)[:, None]
    x_norm = x / torch.max(x_n, eps * torch.ones_like(x_n))
    y_norm = y / torch.max(y_n, eps * torch.ones_like(y_n))
    sim_mt = torch.mm(x_norm, y_norm.transpose(0, 1))
    return sim_mt

def get_samples(samples, device, type):
    """

    Args:
        samples: (List) list of sample
        device: (str) CUDA device
        type: (str) bert or lstm. If encoder is bert, return raw text else ids.

    Returns:
        x, x_length, y which means text(raw/ids), word length, label
    """
    if type == 'bert':
        x = [sample['text'] for sample in samples]
    else:
        x = torch.LongTensor([sample['pad_ids'] for sample in samples]).to(device)
    len = torch.IntTensor([sample['length'] for sample in samples]).to(device)
    y = torch.LongTensor([sample['y'] for sample in samples]).to(device)
    return x, len, y

def log_dict(logger, log):
    """Print result dict in format."""
    for key, value in log.items():
        if isinstance(value, int):
            logger.info('    {:30s}: {}'.format(str(key), value))
        else:
            logger.info('    {:30s}: {:.6}'.format(str(key), value))
        if 'f1' in key:
            logger.info('    {:30s}: '.format('-----------'))

def guassian_kernel(source, target, kernel_mul=2.0, kernel_num=5, fix_sigma=None):
    """Kernel matrix."""
    n_samples = int(source.size()[0]) + int(target.size()[0])
    total = torch.cat([source, target], dim=0)

    total0 = total.unsqueeze(0).expand(int(total.size(0)), \
                                       int(total.size(0)), \
                                       int(total.size(1)))
    total1 = total.unsqueeze(1).expand(int(total.size(0)), \
                                       int(total.size(0)), \
                                       int(total.size(1)))
    L2_distance = ((total0 - total1) ** 2).sum(2)

    if fix_sigma:
        bandwidth = fix_sigma
    else:
        bandwidth = torch.sum(L2_distance.data) / (n_samples ** 2 - n_samples)
    bandwidth /= kernel_mul ** (kernel_num // 2)
    bandwidth_list = [bandwidth * (kernel_mul ** i) for i in range(kernel_num)]

    kernel_val = [torch.exp(-L2_distance / bandwidth_temp) for \
                  bandwidth_temp in bandwidth_list]

    return sum(kernel_val)

def mmd(source, target, kernel_mul=2.0, kernel_num=5, fix_sigma=None):
    """Maximum Mean Discrepancy."""
    batch_size = int(source.size()[0])
    kernels = guassian_kernel(source, target,
                              kernel_mul=kernel_mul,
                              kernel_num=kernel_num,
                              fix_sigma=fix_sigma)
    XX = kernels[:batch_size, :batch_size]  # Source<->Source
    YY = kernels[batch_size:, batch_size:]  # Target<->Target
    XY = kernels[:batch_size, batch_size:]  # Source<->Target
    YX = kernels[batch_size:, :batch_size]  # Target<->Source
    mmd = XX.mean() - XY.mean() - YX.mean() + YY.mean()
    return mmd

def cos_mmd(x, y):
    """Cosine similarity MMD(Maximum Mean Discrepancy in transfer learning)."""
    return cos_sim(x).mean() - 2 * cos_sim(x, y).mean() + cos_sim(y).mean()


from flask import Flask, render_template, request
import json

app = Flask(__name__)
def load_data():
    with open('salary.json', 'r') as file:
        data = json.load(file)
    return data

def averageSalary(data):
    total_salary = sum(float(record['salary']) for record in data)

    return round(total_salary / len(data),2)

def findLast(data, last_name):
    last={}
    for i in data :
        if(i['last_name'].lower() == last_name.lower()):
            last = i
    print(last)

    return last

def calculateMax(data):
    arr = []
    for i in data :arr.append(float(i['salary']))

    return round(max(arr),2)

def calculateMin(data):
    arr = []
    for i in data: arr.append(float(i['salary']))

    return round(min(arr), 2)

@app.route('/', methods=['GET'])
def display_data():
    data = load_data()
    parsed_data = []
    for key, value in data.items():
        record = value.split(';')
        parsed_data.append({
            'id':record[0],
            'last_name': record[1],
            'first_name': record[2],
            'salary': record[3]
        })

    max = calculateMax(parsed_data)
    print(max)
    min = calculateMin(parsed_data)
    average = round(averageSalary(parsed_data),2)

    return render_template('tablica.html', data=parsed_data, max=max, min=min,average=average)

@app.route('/find', methods=['POST'])
def find():
    data = load_data()
    parsed_data = []
    for key, value in data.items():
        record = value.split(';')
        parsed_data.append({
            'id': record[0],
            'last_name': record[1],
            'first_name': record[2],
            'salary': record[3]
        })

    max = calculateMax(parsed_data)
    print(max)
    min = calculateMin(parsed_data)
    average = round(averageSalary(parsed_data), 2)

    last_name = request.form['last_name']
    if last_name:
        matching_records = findLast(parsed_data, last_name)
        return render_template('tablica.html', data=matching_records, max=max, min=min,average=average)

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


from piece import Piece

class Bishop(Piece):

    def __init__(self, x, y, c):
        super().__init__(x, y, c)

    def copy(self):
        return Bishop(self.posX, self.posY, self.colour)

    def check_move(self, x, y, board):
        return super().check_move_diagonale(x, y, board) and super().check_move(x, y)

    @staticmethod
    def covered_spots(posX, posY, board):
        res = set()
        # left-up
        for i in range(min(posX, 7 - posY)):
            if board[posX - 1 - i][posY + i + 1] == None:
                res.add((posX - 1 - i, posY + i + 1))
            else:
                res.add((posX - 1 - i, posY + i + 1))
                break
        # right-up
        for i in range(min(7 - posX, 7 - posY)):
            if board[posX + i + 1][posY + i + 1] == None:
                res.add((posX + i + 1, posY + i + 1))
            else:
                res.add((posX + i + 1, posY + i + 1))
                break
        # right-down
        for i in range(min(7 - posX, posY)):
            if board[posX + i + 1][posY - i - 1] == None:
                res.add((posX + i + 1, posY - i - 1))
            else:
                res.add((posX + i + 1, posY - i - 1))
                break
        # left-down
        for i in range(min(posX, posY)):
            if board[posX - i - 1][posY - i - 1] == None:
                res.add((posX - i - 1, posY - i - 1))
            else:
                res.add((posX - i - 1, posY - i - 1))
                break
        return res

    def __repr__(self):
        return "Bishop"


from django.urls import path
from .import views

# app_name = 'categories'

urlpatterns = [
    path('',views.checkout,name='checkout'),
    path('add_address_check',views.add_address_check , name='add_address_check'),
    path('edit_address_check/<int:editaddress_id>/',views.edit_address_check , name='edit_address_check'),

    path('apply_coupon',views.apply_coupon , name='apply_coupon'),

    path('placeorder',views.placeorder, name='placeorder'),
    path('proceed-to-pay',views.rezorpaycheck , name='proceed-to-pay'),

]


test_cases = int(input().strip())

while test_cases > 0:

    data = [float(n) for n in input().strip().split()]

    beats = data[0]
    seconds = data[1]

    bpm = (60 * beats) / seconds
    timeBetweenBeats = beats / seconds
    apbm = 60 / seconds

    print('ABPM: {:.4f}, BPM: {:.4f}, ABPM+:{:.4f}'.format(apbm, bpm, timeBetweenBeats))

    test_cases -= 1


#! /usr/bin/env python3
#
def random_scatter ( ):

#*****************************************************************************80
#
## random_scatter draws a scatter plot of X Y data.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    25 May 2016
#
#  Author:
#
#    John Burkardt
#
  import matplotlib.pyplot as plt
  import numpy as np
  import platform

  print ( '' )
  print ( 'random_scatter:' )
  print ( '  Python version: %s' % ( platform.python_version ( ) ) )
  print ( '  Make a scatterplot of random XY data.' )

  n = 500
  r = np.random.normal ( 0.0, 1.0, n )
  t = np.pi * np.random.random ( n )
  x = r * np.cos ( t )
  y = r * np.sin ( t )
#
#  Plot the data.
#
  plt.scatter ( x, y )
  plt.grid ( True )
  plt.axis ( 'Equal' )
  plt.xlabel ( '<--- X --->', fontsize = 16 )
  plt.ylabel ( '<--- Y --->', fontsize = 16 )
  plt.title ( '500 Normally Distributed (X,Y) Values', fontsize = 16 )

  filename = 'random_scatter.png'
  plt.savefig ( filename )
  print ( '' )
  print ( '  Graphics saved as "%s"' % ( filename ) )
  plt.show ( block = False )
  plt.clf ( )
#
#  Terminate.
#
  print ( '' )
  print ( 'random_scatter' )
  print ( '  Normal end of execution.' )
  return

if ( __name__ == '__main__' ):
  from timestamp import timestamp
  timestamp ( )
  random_scatter ( )
  timestamp ( )


import sys

numbers = []

for line in sys.stdin:

    if line == '\n':
        break

    numbers.append(int(line.strip()))

modulos = []

for n in numbers:
    try:
        index = modulos.index(n % 42)
    except ValueError:
        modulos.append(n % 42)

print(len(modulos))

Kattis/Difficulty - 1/Difficulty - 1.4/modulo.py


LOCATION_TYPE_STATE = "state"
LOCATION_TYPE_CITY = "city"
LOCATION_TYPE_MLOCALE = "mlocale"

MAX_SEARCH_RESULTS = 10

SCHOOLS_FILE = "./data/school_data.csv"

STATE_NAMES = {
    'AL': 'Alabama',
    'AK': 'Alaska',
    'AZ': 'Arizona',
    'AR': 'Arkansas',
    'CA': 'California',
    'OR': 'Oregon',
    'NV': 'Nevada',
    'CO': 'Colorado',
    'CT': 'Connecticut',
    'DE': 'Delaware',
    'DC': 'District of Columbia',
    'MD': 'Maryland',
    'FL': 'Florida',
    'GA': 'Georgia',
    'HI': 'Hawaii',
    'ID': 'Idaho',
    'IL': 'Illinois',
    'IN': 'Indiana',
    'OH': 'Ohio',
    'IA': 'Iowa'
}


import urllib.request
import bs4
import sqlite3
import json
########################################################################################################################
#                                   Выгрузка данных с биржи WEX.nz                                                     #
########################################################################################################################

def Api(coin):

    htm = urllib.request.urlopen('https://wex.nz/api/3/ticker/'+coin).read()
    soup = bs4.BeautifulSoup(htm, "html.parser")
    txt = str(soup)
    data = json.loads(txt)
    buy=data[coin]['buy']
    sell=(data[coin]['sell'])
    buy=str(buy)
    sell=str(sell)
    coin = str(coin.upper())
    if coin[4:7]== 'RUR':                   # для общего стандарта отображения валют в БД
        coin=coin[0:4]+"RUB"
    conn = sqlite3.connect('database.db')
    c = conn.cursor()
    try:
        c.execute("INSERT INTO Wex (Coin,Buy,Sell) VALUES (?, ?, ?)", (coin, buy, sell))
        conn.commit()
        c.close()
        conn.close()
    except sqlite3.IntegrityError:
        print("error sql")
    return ("wex " + coin + '\n' + " buy " + buy + '\n' + " sell " + sell)

'''
from datetime import datetime
now = str(datetime.now())
coin = ['btc_usd','btc_rur','btc_eur',
        'ltc_btc','ltc_usd','ltc_rur','ltc_eur',
        'dsh_btc','dsh_usd','dsh_rur','dsh_eur','dsh_ltc','dsh_eth','dsh_zec',
        'eth_btc','eth_usd','eth_eur','eth_ltc','eth_rur','eth_zec',
        'bch_usd','bch_btc','bch_rur','bch_eur','bch_ltc','bch_eth','bch_dsh','bch_zec',
        'zec_btc','zec_usd','zec_ltc']
i = 0
while i <= 30:
    answer = ('####' + now + '####' +
              '\n' + Api(coin[i])+'\n'+'\n')
    print(answer)
    i=i+1
'''


def does_robot_fit(x, y, max_w, max_h, m, r):
    """Takes in x, y, map and relative robot coordinates"""
    actual = {(x + xpos, y + ypos) for xpos, ypos in r}
    for xpos, ypos in actual:
        if xpos < 0 or xpos >= max_w or ypos < 0 or ypos >= max_h:
            return False
        if m[ypos][xpos] == "x":
            return False
    return True

def get_cleaned_points(x, y, b):
    """Takes in x, y and relative brush coordinates"""
    actual = {(x + xpos, y + ypos) for xpos, ypos in b}
    return actual

# Set relative brush coordinates
brushes = set()
for xpos in range(-4, 5):
    if xpos not in [-1, 0, 1]:
        brushes.add((xpos, -4))
        brushes.add((xpos, 4))
for xpos in range(-4, 5):
    for ypos in range(-3, 4):
        if not (xpos in [-4, 4] and ypos in [-1, 0, 1]):
            brushes.add((xpos, ypos))

# Set relative robot coordinates
robot = set()
for xpos in range(-1, 2):
    robot.add((xpos, -3))
    robot.add((xpos, 3))
for xpos in range(-2, 3):
    robot.add((xpos, -2))
    robot.add((xpos, 2))
for xpos in range(-3, 4):
    for ypos in range(-1, 2):
        robot.add((xpos, ypos))

# Read map
kart = [list(line.strip("\n")) for line in open("kart.txt").readlines()]
# Read test map
#kart = [list(line.strip()) for line in open("test.txt").readlines()]

# Loop through map and clean it
rows = len(kart)
cols = len(kart[0])
for y in range(rows):
    print(f"\rDone searching row {y + 1} of {rows} ...", end="")
    for x in range(cols):
        if not does_robot_fit(x, y, cols, rows, kart, robot):
            continue
        clean = get_cleaned_points(x, y, brushes)
        for xpos, ypos in clean:
            if xpos < 0 or xpos >= cols or ypos < 0 or ypos >= rows:
                continue
            if kart[ypos][xpos] == " ":
                kart[ypos][xpos] = "."

print()
print(sum([l.count(" ") for l in kart]))

# Write cleaned map to file
with open("cleaned_kart.txt", "w") as f:
    for line in kart:
        f.write("".join(line) + "\n")


# coding: utf-8

from qingcloud.cli.misc.utils import explode_array
from qingcloud.cli.iaas_client.actions.base import BaseAction

class DetachKeyPairsAction(BaseAction):

    action = 'DetachKeyPairs'
    command = 'detach-keypairs'
    usage = '%(prog)s --instances "instance_id, ..." --keypairs "kp_id, ..." [-f <conf_file>]'

    @classmethod
    def add_ext_arguments(cls, parser):

        parser.add_argument('-k', '--keypairs', dest='keypairs',
                action='store', type=str, default='',
                help='the comma separated IDs of keypairs you want to detach from instances. ')

        parser.add_argument('-i', '--instances', dest='instances',
                action='store', type=str, default='',
                help='the IDs of instances the keypairs will be detached from.')

    @classmethod
    def build_directive(cls, options):
        keypairs = explode_array(options.keypairs)
        instances = explode_array(options.instances)
        if not keypairs or not instances:
            return None

        return {
                'keypairs': keypairs,
                'instances': instances,
                }


import setuptools

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setuptools.setup(
    name="irods_fcs",
    version="0.0.1",
    author="d-w-moore",
    author_email="dmoore@renci.org",
    description="FCS metadata keyword extractor for iRODS",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/pypa/sampleproject",
    project_urls={
        "Bug Tracker": "https://github.com/pypa/sampleproject/issues",
    },
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    package_dir={"": "src"},
    packages=setuptools.find_packages(where="src"),
    python_requires=">=3.6",
    install_requires=["FlowCal", "python-irodsclient"],
)


import pandas as pd
import numpy as np
import sklearn
np.random.seed(0)
from sklearn.svm import SVC

class SVM_Built_In:
    def read_data(self, normalise):
        data = pd.read_csv("../data/spambase.data.txt", header=None)
        data = data.values
        np.random.shuffle(data)
        if(normalise):
            data = self.__normalise_data(data)
        self.data = data

    def __normalise_data(self, dataset):
        for i in range(dataset.shape[1] - 1):
            temp = dataset[:, i]
            dataset[:, i] = (temp - np.mean(temp)) / np.std(temp)
        return dataset

    def SVM(self, kernel):
        train_size = int(self.data.shape[0]  * 0.8)
        X_train = self.data[:train_size,:-1]
        Y_train = self.data[:train_size,-1]
        X_test = self.data[train_size:, :-1]
        Y_test = self.data[train_size:,-1]
        classifier = SVC(C = 5, kernel=kernel, gamma='auto', degree=2)
        classifier.fit(X_train, Y_train)
        y_pred_train = classifier.predict(X_train)
        y_pred_test = classifier.predict(X_test)
        print("Training_accuracy for kernel ", kernel, " is = ",  sklearn.metrics.accuracy_score(Y_train, y_pred_train))
        print("Testing_accuracy for kernel ", kernel, " is = ", sklearn.metrics.accuracy_score(Y_test, y_pred_test))

kernels = ['linear', 'poly', 'rbf', 'sigmoid']
for i in range(len(kernels)):
    svm = SVM_Built_In()
    svm.read_data(normalise = True)
    svm.SVM(kernels[i])


import pandas as pd
import openpyxl
import os

def processing_column_other(text: str):
    """
    Функция для подсчета причин указанных в колонке Прочее
    :param text: Текст разделенный запятыми
    :return: Текст разделенный знаками переноса вида:
     семейные обстоятельства -3
     переезд -4
    """
    # Создаем словарь для подсчета
    word_frequency = dict()
    # Очищаем текст от возможных знаков переноса

    text = text.replace('', '')
    text = text.replace("\n", " ")
    # Создаем список
    word_lst = text.split(',')

    # Итерируемся по списку слов и подсчитываем количество
    for word in word_lst:
        # о костыль.Но странно почему replace не срабатывает
        if word == '' or word == 'Отсутствуют':
            continue
        if word in word_frequency:
            # Создаем ключ с заглавной буквы, чтобы потом не тратить на это время
            word_frequency[word] += 1
        else:
            word_frequency[word] = 1
    # Превращаем словарь в список, чтобы метод join правильно отработал
    output_lst = []
    for reason in word_frequency.items():
        output_lst.append(f'{reason[0]} - {reason[1]}')
    return ',\n'.join(output_lst)

def check_data(df, quantity):
    """
    Функция для проверки полученного датафрейма на корректность данных.
    Проверка фактических и планируемых показателей, проверка количества целевиков и инвалидов.
    :param df: однострочный датафрейм полученный после суммирования
    :quantity: количество студентов
    :return: строка со статусом проверки
    """
    # Создаем счетчики для подсчета причин из колонок Прочее и План.Прочее
    real_count_reason = 0
    plan_count_reason = 0
    # Сохраняем данные из колонок Прочее и План.Прочее
    # Превращаем массив numpy в обычный список
    real_text_reasons = df['Прочее'].values[0]

    print(real_text_reasons)
    print(len(real_text_reasons))

    # # считаем количество реальных причин
    # for real_reason in real_text_reasons.split(','):
    #     # Условие, чтобы не учитывать пустую строку которая образуется
    #     if not real_reason == '' or '0' in real_reason:
    #         # print(real_reason)
    #         real_count_reason += 1

    # plan_text_reasons = df['План.Прочее'].values
    # # считаем количество планируемых причин
    # for plan_reason in plan_text_reasons.split(','):
    #     if not plan_reason == '':
    #         plan_count_reason += 1

    # print(real_count_reason)
    # print(plan_count_reason)

    # Удаляем колонки с причинами
    df.drop(['Прочее', 'План.Прочее'], axis=1, inplace=True)
    # Получаем строку с итогами по фактическому распределению выпускников

    d = df.iloc[0, 3:12].sum()

# Создаем базовый  датафрейм
base_df = pd.read_excel('temp/columns.xlsx')

# Получаем список файлов
example_dir = 'C:/Users/1/PycharmProjects/Gwen/resources'
with os.scandir(example_dir) as files:
    lst_files = [file.name for file in files if file.is_file() and file.name.endswith('xlsx')]
# Перебираем файлы
for file in lst_files:
    df = pd.read_excel(f'resources/{file}')
    # Удаляем столбец с ФИО, так как при группировке он будет мешать
    df = df.drop(['ФИО'], axis=1)

    # добавляем параметр numeric_only чтобы текстовые значения также суммировались
    temp_df = df.groupby(['Специальность', 'Группа', 'Куратор'], ).sum(numeric_only=False).reset_index()
    # TODO проверка количества строк. Должно быть не более 1, если больше то в файле присутствует еще одна группа,куратор,специальность

    # Копируем датафрейм, так как внутри функции он будет изменятся
    checked_df = temp_df.copy()
    # Получаем результат проверки
    verification_status = check_data(temp_df, df.shape[0])
    # Добавляем данные в итоговый датафрейм
    checked_df['Статус'] = verification_status

    base_df = base_df.append(checked_df, ignore_index=True)

# Сохраняем промежуточный  результат для того чтобы легче было отслеживать корректность данных
base_df.to_excel('Промежуточный результат.xlsx', index=False)

# Проводим итоговую группировку
# Нужно провести подсчет причин в графе Прочие.
itog_df = base_df.groupby(['Специальность']).sum(numeric_only=False).reset_index()

# Обрабатываем колонку Прочее
# Сначала приводим заменяем возможные 0.0 на строку Отсутствуют
itog_df['Прочее'] = itog_df['Прочее'].apply(lambda x: 'Отсутствуют' if not type(x) == str else x)
itog_df['Прочее'] = itog_df['Прочее'].apply(processing_column_other)
itog_df.to_excel('Итоговый результат.xlsx', index=False)


from typing import List
import collections
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        indegrees = [0] * numCourses

        adjacent = collections.defaultdict(list)

        for (course, prereq) in prerequisites:
            indegrees[course] += 1
            adjacent[prereq].append(course)

        cycle = True
        for i in indegrees:
            if i == 0:
                cycle = False
        if cycle == True:
            return False

        q = collections.deque()
        res = []

        for course in range(numCourses):
            if indegrees[course] == 0:
                q.append(course)

        while q:
            curCourse = q.popleft()
            res.append(curCourse)
            for nei in adjacent[curCourse]:
                indegrees[nei] -= 1
                if indegrees[nei] == 0:
                    q.append(nei)

        return len(res) == numCourses

if __name__ == "__main__":
    (testcase1, ans1) = ([2, [[0, 1]]], True)
    (testcase2, ans2) = ([2, [[1,0],[0,1]]] , False)
    (testcase3, ans3) = ([20, [[0,10],[3,18],[5,5],[6,11],[11,14],[13,1],[15,1],[17,4]]] , False)

    sol = Solution()
    assert sol.canFinish(testcase1[0], testcase1[1]) == ans1, "Testcase 1 failed"
    assert sol.canFinish(testcase2[0], testcase2[1]) == ans2, "Testcase 2 failed"
    assert sol.canFinish(testcase3[0], testcase3[1]) == ans3, "Testcase 3 failed"

    print("All test cases passed Pass")


from django.db.models import Count
from rest_framework import generics, permissions, filters
from django_filters.rest_framework import DjangoFilterBackend
from .models import Post
from yakker.permissions import AuthorOrReadOnly
from .serializers import PostSerializer

class ListPost(generics.ListCreateAPIView):
    """
    Class-based view to list all posts.
    """
    queryset = Post.objects.annotate(
        reyakks_count=Count('post_reyakker', distinct=True),
        comment_count=Count('comment', distinct=True),
    ).order_by('-created_at')
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    serializer_class = PostSerializer
    filter_backends = [
        filters.OrderingFilter,
        filters.SearchFilter,
        DjangoFilterBackend,
    ]
    filterset_fields = [
        # user feed
        'author__followed_user__author__yakfile',
        # user liked posts
        'post_reyakker__post_reyakker__yakfile',
        # user posts
        'author__yakfile',
    ]
    search_fields = [
        'author__username',
        'title',
        'content',
    ]
    ordering_fields = [
        'reyakks_count',
        'comment_count',
        'post_reyakker__created_at',
    ]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

class DetailPost(generics.RetrieveUpdateDestroyAPIView):
    """
    Class-based detailed view to retrieve a post.
    Can edit, or delete a post if you're the author.
    """
    queryset = Post.objects.annotate(
        reyakks_count=Count('post_reyakker', distinct=True),
        comment_count=Count('comment', distinct=True),
    ).order_by('-created_at')
    permission_classes = [AuthorOrReadOnly]
    serializer_class = PostSerializer


# Copyright 2018 Deep Learning Service of Huawei Cloud. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from moxing.pytorch.executor.enumerate import *
from torch.optim import lr_scheduler
from torch.utils.data import distributed

import torch
import moxing.pytorch as mox
import torch.optim as optim
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import multiprocessing as mp
import torch.nn.functional as F

def load_data():
  transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.1307,), (0.3081,))])
  trainset = torchvision.datasets.MNIST(root='./data/mnist', train=True, download=False, transform=transform)
  train_loader = torch.utils.data.DataLoader(
    trainset, batch_size=16, shuffle=True,
    num_workers=10, pin_memory=True, sampler=None)
  return train_loader

def loss_fn(model, inputs):
  rank = mox.get_flag('rank')
  x, y = inputs
  x = x.cuda()
  y = y.cuda()
  outputs = model(x)
  loss = F.nll_loss(outputs, y)
  return loss

class Net(nn.Module):
  """ Network architecture. """

  def __init__(self):
    super(Net, self).__init__()
    self.conv1 = nn.Conv2d(1, 1, kernel_size=3)
    self.conv2 = nn.Conv2d(1, 1, kernel_size=3)
    self.conv2_drop = nn.Dropout2d()
    self.fc1 = nn.Linear(25, 5)
    self.fc2 = nn.Linear(5, 10)

  def forward(self, x):
    x = F.relu(F.max_pool2d(self.conv1(x), 2))
    x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
    x = x.view(-1, 25)
    x = F.relu(self.fc1(x))
    x = F.dropout(x, training=self.training)
    x = self.fc2(x)
    return F.log_softmax(x, dim=1)

if __name__ == '__main__':
  mox.dist.init_process_group()
  dataset = load_data()
  model = Net()
  optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
  scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)

  mox.run(input_data=dataset,
          model=model,
          run_mode=ModeKeys.TRAIN,
          log_dir='/var/log/tmp',
          optimizer=optimizer,
          scheduler=scheduler,
          loss_fn=loss_fn,
          epoches=2,
          print_freq=128)


import math

with open("input12") as f:
    datos = f.read().splitlines()

class Moon():
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z

        self.x_speed = 0
        self.y_speed = 0
        self.z_speed = 0

    def update_speed(self,inc_x = 0,inc_y = 0,inc_z = 0):
        self.x_speed += inc_x
        self.y_speed += inc_y
        self.z_speed += inc_z

    def update_pos(self):
        self.x += self.x_speed
        self.y += self.y_speed
        self.z += self.z_speed

    def __str__(self):
        return f"Position: {self.x} {self.y} {self.z}\nVel: {self.x_speed} {self.y_speed} {self.z_speed}"

    def getCoords(self):
        return f"Position: {self.x} {self.y} {self.z}"

    def getDatos(self):
        return f"{str(self.x)}{str(self.y)}{str(self.z)}{str(self.x_speed)}{str(self.y_speed)}{str(self.z_speed)}"
    def getEnergy(self):
        #pot: 2 + 1 + 3 =  6;   kin: 3 + 2 + 1 = 6;   total:  6 * 6 = 36
        return (abs(self.x)+abs(self.y)+abs(self.z)) * \
            (abs(self.x_speed)+abs(self.y_speed)+abs(self.z_speed))
    def miHash(self):
        return f"{hash(str(self.x))}{hash(str(self.y))}{hash(str(self.z))}{hash(str(self.x_speed))} \
            {hash(str(self.y_speed))}{hash(str(self.z_speed))}"
lista_lunas = []
for d in datos:
    d = d.replace("=","--").replace(",","--").replace(">","").split("--")
    params = []
    for datin in d:
        try:
            params.append(int(datin))
        except:
            pass

    x,y,z = (params)
    lista_lunas.append(Moon(x,y,z))

import itertools
combi = (list(itertools.combinations(lista_lunas,2)))

step = 0

datosx = set()
datosy = set()
datosz = set()

def lcm(x, y):
    a, b = x, y
    while a:
        a, b = b % a, a
    return x // b * y

run  = True
while run:
    for c in combi:
        moon1 = c[0]
        moon2 = c[1]

        list_x = []
        list_y = []
        list_z = []

        if moon1.x > moon2.x:
            moon1.update_speed(-1)
            moon2.update_speed(1)
        elif moon2.x > moon1.x:
            moon1.update_speed(1)
            moon2.update_speed(-1)

        if moon1.y > moon2.y:
            moon1.update_speed(inc_y = -1)
            moon2.update_speed(inc_y = 1)
        elif moon2.y > moon1.y:
            moon1.update_speed(inc_y = 1)
            moon2.update_speed(inc_y = -1)

        if moon1.z > moon2.z:
            moon1.update_speed(inc_z = -1)
            moon2.update_speed(inc_z = 1)
        elif moon2.z > moon1.z:
            moon1.update_speed(inc_z = 1)
            moon2.update_speed(inc_z = -1)

    for moon in lista_lunas:
        moon.update_pos()
        list_x.append((moon.x,moon.x_speed))
        list_y.append((moon.y,moon.y_speed))
        list_z.append((moon.z,moon.z_speed))

    if tuple(list_x) in datosx and tuple(list_y) in datosy and tuple(list_z) in datosz:
        print(lcm(len(datosx), lcm(len(datosy), len(datosz))))
        run = False
        break
    else:
        datosx.add(tuple(list_x))
        datosy.add(tuple(list_y))
        datosz.add(tuple(list_z))
    step += 1

'''
pART 1
total_energy = 0
for moon in lista_lunas:
    total_energy += moon.getEnergy()
print(total_energy)
'''


# encoding: utf-8

# Images.py
# Este código va orientado a la toma de imágenes de video mediante la librería open cv en Python...
# Genera un número finito de imagenes en la carpeta enumerandolas del 1 al final de la toma de datos
# Para finalizar la toma de datos pulsa la tecla Q minúscula "q"

# Programador Sergio Luis Beleño Díaz
# 29.Octubre.2019

#Para empezar se importa la librería de Open cv para visión Artificial

import cv2
import os
#import vlc
#import time

# Asignamos la cámara ingresando cv2.VideoCapture(0)
# Si quiere asignar una segunda cámara externa puede usar cv2.VideoCapture(1)
cap = cv2.VideoCapture('C3.mp4')

formato = '.jpg'
name = 11637
tipo = 'Background_'

# Toma parámetros de captura de la cámara
[rec, camara] = cap.read()

while(rec == 1):

	# Toma parámetros de captura de la cámara
	[rec, camara] = cap.read()
	name = name + 1 # Contador de imagenes tomadas

	# Muestra la imagen tomada en una ventana
	if (rec ==1):

		#cv2.imshow('Captura', camara)
		file = str(tipo) + str(name) + formato
		# rotation angle in degree
		camara = cv2.resize(camara, None, fx = 0.7, fy= 0.7)
		camara = camara[0:480, 0:640]

		# Reescala la imagen
		#camara = cv2.resize(camara, (240,320))

		cv2.imshow('Camara',camara)

		if name%8 == 0:
			# Guarda la imagen tomada
			cv2.imwrite('7_Background/'+file,camara)
			contador_de_retardo = 0

		print("Imagen numero: " + str(name))

	if cv2.waitKey(1) & 0xFF == ord('q'):
		break

#plays = vlc.MediaPlayer("Beep_Short.mp3")
#plays.play()
#time.sleep(1)

cap.release()
cv2.destroyAllWindows()


# coding: utf-8

from qingcloud.cli.iaas_client.actions import job
from qingcloud.cli.iaas_client.actions import instance
from qingcloud.cli.iaas_client.actions import volume
from qingcloud.cli.iaas_client.actions import eip
from qingcloud.cli.iaas_client.actions import image
from qingcloud.cli.iaas_client.actions import keypair
from qingcloud.cli.iaas_client.actions import router
from qingcloud.cli.iaas_client.actions import sg
from qingcloud.cli.iaas_client.actions import vxnet
from qingcloud.cli.iaas_client.actions import lb
from qingcloud.cli.iaas_client.actions import monitor
from qingcloud.cli.iaas_client.actions import snapshot

class ActionManager(object):

    @classmethod
    def get_action(cls, action):
        return cls.action_table.get(action)

    action_table = {
            ## job ##
            'describe-jobs': job.DescribeJobsAction,

            ## instance ##
            'run-instances': instance.RunInstancesAction,
            'modify-instance-attributes': instance.ModifyInstanceAttributesAction,
            'reset-instances': instance.ResetInstancesAction,
            'resize-instances': instance.ResizeInstancesAction,
            'describe-instances': instance.DescribeInstancesAction,
            'restart-instances': instance.RestartInstancesAction,
            'start-instances': instance.StartInstancesAction,
            'stop-instances': instance.StopInstancesAction,
            'terminate-instances': instance.TerminateInstancesAction,

            ## volume ##
            'create-volumes': volume.CreateVolumesAction,
            'modify-volume-attributes': volume.ModifyVolumeAttributesAction,
            'describe-volumes': volume.DescribeVolumesAction,
            'attach-volumes': volume.AttachVolumesAction,
            'detach-volumes': volume.DetachVolumesAction,
            'delete-volumes': volume.DeleteVolumesAction,
            'resize-volumes': volume.ResizeVolumesAction,

            ## eip ##
            'describe-eips': eip.DescribeEipsAction,
            'allocate-eips': eip.AllocateEipsAction,
            'release-eips': eip.ReleaseEipsAction,
            'modify-eip-attributes': eip.ModifyEipAttributesAction,
            'associate-eip': eip.AssociateEipAction,
            'dissociate-eips': eip.DissociateEipsAction,
            'change-eips-bandwidth': eip.ChangeEipsBandwidthAction,

            ## sg ##
            'create-security-group': sg.CreateSecurityGroupAction,
            'describe-security-groups': sg.DescribeSecurityGroupsAction,
            'modify-security-group-attributes': sg.ModifySecurityGroupAttributesAction,
            'apply-security-group': sg.ApplySecurityGroupAction,
            'delete-security-groups': sg.DeleteSecurityGroupsAction,
            'describe-security-group-rules': sg.DescribeSecurityGroupRulesAction,
            'modify-security-group-rule-attributes': sg.ModifySecurityGroupRuleAttributesAction,
            'add-security-group-rules': sg.AddSecurityGroupRulesAction,
            'delete-security-group-rules': sg.DeleteSecurityGroupRulesAction,

            ## keypair ##
            'create-keypair': keypair.CreateKeyPairAction,
            'describe-keypairs': keypair.DescribeKeyPairsAction,
            'attach-keypairs': keypair.AttachKeyPairsAction,
            'detach-keypairs': keypair.DetachKeyPairsAction,
            'modify-keypair-attributes': keypair.ModifyKeyPairAttributesAction,
            'delete-keypairs': keypair.DeleteKeyPairsAction,

            ## vxnet ##
            'create-vxnets': vxnet.CreateVxnetsAction,
            'describe-vxnet-instances': vxnet.DescribeVxnetInstancesAction,
            'describe-vxnets': vxnet.DescribeVxnetsAction,
            'join-vxnet': vxnet.JoinVxnetAction,
            'leave-vxnet': vxnet.LeaveVxnetAction,
            'modify-vxnet-attributes': vxnet.ModifyVxnetAttributesAction,
            'delete-vxnets': vxnet.DeleteVxnetsAction,

            ## router ##
            'add-router-statics': router.AddRouterStaticsAction,
            'join-router': router.JoinRouterAction,
            'leave-router': router.LeaveRouterAction,
            'create-routers': router.CreateRoutersAction,
            'modify-router-attributes': router.ModifyRouterAttributesAction,
            'modify-router-static-attributes': router.ModifyRouterStaticAttributesAction,
            'delete-router-statics': router.DeleteRouterStaticsAction,
            'delete-routers': router.DeleteRoutersAction,
            'poweroff-routers': router.PowerOffRoutersAction,
            'poweron-routers': router.PowerOnRoutersAction,
            'describe-routers': router.DescribeRoutersAction,
            'describe-router-statics': router.DescribeRouterStaticsAction,
            'describe-router-vxnets': router.DescribeRouterVxnetsAction,
            'update-routers': router.UpdateRoutersAction,

            ## image ##
            'describe-images': image.DescribeImagesAction,
            'modify-image-attributes': image.ModifyImageAttributesAction,
            'capture-instance': image.CaptureInstanceAction,
            'delete-images': image.DeleteImagesAction,

            ## load balancer ##
            'add-loadbalancer-backends': lb.AddLoadBalancerBackendsAction,
            'add-loadbalancer-listeners': lb.AddLoadBalancerListenersAction,
            'associate-eips-to-loadbalancer': lb.AssociateEipsToLoadBalancerAction,
            'create-loadbalancers': lb.CreateLoadBalancerAction,
            'delete-loadbalancer-backends': lb.DeleteLoadBalancerBackendsAction,
            'delete-loadbalancer-listeners': lb.DeleteLoadBalancerListenersAction,
            'delete-loadbalancers': lb.DeleteLoadBalancersAction,
            'describe-loadbalancer-backends': lb.DescribeLoadBalancerBackendsAction,
            'describe-loadbalancer-listeners': lb.DescribeLoadBalancerListenersAction,
            'describe-loadbalancers': lb.DescribeLoadBalancersAction,
            'dissociate-eips-from-loadbalancer': lb.DissociateEipsFromLoadBalancerAction,
            'modify-loadbalancer-attributes': lb.ModifyLoadBalancerAttributesAction,
            'modify-loadbalancer-backend-attributes': lb.ModifyLoadBalancerBackendAttributesAction,
            'modify-loadbalancer-listener-attributes': lb.ModifyLoadBalancerListenerAttributessAction,
            'start-loadbalancers': lb.StartLoadBalancersAction,
            'stop-loadbalancers': lb.StopLoadBalancersAction,
            'update-loadbalancers': lb.UpdateLoadBalancersAction,

            ## monitor ##
            'get-monitoring-data': monitor.GetMonitorAction,
            'get-loadbalancer-monitoring-data': monitor.GetLoadBalancerMonitorAction,

            ## snapshot ##
            'create-snapshots': snapshot.CreateSnapshotsAction,
            'delete-snapshots': snapshot.DeleteSnapshotsAction,
            'describe-snapshots': snapshot.DescribeSnapshotsAction,
            }


"""
containers.py - Module that provides support decorators for running tasks inside containers
"""
import logging
import inspect
import re
from functools import partial
import docker as dkr

client = dkr.from_env()

def docker(function=None,
           image=None,
           packages=None,
           consume_gpu=True):
    """

    :param function:
    :param image:
    :param sleep:
    :return:
    """
    def decorator(func):
        def wrapper(f_func):

            lines = inspect.getsource(f_func)
            logging.info("Running container: %s",image)
            lines = re.sub('@', '#@', lines)
            name = f_func.__name__

            installpackages = []
            for package in packages:
                installpackages += ["pip install -q {}".format(package)]

            code = "bash -c \"{}\npython <<HEREDOC {}\nprint({}())\"\nHEREDOC".format(
                ";".join(installpackages), lines, name)

            logging.debug(code)
            env = {}

            if not consume_gpu:
                env['TF_FORCE_GPU_ALLOW_GROWTH'] = True

            result = client.containers.run(
                image, code, environment=env)

            logging.debug(result)
            return result

        pfunc = partial(wrapper, func)
        pfunc.__name__ = func.__name__

        return pfunc

    if function is not None:
        return decorator(function)

    return decorator


# import re
# numbers = [-2,-1,0,1,2]
# def extract_positive(numbers):
#     positive_numbers = []
#     for number in numbers:
#         if number > 0:
#             positive_numbers.append(number)
#     return positive_numbers
# extract_positive(numbers)
# numbers = [-2,-1,0,1,2]
# positive_numbers = filter(lambda n: n>0, numbers)
# positive_numbers
# list(positive_numbers)
# def is_positive(n):
#     return n > 0
# list(filter(is_positive, numbers))
# def identity(x):
#     return x
# identity(42)
# load_fp = input('Enter your damn file path(use foward slash), brad: ')
# filepath = 'C:/Users/ranch/Downloads/jack.txt'
            # print(sum(nums))
# for element in mylines:
#     print(element)

# try:
    # num = float(num)
#     if num == 'logical reads':
#         num = " " + num
#     print(num)
# except ValueError:
#     print('The provided value is not a number')
# num = 0
# while True:
#     try:
#         num = int(input("Enter your favorite integer: "))
#     except ValueError:
#         print("Please enter a valid integer")
#         continue
#     else:
#         print(f'You entered: {num}')
#         break

# import re
# with open('C:/Users/J/Downloads/jack.txt', 'rt') as fp:
#     line = fp.readline()
#     while line:
#         match= re.search(r'(?<=logical reads )[^,]*',line)
#         if match is not None:
#             nums = int(match.group(0))
#             list_nums = [nums]
#             print(sum(list_nums))
#         line = fp.readline()

# --------- close -------------
# path = 'C:/Users/J/Downloads/jack.txt'
# with open(path) as fp:
#     for line in fp:
#         match= re.search(r'(?<=logical reads )[^,]*',line)
#         if match is not None:
#             nums = int(match.group(0))
#             print(nums)
# -------------------------------------------------------
import re,np,math
usrInput = input("Stop asking me to calculate, Enter dir path: ")
# text = open('C:/Users/ranch/Downloads/jack.txt')
text = open(usrInput)
final = []
for line in text:
    line = line.strip()
    match = re.findall('(?<=logical reads )[^,]*',line)

    if len(match) > 0:
         lineVal = (sum(map(int, match))*8096)/1000000
         final.append(lineVal)
        #  print("line sum = {0}".format(lineVal))
write = open('result.txt' , 'w')
write.write("Final sum = {: ,} ".format(math.ceil(np.sum(final))) + "MB")
# print("Final sum = {: ,}".format(np.sum(final)),"MB")
# print("Final sum = {: ,} ".format(math.ceil(np.sum(final))) + "MB")
# input("Press enter to close program")
# --------------------------------------------------------------


# BiGRU implementation in Tensorflow
# Contributors: DJ Jin, T Liu, J Yasmin
# CISC867 Reproducibility study 2021
# Queen's University, Canada

# The following is an implementation of a bidirectional GRU network.
# This implementation is based on the PyTorch equivalent implemented by
# S. Panthaplackel, J.J. Li, G. Milos, and R.J. Mooney (2020),
# hosted at https://github.com/panthap2/deep-jit-inconsistency-detection

import tensorflow as tf
from tensorflow.keras.layers import GRU
from tensorflow.keras.layers import Bidirectional
from tensorflow.keras.layers import Dense

class BiGru (tf.Module):
    def __init__(self, embedding_size, hidden_size,
                 num_layers, dropout, bidirectional=True):
        super(BiGru, self).__init__()
        self.__rnn = Bidirectional(GRU(input_size=embedding_size,
                         hidden_size=hidden_size,
                         dropout=dropout,
                         num_layer=num_layers,
                         time_major=False)) #data on tensorflow is batch-major by default

    def forward(selfself, src_embedded_tokens, src_lengths, device):
        encoder_hidden_states, _ = self.__rnn.forward(src_embedded_tokens)
        return encoder_hidden_states, encoder_final_state