from pythondaq.models.diode_experiment import DiodeExperiment
import csv
from os import listdir, path, mkdir, getcwd
import matplotlib.pyplot as plt
import click

@click.group()
def cmd_group():
    pass

@cmd_group.command(name="list")
@click.option(
    "-s",
    "--search",
    default=None,
    help="only return devices which match with given search value",
    show_default=True,
)
def click_list(search=None):
    """Function that prints a list of the connected devices

    Args:
        search (string, optional): search term to match connected devices to. Defaults to None.
    """
    list_devices(search, display=True)

def list_devices(search=None, display=False):
    """Function that prints a list of the connected devices

    Args:
        search (string, optional): search term to match connected devices to. Defaults to None.
        display (bool, optional): flag to toggle printing the device list. Defaults to False.

    Returns:
        list: list containing the ports of connected devices
    """
    if not search:
        print(DiodeExperiment().get_connected_devices())
        return DiodeExperiment().get_connected_devices()
    else:
        matching = []
        for device in DiodeExperiment().get_connected_devices():
            if search in device:
                matching.append(device)
        # This makes sure that nothing is printed when the function is called in info() or scan()
        if display:
            print(matching)
            return
        return matching

@cmd_group.command()
@click.option(
    "-p",
    "--port",
    default=None,
    help="port of the device from which info is requested",
    show_default=None,
)
def info(port):
    """Function that requests the identification string from a device

    Args:
        port (string): port of a connected device. Partial ports are attempted to be matched.
    """
    if not port:
        print("No device port was given")

    else:
        ports = list_devices(port)
        assert (
            len(ports) < 2
        ), f"More than one device matches the given port value: {ports}"
        assert len(ports) > 0, "No devices match the given port value"
        port = ports.pop()
        DiodeExperiment().device_info(port=port)

@cmd_group.command()
@click.option(
    "-b",
    "--begin",
    default=0,
    type=click.FloatRange(0, 3.3),
    help="Voltage where scan should start",
    show_default=True,
)
@click.option(
    "-e",
    "--end",
    default=3.3,
    type=click.FloatRange(0, 3.3),
    help="Voltage where scan should end",
    show_default=True,
)
@click.option(
    "-o",
    "--output",
    default=None,
    help="File path where ouput should be saved if specified",
    show_default=True,
)
@click.option(
    "-g",
    "--graph/--no-graph",
    help="flag option to specify if results should be plotted",
)
@click.option(
    "-n",
    "--number",
    default=5,
    help="sample size of measurments per voltage",
    show_default=True,
)
@click.argument("port", type=str)
def scan(port, begin, end, output, graph, number):
    """Function that starts an experiment

    Args:
        port (string): port of the experiment controller device. Partial ports are attempted to be matched.
        begin (float): analog voltage at which the experiment starts. Defaults to 0.0.
        end (float): analog voltage at which the experiment stops. Defaults to 3.3.
        output (string): path at which data should be stored. Defaults to None.
        graph (bool): flag variable to determine whether output needs to be plotted. Defaults to False.
        number (int): number of samples to take at each voltage level. Defaults to 5.
    """
    assert begin <= end, "Cannot have the begin value be greater then the end value"
    assert number > 0, "Cannot have a sample size of less then one"

    # This uses the searh functionality of the list function to match incomplete port inputs
    ports = list_devices(port)
    assert len(ports) < 2, f"More than one device matches the given port value: {ports}"
    assert len(ports) > 0, "No devices match the given port value"
    port = ports.pop()

    header, data = DiodeExperiment().scan(
        port=port, start=begin, stop=end, sample_size=number
    )

    # Create lists to extract LED Voltages and currents plus their errors
    led_volts = []
    led_volt_errors = []
    currents = []
    current_errors = []

    if not output:
        for (
            total_volt,
            total_volt_error,
            resistor_volt,
            resistor_volt_error,
            led_volt,
            led_volt_error,
            current,
            current_error,
            resistance,
        ) in data:
            led_volts.append(led_volt)
            led_volt_errors.append(led_volt_error)
            currents.append(current)
            current_errors.append(current_error)

        # print the lists containing the data
        print(led_volts)
        print(currents)

        if graph:
            # plotting the data
            plt.errorbar(
                led_volts,
                currents,
                xerr=led_volt_errors,
                yerr=current_errors,
                linestyle="None",
                marker="o",
                markersize=3,
            )

            # formatting the plot
            plt.xlim(0, 3)
            plt.ylim(0, 0.003)
            plt.title("U,I-characteristic plot for an LED", fontsize=17)
            plt.xlabel("LED volage (V)", fontsize=14)
            plt.ylabel("LED current (A)", fontsize=14)
            plt.tight_layout()
            plt.show()

    else:
        with open(output, "w", newline="") as file:
            writer = csv.writer(file)

            # write the header into the file first
            writer.writerow(header)

            # unpack the zip object (data) with a for loop
            for (
                total_volt,
                total_volt_error,
                resistor_volt,
                resistor_volt_error,
                led_volt,
                led_volt_error,
                current,
                current_error,
                resistance,
            ) in data:

                # write all values into a the CSV file
                writer.writerow(
                    [
                        total_volt,
                        total_volt_error,
                        resistor_volt,
                        resistor_volt_error,
                        led_volt,
                        led_volt_error,
                        current,
                        current_error,
                        resistance,
                    ]
                )

                # save values to plot/print later
                led_volts.append(led_volt)
                led_volt_errors.append(led_volt_error)
                currents.append(current)
                current_errors.append(current_error)

        # print the lists containing the data
        print(led_volts)
        print(currents)

        if graph:
            # plotting the data
            plt.errorbar(
                led_volts,
                currents,
                xerr=led_volt_errors,
                yerr=current_errors,
                linestyle="None",
                marker="o",
                markersize=3,
            )

            # formatting the plot
            plt.xlim(0, 3)
            plt.ylim(0, 0.003)
            plt.title("U,I-characteristic plot for an LED", fontsize=17)
            plt.xlabel("LED volage (V)", fontsize=14)
            plt.ylabel("LED current (A)", fontsize=14)
            plt.tight_layout()
            plt.show()

    return

if __name__ == "main":
    cmd_group()


'''
##############################
Plot tools (``owtools``)
##############################

.. autofunction:: resize_plot_item_list

.. autofunction:: move_item

.. autofunction:: move_item_xy

.. autoclass:: TooltipManager
    :members:

.. autoclass:: PolygonCurve
    :members:
    :show-inheritance:

.. autoclass:: RectangleCurve
    :members:
    :show-inheritance:

.. autoclass:: CircleCurve
    :members:
    :show-inheritance:

.. autoclass:: UnconnectedLinesCurve
    :members:
    :show-inheritance:

.. autoclass:: Marker
    :members:
    :show-inheritance:

'''

from PyQt4.QtGui import QGraphicsItem, QGraphicsRectItem, QPolygonF, QGraphicsPolygonItem, QGraphicsEllipseItem, QPen, QBrush
from PyQt4.QtCore import Qt, QRectF, QPointF, QPropertyAnimation

from owcurve import *
from owpalette import OWPalette

from Orange.data.preprocess.scaling import get_variable_values_sorted
from Orange import orangeom
import ColorPalette

def resize_plot_item_list(lst, size, item_type, parent):
    """
        Efficiently resizes a list of QGraphicsItems (PlotItems, Curves, etc.).
        If the list is to be reduced, i.e. if len(lst) > size, then the extra items are first removed from the scene.
        If items have to be added to the scene, new items will be of type ``item_type`` and will have ``parent``
        as their parent item.

        The list is resized in place, this function returns nothing.

        :param lst: The list to be resized
        :type lst: list of QGraphicsItem

        :param size: The needed size of the list
        :type size: int

        :param item_type: The type of items that should be added if the list has to be increased
        :type item_type: type

        :param parent: Any new items will have this as their parent item
        :type parent: QGraphicsItem
    """
    n = len(lst)
    if n > size:
        for i in lst[size:]:
            i.setParentItem(None)
            if i.scene():
                i.scene().removeItem(i)
        del lst[size:]
    elif n < size:
        lst.extend(item_type(parent) for i in range(size - n))

def move_item(item, pos, animate = True, duration = None):
    '''
        Animates ``item`` to move to position ``pos``.
        If animations are turned off globally, the item is instead move immediately, without any animation.

        :param item: The item to move
        :type item: QGraphicsItem

        :param pos: The final position of the item
        :type pos: QPointF

        :param duration: The duration of the animation. If unspecified, Qt's default value of 250 miliseconds is used.
        :type duration: int
    '''
    if not duration:
        duration = 250
    orangeqt.PlotItem.move_item(item, pos, animate, duration)

def move_item_xy(item, x, y, animate = True, duration = None):
    '''
        Same as
        move_item(item, QPointF(x, y), duration)
    '''
    move_item(item, QPointF(x, y), animate, duration)

class TooltipManager:
    """
        A dynamic tool tip manager.

        :param plot: The plot used for transforming the coordinates
        :type plot: :obj:`.OWPlot`
    """
    def __init__(self, plot):
        self.graph = plot
        self.positions=[]
        self.texts=[]

    def addToolTip(self, x, y, text, customX = 0, customY = 0):
        """
            Adds a tool tip. If a tooltip with the same name already exists, it updates it instead of adding a new one.

            :param x: The x coordinate of the tip, in data coordinates.
            :type x: float

            :param y: The y coordinate of the tip, in data coordinates.
            :type y: float

            :param text: The text to show in the tip.
            :type text: str or int

            :param customX: The maximum horizontal distance in pixels from the point (x,y) at which to show the tooltip.
            :type customX: float

            :param customY: The maximum vertical distance in pixels from the point (x,y) at which to show the tooltip.
            :type customY: float

            If ``customX`` and ``customY`` are omitted, a default of 6 pixels is used.
        """
        self.positions.append((x,y, customX, customY))
        self.texts.append(text)

    #Decides whether to pop up a tool tip and which text to pop up
    def maybeTip(self, x, y):
        """
            Decides whether to pop up a tool tip and which text to show in it.

            :param x: the x coordinate of the mouse in data coordinates.
            :type x: float

            :param y: the y coordinate of the mouse in data coordinates.
            :type y: float

            :returns: A tuple consisting of the ``text``, ``x`` and ``y`` arguments to :meth:`addToolTip` of the
                      closest point.
            :rtype: tuple of (int or str), float, float
        """
        if len(self.positions) == 0: return ("", -1, -1)
        dists = [max(abs(x-position[0])- position[2],0) + max(abs(y-position[1])-position[3], 0) for position in self.positions]
        nearestIndex = dists.index(min(dists))

        intX = abs(self.graph.transform(xBottom, x) - self.graph.transform(xBottom, self.positions[nearestIndex][0]))
        intY = abs(self.graph.transform(yLeft, y) - self.graph.transform(yLeft, self.positions[nearestIndex][1]))
        if self.positions[nearestIndex][2] == 0 and self.positions[nearestIndex][3] == 0:   # if we specified no custom range then assume 6 pixels
            if intX + intY < 6:  return (self.texts[nearestIndex], self.positions[nearestIndex][0], self.positions[nearestIndex][1])
            else:                return ("", None, None)
        else:
            if abs(self.positions[nearestIndex][0] - x) <= self.positions[nearestIndex][2] and abs(self.positions[nearestIndex][1] - y) <= self.positions[nearestIndex][3]:
                return (self.texts[nearestIndex], x, y)
            else:
                return ("", None, None)

    def removeAll(self):
        """
            Removes all tips
        """
        self.positions = []
        self.texts = []

class PolygonCurve(OWCurve):
    """
        A plot item that shows a filled or empty polygon.

        :param pen: The pen used to draw the polygon's outline
        :type pen: :obj:`.QPen`

        :param brush: The brush used to paint the polygon's inside
        :type brush: :obj:`.QBrush`

        :param xData: The list of x coordinates
        :type xData: list of float

        :param yData: The list of y coordinates
        :type yData: list of float

        :param tooltip: The tool tip shown when hovering over this curve
        :type tooltip: str
    """
    def __init__(self, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = [], yData = [], tooltip = None):
        OWCurve.__init__(self, xData, yData, tooltip=tooltip)
        self._data_polygon = self.polygon_from_data(xData, yData)
        self._polygon_item = QGraphicsPolygonItem(self)
        self.set_pen(pen)
        self.set_brush(brush)

    def update_properties(self):
        self._polygon_item.setPolygon(self.graph_transform().map(self._data_polygon))
        self._polygon_item.setPen(self.pen())
        self._polygon_item.setBrush(self.brush())

    @staticmethod
    def polygon_from_data(xData, yData):
        """
            Creates a polygon from a list of x and y coordinates.

            :returns: A polygon with point corresponding to ``xData`` and ``yData``.
            :rtype: QPolygonF
        """
        if xData and yData:
            n = min(len(xData), len(yData))
            p = QPolygonF(n+1)
            for i in range(n):
                p[i] = QPointF(xData[i], yData[i])
            p[n] = QPointF(xData[0], yData[0])
            return p
        else:
            return QPolygonF()

    def set_data(self, xData, yData):
        self._data_polygon = self.polygon_from_data(xData, yData)
        OWCurve.set_data(self, xData, yData)

class RectangleCurve(OWCurve):
    """
        A plot item that shows a rectangle.

        This class accepts the same options as :obj:`.PolygonCurve`.
        The rectangle is calculated as the smallest rectangle that contains all points in ``xData`` and ``yData``.
    """
    def __init__(self, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None, tooltip = None):
        OWCurve.__init__(self, xData, yData, tooltip=tooltip)
        self.set_pen(pen)
        self.set_brush(brush)
        self._item = QGraphicsRectItem(self)

    def update_properties(self):
        self._item.setRect(self.graph_transform().mapRect(self.data_rect()))
        self._item.setPen(self.pen())
        self._item.setBrush(self.brush())

class UnconnectedLinesCurve(orangeqt.UnconnectedLinesCurve):
    """
        A plot item that shows a series of unconnected straight lines.

        :param name: The name of this curve. :seealso: :attr:`.OWCurve.name`
        :type name: str

        :param pen: The pen used to draw the lines
        :type pen: QPen

        :param xData: The list of x coordinates
        :type xData: list of float

        :param yData: The list of y coordinates
        :type yData: list of float

        The data should contain an even number of elements. Lines are drawn between the `n`-th and
        `(n+1)`-th point for each even `n`.
    """
    def __init__(self, name, pen = QPen(Qt.black), xData = None, yData = None):
        orangeqt.UnconnectedLinesCurve.__init__(self)
        self.set_data(xData, yData)
        if pen:
            self.set_pen(pen)
        self.name = name

class CircleCurve(OWCurve):
    """
        Displays a circle on the plot

        :param pen: The pen used to draw the outline of the circle
        :type pen: QPen

        :param brush: The brush used to paint the inside of the circle
        :type brush: QBrush

        :param xCenter: The x coordinate of the circle's center
        :type xCenter: float

        :param yCenter: The y coordinate of the circle's center
        :type yCenter: float

        :param radius: The circle's radius
        :type radius: float
    """
    def __init__(self, pen = QPen(Qt.black), brush = QBrush(Qt.NoBrush), xCenter = 0.0, yCenter = 0.0, radius = 1.0):
        OWCurve.__init__(self)
        self._item = QGraphicsEllipseItem(self)
        self.center = xCenter, yCenter
        self.radius = radius
        self._rect = QRectF(xCenter-radius, yCenter-radius, 2*radius, 2*radius)
        self.set_pen(pen)
        self.set_brush(brush)

    def update_properties(self):
        self._item.setRect(self.graph_transform().mapRect(self.data_rect()))
        self._item.setPen(self.pen())
        self._item.setBrush(self.brush())

    def data_rect(self):
        x, y = self.center
        r = self.radius
        return QRectF(x-r, y-r, 2*r, 2*r)

class Marker(orangeqt.PlotItem):
    """
        Displays a text marker on the plot.

        :param text: The text to display. It can be HTML-formatted
        :type tex: str

        :param x: The x coordinate of the marker's position
        :type x: float

        :param y: The y coordinate of the marker's position
        :type y: float

        :param align: The text alignment
        :type align:

        :param bold: If ``True``, the text will be show bold.
        :type bold: int

        :param color: The text color
        :type color: QColor

        :param brushColor: The color of the brush user to paint the background
        :type color: QColor

        :param size: Font size
        :type size: int

        Markers have the QGraphicsItem.ItemIgnoresTransformations flag set by default,
        so text remains the same size when zooming. There is no need to scale the manually.
    """
    def __init__(self, text, x, y, align, bold = 0, color = None, brushColor = None, size=None):
        orangeqt.PlotItem.__init__(self)
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
        self._item = QGraphicsTextItem(text, parent=self)
        self._data_point = QPointF(x,y)
        f = self._item.font()
        f.setBold(bold)
        if size:
            f.setPointSize(size)
        self._item.setFont(f)
        self._item.setPos(x, y)

    def update_properties(self):
        self._item.setPos(self.graph_transform().map(self._data_point))

class ProbabilitiesItem(orangeqt.PlotItem):
    """
        Displays class probabilities in the background

        :param classifier: The classifier for which the probabilities are calculated
        :type classifier: orange.P2NN

        :param granularity: The size of individual cells
        :type granularity: int

        :param scale: The data scale factor
        :type scale: float

        :param spacing: The space between cells
        :param spacing: int

        :param rect: The rectangle into which to draw the probabilities. If unspecified, the entire plot is used.
        :type rect: QRectF
    """
    def __init__(self, classifier, granularity, scale, spacing, rect=None):
        orangeqt.PlotItem.__init__(self)
        self.classifier = classifier
        self.rect = rect
        self.granularity = granularity
        self.scale = scale
        self.spacing = spacing
        self.pixmap_item = QGraphicsPixmapItem(self)
        self.set_in_background(True)
        self.setZValue(ProbabilitiesZValue)

    def update_properties(self):
        ## Mostly copied from OWScatterPlotGraph
        if not self.plot():
            return

        if not self.rect:
            x,y = self.axes()
            self.rect = self.plot().data_rect_for_axes(x,y)
        s = self.graph_transform().mapRect(self.rect).size().toSize()
        if not s.isValid():
            return
        rx = s.width()
        ry = s.height()

        rx -= rx % self.granularity
        ry -= ry % self.granularity

        p = self.graph_transform().map(QPointF(0, 0)) - self.graph_transform().map(self.rect.topLeft())
        p = p.toPoint()

        ox = p.x()
        oy = -p.y()

        if self.classifier.classVar.varType == orange.VarTypes.Continuous:
            imagebmp = orangeom.potentialsBitmap(self.classifier, rx, ry, ox, oy, self.granularity, self.scale)
            palette = [qRgb(255.*i/255., 255.*i/255., 255-(255.*i/255.)) for i in range(255)] + [qRgb(255, 255, 255)]
        else:
            imagebmp, nShades = orangeom.potentialsBitmap(self.classifier, rx, ry, ox, oy, self.granularity, self.scale, self.spacing)
            palette = []
            sortedClasses = get_variable_values_sorted(self.classifier.domain.classVar)
            for cls in self.classifier.classVar.values:
                color = self.plot().discPalette.getRGB(sortedClasses.index(cls))
                towhite = [255-c for c in color]
                for s in range(nShades):
                    si = 1-float(s)/nShades
                    palette.append(qRgb(*tuple([color[i]+towhite[i]*si for i in (0, 1, 2)])))
            palette.extend([qRgb(255, 255, 255) for i in range(256-len(palette))])

        self.potentialsImage = QImage(imagebmp, rx, ry, QImage.Format_Indexed8)
        self.potentialsImage.setColorTable(ColorPalette.signedPalette(palette) if qVersion() < "4.5" else palette)
        self.potentialsImage.setNumColors(256)
        self.pixmap_item.setPixmap(QPixmap.fromImage(self.potentialsImage))
        self.pixmap_item.setPos(self.graph_transform().map(self.rect.bottomLeft()))

    def data_rect(self):
        return self.rect if self.rect else QRectF()

@deprecated_members({
        'enableX' : 'set_x_enabled',
        'enableY' : 'set_y_enabled',
        'xEnabled' : 'is_x_enabled',
        'yEnabled' : 'is_y_enabled',
        'setPen' : 'set_pen'
    })
class PlotGrid(orangeqt.PlotItem):
    """
        Draws a grid onto the plot

        :param plot: If specified, the grid will be attached to the ``plot``.
        :type plot: :obj:`.OWPlot`
    """
    def __init__(self, plot = None):
        orangeqt.PlotItem.__init__(self)
        self._x_enabled = True
        self._y_enabled = True
        self._path_item = QGraphicsPathItem(self)
        self.set_in_background(True)
        if plot:
            self.attach(plot)
            self._path_item.setPen(plot.color(OWPalette.Grid))

    def set_x_enabled(self, b):
        """
            Enables or disabled vertial grid lines
        """
        if b < 0:
            b = not self._x_enabled
        self._x_enabled = b
        self.update_properties()

    def is_x_enabled(self):
        """
            Returns whether vertical grid lines are enabled
        """
        return self._x_enabled

    def set_y_enabled(self, b):
        """
            Enables or disabled horizontal grid lines
        """
        if b < 0:
            b = not self._y_enabled
        self._y_enabled = b
        self.update_properties()

    def is_y_enabled(self):
        """
            Returns whether horizontal grid lines are enabled
        """
        return self._y_enabled

    def set_pen(self, pen):
        """
            Sets the pen used for drawing the grid lines
        """
        self._path_item.setPen(pen)

    def update_properties(self):
        p = self.plot()
        if p is None:
            return
        x_id, y_id = self.axes()
        rect = p.data_rect_for_axes(x_id, y_id)
        path = QPainterPath()
        if self._x_enabled and x_id in p.axes:
            for pos, label, size, _w in p.axes[x_id].ticks():
                path.moveTo(pos, rect.bottom())
                path.lineTo(pos, rect.top())
        if self._y_enabled and y_id in p.axes:
            for pos, label, size, _w in p.axes[y_id].ticks():
                path.moveTo(rect.left(), pos)
                path.lineTo(rect.right(), pos)
        self._path_item.setPath(self.graph_transform().map(path))


import collections
class Solution:
    def loudAndRich(self, richer, quiet):
        richer_count = [0 for _ in range(len(quiet))]
        graph = collections.defaultdict(list)
        answer = [idx for idx in range(len(quiet))]

        for rich, poor in richer:
            graph[rich].append(poor)
            richer_count[poor] += 1

        queue = [] #In queue starts 2,4,5,6
        for person, rich_count in enumerate(richer_count):
            if not rich_count:
                queue.append(person)

        while queue:
            cur = queue.pop(0)
            quieter = answer[cur]
            print(quieter)
            for poorer in graph[cur]:
                print(poorer)
                quieter_richer = answer[poorer] #
                print(quieter_richer)
                answer[poorer]=min(quieter, quieter_richer, key = lambda x: quiet[x])
                print(answer[poorer])
                richer_count[poorer] -=1
                if not richer_count[poorer]:
                    queue.append(poorer)

        return answer

richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]]
quiet = [3,2,5,4,6,1,7,0]

print(Solution().loudAndRich(richer, quiet))


#!/usr/bin/env python

from setuptools import setup, find_packages

import pathlib

here = pathlib.Path(__file__).parent.resolve()

setup(name='oo_scoping',
      version='1.0',
      description='Object-Oriented state abstraction',
      long_description=(here / 'README.md').read_text(encoding='utf-8'),
      author='Michael Fishman and Nishanth Kumar',
      author_email='michaeljfishman@protonmail.com, nishanth.kumar20@gmail.com',
      url='https://github.com/h2r/OO-Scoping-IPC',
      install_requires=[
          'z3-solver'
      ],
      py_modules=[]
)


from PyQt5.QtWidgets import QApplication, QMessageBox

import sys

def fatal(message):
  if QMessageBox:
    try:
      app = QApplication(sys.argv)
      QMessageBox.critical(None, 'Error', str(message))
    except BaseException as exc:
      print('fatal:', message)
      print('during handling of the above error, following error occured')
      print('fatal:', exc)
  else:
    print('fatal:', message)
  sys.exit(1)


import discord
import os
import re
import requests
from bs4 import BeautifulSoup
import json
from nltk.corpus import wordnet
import nltk
from sklearn.feature_extraction.text import TfidfVectorizer
import joblib
import numpy as np
from unidecode import unidecode
nltk.download('wordnet')
nltk.download('omw')
nltk.download('omw-1.4')
nltk.download('punkt')

import dotenv # comentar no monstrao
dotenv.load_dotenv() # comentar no monstrao
intents = discord.Intents.all()
vectorizer = TfidfVectorizer()
client = discord.Client(intents=intents)
api_ip = os.getenv('API_IP')
@client.event
async def on_message(message: discord.Message):

    if message.author == client.user:
        return

    if message.content.lower() == '!oi':
        # get user name
        user = message.author
        user = user.name.split('#')[0]
        await message.channel.send(f'Olá {user}! ')

    elif message.content.lower() == '!source':
        await message.channel.send('O meu código fonte pode ser encontrado nesse repositório: https://github.com/MarceloCMiguel/discord-nlp/')

    elif message.content.lower() == "!author":
        await message.channel.send('Meu criador é o Marcelo Miguel ( marcelocm8@al.insper.edu.br )')

    # check if the first 4 words is !run
    elif message.content.lower()[:4] == '!run':
        # Regular expression pattern for matching IP address
        ip_pattern = r"\b(?:\d{1,3}\.){3}\d{1,3}\b"

        ip_adress = message.content.lower()[5:].strip()
        # check if the ip adress is valid
        if re.match(ip_pattern, ip_adress):
            # send the message to the channel
            response = requests.get('https://api.ipgeolocation.io/ipgeo',
                        params=
                        {'apiKey': api_ip,
                         'ip': ip_adress})
            if response.status_code != 200:
                await message.channel.send('Erro ao obter informações do IP, tente novamente mais tarde')
                return
            data = response.json()
            isp = data['isp']
            country = data['country_name']
            city = data['city']
            await message.channel.send(f'O seu provedor de internet é o {isp}\n situado no país {country} e na cidade {city}')

        else:
            # send the message to the channel
            await message.channel.send('Endereço de IP inválido')

    # if start with !crawl
    elif message.content.lower()[:6] == '!crawl':

        pipeline = joblib.load('model_sentiment.joblib')

        # create folder website_data if not exists
        if not os.path.exists('website_data'):
            os.mkdir('website_data')

        # check if file inverted_index.json exists
        if not os.path.exists('inverted_index.json'):
            inverted_index = {}
        else:
            with open('inverted_index.json', 'r') as f:
                inverted_index = json.load(f)

        # Regular expression pattern for matching url address
        url_pattern = r"\b(?:https?://)?(?:www\.)?([a-zA-Z0-9-]+)\.([a-zA-Z0-9-]+)\b"
        url_adress = message.content.lower()[7:].strip()
        # check if the url adress is valid
        if re.match(url_pattern, url_adress):
            # get the url
            response = requests.get(url_adress)
            if response.status_code != 200:
                print(response.status_code)
                await message.channel.send('Erro ao obter informações da URL, tente novamente mais tarde')
                return
            # get the html
            html = response.text
            # parse the html
            soup = BeautifulSoup(html, 'html.parser')
            text = soup.get_text( separator=' ')
            words = re.findall(r'\b\w+\b', text)
            data = {}
            data["url"] = url_adress
            title = soup.title.string
            # remove all tokens and accents from title
            title = unidecode(title)

            data['title'] = title
            data['links'] = [link.get('href') for link in soup.find_all('a')]
            data["html"] = html
            # transform text to a list of words (the text is words separated by spaces)
            text_list = text.split(' ')
            print('test',pipeline.predict_log_proba([text])[0])
            # converter as probabilidades logarítmicas em probabilidades não logarítmicas
            # pred_log_proba = pipeline.predict_log_proba([text])[0]
            sentiment = pipeline.predict_log_proba(["happy"]).max()
            data['sentiment'] = sentiment

            try:

                await message.channel.send(f'''
                Sentimento: {data['sentiment']}
                Título: {data['title']}
                Links: {data['links']}
                ''')
            except:
                await message.channel.send('Response too long, but the crawler works!')
            # save the data in a new json file with the name of the title
            with open(f'website_data/{title}.json', 'w+', encoding='utf-8') as f:
                json.dump(data, f)

            # now, create a inverted index with term frequencies (TF)

            # lower case all words
            words = [word.lower() for word in words]

            # count the number of times each word appears in the text
            count_words = {}
            for word in words:
                if word not in count_words:
                    count_words[word] = 0
                count_words[word] += 1
            total_words = len(words)

            # calculate the TF for each word in inverted_index
            for word in count_words:
                if total_words == 0:
                    tf_word = 0
                elif count_words[word] == 0:
                    tf_word = 0
                else:
                    tf_word = count_words[word] / total_words
                if word not in inverted_index:
                    inverted_index[word] = {}
                if title not in inverted_index[word]:
                    inverted_index[word][title] = tf_word

            # save the inverted index in a json file
            with open('inverted_index.json', 'w+', encoding= 'utf-8') as f:
                json.dump(inverted_index, f, ensure_ascii=False, indent=4)

            # send the message to the channel telling that the crawl was successful and the sentiment
            try:
                await message.channel.send(f'Crawled {url_adress} with sentiment {sentiment}')
            except:
                pass

    # check if the message start with !search
    elif message.content.lower()[:8] == '!search ':
        threshold = None
        input = message.content.lower()[8:].strip()
        pattern = r'^[^\s]+ th=(-?\d+\.\d+)$'
        match1 = re.match(pattern, input)
        if match1:
            threshold = float(match1.group(1))
            print(threshold)
            if (threshold < -1) or (threshold > 1):
                await message.channel.send('Threshold inválido, deve estar entre -1 e 1')
                return
            # remove the th=... from the input
            input = input.replace("th="+match1.group(1), '').strip()
            print(input)

        # get the rest of the message
        search_term = input

        # count the number of files in website_data
        count_files = 0
        sentiments_title = {}
        for file in os.listdir('website_data'):
            count_files += 1
            # enter in the folder website_data
            with open(f'website_data/{file}', 'r') as f:
                print("abrindo arquivo")
                # check if has the key sentiment
                data = json.load(f)
                if 'sentiment' in data.keys():
                    sentiments_title[data['title']] = data['sentiment']
        if count_files == 0:
            await message.channel.send('Não há nenhum website salvo, rode um !crawl <URL> primeiro')
            return

        print("procurando por: ", search_term, "")
        # check if file inverted_index.json exists
        if not os.path.exists('inverted_index.json'):
            await message.channel.send('Não há nenhum índice invertido salvo, rode um !crawl <URL> primeiro')
            return
        else:
            with open('inverted_index.json', 'r') as f:
                inverted_index = json.load(f)
        # check if the search term is in the inverted index
        if search_term not in inverted_index:
            await message.channel.send('Termo não encontrado')
            return
        else:
            # check which website has the highest TF
            max_tf = 0
            max_tf_website = ''
            tf_maior_0 = 0
            for website in inverted_index[search_term]:
                # check if threshold is not None
                if threshold is not None:
                    # check if the sentiment is higher than the threshold
                    if sentiments_title[website] < threshold:
                        print(sentiments_title[website])
                        continue

                if inverted_index[search_term][website] > max_tf:
                    max_tf = inverted_index[search_term][website]
                    max_tf_website = website
                if inverted_index[search_term][website] > 0:
                    tf_maior_0 += 1
            if tf_maior_0 == 0:
                await message.channel.send('Termo não encontrado')
                return
            # df = numbers of website with tf_0 divided by the total number of websites
            df = tf_maior_0 / count_files
            tf_df = max_tf/df

            await message.channel.send(f'''
            O termo {search_term} com o maior TF/DF esta no documento {max_tf_website} com o valor de {tf_df}, o TF é {max_tf} e o DF é {df}
            ''')

    # check if the message start with !wn_search
    elif message.content.lower()[:10] == '!wn_search':

        threshold = None
        input = message.content.lower()[10:].strip()
        pattern = r'^[^\s]+ th=(-?\d+\.\d+)$'
        match1 = re.match(pattern, input)
        if match1:
            threshold = float(match1.group(1))
            print(threshold)
            if (threshold < -1) or (threshold > 1):
                await message.channel.send('Threshold inválido, deve estar entre -1 e 1')
                return
            # remove the th=... from the input
            input = input.replace("th="+match1.group(1), '').strip()
            print(input)

        terms =re.findall('\w+', input)

        relevancy = {}

        sentiments_title = {}
        for file in os.listdir('website_data'):
            # enter in the folder website_data
            with open(f'website_data/{file}', 'r') as f:
                # check if has the key sentiment
                data = json.load(f)
                if 'sentiment' in data.keys():
                    sentiments_title[data['title']] = data['sentiment']

        await message.channel.send(f'''
        Procurando por: {terms} ou palavras similares
        ''')
        # check if file inverted_index.json exists
        if not os.path.exists('inverted_index.json'):
            await message.channel.send('Não há nenhum índice invertido salvo, rode um !crawl <URL> primeiro')
            return

        # get the file inverted_index.json
        with open('inverted_index.json', 'r') as f:
            inverted_index = json.load(f)

        keys = list(inverted_index.keys())

        # check if threshold is not None
        if threshold is not None:
            keys = []
            for key in inverted_index.keys():
                websites = inverted_index[key]
                websites_keys = list(websites.keys())
                for website in websites_keys:
                    if sentiments_title[website] >= threshold:
                        keys.append(key)

        for voc in keys:
            valor_soma = 0
            for word in terms:
                voc_lower = re.sub(r'[^\w\s]', '', voc.lower())

                syns1 = wordnet.synsets(word)
                syns2 = wordnet.synsets(voc_lower)
                print("procurando por ", word, " e ", voc_lower, "")
                if len(syns1) > 0 and len(syns2) > 0:
                    similarity = syns1[0].wup_similarity(syns2[0])
                    print("a similaridade entre ", word, " e ", voc_lower, " é ", similarity, "")
                    if similarity is not None:
                        valor_soma += similarity
            relevancy[voc] = valor_soma

        # remove all terms from relevancy that is 0
        relevancy = {k: v for k, v in relevancy.items() if v != 0}
        if len(relevancy) == 0:
            await message.channel.send('Não há palavras similares')
            return

        # sort the relevancy dict and get the first 5 items
        similar_terms = sorted(relevancy.items(), key=lambda x: x[1], reverse=True)[:5]

        # search for the similar words in the inverted index
        similarity_words = []
        for term in similar_terms:
            if term[0] in inverted_index:
                similarity_words.append(term[0])

        # if there is no similar words, send a message
        if len(similarity_words) == 0:
            await message.channel.send('Não há palavras similares')
            return

        # send the message
        await message.channel.send(f'''
        Palavras similares a {terms}:
        {similarity_words}
        ''')

    elif message.content.lower() == '!help':
        await message.channel.send('''
        Comandos disponíveis:
        !oi - Retorna uma mensagem de boas vindas
        !source - Retorna o link do repositório do bot
        !author - Retorna o email do autor do bot
        !run <IP> - Retorna informações sobre o IP informado
        !crawl <URL> - Retorna informações sobre a URL informada
        !help - Retorna uma lista com os comandos disponíveis''')

@client.event
async def on_ready():
    print('client Online')

def find_similar_words(word, word_list):

    # Create an empty list to store the similar words
    similar_words = []

    # Get the synsets (sets of synonyms) for the word
    synsets = wordnet.synsets(word)
    print(synsets)

    # Iterate through each synset and add its lemmas (synonyms) to the list of similar words
    for synset in synsets:
        for lemma in synset.lemmas():
            similar_words.append(lemma.name())

    # Add the original word to the list of similar words
    similar_words.append(word)

    print(similar_words)

    # Create an empty list to store the words that appear in both similar_words and word_list
    matching_words = []

    # Iterate through each word in similar_words and check if it appears in word_list
    for similar_word in similar_words:
        if similar_word in word_list:
            matching_words.append(similar_word)

    return matching_words

client.run(os.getenv('TOKEN'))


#15651 N과M(3)
import sys
from itertools import product
input = sys.stdin.readline

N,M = map(int, input().split())

P = product([str(i) for i in range(1, N+1)], repeat=M)

for num in P:
    print(' '.join(map(str,num)))


from adtk.data import validate_series
from adtk.detector import ThresholdAD
import pandas as pd
import warnings
warnings.filterwarnings("ignore")

def anomaly_detection(dataset, high, low, column):
    data = dataset.loc[:, ["TimeStamp",
                           column]]
    data = data.set_index("TimeStamp")
    data.index = pd.to_datetime(data.index)
    data = validate_series(data)
    threshold_ad = ThresholdAD(high=high, low=low)
    anomalies = threshold_ad.detect(data)
    data["Anomaly"] = anomalies.values
    data["Anomaly"] = pd.get_dummies(data["Anomaly"], drop_first=True)

    return data["Anomaly"].values

def anomaly_detection_manual(data, column, high, low):
    data_true = data.loc[(data[column] > high) | (data[column] < low)]
    index = data_true.index.values

    return index


from flask import Flask

app = Flask(__name__)

@app.route('/math/<numb1>,<numb2>')
def home(numb1, numb2):
    sum = int(numb1) + int(numb2)
    sum = str(sum)
    return 'hello, user: ' + sum

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


import torch
from torch.autograd.gradcheck import gradcheck

import dcnv3

def test_dcnv3(dtype=torch.float64,
               device='cuda'):
    torch.manual_seed(12)
    device = torch.device(device)

    input = torch.randn(1, 10, 10, 4,
                        dtype=dtype, device=device, requires_grad=True)
    kernel_h, kernel_w = 3, 3
    stride_h, stride_w = 1, 1
    pad_h, pad_w = 1, 1
    dilation_h, dilation_w = 1, 1
    group = 2
    group_channels = input.size(-1) // group
    offset_scale = 1.0
    im2col_step = 256
    remove_center = 0

    offset = torch.randn(*input.shape[:-1], group * 2 * (kernel_h * kernel_w - remove_center),
                         dtype=dtype, device=device, requires_grad=True)
    mask = torch.rand(*input.shape[:-1], group * (kernel_h * kernel_w - remove_center),
                      dtype=dtype, device=device, requires_grad=True)

    optim = torch.optim.Optimizer([input, offset, mask], {})

    c_output = dcnv3.ops.dcnv3(input, offset, mask,
                               kernel_h, kernel_w,
                               stride_h, stride_w,
                               pad_h, pad_w,
                               dilation_h, dilation_w,
                               group, group_channels,
                               offset_scale,
                               im2col_step,
                               remove_center)
    c_output.sum().backward()
    c_input_grad = input.grad.clone()
    c_offset_grad = offset.grad.clone()
    c_mask_grad = mask.grad.clone()
    optim.zero_grad()
    print(c_output)

    grad_ok = gradcheck(
        lambda inp, off, msk: dcnv3.ops.dcnv3(inp, off, msk,
                                              kernel_h, kernel_w,
                                              stride_h, stride_w,
                                              pad_h, pad_w,
                                              dilation_h, dilation_w,
                                              group, group_channels,
                                              offset_scale,
                                              im2col_step, remove_center),
        (input, offset, mask), nondet_tol=1e-5)
    print('grad_check:', grad_ok)

if __name__ == '__main__':
    test_dcnv3()


# Construccion de una Pokedex

# Se construira un programa en el cual el usuario podra ingresar el nombre de un pokemon del cual quiera saber sus
# caracteristicas principales y su imagen, el programa contara con 3 opciones en las que el usuario podra agregar un Pokemon
# nuevo a la coleccion o podra ver los Pokemones que ya se hayan agregado anteriormente.
# Asi mismo, el usuario podra salir del programa cuando lo desee.

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

# En este primer bloque del programa se importaran las librerias necesarias para realizar las tareas y funciones
# de la Pokedex

from urllib.request import urlopen
from PIL import Image
import matplotlib.pyplot as plt
import requests

# Se inicia estableciendo un ciclo while para asegurar que el prgrama va a funcionar hasta que el usuario lo decida.

while True:

    # En esta primera seccion del ciclo se le pregunta al usuario lo que desea hacer en el programa

    print("""
            ¿Que desea hacer?
            1. Agregar un nuevo Pokemon.
            2. Ver pokemones y caracteristicas que han sido agregados a la Pokedex.
            3. Salir de la Pokedex.
            """)

    opcion = input(
        'Por favor ingrese una opcion: ')

# Luego, dependiendo de la opcion elegida por el usuario, se inicia con la accion que el usuario ha elegido.

    if opcion == '1':

        # Para la primera opcion se inicia creando las listas vacias necesarias para el manejo de la informacion,
        # fue necesario crear una lista para cada dato que contenia mas de 1 elemento ya que si se guardaba directamente
        # en los datos del pokemon solo se guardaba el primer dato.

        pokemones = []
        datos_pokemon = []
        lista_mov = []
        lista_hab = []
        lista_tip = []

# Se le pide al usuario que ingrese el nombre de un pokemon que conozca o quiera conocer.

        pokemon = input('Ingresa el nombre de un pokemon: ')

# Este es la url de la API de donde obtendremos los datos del programa.

        url = 'https://pokeapi.co/api/v2/pokemon/' + pokemon

# Se incluye un manejo de excepciones respecto al tiempo de espera para que el programa finalice
# si los datos no son obtenidos desde la API en un tiempo igual o menor a 12 segundos

        try:
            respuesta = requests.get(url, timeout=12)
        except requests.Timeout:
            print('Error: tiempo de espera ha finalizado')

# En esta seccion se verifica que la respuesta sea la adecuada y que los datos sean obtenidos correctamente

        if respuesta.status_code != 200:
            print('Pokemon no encontrado')
            print('Vuelva a intentarlo')
            continue

# Se hace la conversion de los datos de respuesta a json para que python los pueda interpretar de manera correcta

        datos = respuesta.json()

# Se realiza un manejo de excepciones para verificar que el Pokemon ingresado si tenga una imagen relacionada en la API
# En caso de no tener ninguna imagen relacionada, el programa finalizara.
        try:
            url_imagen = datos['sprites']['front_default']
            imagen = Image.open(urlopen(url_imagen))
        except:
            print('El pokemon no tiene imagen')
            exit()

# En esta seccion del programa, se obtendran todos los datos del Pokemon que ha ingresado el usuario

        peso = datos['weight']
        datos_pokemon.append(peso)

        tamaño = datos['height']
        datos_pokemon.append(tamaño)

# Fue necesario crear ciclos for para obtener los datos de las secciones que tenian mas de 1 elemento.

        movimiento = datos['moves']
        for i in range(int(len(movimiento))):
            movimientos = movimiento[i]['move']['name']
            lista_mov.append(movimientos)
        datos_pokemon.append(lista_mov)

        habilidad = datos['abilities']
        for i in range(int(len(habilidad))):
            habilidades = habilidad[i]['ability']['name']
            lista_hab.append(habilidades)
        datos_pokemon.append(lista_hab)

        tipos = datos['types']
        for i in range(int(len(tipos))):
            tipo = tipos[i]['type']['name']
            lista_tip.append(tipo)
        datos_pokemon.append(lista_tip)

# Se realiza la consolidacion de todos los datos en la lista vacia de Pokemones

        pokemones.append(pokemon)

# En esta seccion se muestran los datos del pokemon ingresado.

        lista_datos = (
            f' Nombre: {pokemon} , Peso: {datos_pokemon[0]}\t  Tamaño: {datos_pokemon[1]}\t --- Movimientos: {lista_mov}\t --- Habilidades: {lista_hab}\t --- Tipo: {lista_tip}\t imagen: {url_imagen}\n')

        print('''Los datos del Pokemon son:
            ''')
        print(lista_datos)

# Se abre un archivo de texto llamado Pokedex.txt el cual contendra toda la informaciond e los Pokemones que se consulten

        with open('Pokedex.txt', 'a') as f_Pokedex:
            for i in pokemones:
                f_Pokedex.write(f'{lista_datos} \n')
        f_Pokedex.close()
        print(f'Se ha agregado a {pokemon} a la Pokedex')
        print('Datos del Pokemon guardados en la Pokedex')

# Esta seccion muestra la imagen del Pokemon.

        plt.title(datos['name'])
        imgplot = plt.imshow(imagen)
        plt.show()

# En esta seccion se muestran los datos de todos los Pokemon que han sido agregados a la Pokedex.

    elif opcion == '2':

        with open('Pokedex.txt', 'r') as f_lectura:
            numero_pokemones = 0
            for i in f_lectura:
                numero_pokemones += 1
                print(f'Pokemon {numero_pokemones}: {i}')
        f_lectura.close()
        exit()

# Esta seccion es cuando el usuario desea salir de una forma segura de la Pokedex.

    elif opcion == 3:
        print('La pokedex se ha cerrado correctamente. Hasta pronto.')
        exit()

# Esta seccion contiene dos mensajes que se le mostraran al usuario cuando no ingrese ninguna de las 3 opciones.

    else:
        print('Opcion invalida')
        print('Volver a intentar')

# FIN DEL PROGRAMA


import numpy as np
from scipy.integrate import odeint
from scipy.signal import find_peaks
import matplotlib.pyplot as plt

# Total population, N.
# N = 1000
N = 64.8
# Initial number of infected and recovered individuals, I0 and R0.
# I0, R0 = 1, 0
I0, R0 = 1, 0
# Everyone else, S0, is susceptible to infection initially.
S0 = N - I0 - R0
# Contact rate, beta, and mean recovery rate, gamma, (in 1/days).
# beta, gamma = 0.2, 1./10
beta, gamma = 0.594, 0.07
# A grid of time points (in days)
t = np.linspace(0, 60, 60)

# The SIR model differential equations.
def deriv(y, t, N, beta, gamma):

    dSdt = -beta * S * I / N
    dIdt = beta * S * I / N - gamma * I
    dRdt = gamma * I
    return

# Initial conditions vector
y0 = S0, I0, R0
# Integrate the SIR equations over the time grid, t.
ret = odeint(deriv)
S, I, R = ret.T

for z,j,k,l in zip(t, S, I, R):
    print("{0}\t {1}\t {2}\t {3}\t".format(t,j/1000,k/1000,l/1000))

# Plot the data on three separate curves for S(t), I(t) and R(t)
fig = plt.figure(facecolor='w')
#fig.suptitle('This is a somewhat long figure title', fontsize=16)
ax = fig.add_subplot(111,  axisbelow=True)
ax.plot(t, S/1000, 'b', alpha=0.5, lw=2, label='Susceptible')
ax.plot(t, I/1000, 'r', alpha=0.5, lw=2, label='Infected')
ax.plot(t, R/1000, 'g', alpha=0.5, lw=2, label='Recovered with immunity')
ax.set_xlabel('Time /days')
ax.set_ylabel('Number of People (millions)')
ax.set_title('SIR Python Model Graph for Kalangala')
ax.set_ylim(0,1.2)
ax.yaxis.set_tick_params(length=0)
ax.xaxis.set_tick_params(length=0)
ax.grid(b=True, which='major', c='w', lw=2, ls='-')
legend = ax.legend()
legend.get_frame().set_alpha(0.5)
for spine in ('top', 'right', 'bottom', 'left'):
    ax.spines[spine].set_visible(False)
plt.show()

# pieLabels = 'Susceptible', 'Infected', 'Recovered with immunity'
# pieData =[S/1000, I/1000, R/1000]
# figureObject, axesObject = plt.subplots()
# axesObject.pie(pieData,

#         labels=pieLabels,

#         autopct='%1.2f',
# )
# axesObject.axis('equal')
# plt.show()


import torch
from torch import nn

class UNet(nn.Module):

    def __init__(self, num_classes, start_filters, channels_in=1, transpose=False, batch_norm=False):
        # five sets of standard conv blocks
        super().__init__()
        self.conv1 = self.gen_conv_block(channels_in, start_filters, pooling=False, batch_norm=batch_norm)
        self.conv2 = self.gen_conv_block(start_filters, start_filters * 2, batch_norm=batch_norm)
        self.conv3 = self.gen_conv_block(start_filters * 2, start_filters * 4, batch_norm=batch_norm)
        self.conv4 = self.gen_conv_block(start_filters * 4, start_filters * 8, batch_norm=batch_norm)
        self.conv5 = self.gen_conv_block(start_filters * 8, start_filters * 16, batch_norm=batch_norm)

        # four sets of upsampling layers
        self.up6 = self.gen_upsampling_block(start_filters * 16, start_filters * 8, transpose)
        self.conv6 = self.gen_conv_block(start_filters * 16, start_filters * 8, pooling=False, batch_norm=batch_norm)

        self.up7 = self.gen_upsampling_block(start_filters * 8, start_filters * 4, transpose)
        self.conv7 = self.gen_conv_block(start_filters * 8, start_filters * 4, pooling=False, batch_norm=batch_norm)

        self.up8 = self.gen_upsampling_block(start_filters * 4, start_filters * 2, transpose)
        self.conv8 = self.gen_conv_block(start_filters * 4, start_filters * 2, pooling=False, batch_norm=batch_norm)

        self.up9 = self.gen_upsampling_block(start_filters * 2, start_filters, transpose)
        self.conv9 = self.gen_conv_block(start_filters * 2, start_filters, pooling=False, batch_norm=batch_norm)
        # 1x1xC conv with no upsampling
        self.conv10 = nn.Sequential(
            nn.Conv2d(start_filters, num_classes, kernel_size=1, stride=1),
            nn.Sigmoid()
        )

    @staticmethod
    def get_final_block(channels_in, num_classes):
        layers = [nn.Conv2d(channels_in, num_classes, kernel_size=1, stride=1)]
        if num_classes > 1:
            layers.append(nn.Softmax())
        else:
            layers.append(nn.Sigmoid())
        return nn.Sequential(*layers)

    @staticmethod
    def gen_upsampling_block(channels_in, channels_out, transpose=False, batch_norm=False):
        layers = []
        if transpose:
            layers.append(nn.ConvTranspose2d(channels_in, channels_out,
                                             kernel_size=2, stride=2))
        else:
            layers += [nn.Upsample(scale_factor=2, mode='nearest'),
                       nn.Conv2d(channels_in, channels_out, kernel_size=3, padding=[1, 1])]
        if batch_norm:
            layers.append(nn.BatchNorm2d(channels_out))
            nn.ReLU()
        return nn.Sequential(*layers)

    @staticmethod
    def gen_conv_block(channels_in, channels_out, kernel_size=3,
                       pooling=True, batch_norm=False):
        if pooling:
            layers = [nn.MaxPool2d(kernel_size=2, stride=2)]
        else:
            layers = []
        layers.append(nn.Conv2d(channels_in, channels_out, kernel_size, padding=[1, 1]))
        if batch_norm:
            layers.append(nn.BatchNorm2d(channels_out))
        layers += [nn.ReLU(),
                   nn.Conv2d(channels_out, channels_out, kernel_size, padding=[1, 1])]
        if batch_norm:
            layers.append(nn.BatchNorm2d(channels_out))
        layers.append(nn.ReLU())
        return nn.Sequential(*layers)

    def forward(self, x):
        x1 = self.conv1(x)
        x2 = self.conv2(x1)
        x3 = self.conv3(x2)
        x4 = self.conv4(x3)
        x5 = self.conv5(x4)

        u6 = self.up6(x5)
        x6 = self.conv6(torch.cat([u6, x4], dim=1))

        u7 = self.up7(x6)
        x7 = self.conv7(torch.cat([u7, x3], dim=1))

        u8 = self.up8(x7)
        x8 = self.conv8(torch.cat([u8, x2], dim=1))

        u9 = self.up9(x8)
        x9 = self.conv9(torch.cat([u9, x1], dim=1))

        x10 = self.conv10(x9)
        return x10


import datetime
import pandas as pd
import requests
import xml.etree.ElementTree as ET
from lxml import html
import re

def transform_gold(x):
    if len(x) == 10:
        x = str(x).replace(',', '').replace(' ', '')
        return float(x[:4] + '.' + x[4:])
    else:
        return float(x)

# OnlineCommands
class OnlineCommands:
    def __init__(self, message):
        self.message = message

    @staticmethod
    def currency_today():
        today_date = datetime.datetime.now().strftime('%d.%m.%Y')
        currency_xml = requests.get(f'http://www.cbr.ru/scripts/XML_daily.asp?date_req={today_date}').text
        root = ET.fromstring(currency_xml)
        for child in root:
            if child.attrib['ID'] == 'R01035':
                gbp_text = child.find('CharCode').text
                gbp_value = child.find('Value').text
            if child.attrib['ID'] == 'R01235':
                usd_text = child.find('CharCode').text
                usd_value = child.find('Value').text
            if child.attrib['ID'] == 'R01239':
                eur_text = child.find('CharCode').text
                eur_value = child.find('Value').text
        currency_today_message =f"""Курс валют на сегодня ({today_date}):
    - Доллар стоит {usd_value} руб.
    - Евро стоит {eur_value} руб.
    - Фунт стерлинга стоит {gbp_value} руб.
    """
        return currency_today_message

    @staticmethod
    def metals_today():
        dragmetals_online = pd.read_html(
        'https://www.cbr.ru/hd_base/metall/metall_base_new/', decimal=',', thousands='d')
        dragmetals_online = dragmetals_online[0]
        dragmetals_online.columns = ['Дата', 'Золото', 'Серебро', 'Платина', 'Палладий']
        today_date = datetime.datetime.now().strftime('%d.%m.%Y')

        dragmetals_online['Золото'] = dragmetals_online['Золото'].apply(transform_gold)
        dragmetals_online['Платина'] = dragmetals_online['Платина'].apply(transform_gold)
        dragmetals_online['Палладий'] = dragmetals_online['Палладий'].apply(transform_gold)
        drag_message = f"""Стоимость драг. металлов на сегодня ({today_date})\n"""
        drag_actual = dragmetals_online.head(1).to_dict()
        for k, v in drag_actual.items():
            if k != 'Дата':
                drag_message = drag_message + k + ' стоит ' + str(v[0]) + ' руб.\n'
        return drag_message

    @staticmethod
    def key_indices_today():
        today_date = datetime.datetime.now().strftime('%d.%m.%Y')
        key_indices = requests.get('https://www.cbr.ru/key-indicators/')
        tree = html.fromstring(key_indices.content)
        target_inflation = tree.xpath('/html/body/main/div/div/div/div[1]/div[1]/div[2]/div[1]/div[2]') # inflation target
        target_inflation = target_inflation[0].text.split('\r')[0]
        fact_inflation = tree.xpath('/html/body/main/div/div/div/div[1]/div[1]/div[2]/div[2]/div[2]')
        fact_inflation = fact_inflation[0].text.split('\r')[0]
        fact_inflation_month = tree.xpath('/html/body/main/div/div/div/div[1]/div[1]/div[2]/div[2]/div[1]/div[1]')
        fact_inflation_month = fact_inflation_month[0].text.split('\r')[0]
        key_rate = tree.xpath('/html/body/main/div/div/div/div[1]/div[2]/div[2]/div/div[2]')
        key_rate = key_rate[0].text.split('\r')[0]
        key_rate_date = tree.xpath('/html/body/main/div/div/div/div[1]/div[2]/div[2]/div/div[1]/div[1]')
        key_rate_date = key_rate_date[0].text.split('\xa0')[-1]
        key_indices_message = f"""Ключевые показатели ЦБ на {today_date}
    Цель по инфляции {target_inflation}
    Фактическая инфляция {fact_inflation} на {fact_inflation_month.lower()}
    Ключевая ставка с {key_rate_date} равна {key_rate}
    """
        return key_indices_message


import numpy as np
import matplotlib.pyplot as plt

n = 100

def func(x):
    return x ** 5

ax = np.linspace(-1, 1, 10)
ay = [func(x) for x in ax]
ay_ = [func(x) - np.random.random(n) for x in ax]
ay__ = [func(x) + np.random.random(n) for x in ax]

plt.figure(figsize=(5, 4))

plt.xticks(np.linspace(-1, 1, 5))

plt.scatter(ax, ay, c='k', alpha=.9)
plt.plot(ax, ay_, c='r', alpha=.5)
plt.plot(ax, ay__, c='b', alpha=.5)
plt.savefig('out.jpg')
plt.show()


import torch
import pystk
import ray
import numpy as np
from config import device
from IPython.display import Video, display
import imageio

def init_ray():
    ray.init()

class Rollout:

    def euclidean_distance(self,pos1, pos2):
        return np.linalg.norm(np.array(pos1) - np.array(pos2))

    def __init__(self, screen_width, screen_height, hd=True, track='icy_soccer_field', render=True, frame_skip=1):

        config = pystk.GraphicsConfig.hd()
        config.screen_width = screen_width
        config.screen_height = screen_height
        pystk.init(config)

        self.frame_skip = frame_skip
        self.render = render
        config = pystk.RaceConfig()
        config.mode = config.RaceMode.SOCCER
        config.track = "icy_soccer_field"
        config.step_size = 0.1
        config.num_kart = 2
        config.players[0].kart = "wilber"
        config.players[0].controller = pystk.PlayerConfig.Controller.PLAYER_CONTROL
        config.players[0].team = 0
        config.players.append(
        pystk.PlayerConfig("", pystk.PlayerConfig.Controller.AI_CONTROL, 1))

        self.race = pystk.Race(config)
        self.race.start()

    def __call__(self, agent, n_steps=200):
        torch.set_num_threads(1)
        self.race.restart()
        self.race.step()
        data = []
        world_info = pystk.WorldState()
        world_info.update()
        total_distance = 0
        prev_position = world_info.players[0].kart.location
        for i in range(n_steps // self.frame_skip):
            world_info = pystk.WorldState()

            world_info.update()

            player_info = world_info.players[0].kart
            opponent_info = world_info.players[1].kart
            soccer_ball = world_info.soccer.ball
            soccer_state = world_info.soccer
            soccer_ball_loc = world_info.soccer.ball.location
            goal_location = soccer_state.goal_line[1]
            goal_ball_distance = np.array(soccer_ball_loc) - np.array(goal_location[1])
            puck_goal_distance = np.linalg.norm(goal_ball_distance)
            reward_state = 1/(puck_goal_distance +1)

            current_position = np.array(player_info.location)
            total_distance += self.euclidean_distance(prev_position, current_position)
            prev_position = current_position

            agent_data = { 'player_state': player_info,'opponent_state':opponent_info,'soccer_state':soccer_state,'overall_distance':total_distance,"reward_state":reward_state}
            if self.render:
                agent_data['image'] = np.array(self.race.render_data[0].image)

            action = agent(**agent_data)
            agent_data['action'] = action

            for it in range(self.frame_skip):
                self.race.step(action)

            data.append(agent_data)
        return data

def create_rollout(screen_width, screen_height, use_ray, hd=True, track='icy_soccer_field', render=True, frame_skip=1):
    if use_ray:
        remoteRollout = ray.remote(Rollout)
        return remoteRollout.remote(screen_width, screen_height, hd=hd, track=track, render=render, frame_skip=frame_skip)
    else:
        return Rollout(screen_width, screen_height, hd=hd, track=track, render=render, frame_skip=frame_skip)

def perform_rollout(rollout_instance, agent, n_steps=200, use_ray=False):
    if use_ray:
        return ray.get(rollout_instance.__call__.remote(agent, n_steps=n_steps))
    else:
        return rollout_instance.__call__(agent, n_steps=n_steps)

def show_video(frames, fps=30):
    imageio.mimwrite('/tmp/test.mp4', frames, fps=fps, bitrate=1000000)
    display(Video('/tmp/test.mp4', width=800, height=600, embed=True))

def rollout_many(many_agents, use_ray=True, **kwargs):
    if use_ray and not ray.is_initialized():
        init_ray()
    rollouts = [create_rollout(50, 50, True, hd=False, render=False, frame_skip=5) for i in range(10)]
    rollout_data = []
    for i, agent in enumerate(many_agents):
        rollout_data.append(perform_rollout(rollouts[i % len(rollouts)], agent, use_ray=use_ray, **kwargs))
    return rollout_data

def show_agent(agent, n_steps=600,use_ray=False):
    if use_ray and not ray.is_initialized():
        init_ray()
    viz_rollout = create_rollout(400, 300, False)
    data = perform_rollout(viz_rollout, agent, n_steps=n_steps, use_ray=False)
    show_video([d['image'] for d in data])


import torch.utils.data as data

from PIL import Image

import os
import os.path
import sys

def has_file_allowed_extension(filename, extensions):
    """Checks if a file is an allowed extension.

    Args:
        filename (string): path to a file
        extensions (iterable of strings): extensions to consider (lowercase)

    Returns:
        bool: True if the filename ends with one of given extensions
    """
    filename_lower = filename.lower()
    return any(filename_lower.endswith(ext) for ext in extensions)

def is_image_file(filename):
    """Checks if a file is an allowed image extension.

    Args:
        filename (string): path to a file

    Returns:
        bool: True if the filename ends with a known image extension
    """
    return has_file_allowed_extension(filename, IMG_EXTENSIONS)

def make_dataset(dir, class_to_idx, extensions):
    images = []
    dir = os.path.expanduser(dir)
    for target in sorted(class_to_idx.keys()):
        d = os.path.join(dir, target)
        if not os.path.isdir(d):
            continue

        for root, _, fnames in sorted(os.walk(d)):
            for fname in sorted(fnames):
                if has_file_allowed_extension(fname, extensions):
                    path = os.path.join(root, fname)
                    item = (path, class_to_idx[target])
                    images.append(item)

    return images

def read_list(path_in):
    with open(path_in) as fin:
        while True:
            line = fin.readline()
            if not line:
                break
            line = [i.strip() for i in line.strip().split('\t')]
            line_len = len(line)
            if line_len < 3:
                print('lst should at least has three parts, but only has %s parts for %s' %(line_len, line))
                continue
            try:
                item = [int(line[0])] + [line[-1]] + [float(i) for i in line[1:-1]]
            except Exception as e:
                print('Parsing lst met error for %s, detail: %s' %(line, e))
                continue
            yield item

class DatasetDetection(data.Dataset):
    """A generic data loader where the samples are arranged in this way: ::

        root/class_x/xxx.ext
        root/class_x/xxy.ext
        root/class_x/xxz.ext

        root/class_y/123.ext
        root/class_y/nsdf3.ext
        root/class_y/asd932_.ext

    Args:
        root (string): Root directory path.
        loader (callable): A function to load a sample given its path.
        extensions (list[string]): A list of allowed extensions.
        transform (callable, optional): A function/transform that takes in
            a sample and returns a transformed version.
            E.g, ``transforms.RandomCrop`` for images.
        target_transform (callable, optional): A function/transform that takes
            in the target and transforms it.

     Attributes:
        classes (list): List of the class names.
        class_to_idx (dict): Dict with items (class_name, class_index).
        samples (list): List of (sample path, class_index) tuples
        targets (list): The class_index value for each image in the dataset
    """

    def __init__(self, root, loader, image_folders, lable_lst, extensions, phase=None, transform=None, target_transform=None):
        # classes, class_to_idx = self._find_classes(root)
        samples = read_list(os.path.join(root, lable_lst))
        # samples = make_dataset(root, class_to_idx, extensions)
        if len(samples) == 0:
            raise(RuntimeError("Found 0 files in subfolders of: " + root + "\n"
                               "Supported extensions are: " + ",".join(extensions)))

        self.root = root
        self.loader = loader
        self.extensions = extensions

        self.classes = classes
        self.class_to_idx = class_to_idx
        self.samples = samples
        # self.targets = [s[1] for s in samples]
        self.images_path = [s[1] for s in samples]

        self.transform = transform
        self.target_transform = target_transform

    def _check_valid_label(self, label):
        """Validate label and its shape."""
        if len(label.shape) != 2 or label.shape[1] < 5:
            msg = "Label with shape (1+, 5+) required, %s received." % str(label)
            raise RuntimeError(msg)
        valid_label = np.where(np.logical_and(label[:, 0] >= 0, label[:, 3] > label[:, 1],
                                              label[:, 4] > label[:, 2]))[0]
        if valid_label.size < 1:
            raise RuntimeError('Invalid label occurs.')

    def _estimate_label_shape(self):
        """Helper function to estimate label shape"""
        max_count = 0
        self.reset()
        try:
            while True:
                label, _ = self.next_sample()
                label = self._parse_label(label)
                max_count = max(max_count, label.shape[0])
        except StopIteration:
            pass
        self.reset()
        return (max_count, label.shape[1])

    def _parse_label(self, label):
        """Helper function to parse object detection label.

        Format for raw label:
        n \t k \t ... \t [id \t xmin\t ymin \t xmax \t ymax \t ...] \t [repeat]
        where n is the width of header, 2 or larger
        k is the width of each object annotation, can be arbitrary, at least 5
        """
        if isinstance(label, nd.NDArray):
            label = label.asnumpy()
        raw = label.ravel()
        if raw.size < 7:
            raise RuntimeError("Label shape is invalid: " + str(raw.shape))
        header_width = int(raw[0])
        obj_width = int(raw[1])
        if (raw.size - header_width) % obj_width != 0:
            msg = "Label shape %s inconsistent with annotation width %d." \
                %(str(raw.shape), obj_width)
            raise RuntimeError(msg)
        out = np.reshape(raw[header_width:], (-1, obj_width))
        # remove bad ground-truths
        valid = np.where(np.logical_and(out[:, 3] > out[:, 1], out[:, 4] > out[:, 2]))[0]
        if valid.size < 1:
            raise RuntimeError('Encounter sample with no valid label.')
        return out[valid, :]

    def reshape(self, data_shape=None, label_shape=None):
        """Reshape iterator for data_shape or label_shape.

        Parameters
        ----------
        data_shape : tuple or None
            Reshape the data_shape to the new shape if not None
        label_shape : tuple or None
            Reshape label shape to new shape if not None
        """
        if data_shape is not None:
            self.check_data_shape(data_shape)
            self.provide_data = [(self.provide_data[0][0], (self.batch_size,) + data_shape)]
        if label_shape is not None:
            self.check_label_shape(label_shape)
            self.provide_label = [(self.provide_label[0][0], (self.batch_size,) + label_shape)]

    def __getitem__(self, index):
        """
        Args:
            index (int): Index

        Returns:
            tuple: (sample, target) where target is class_index of the target class.
        """
        path, target = self.samples[index]
        sample = self.loader(path)
        if self.transform is not None:
            sample = self.transform(sample)
        if self.target_transform is not None:
            target = self.target_transform(target)

        return sample, target

    def __len__(self):
        return len(self.samples)

    def __repr__(self):
        fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
        fmt_str += '    Number of datapoints: {}\n'.format(self.__len__())
        fmt_str += '    Root Location: {}\n'.format(self.root)
        tmp = '    Transforms (if any): '
        fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
        tmp = '    Target Transforms (if any): '
        fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
        return fmt_str

IMG_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif']

def pil_loader(path):
    # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)
    with open(path, 'rb') as f:
        img = Image.open(f)
        return img.convert('RGB')

def accimage_loader(path):
    import accimage
    try:
        return accimage.Image(path)
    except IOError:
        # Potentially a decoding problem, fall back to PIL.Image
        return pil_loader(path)

def default_loader(path):
    from torchvision import get_image_backend
    if get_image_backend() == 'accimage':
        return accimage_loader(path)
    else:
        return pil_loader(path)

class ImageDetection(DatasetDetection):
    """A generic data loader where the images are arranged in this way: ::

        root/dog/xxx.png
        root/dog/xxy.png
        root/dog/xxz.png

        root/cat/123.png
        root/cat/nsdf3.png
        root/cat/asd932_.png

    Args:
        root (string): Root directory path.
        transform (callable, optional): A function/transform that  takes in an PIL image
            and returns a transformed version. E.g, ``transforms.RandomCrop``
        target_transform (callable, optional): A function/transform that takes in the
            target and transforms it.
        loader (callable, optional): A function to load an image given its path.

     Attributes:
        classes (list): List of the class names.
        class_to_idx (dict): Dict with items (class_name, class_index).
        imgs (list): List of (image path, class_index) tuples
    """
    def __init__(self, root, transform=None, target_transform=None,
                 loader=default_loader):
        super(ImageFolder, self).__init__(root, loader, IMG_EXTENSIONS,
                                          transform=transform,
                                          target_transform=target_transform)
        self.imgs = self.samples


import sublime
import os
import re
import threading
import io
import subprocess
import sys

# Define "check_output" for Python <= 2.6 (ST2 uses this)
if "check_output" not in dir( subprocess ):
  def f(*popenargs, **kwargs):
    if 'stdout' in kwargs:
      raise ValueError('stdout argument not allowed, it will be overridden.')
    process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
    output, unused_err = process.communicate()
    retcode = process.poll()
    if retcode:
      cmd = kwargs.get("args")
      if cmd is None:
        cmd = popenargs[0]
      raise subprocess.CalledProcessError(retcode, cmd)
    return output
  subprocess.check_output = f

SUBLIME_VERSION = "not set"
PLUGIN_PATH = "not set"
PACKAGE_NAME = "not set"
PACKAGE_DIR = "not set"
PACKAGE_USER_DIR = "not set"
ST_PACKAGE_PATH = "not set"
_corona_sdk_debug = False

# In Sublime Text 3 most APIs are unavailable until a module level function is called (fortunately
# sublime.version() is available so we can correctly fake things in Sublime Text 2; see about.py)
SUBLIME_VERSION = 3000 if sublime.version() == '' else int(sublime.version())

def GetSetting(key,default=None):
  # repeated calls to load_settings return same object without further disk reads
  debug("GetSetting: " + str(key) + " (default: " + str(default) + ")")
  settings = sublime.load_settings('Corona Editor.sublime-settings')
  debug("GetSetting: value from CE settings: " + str(settings.get(key, default)))
  # If we don't have a value for this preference in the Corona Editor settings, look in the view for a value
  # (this happens if the preference is set in the main Sublime Text preference file instead of the Corona Editor file)
  if not settings.get(key, default) and sublime and sublime.active_window() and sublime.active_window().active_view():
    debug("GetSetting: getting value from view: " + str(sublime.active_window().active_view()))
    settings = sublime.active_window().active_view().settings()

  value = settings.get(key, default)

  if not value:
    debug("GetSetting: no value for preference '" + str(key) + "' found (using default '"+ str(default) + "')")

  return value

def debug(*args):
  global _corona_sdk_debug
  if _corona_sdk_debug:
    print("Corona Editor: ", '\t'.join(map(str, args)))

InitializedEvent = threading.Event()

def Init():
  global SUBLIME_VERSION
  global PLUGIN_PATH
  global PACKAGE_NAME
  global PACKAGE_DIR
  global PACKAGE_USER_DIR
  global ST_PACKAGE_PATH
  global _corona_sdk_debug

  # Always look for "corona_sdk_debug" in 'Corona Editor.sublime-settings'
  settings = sublime.load_settings('Corona Editor.sublime-settings')
  _corona_sdk_debug = settings.get("corona_sdk_debug", False)

  print("Corona Editor: Init")
  debug("Python: " + str(sys.version))

  PLUGIN_PATH = os.path.dirname(os.path.realpath(__file__))
  if PLUGIN_PATH.lower().endswith('coronasdk-sublimetext'):
    if SUBLIME_VERSION < 3000:
      PLUGIN_PATH = os.path.expanduser('~/Library/Application Support/Sublime Text 2/Packages/Corona Editor')
    else:
      PLUGIN_PATH = os.path.expanduser('~/Library/Application Support/Sublime Text 3/Packages/Corona Editor')
  debug("PLUGIN_PATH: " + PLUGIN_PATH)

  PACKAGE_NAME = os.path.basename(PLUGIN_PATH) if SUBLIME_VERSION < 3000 else os.path.basename(PLUGIN_PATH).replace(".sublime-package", "")
  debug("PACKAGE_NAME: " + PACKAGE_NAME)

  # This is the actual package dir on ST2 and the "unpacked" package dir on ST3 ("~/Library/Application Support/Sublime Text 2/Packages")
  PACKAGE_DIR = os.path.join(sublime.packages_path(), PACKAGE_NAME)
  debug("PACKAGE_DIR: " + PACKAGE_DIR)

  # This is the user dir on ST
  PACKAGE_USER_DIR = os.path.join(sublime.packages_path(), 'User', PACKAGE_NAME)
  debug("PACKAGE_USER_DIR: " + PACKAGE_USER_DIR)

  # This is the faux path used by various Sublime Text functions ("Packages/CoronaSDK/")
  ST_PACKAGE_PATH = "Packages/" + PACKAGE_NAME + "/"
  debug("ST_PACKAGE_PATH: " + ST_PACKAGE_PATH)

  # This allows other threads to wait until this code has run
  InitializedEvent.set()

# This is run by ST3 after the plugins have loaded (and the ST API is ready for calls)
def plugin_loaded():
  Init()

# This fakes the above functionality on ST2
if SUBLIME_VERSION < 3000:
  Init()

# Return the path to the Simulator for the current project and platform
# First we look in any build.settings file in the project, then we look
# for a user preference, then we pick a platform appropriate default
def GetSimulatorCmd(mainlua=None, debug=False):
  platform = sublime.platform()
  arch = sublime.arch()
  view = sublime.active_window().active_view()

  simulator_path = ""
  simulator_flags = []
  simulator_version = GetSetting("corona_sdk_version", None)

  if mainlua is not None:
    simulator_path = GetSimulatorPathFromBuildSettings(mainlua)
    if simulator_path is None:
      simulator_path = GetSetting("corona_sdk_simulator_path", None)

  if platform == "osx":
    if simulator_path is None:
      simulator_path = GetLatestDailyBuildSimulatorPath()
    if simulator_path is None:
      simulator_path = "/Applications/Corona/Corona Simulator.app"
    if simulator_path.endswith(".app"):
      simulator_path += "/Contents/MacOS/Corona Simulator"
    simulator_flags = ["-singleton", "1"]
    if not GetSetting("corona_sdk_simulator_show_console", False):
      simulator_flags += ["-no-console", "1"]
    if debug:
      simulator_flags.append("-debug")
      simulator_flags.append("1")
      simulator_flags.append("-project")
    if os.path.isfile(simulator_path) and os.access(simulator_path, os.X_OK):
      simulator_version = str(subprocess.check_output(['defaults', 'read', os.path.join(os.path.dirname(simulator_path), '../Info.plist'), 'CFBundleVersion'], stderr=subprocess.STDOUT).decode('utf8').strip())
  elif platform == 'windows':
    if simulator_path is None:
      if arch == "x64":
        simulator_path = "C:\\Program Files (x86)\\Corona Labs\\Corona\\Corona Simulator.exe"
        if not os.path.isfile(simulator_path):
          simulator_path = "C:\\Program Files (x86)\\Corona Labs\\Corona SDK\\Corona Simulator.exe" # old location
      else:
        simulator_path = "C:\\Program Files\\Corona Labs\\Corona\\Corona Simulator.exe"
        if not os.path.isfile(simulator_path):
          simulator_path = "C:\\Program Files\\Corona Labs\\Corona SDK\\Corona Simulator.exe" # old location
    simulator_flags = ["/singleton"]
    if not GetSetting("corona_sdk_simulator_show_console", False):
      simulator_flags += ["/no-console"]
    if debug:
      simulator_flags.append("/debug")

  # Can we find an executable file at the path
  if not os.path.isfile(simulator_path) or not os.access(simulator_path, os.X_OK):
    sublime.error_message("Cannot find executable Corona Simulator at path '{0}'\n\nYou can set the user preference 'corona_sdk_simulator_path' to the location of the Simulator.".format(simulator_path))
    return None, None, None

  return simulator_path, simulator_flags, simulator_version

# Find the highest numbered CoronaSDK directory in /Applications
def GetLatestDailyBuildSimulatorPath():
  dirs = os.listdir("/Applications")

  # Find the highest numbered Daily Build with either the old or new style name
  maxBuildNum = 0
  buildNum = 0
  latestSDK = ""
  for entry in dirs:
    if entry.startswith("CoronaSDK-") or entry.startswith("Corona-"):
      result = re.findall(r'\d+', entry)
      if len(result) > 0:
        buildNum = int(re.findall(r'\d+', entry)[0])
      if buildNum > maxBuildNum:
        maxBuildNum = buildNum
        latestSDK = "/Applications/" + entry

  if len(latestSDK) > 0:
    return  latestSDK + "/Corona Simulator.app"
  else:
    return None

# Given a path to a main.lua file, see if there's a "corona_sdk_simulator_path" setting in
# the corresponding build.settings file
def GetSimulatorPathFromBuildSettings(mainlua):
  simulator_path = None
  project_path = os.path.dirname(mainlua)
  build_settings = os.path.join(project_path, "build.settings")
  bs_contents = None
  if os.path.isfile(build_settings):
    try:
      try: # see if we're in P3
        with open(build_settings, "r", encoding="utf-8") as bs_fd:
          bs_contents = bs_fd.read()
      except: # nope, try a P2 idiom
        with io.open(build_settings, "r", encoding="utf-8") as bs_fd:
          bs_contents = bs_fd.read()
    except IOError:
      pass  # we don't care if the file doesn't exist

  # debug("bs_contents: ", str(bs_contents))
  if bs_contents is not None:
    # Remove comments
    bs_contents = re.sub(r'--.*', '', bs_contents)
    # Note we can't use a Python r'' string here because we then can't escape the single quotes
    bs_matches = re.findall('corona_sdk_simulator_path\s*=\s*["\'](.*)["\']', bs_contents)
    if bs_matches is not None and len(bs_matches) > 0:
      # Last one wins
      simulator_path = bs_matches[-1]
      print("Corona Editor: corona_sdk_simulator_path set from "+str(build_settings))

  return simulator_path

# Given an existing file path or directory, find the likely "main.lua" for this project
def ResolveMainLua(path):
  # debug("ResolveMainLua: path: "+str(path))
  path = os.path.abspath(path)
  if not os.path.isdir(path):
    path = os.path.dirname(path)

  mainlua = os.path.join(path, "main.lua")
  if mainlua == "/main.lua" or mainlua == "\\main.lua":
    return None
  elif os.path.isfile(mainlua):
    return mainlua
  else:
    return ResolveMainLua(os.path.join(path, ".."))


import datetime
import cowsay
import time
import os
from config import *

#write a function to clear the console
def clear():
    os.system('cls' if os.name == 'nt' else 'clear')

while True:
    present = datetime.datetime.now()
    difference = goaldate - present
    seconds = (round(difference.total_seconds()))
    minutes = round(seconds / 60)
    hours = round(minutes/60,2)
    days = round(hours/24,2)
    weeks = round(days/7,2)

    #this script will only support 4 custom lengths before the text overflows onto another screen
    Len1 = round(minutes/Len1Length,2)
    Len2 = round(minutes/Len2Length,2)
    Len3 = round(minutes/Len3Length,2)
    Len4 = round(minutes/Len4Length,2)
    if seconds <= 0:
        break
    cowsay.milk("There are \n " + str(seconds) + " seconds or \n" + str(minutes) +
    " minutes or \n" + str(days) + " days or \n " + str(weeks) + " weeks or \n " +
    str(Len1) + " " + Len1Name + "\n" +
    str(Len2) + " " + Len2Name + "\n " +
    str(Len3) + " " + Len3Name + "\n " +
    str(Len4) + " " + Len4Name + "\n " +
    " until " + str(eventName))
    time.sleep(1)
    clear()
cowsay.tux(FinalMessage)


#!/usr/bin/env python

from sqlalchemy import *
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

Base = declarative_base()

class Todo(Base):
    __tablename__ = 'todos'

    id = Column(Integer, primary_key=True)
    task = Column(String(255))

if __name__ == "__main__":
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)


import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QLabel, QStyle, QSizePolicy, QFileDialog, QLineEdit
from PyQt5.QtGui import QIcon #, QPalette
from PyQt5.QtCore import Qt, QDir

class TubeGet(QWidget):
    def __init__(self):
        super().__init__()

        # define maine window
        self.setWindowTitle('TubeGet')
        self.setGeometry(350, 100, 700, 200)
        self.setWindowIcon(QIcon('tubeget.png'))

        self.url = QLineEdit()
        self.path_location = QLineEdit()
        download = QPushButton('Donwload')

        self.url.setPlaceholderText('URL')
        self.path_location.setPlaceholderText('File save location')

        self.browse_location = QPushButton('Brose...')
        self.browse_location.clicked.connect(self.open_location)

        # define main window bacground color
        # p = self.palette()
        # p.setColor(QPalette.Window, Qt.gray)
        # self.setPalette(p)

        self.main_ui()

        self.show()

    def main_ui(self):
        '''Create Window ui'''

        # create store location
        # store_path = QPushButton('Browse...')
        # store_path.clicked.connect(self.open_location)

        main_v_layout = QVBoxLayout()

        path_h_layout = QHBoxLayout()
        path_h_layout.addWidget(self.path_location)
        path_h_layout.addWidget(self.browse_location)

        main_v_layout.addWidget(self.url)
        main_v_layout.addLayout(path_h_layout)

        self.setLayout(main_v_layout)

    def open_location(self):
        file_location = QFileDialog.getSaveFileName(self, caption='Save File As', directory='.', filter='All Files(*.*)')
        self.path_location.setText(QDir.toNativeSeparators(file_location[0]))

app = QApplication(sys.argv)
tg = TubeGet()
sys.exit(app.exec_())


# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals, with_statement, division, absolute_import
from os import listdir
from os.path import isfile, join, basename
from pandas.io.json import json_normalize
import pandas as pd
import numpy as np
import json
import sys

# This scripts loads all json data generated at 'results_folder' and feeds it to
# pandas' dataframes. We do so in four layouts, for convenience:
#       Basic Table
#       Basic Table (described)
#       Multi-Index
#       Multi-Index (described)

# configurable parameters

def process_results(results_folder):
    # reads all test resulsts
    results = [f for f in listdir(results_folder) if isfile(join(results_folder, f)) and f.endswith('.json')]
    if len(results) == 0:
        return

    frame = pd.DataFrame() # keeps a master dataframe to store all algorithms
    for r in results:
        with (open(join(results_folder, r), "r")) as file:
            data = json.load(file)

            # we are interested on the scene's simple name, the algorithm and the n of objects
            scene_file = data["Settings"]["m_inputScene"]
            with open(scene_file, "rb") as f:
                # the scene's name and object types are encoded as c-style strings on the first 256 bytes of the file
                scene_name = f.read(128)
                objtype_name = f.read(128)
                if sys.version_info[0] < 3:
                    scene_name = ''.join([c for c in scene_name if c != b'\x00'])
                    objtype_name = ''.join([c for c in objtype_name if c != b'\x00'])
                else:
                    scene_name = ''.join([chr(c) for c in scene_name if bytes([c]) != b'\x00'])
                    objtype_name = ''.join([chr(c) for c in objtype_name if bytes([c]) != b'\x00'])

                scene = scene_name + ' ' + objtype_name

            algorithm = data["Settings"]["m_algorithm_prettyName"]
            n = data["Settings"]["m_numberOfObjects"]

            # loads the data into a dataframe and store the "Total" column
            df = json_normalize(data["Frames"])
            df = pd.DataFrame(data["Frames"])
            frame[(scene, n, algorithm)] = df["Total"]

    # The master dataframe ready for use
    # Columns: (scene, n, algorithm)
    # Rows: frame_number
    main_frame = frame
    main_frame.to_csv(join(results_folder, "main_frame.csv"), sep=str(';'))
    main_frame.to_excel(join(results_folder, "main_frame.xlsx"))
    main_frame.to_pickle(join(results_folder, "main_frame.pickle"))
    #print("main_frame written!")

    # The master dataframe in described form
    # Columns: (scene, n, algorithm)
    # Rows: frame_number
    described_frame = frame.describe()
    described_frame.to_csv(join(results_folder, "main_described_frame.csv"), sep=str(';'))
    described_frame.to_excel(join(results_folder, "main_described_frame.xlsx"))
    described_frame.to_pickle(join(results_folder, "main_described_frame.pickle"))
    #print("main_described_frame written!")

    # Creates a multi-indexed dataframe grouping algorithms by scene then by n
    # Columns: frame_number
    # Rows: Scene > N > Algorithm
    index = pd.MultiIndex.from_tuples(frame.columns)
    mi_frame = frame.transpose()
    mi_frame = mi_frame.set_index(index)

    labels = (mi_frame.columns.to_series() / 50).astype(int)
    mi_frame = mi_frame.groupby(labels, axis=1).mean()

    mi_frame.to_csv(join(results_folder, "multi_index_frame.csv"), sep=str(';'))
    mi_frame.to_excel(join(results_folder, "multi_index_frame.xlsx"))
    mi_frame.to_pickle(join(results_folder, "multi_index_frame.pickle"))
    #print("multi_index_frame written!")

    # Creates a multi-indexed dataframe of described data
    # Columns: count, mean, std, min, 25%, 50%, 75%, max
    # Rows: Scene > N > Algorithm
    index = pd.MultiIndex.from_tuples(frame.columns)
    dmi_frame = frame.describe().transpose()
    dmi_frame = dmi_frame.set_index(index)
    dmi_frame.to_csv(join(results_folder, "multi_index_described_frame.csv"), sep=str(';'))
    dmi_frame.to_excel(join(results_folder, "multi_index_described_frame.xlsx"))
    dmi_frame.to_pickle(join(results_folder, "multi_index_described_frame.pickle"))
    #print("multi_index_described_frame written!")

    lines_frame = dmi_frame["mean"].transpose()
    lines_frame = lines_frame.reset_index()
    lines_frame = pd.pivot_table(lines_frame, values="mean", index="level_1", columns="level_2")
    lines_frame.to_csv(join(results_folder, "lines_frame.csv"), sep=str(';'))
    lines_frame.to_excel(join(results_folder, "lines_frame.xlsx"))
    lines_frame.to_pickle(join(results_folder, "lines_frame.pickle"))
    #print("lines_frame written!")