import asyncio
import enum
import os.path
import time
import sys
import platform
import queue
import traceback
import os
import webbrowser
from decimal import Decimal
from functools import partial, lru_cache, wraps
from typing import (NamedTuple, Callable, Optional, TYPE_CHECKING, Union, List, Dict, Any,
                    Sequence, Iterable, Tuple, Type)

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import (QFont, QColor, QCursor, QPixmap, QStandardItem, QImage,
                         QPalette, QIcon, QFontMetrics, QShowEvent, QPainter, QHelpEvent, QMouseEvent,
                         QContextMenuEvent)
from PyQt5.QtCore import (Qt, QPersistentModelIndex, QModelIndex, pyqtSignal,
                          QCoreApplication, QItemSelectionModel, QThread,
                          QSortFilterProxyModel, QSize, QLocale, QAbstractItemModel,
                          QEvent, QRect, QPoint, QObject)
from PyQt5.QtWidgets import (QPushButton, QLabel, QMessageBox, QHBoxLayout,
                             QAbstractItemView, QVBoxLayout, QLineEdit,
                             QStyle, QDialog, QGroupBox, QButtonGroup, QRadioButton,
                             QFileDialog, QWidget, QToolButton, QTreeView, QPlainTextEdit,
                             QHeaderView, QApplication, QToolTip, QTreeWidget, QStyledItemDelegate,
                             QMenu, QStyleOptionViewItem, QLayout, QLayoutItem, QAbstractButton,
                             QGraphicsEffect, QGraphicsScene, QGraphicsPixmapItem, QSizePolicy)

from electrum.i18n import _, languages
from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, resource_path
from electrum.util import EventListener, event_listener, get_logger
from electrum.invoices import PR_UNPAID, PR_PAID, PR_EXPIRED, PR_INFLIGHT, PR_UNKNOWN, PR_FAILED, PR_ROUTING, PR_UNCONFIRMED, PR_BROADCASTING, PR_BROADCAST
from electrum.logging import Logger
from electrum.qrreader import MissingQrDetectionLib

if TYPE_CHECKING:
    from .main_window import ElectrumWindow
    from .paytoedit import PayToEdit

    from electrum.simple_config import SimpleConfig
    from electrum.simple_config import ConfigVarWithConfig

if platform.system() == 'Windows':
    MONOSPACE_FONT = 'Lucida Console'
elif platform.system() == 'Darwin':
    MONOSPACE_FONT = 'Monaco'
else:
    MONOSPACE_FONT = 'monospace'

_logger = get_logger(__name__)

dialogs = []

pr_icons = {
    PR_UNKNOWN:"warning.png",
    PR_UNPAID:"unpaid.png",
    PR_PAID:"confirmed.png",
    PR_EXPIRED:"expired.png",
    PR_INFLIGHT:"unconfirmed.png",
    PR_FAILED:"warning.png",
    PR_ROUTING:"unconfirmed.png",
    PR_UNCONFIRMED:"unconfirmed.png",
    PR_BROADCASTING:"unconfirmed.png",
    PR_BROADCAST:"unconfirmed.png",
}

# filter tx files in QFileDialog:
TRANSACTION_FILE_EXTENSION_FILTER_ANY = "Transaction (*.txn *.psbt);;All files (*)"
TRANSACTION_FILE_EXTENSION_FILTER_ONLY_PARTIAL_TX = "Partial Transaction (*.psbt)"
TRANSACTION_FILE_EXTENSION_FILTER_ONLY_COMPLETE_TX = "Complete Transaction (*.txn)"
TRANSACTION_FILE_EXTENSION_FILTER_SEPARATE = (f"{TRANSACTION_FILE_EXTENSION_FILTER_ONLY_PARTIAL_TX};;"
                                              f"{TRANSACTION_FILE_EXTENSION_FILTER_ONLY_COMPLETE_TX};;"
                                              f"All files (*)")

class EnterButton(QPushButton):
    def __init__(self, text, func):
        QPushButton.__init__(self, text)
        self.func = func
        self.clicked.connect(func)
        self._orig_text = text

    def keyPressEvent(self, e):
        if e.key() in [Qt.Key_Return, Qt.Key_Enter]:
            self.func()

    def restore_original_text(self):
        self.setText(self._orig_text)

class ThreadedButton(QPushButton):
    def __init__(self, text, task, on_success=None, on_error=None):
        QPushButton.__init__(self, text)
        self.task = task
        self.on_success = on_success
        self.on_error = on_error
        self.clicked.connect(self.run_task)

    def run_task(self):
        self.setEnabled(False)
        self.thread = TaskThread(self)
        self.thread.add(self.task, self.on_success, self.done, self.on_error)

    def done(self):
        self.setEnabled(True)
        self.thread.stop()

class WWLabel(QLabel):
    def __init__ (self, text="", parent=None):
        QLabel.__init__(self, text, parent)
        self.setWordWrap(True)
        self.setTextInteractionFlags(Qt.TextSelectableByMouse)

class AmountLabel(QLabel):
    def __init__(self, *args, **kwargs):
        QLabel.__init__(self, *args, **kwargs)
        self.setFont(QFont(MONOSPACE_FONT))
        self.setTextInteractionFlags(Qt.TextSelectableByMouse)

class HelpMixin:
    def __init__(self, help_text: str, *, help_title: str = None):
        assert isinstance(self, QWidget), "HelpMixin must be a QWidget instance!"
        self.help_text = help_text
        self._help_title = help_title or _('Help')
        if isinstance(self, QLabel):
            self.setTextInteractionFlags(
                (self.textInteractionFlags() | Qt.TextSelectableByMouse)
                & ~Qt.TextSelectableByKeyboard)

    def show_help(self):
        custom_message_box(
            icon=QMessageBox.Information,
            parent=self,
            title=self._help_title,
            text=self.help_text,
            rich_text=True,
        )

class HelpLabel(HelpMixin, QLabel):

    def __init__(self, text: str, help_text: str):
        QLabel.__init__(self, text)
        HelpMixin.__init__(self, help_text)
        self.app = QCoreApplication.instance()
        self.font = self.font()

    @classmethod
    def from_configvar(cls, cv: 'ConfigVarWithConfig') -> 'HelpLabel':
        return HelpLabel(cv.get_short_desc() + ':', cv.get_long_desc())

    def mouseReleaseEvent(self, x):
        self.show_help()

    def enterEvent(self, event):
        self.font.setUnderline(True)
        self.setFont(self.font)
        self.app.setOverrideCursor(QCursor(Qt.PointingHandCursor))
        return QLabel.enterEvent(self, event)

    def leaveEvent(self, event):
        self.font.setUnderline(False)
        self.setFont(self.font)
        self.app.setOverrideCursor(QCursor(Qt.ArrowCursor))
        return QLabel.leaveEvent(self, event)

class HelpButton(HelpMixin, QToolButton):
    def __init__(self, text: str):
        QToolButton.__init__(self)
        HelpMixin.__init__(self, text)
        self.setText('?')
        self.setFocusPolicy(Qt.NoFocus)
        self.setFixedWidth(round(2.2 * char_width_in_lineedit()))
        self.clicked.connect(self.show_help)

class InfoButton(HelpMixin, QPushButton):
    def __init__(self, text: str):
        QPushButton.__init__(self, 'Info')
        HelpMixin.__init__(self, text, help_title=_('Info'))
        self.setFocusPolicy(Qt.NoFocus)
        self.setFixedWidth(6 * char_width_in_lineedit())
        self.clicked.connect(self.show_help)

class Buttons(QHBoxLayout):
    def __init__(self, *buttons):
        QHBoxLayout.__init__(self)
        self.addStretch(1)
        for b in buttons:
            if b is None:
                continue
            self.addWidget(b)

class CloseButton(QPushButton):
    def __init__(self, dialog):
        QPushButton.__init__(self, _("Close"))
        self.clicked.connect(dialog.close)
        self.setDefault(True)

class CopyButton(QPushButton):
    def __init__(self, text_getter, app):
        QPushButton.__init__(self, _("Copy"))
        self.clicked.connect(lambda: app.clipboard().setText(text_getter()))

class CopyCloseButton(QPushButton):
    def __init__(self, text_getter, app, dialog):
        QPushButton.__init__(self, _("Copy and Close"))
        self.clicked.connect(lambda: app.clipboard().setText(text_getter()))
        self.clicked.connect(dialog.close)
        self.setDefault(True)

class OkButton(QPushButton):
    def __init__(self, dialog, label=None):
        QPushButton.__init__(self, label or _("OK"))
        self.clicked.connect(dialog.accept)
        self.setDefault(True)

class CancelButton(QPushButton):
    def __init__(self, dialog, label=None):
        QPushButton.__init__(self, label or _("Cancel"))
        self.clicked.connect(dialog.reject)

class MessageBoxMixin(object):
    def top_level_window_recurse(self, window=None, test_func=None):
        window = window or self
        classes = (WindowModalDialog, QMessageBox)
        if test_func is None:
            test_func = lambda x: True
        for n, child in enumerate(window.children()):
            # Test for visibility as old closed dialogs may not be GC-ed.
            # Only accept children that confirm to test_func.
            if isinstance(child, classes) and child.isVisible() \
                    and test_func(child):
                return self.top_level_window_recurse(child, test_func=test_func)
        return window

    def top_level_window(self, test_func=None):
        return self.top_level_window_recurse(test_func)

    def question(self, msg, parent=None, title=None, icon=None, **kwargs) -> bool:
        Yes, No = QMessageBox.Yes, QMessageBox.No
        return Yes == self.msg_box(icon=icon or QMessageBox.Question,
                                   parent=parent,
                                   title=title or '',
                                   text=msg,
                                   buttons=Yes|No,
                                   defaultButton=No,
                                   **kwargs)

    def show_warning(self, msg, parent=None, title=None, **kwargs):
        return self.msg_box(QMessageBox.Warning, parent,
                            title or _('Warning'), msg, **kwargs)

    def show_error(self, msg, parent=None, **kwargs):
        return self.msg_box(QMessageBox.Warning, parent,
                            _('Error'), msg, **kwargs)

    def show_critical(self, msg, parent=None, title=None, **kwargs):
        return self.msg_box(QMessageBox.Critical, parent,
                            title or _('Critical Error'), msg, **kwargs)

    def show_message(self, msg, parent=None, title=None, **kwargs):
        return self.msg_box(QMessageBox.Information, parent,
                            title or _('Information'), msg, **kwargs)

    def msg_box(self, icon, parent, title, text, *, buttons=QMessageBox.Ok,
                defaultButton=QMessageBox.NoButton, rich_text=False,
                checkbox=None):
        parent = parent or self.top_level_window()
        return custom_message_box(icon=icon,
                                  parent=parent,
                                  title=title,
                                  text=text,
                                  buttons=buttons,
                                  defaultButton=defaultButton,
                                  rich_text=rich_text,
                                  checkbox=checkbox)

def custom_message_box(*, icon, parent, title, text, buttons=QMessageBox.Ok,
                       defaultButton=QMessageBox.NoButton, rich_text=False,
                       checkbox=None):
    if type(icon) is QPixmap:
        d = QMessageBox(QMessageBox.Information, title, str(text), buttons, parent)
        d.setIconPixmap(icon)
    else:
        d = QMessageBox(icon, title, str(text), buttons, parent)
    d.setWindowModality(Qt.WindowModal)
    d.setDefaultButton(defaultButton)
    if rich_text:
        d.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse)
        # set AutoText instead of RichText
        # AutoText lets Qt figure out whether to render as rich text.
        # e.g. if text is actually plain text and uses "\n" newlines;
        #      and we set RichText here, newlines would be swallowed
        d.setTextFormat(Qt.AutoText)
    else:
        d.setTextInteractionFlags(Qt.TextSelectableByMouse)
        d.setTextFormat(Qt.PlainText)
    if checkbox is not None:
        d.setCheckBox(checkbox)
    return d.exec_()

class WindowModalDialog(QDialog, MessageBoxMixin):
    '''Handy wrapper; window modal dialogs are better for our multi-window
    daemon model as other wallet windows can still be accessed.'''
    def __init__(self, parent, title=None):
        QDialog.__init__(self, parent)
        self.setWindowModality(Qt.WindowModal)
        if title:
            self.setWindowTitle(title)

class WaitingDialog(WindowModalDialog):
    '''Shows a please wait dialog whilst running a task.  It is not
    necessary to maintain a reference to this dialog.'''
    def __init__(self, parent: QWidget, message: str, task, on_success=None, on_error=None, on_cancel=None):
        assert parent
        if isinstance(parent, MessageBoxMixin):
            parent = parent.top_level_window()
        WindowModalDialog.__init__(self, parent, _("Please wait"))
        self.message_label = QLabel(message)
        vbox = QVBoxLayout(self)
        vbox.addWidget(self.message_label)
        if on_cancel:
            self.cancel_button = CancelButton(self)
            self.cancel_button.clicked.connect(on_cancel)
            vbox.addLayout(Buttons(self.cancel_button))
        self.accepted.connect(self.on_accepted)
        self.show()
        self.thread = TaskThread(self)
        self.thread.finished.connect(self.deleteLater)  # see #3956
        self.thread.add(task, on_success, self.accept, on_error)

    def wait(self):
        self.thread.wait()

    def on_accepted(self):
        self.thread.stop()

    def update(self, msg):
        print(msg)
        self.message_label.setText(msg)

class BlockingWaitingDialog(WindowModalDialog):
    """Shows a waiting dialog whilst running a task.
    Should be called from the GUI thread. The GUI thread will be blocked while
    the task is running; the point of the dialog is to provide feedback
    to the user regarding what is going on.
    """
    def __init__(self, parent: QWidget, message: str, task: Callable[[], Any]):
        assert parent
        if isinstance(parent, MessageBoxMixin):
            parent = parent.top_level_window()
        WindowModalDialog.__init__(self, parent, _("Please wait"))
        self.message_label = QLabel(message)
        vbox = QVBoxLayout(self)
        vbox.addWidget(self.message_label)
        self.finished.connect(self.deleteLater)  # see #3956
        # show popup
        self.show()
        # refresh GUI; needed for popup to appear and for message_label to get drawn
        QCoreApplication.processEvents()
        QCoreApplication.processEvents()
        try:
            # block and run given task
            task()
        finally:
            # close popup
            self.accept()

def line_dialog(parent, title, label, ok_label, default=None):
    dialog = WindowModalDialog(parent, title)
    dialog.setMinimumWidth(500)
    l = QVBoxLayout()
    dialog.setLayout(l)
    l.addWidget(QLabel(label))
    txt = QLineEdit()
    if default:
        txt.setText(default)
    l.addWidget(txt)
    l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
    if dialog.exec_():
        return txt.text()

def text_dialog(
        *,
        parent,
        title,
        header_layout,
        ok_label,
        default=None,
        allow_multi=False,
        config: 'SimpleConfig',
):
    from .qrtextedit import ScanQRTextEdit
    dialog = WindowModalDialog(parent, title)
    dialog.setMinimumWidth(600)
    l = QVBoxLayout()
    dialog.setLayout(l)
    if isinstance(header_layout, str):
        l.addWidget(QLabel(header_layout))
    else:
        l.addLayout(header_layout)
    txt = ScanQRTextEdit(allow_multi=allow_multi, config=config)
    if default:
        txt.setText(default)
    l.addWidget(txt)
    l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
    if dialog.exec_():
        return txt.toPlainText()

class ChoicesLayout(object):
    def __init__(self, msg, choices, on_clicked=None, checked_index=0):
        vbox = QVBoxLayout()
        if len(msg) > 50:
            vbox.addWidget(WWLabel(msg))
            msg = ""
        gb2 = QGroupBox(msg)
        vbox.addWidget(gb2)
        vbox2 = QVBoxLayout()
        gb2.setLayout(vbox2)
        self.group = group = QButtonGroup()
        if isinstance(choices, list):
            iterator = enumerate(choices)
        else:
            iterator = choices.items()
        for i, c in iterator:
            button = QRadioButton(gb2)
            button.setText(c)
            vbox2.addWidget(button)
            group.addButton(button)
            group.setId(button, i)
            if i == checked_index:
                button.setChecked(True)
        if on_clicked:
            group.buttonClicked.connect(partial(on_clicked, self))
        self.vbox = vbox

    def layout(self):
        return self.vbox

    def selected_index(self):
        return self.group.checkedId()

class ChoiceWidget(QWidget):
    itemSelected = pyqtSignal([int], arguments=['index'])

    def __init__(self, *, message=None, choices=None, selected=None):
        QWidget.__init__(self)
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        if choices is None:
            choices = []

        self.selected_index = -1
        self.selected_item = None
        self.choices = choices

        if message and len(message) > 50:
            vbox.addWidget(WWLabel(message))
            message = ""
        gb2 = QGroupBox(message)
        vbox.addWidget(gb2)
        vbox2 = QVBoxLayout()
        gb2.setLayout(vbox2)
        self.group = group = QButtonGroup()
        assert isinstance(choices, list)
        iterator = enumerate(choices)
        for i, c in iterator:
            button = QRadioButton(gb2)
            button.setText(c[1])
            vbox2.addWidget(button)
            group.addButton(button)
            group.setId(button, i)
            if (i == 0 and selected is None) or c[0] == selected:
                self.selected_index = i
                self.selected_item = c
                button.setChecked(True)
        group.buttonClicked.connect(self.on_selected)

    def on_selected(self, button):
        self.selected_index = self.group.id(button)
        self.selected_item = self.choices[self.selected_index]
        self.itemSelected.emit(self.selected_index)

def address_field(addresses):
    hbox = QHBoxLayout()
    address_e = QLineEdit()
    if addresses and len(addresses) > 0:
        address_e.setText(addresses[0])
    else:
        addresses = []
    def func():
        try:
            i = addresses.index(str(address_e.text())) + 1
            i = i % len(addresses)
            address_e.setText(addresses[i])
        except ValueError:
            # the user might have changed address_e to an
            # address not in the wallet (or to something that isn't an address)
            if addresses and len(addresses) > 0:
                address_e.setText(addresses[0])
    button = QPushButton(_('Address'))
    button.clicked.connect(func)
    hbox.addWidget(button)
    hbox.addWidget(address_e)
    return hbox, address_e

def filename_field(parent, config, defaultname, select_msg):

    vbox = QVBoxLayout()
    vbox.addWidget(QLabel(_("Format")))
    gb = QGroupBox("format", parent)
    b1 = QRadioButton(gb)
    b1.setText(_("CSV"))
    b1.setChecked(True)
    b2 = QRadioButton(gb)
    b2.setText(_("json"))
    vbox.addWidget(b1)
    vbox.addWidget(b2)

    hbox = QHBoxLayout()

    directory = config.IO_DIRECTORY
    path = os.path.join(directory, defaultname)
    filename_e = QLineEdit()
    filename_e.setText(path)

    def func():
        text = filename_e.text()
        _filter = "*.csv" if defaultname.endswith(".csv") else "*.json" if defaultname.endswith(".json") else None
        p = getSaveFileName(
            parent=None,
            title=select_msg,
            filename=text,
            filter=_filter,
            config=config,
        )
        if p:
            filename_e.setText(p)

    button = QPushButton(_('File'))
    button.clicked.connect(func)
    hbox.addWidget(button)
    hbox.addWidget(filename_e)
    vbox.addLayout(hbox)

    def set_csv(v):
        text = filename_e.text()
        text = text.replace(".json",".csv") if v else text.replace(".csv",".json")
        filename_e.setText(text)

    b1.clicked.connect(lambda: set_csv(True))
    b2.clicked.connect(lambda: set_csv(False))

    return vbox, filename_e, b1

def get_iconname_qrcode() -> str:
    return "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png"

def get_iconname_camera() -> str:
    return "camera_white.png" if ColorScheme.dark_scheme else "camera_dark.png"

def editor_contextMenuEvent(self, p: 'PayToEdit', e: 'QContextMenuEvent') -> None:
    m = self.createStandardContextMenu()
    m.addSeparator()
    m.addAction(read_QIcon(get_iconname_camera()),    _("Read QR code with camera"), p.on_qr_from_camera_input_btn)
    m.addAction(read_QIcon("picture_in_picture.png"), _("Read QR code from screen"), p.on_qr_from_screenshot_input_btn)
    m.addAction(read_QIcon("file.png"), _("Read file"), p.on_input_file)
    m.exec_(e.globalPos())

class GenericInputHandler:

    def input_qr_from_camera(
            self,
            *,
            config: 'SimpleConfig',
            allow_multi: bool = False,
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
            parent: QWidget = None,
    ) -> None:
        if setText is None:
            setText = self.setText
        def cb(success: bool, error: str, data):
            if not success:
                if error:
                    show_error(error)
                return
            if not data:
                data = ''
            if allow_multi:
                new_text = self.text() + data + '\n'
            else:
                new_text = data
                try:
                    setText(new_text)
                except Exception as e:
                    show_error(_('Invalid payment identifier in QR') + ':\n' + repr(e))

        from .qrreader import scan_qrcode
        if parent is None:
            parent = self if isinstance(self, QWidget) else None
        scan_qrcode(parent=parent, config=config, callback=cb)

    def input_qr_from_screenshot(
            self,
            *,
            allow_multi: bool = False,
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
    ) -> None:
        if setText is None:
            setText = self.setText
        from .qrreader import scan_qr_from_image
        screenshots = [screen.grabWindow(0).toImage()
                       for screen in QApplication.instance().screens()]
        if all(screen.allGray() for screen in screenshots):
            show_error(_("Failed to take screenshot."))
            return
        scanned_qr = None
        for screenshot in screenshots:
            try:
                scan_result = scan_qr_from_image(screenshot)
            except MissingQrDetectionLib as e:
                show_error(_("Unable to scan image.") + "\n" + repr(e))
                return
            if len(scan_result) > 0:
                if (scanned_qr is not None) or len(scan_result) > 1:
                    show_error(_("More than one QR code was found on the screen."))
                    return
                scanned_qr = scan_result
        if scanned_qr is None:
            show_error(_("No QR code was found on the screen."))
            return
        data = scanned_qr[0].data
        if allow_multi:
            new_text = self.text() + data + '\n'
        else:
            new_text = data
            try:
                setText(new_text)
            except Exception as e:
                show_error(_('Invalid payment identifier in QR') + ':\n' + repr(e))

    def input_file(
            self,
            *,
            config: 'SimpleConfig',
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
    ) -> None:
        if setText is None:
            setText = self.setText
        fileName = getOpenFileName(
            parent=None,
            title='select file',
            config=config,
        )
        if not fileName:
            return
        try:
            try:
                with open(fileName, "r") as f:
                    data = f.read()
            except UnicodeError as e:
                with open(fileName, "rb") as f:
                    data = f.read()
                data = data.hex()
        except BaseException as e:
            show_error(_('Error opening file') + ':\n' + repr(e))
        else:
            try:
                setText(data)
            except Exception as e:
                show_error(_('Invalid payment identifier in file') + ':\n' + repr(e))

    def input_paste_from_clipboard(
            self,
            *,
            setText: Callable[[str], None] = None,
    ) -> None:
        if setText is None:
            setText = self.setText
        app = QApplication.instance()
        setText(app.clipboard().text())

class OverlayControlMixin(GenericInputHandler):
    STYLE_SHEET_COMMON = '''
    QPushButton { border-width: 1px; padding: 0px; margin: 0px; }
    '''

    STYLE_SHEET_LIGHT = '''
    QPushButton { border: 1px solid transparent; }
    QPushButton:hover { border: 1px solid #3daee9; }
    '''

    def __init__(self, middle: bool = False):
        GenericInputHandler.__init__(self)
        assert isinstance(self, QWidget)
        assert isinstance(self, OverlayControlMixin)  # only here for type-hints in IDE
        self.middle = middle
        self.overlay_widget = QWidget(self)
        style_sheet = self.STYLE_SHEET_COMMON
        if not ColorScheme.dark_scheme:
            style_sheet = style_sheet + self.STYLE_SHEET_LIGHT
        self.overlay_widget.setStyleSheet(style_sheet)
        self.overlay_layout = QHBoxLayout(self.overlay_widget)
        self.overlay_layout.setContentsMargins(0, 0, 0, 0)
        self.overlay_layout.setSpacing(1)
        self._updateOverlayPos()

    def resizeEvent(self, e):
        super().resizeEvent(e)
        self._updateOverlayPos()

    def _updateOverlayPos(self):
        frame_width = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        overlay_size = self.overlay_widget.sizeHint()
        x = self.rect().right() - frame_width - overlay_size.width()
        y = self.rect().bottom() - overlay_size.height()
        middle = self.middle
        if hasattr(self, 'document'):
            # Keep the buttons centered if we have less than 2 lines in the editor
            line_spacing = QFontMetrics(self.document().defaultFont()).lineSpacing()
            if self.rect().height() < (line_spacing * 2):
                middle = True
        y = (y / 2) + frame_width if middle else y - frame_width
        if hasattr(self, 'verticalScrollBar') and self.verticalScrollBar().isVisible():
            scrollbar_width = self.style().pixelMetric(QStyle.PM_ScrollBarExtent)
            x -= scrollbar_width
        self.overlay_widget.move(int(x), int(y))

    def addWidget(self, widget: QWidget):
        # The old code positioned the items the other way around, so we just insert at position 0 instead
        self.overlay_layout.insertWidget(0, widget)

    def addButton(self, icon_name: str, on_click, tooltip: str) -> QPushButton:
        button = QPushButton(self.overlay_widget)
        button.setToolTip(tooltip)
        button.setIcon(read_QIcon(icon_name))
        button.setCursor(QCursor(Qt.PointingHandCursor))
        button.clicked.connect(on_click)
        self.addWidget(button)
        return button

    def addCopyButton(self):
        def on_copy():
            app = QApplication.instance()
            app.clipboard().setText(self.text())
            QToolTip.showText(QCursor.pos(), _("Text copied to clipboard"), self)

        self.addButton("copy.png", on_copy, _("Copy to clipboard"))

    def addPasteButton(
            self,
            *,
            setText: Callable[[str], None] = None,
    ):
        input_paste_from_clipboard = partial(
            self.input_paste_from_clipboard,
            setText=setText,
        )
        self.addButton("copy.png", input_paste_from_clipboard, _("Paste from clipboard"))

    def add_qr_show_button(self, *, config: 'SimpleConfig', title: Optional[str] = None):
        if title is None:
            title = _("QR code")

        def qr_show():
            from .qrcodewidget import QRDialog
            try:
                s = str(self.text())
            except Exception:
                s = self.text()
            if not s:
                return
            QRDialog(
                data=s,
                parent=self,
                title=title,
                config=config,
            ).exec_()

        self.addButton(get_iconname_qrcode(), qr_show, _("Show as QR code"))
        # side-effect: we export this method:
        self.on_qr_show_btn = qr_show

    def add_qr_input_combined_button(
            self,
            *,
            config: 'SimpleConfig',
            allow_multi: bool = False,
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
    ):
        input_qr_from_camera = partial(
            self.input_qr_from_camera,
            config=config,
            allow_multi=allow_multi,
            show_error=show_error,
            setText=setText,
        )
        input_qr_from_screenshot = partial(
            self.input_qr_from_screenshot,
            allow_multi=allow_multi,
            show_error=show_error,
            setText=setText,
        )
        self.add_menu_button(
            icon=get_iconname_camera(),
            tooltip=_("Read QR code"),
            options=[
                (get_iconname_camera(),    _("Read QR code from camera"), input_qr_from_camera),
                ("picture_in_picture.png", _("Read QR code from screen"), input_qr_from_screenshot),
            ],
        )
        # side-effect: we export these methods:
        self.on_qr_from_camera_input_btn = input_qr_from_camera
        self.on_qr_from_screenshot_input_btn = input_qr_from_screenshot

    def add_qr_input_from_camera_button(
            self,
            *,
            config: 'SimpleConfig',
            allow_multi: bool = False,
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
    ):
        input_qr_from_camera = partial(
            self.input_qr_from_camera,
            config=config,
            allow_multi=allow_multi,
            show_error=show_error,
            setText=setText,
        )
        self.addButton(get_iconname_camera(), input_qr_from_camera, _("Read QR code from camera"))
        # side-effect: we export these methods:
        self.on_qr_from_camera_input_btn = input_qr_from_camera

    def add_file_input_button(
            self,
            *,
            config: 'SimpleConfig',
            show_error: Callable[[str], None],
            setText: Callable[[str], None] = None,
    ) -> None:
        input_file = partial(
            self.input_file,
            config=config,
            show_error=show_error,
            setText=setText,
        )
        self.addButton("file.png", input_file, _("Read file"))

    def add_menu_button(
            self,
            *,
            options: Sequence[Tuple[Optional[str], str, Callable[[], None]]],  # list of (icon, text, cb)
            icon: Optional[str] = None,
            tooltip: Optional[str] = None,
    ):
        if icon is None:
            icon = "menu_vertical_white.png" if ColorScheme.dark_scheme else "menu_vertical.png"
        if tooltip is None:
            tooltip = _("Other options")
        btn = self.addButton(icon, lambda: None, tooltip)
        menu = QMenu()
        for opt_icon, opt_text, opt_cb in options:
            if opt_icon is None:
                menu.addAction(opt_text, opt_cb)
            else:
                menu.addAction(read_QIcon(opt_icon), opt_text, opt_cb)
        btn.setMenu(menu)

class ButtonsLineEdit(OverlayControlMixin, QLineEdit):
    def __init__(self, text=None):
        QLineEdit.__init__(self, text)
        OverlayControlMixin.__init__(self, middle=True)

class ShowQRLineEdit(ButtonsLineEdit):
    """ read-only line with qr and copy buttons """
    def __init__(self, text: str, config, title=None):
        ButtonsLineEdit.__init__(self, text)
        self.setReadOnly(True)
        self.setFont(QFont(MONOSPACE_FONT))
        self.add_qr_show_button(config=config, title=title)
        self.addCopyButton()

class ButtonsTextEdit(OverlayControlMixin, QPlainTextEdit):
    def __init__(self, text=None):
        QPlainTextEdit.__init__(self, text)
        OverlayControlMixin.__init__(self)
        self.setText = self.setPlainText
        self.text = self.toPlainText

class PasswordLineEdit(QLineEdit):
    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
        self.setEchoMode(QLineEdit.Password)

    def clear(self):
        # Try to actually overwrite the memory.
        # This is really just a best-effort thing...
        self.setText(len(self.text()) * " ")
        super().clear()

class TaskThread(QThread, Logger):
    '''Thread that runs background tasks.  Callbacks are guaranteed
    to happen in the context of its parent.'''

    class Task(NamedTuple):
        task: Callable
        cb_success: Optional[Callable]
        cb_done: Optional[Callable]
        cb_error: Optional[Callable]
        cancel: Optional[Callable] = None

    doneSig = pyqtSignal(object, object, object)

    def __init__(self, parent, on_error=None):
        QThread.__init__(self, parent)
        Logger.__init__(self)
        self.on_error = on_error
        self.tasks = queue.Queue()
        self._cur_task = None  # type: Optional[TaskThread.Task]
        self._stopping = False
        self.doneSig.connect(self.on_done)
        self.start()

    def add(self, task, on_success=None, on_done=None, on_error=None, *, cancel=None):
        if self._stopping:
            self.logger.warning(f"stopping or already stopped but tried to add new task.")
            return
        on_error = on_error or self.on_error
        task_ = TaskThread.Task(task, on_success, on_done, on_error, cancel=cancel)
        self.tasks.put(task_)

    def run(self):
        while True:
            if self._stopping:
                break
            task = self.tasks.get()  # type: TaskThread.Task
            self._cur_task = task
            if not task or self._stopping:
                break
            try:
                result = task.task()
                self.doneSig.emit(result, task.cb_done, task.cb_success)
            except BaseException:
                self.doneSig.emit(sys.exc_info(), task.cb_done, task.cb_error)

    def on_done(self, result, cb_done, cb_result):
        # This runs in the parent's thread.
        if cb_done:
            cb_done()
        if cb_result:
            cb_result(result)

    def stop(self):
        self._stopping = True
        # try to cancel currently running task now.
        # if the task does not implement "cancel", we will have to wait until it finishes.
        task = self._cur_task
        if task and task.cancel:
            task.cancel()
        # cancel the remaining tasks in the queue
        while True:
            try:
                task = self.tasks.get_nowait()
            except queue.Empty:
                break
            if task and task.cancel:
                task.cancel()
        self.tasks.put(None)  # in case the thread is still waiting on the queue
        self.exit()
        self.wait()

class ColorSchemeItem:
    def __init__(self, fg_color, bg_color):
        self.colors = (fg_color, bg_color)

    def _get_color(self, background):
        return self.colors[(int(background) + int(ColorScheme.dark_scheme)) % 2]

    def as_stylesheet(self, background=False):
        css_prefix = "background-" if background else ""
        color = self._get_color(background)
        return "QWidget {{ {}color:{}; }}".format(css_prefix, color)

    def as_color(self, background=False):
        color = self._get_color(background)
        return QColor(color)

class ColorScheme:
    dark_scheme = False

    GREEN = ColorSchemeItem("#117c11", "#8af296")
    YELLOW = ColorSchemeItem("#897b2a", "#ffff00")
    RED = ColorSchemeItem("#7c1111", "#f18c8c")
    BLUE = ColorSchemeItem("#123b7c", "#8cb3f2")
    LIGHTBLUE = ColorSchemeItem("black", "#d0f0ff")
    DEFAULT = ColorSchemeItem("black", "white")
    GRAY = ColorSchemeItem("gray", "gray")

    @staticmethod
    def has_dark_background(widget):
        brightness = sum(widget.palette().color(QPalette.Background).getRgb()[0:3])
        return brightness < (255*3/2)

    @staticmethod
    def update_from_widget(widget, force_dark=False):
        ColorScheme.dark_scheme = bool(force_dark or ColorScheme.has_dark_background(widget))

class AcceptFileDragDrop:
    def __init__(self, file_type=""):
        assert isinstance(self, QWidget)
        self.setAcceptDrops(True)
        self.file_type = file_type

    def validateEvent(self, event):
        if not event.mimeData().hasUrls():
            event.ignore()
            return False
        for url in event.mimeData().urls():
            if not url.toLocalFile().endswith(self.file_type):
                event.ignore()
                return False
        event.accept()
        return True

    def dragEnterEvent(self, event):
        self.validateEvent(event)

    def dragMoveEvent(self, event):
        if self.validateEvent(event):
            event.setDropAction(Qt.CopyAction)

    def dropEvent(self, event):
        if self.validateEvent(event):
            for url in event.mimeData().urls():
                self.onFileAdded(url.toLocalFile())

    def onFileAdded(self, fn):
        raise NotImplementedError()

def import_meta_gui(electrum_window: 'ElectrumWindow', title, importer, on_success):
    filter_ = "JSON (*.json);;All files (*)"
    filename = getOpenFileName(
        parent=electrum_window,
        title=_("Open {} file").format(title),
        filter=filter_,
        config=electrum_window.config,
    )
    if not filename:
        return
    try:
        importer(filename)
    except FileImportFailed as e:
        electrum_window.show_critical(str(e))
    else:
        electrum_window.show_message(_("Your {} were successfully imported").format(title))
        on_success()

def export_meta_gui(electrum_window: 'ElectrumWindow', title, exporter):
    filter_ = "JSON (*.json);;All files (*)"
    filename = getSaveFileName(
        parent=electrum_window,
        title=_("Select file to save your {}").format(title),
        filename='electrum_{}.json'.format(title),
        filter=filter_,
        config=electrum_window.config,
    )
    if not filename:
        return
    try:
        exporter(filename)
    except FileExportFailed as e:
        electrum_window.show_critical(str(e))
    else:
        electrum_window.show_message(_("Your {0} were exported to '{1}'")
                                     .format(title, str(filename)))

def getOpenFileName(*, parent, title, filter="", config: 'SimpleConfig') -> Optional[str]:
    """Custom wrapper for getOpenFileName that remembers the path selected by the user."""
    directory = config.IO_DIRECTORY
    fileName, __ = QFileDialog.getOpenFileName(parent, title, directory, filter)
    if fileName and directory != os.path.dirname(fileName):
        config.IO_DIRECTORY = os.path.dirname(fileName)
    return fileName

def getSaveFileName(
        *,
        parent,
        title,
        filename,
        filter="",
        default_extension: str = None,
        default_filter: str = None,
        config: 'SimpleConfig',
) -> Optional[str]:
    """Custom wrapper for getSaveFileName that remembers the path selected by the user."""
    directory = config.IO_DIRECTORY
    path = os.path.join(directory, filename)

    file_dialog = QFileDialog(parent, title, path, filter)
    file_dialog.setAcceptMode(QFileDialog.AcceptSave)
    if default_extension:
        # note: on MacOS, the selected filter's first extension seems to have priority over this...
        file_dialog.setDefaultSuffix(default_extension)
    if default_filter:
        assert default_filter in filter, f"default_filter={default_filter!r} does not appear in filter={filter!r}"
        file_dialog.selectNameFilter(default_filter)
    if file_dialog.exec() != QDialog.Accepted:
        return None

    selected_path = file_dialog.selectedFiles()[0]
    if selected_path and directory != os.path.dirname(selected_path):
        config.IO_DIRECTORY = os.path.dirname(selected_path)
    return selected_path

def icon_path(icon_basename: str):
    return resource_path('gui', 'icons', icon_basename)

@lru_cache(maxsize=1000)
def read_QIcon(icon_basename: str) -> QIcon:
    return QIcon(icon_path(icon_basename))

class IconLabel(QWidget):
    HorizontalSpacing = 2
    def __init__(self, *, text='', final_stretch=True):
        super(QWidget, self).__init__()
        size = max(16, font_height())
        self.icon_size = QSize(size, size)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.icon = QLabel()
        self.label = QLabel(text)
        self.label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        layout.addWidget(self.label)
        layout.addSpacing(self.HorizontalSpacing)
        layout.addWidget(self.icon)
        if final_stretch:
            layout.addStretch()
    def setText(self, text):
        self.label.setText(text)
    def setIcon(self, icon):
        self.icon.setPixmap(icon.pixmap(self.icon_size))
        self.icon.repaint()  # macOS hack for #6269

def char_width_in_lineedit() -> int:
    char_width = QFontMetrics(QLineEdit().font()).averageCharWidth()
    # 'averageCharWidth' seems to underestimate on Windows, hence 'max()'
    return max(9, char_width)

def font_height() -> int:
    return QFontMetrics(QLabel().font()).height()

def webopen(url: str):
    if sys.platform == 'linux' and os.environ.get('APPIMAGE'):
        # When on Linux webbrowser.open can fail in AppImage because it can't find the correct libdbus.
        # We just fork the process and unset LD_LIBRARY_PATH before opening the URL.
        # See #5425
        if os.fork() == 0:
            del os.environ['LD_LIBRARY_PATH']
            webbrowser.open(url)
            os._exit(0)
    else:
        webbrowser.open(url)

class FixedAspectRatioLayout(QLayout):
    def __init__(self, parent: QWidget = None, aspect_ratio: float = 1.0):
        super().__init__(parent)
        self.aspect_ratio = aspect_ratio
        self.items: List[QLayoutItem] = []

    def set_aspect_ratio(self, aspect_ratio: float = 1.0):
        self.aspect_ratio = aspect_ratio
        self.update()

    def addItem(self, item: QLayoutItem):
        self.items.append(item)

    def count(self) -> int:
        return len(self.items)

    def itemAt(self, index: int) -> QLayoutItem:
        if index >= len(self.items):
            return None
        return self.items[index]

    def takeAt(self, index: int) -> QLayoutItem:
        if index >= len(self.items):
            return None
        return self.items.pop(index)

    def _get_contents_margins_size(self) -> QSize:
        margins = self.contentsMargins()
        return QSize(margins.left() + margins.right(), margins.top() + margins.bottom())

    def setGeometry(self, rect: QRect):
        super().setGeometry(rect)
        if not self.items:
            return

        contents = self.contentsRect()
        if contents.height() > 0:
            c_aratio = contents.width() / contents.height()
        else:
            c_aratio = 1
        s_aratio = self.aspect_ratio
        item_rect = QRect(QPoint(0, 0), QSize(
            contents.width() if c_aratio < s_aratio else int(contents.height() * s_aratio),
            contents.height() if c_aratio > s_aratio else int(contents.width() / s_aratio)
        ))

        content_margins = self.contentsMargins()
        free_space = contents.size() - item_rect.size()

        for item in self.items:
            if free_space.width() > 0 and not item.alignment() & Qt.AlignLeft:
                if item.alignment() & Qt.AlignRight:
                    item_rect.moveRight(contents.width() + content_margins.right())
                else:
                    item_rect.moveLeft(content_margins.left() + (free_space.width() // 2))
            else:
                item_rect.moveLeft(content_margins.left())

            if free_space.height() > 0 and not item.alignment() & Qt.AlignTop:
                if item.alignment() & Qt.AlignBottom:
                    item_rect.moveBottom(contents.height() + content_margins.bottom())
                else:
                    item_rect.moveTop(content_margins.top() + (free_space.height() // 2))
            else:
                item_rect.moveTop(content_margins.top())

            item.widget().setGeometry(item_rect)

    def sizeHint(self) -> QSize:
        result = QSize()
        for item in self.items:
            result = result.expandedTo(item.sizeHint())
        return self._get_contents_margins_size() + result

    def minimumSize(self) -> QSize:
        result = QSize()
        for item in self.items:
            result = result.expandedTo(item.minimumSize())
        return self._get_contents_margins_size() + result

    def expandingDirections(self) -> Qt.Orientations:
        return Qt.Horizontal | Qt.Vertical

def QColorLerp(a: QColor, b: QColor, t: float):
    """
    Blends two QColors. t=0 returns a. t=1 returns b. t=0.5 returns evenly mixed.
    """
    t = max(min(t, 1.0), 0.0)
    i_t = 1.0 - t
    return QColor(
        int((a.red()   * i_t) + (b.red()   * t)),
        int((a.green() * i_t) + (b.green() * t)),
        int((a.blue()  * i_t) + (b.blue()  * t)),
        int((a.alpha() * i_t) + (b.alpha() * t)),
    )

class ImageGraphicsEffect(QObject):
    """
    Applies a QGraphicsEffect to a QImage
    """

    def __init__(self, parent: QObject, effect: QGraphicsEffect):
        super().__init__(parent)
        assert effect, 'effect must be set'
        self.effect = effect
        self.graphics_scene = QGraphicsScene()
        self.graphics_item = QGraphicsPixmapItem()
        self.graphics_item.setGraphicsEffect(effect)
        self.graphics_scene.addItem(self.graphics_item)

    def apply(self, image: QImage):
        assert image, 'image must be set'
        result = QImage(image.size(), QImage.Format_ARGB32)
        result.fill(Qt.transparent)
        painter = QPainter(result)
        self.graphics_item.setPixmap(QPixmap.fromImage(image))
        self.graphics_scene.render(painter)
        self.graphics_item.setPixmap(QPixmap())
        return result

class QtEventListener(EventListener):
    qt_callback_signal = QtCore.pyqtSignal(tuple)

    def register_callbacks(self):
        self.qt_callback_signal.connect(self.on_qt_callback_signal)
        EventListener.register_callbacks(self)

    def unregister_callbacks(self):
        try:
            self.qt_callback_signal.disconnect()
        except RuntimeError:  # wrapped Qt object might be deleted
            pass
        EventListener.unregister_callbacks(self)

    def on_qt_callback_signal(self, args):
        func = args[0]
        return func(self, *args[1:])

# decorator for members of the QtEventListener class
def qt_event_listener(func):
    func = event_listener(func)
    @wraps(func)
    def decorator(self, *args):
        self.qt_callback_signal.emit( (func,) + args)
    return decorator

if __name__ == "__main__":
    app = QApplication([])
    t = WaitingDialog(None, 'testing ...', lambda: [time.sleep(1)], lambda x: QMessageBox.information(None, 'done', "done"))
    t.start()
    app.exec_()


import sys
import file_editor

def get_params(fe):
	fe.params.filename = input("Please enter a filename, or press enter to quit.\n> ")
	if not fe.params.filename:
		return False

	fe.params.word = input("Please enter a word to nuke, or press enter to quit.\n> ")
	if not fe.params.word:
		return False

	tmp = input("Would you like to replace this word with another word? ( y/n ) or press enter to quit.\n> ")
	if not tmp:
		return False
	else:
		fe.params.replace = "y" in tmp.lower()

	if fe.params.replace:
		fe.params.replace_word = input("Please enter the replacement word, or press enter to quit.\n> ")
		if not fe.params.replace_word:
			return False

	return True

def loop_prompt(fe):
	continue_looping = True
	while continue_looping:
		if get_params(fe):
			fe.nuke()
		else:
			continue_looping = False

def main():
	pass
	fe = file_editor.FileEditor()
	if len(sys.argv) > 1:
		fe.params.filename = sys.argv[1]
		fe.nuke()
	else:
		loop_prompt(fe)
	print("Goodbye!")

if __name__ == "__main__":
	main()


from django.shortcuts import render

# Create your views here.
from students.models import *

from course.models import *

def home(request):
	students = Student.objects.all()
	male_std = Student.objects.filter(gender='M')
	female_std = Student.objects.filter(gender='M')
	no_of_std = students.count()
	no_male_std = male_std.count()
	no_female_std = male_std.count()
	print (no_male_std)
	context = {
		'no_of_std':no_of_std,
		'no_male_std':no_male_std,
		'no_female_std':no_female_std
	}
	return render(request, 'home.html', context)

def get_students(request):
	students = Student.objects.all()
	for student in students:
		print (student.first_name + " "+ student.last_name)
		print (student.gender)
	context = {
		"students":students
	}
	return render(request, 'students/student.html', context)

def get_course(request):
	courses = Course.objects.all()
	print (courses)
	# for student in students:
	# 	print (student.first_name + " "+ student.last_name)
	context = {
		"courses":courses
	}
	return render(request, 'course/course.html', context)


#coding=utf8
from utils import *
from models.LSTMSelfAttention import *
from mydatasets import *
import sys
def validate(model, val_iter, args):
    model.eval()
    corrects, avg_loss = 0.0, 0.0
    for batch in val_iter:

        (inputs, inputs_length), target = batch.text, batch.label - 1

        if args.cuda and args.device != -1:
            inputs, inputs_length, target = inputs.cuda(), inputs_length.cuda(), target.cuda()

        logit = model(inputs, inputs_length)
        loss = F.cross_entropy(logit, target, size_average=False)
        correct = (torch.max(logit, 1)[1].view(target.size()).data == target.data).sum()

        avg_loss += loss.item()
        corrects += correct

    size = len(val_iter.dataset)
    avg_loss /= size
    accuracy = 100.0 * corrects/size
    model.train()
    print('\nEvaluation - loss: {:.6f}  acc: {:.4f}%({}/{}) '.format(avg_loss,
                                                                       accuracy,
                                                                       corrects,
                                                                       size))

def train(model, train_iter, val_iter, args):
    print("begin to train models...")
    optimizer = torch.optim.Adam(model.parameters(), lr = args.lr)
    steps = 0

    for epoch in range(1, args.epochs + 1):
        for batch in train_iter:
            (inputs, inputs_length), target = batch.text, batch.label - 1
            if args.cuda and args.device != -1:
                inputs, inputs_length, target = inputs.cuda(), inputs_length.cuda(), target.cuda()

            optimizer.zero_grad()
            logit = model(inputs, inputs_length)
            loss = F.cross_entropy(logit, target)
            loss.backward()
            optimizer.step()
            steps += 1
            if steps % args.log_interval == 0:
                corrects = (torch.max(logit, 1)[1].view(target.size()).data == target.data).sum()

                accuracy = 100*corrects/batch.batch_size
                sys.stdout.write(
                    '\rBatch[{}] - loss: {:.6f}  acc: {:.4f}%({}/{})'.format(steps,
                                                                             loss.item(),
                                                                             accuracy,
                                                                             corrects,
                                                                             batch.batch_size))

            if steps % args.test_interval == 0:
                validate(model, val_iter, args)

def train_distil_model_joint(full_model, small_model, train_iter, val_iter, full_model_args, small_model_args):
    full_model_optimizer = torch.optim.Adam(full_model.parameters(), lr = full_model_args.lr)
    small_model_optimizer = torch.optim.Adam(small_model.parameters(), lr = small_model_args.lr)
    steps = 0
    big_temperature = 10
    for epoch in range(1, full_model_args.epochs +1):
        for batch in train_iter:
            (inputs, inputs_length), target = batch.text, batch.label - 1
            # print(inputs)
            # print(target)
            target = torch.zeros(full_model_args.batch_size, full_model_args.class_num).scatter_(1, target.view(full_model_args.batch_size, 1), 1)
            full_inputs, full_inputs_length, full_target = inputs, inputs_length, target
            small_inputs, small_inputs_length, small_target = inputs, inputs_length, target
            if full_model_args.cuda and full_model_args.device != -1:
                full_inputs, full_inputs_length, full_target = inputs.cuda(), \
                                                               inputs_length.cuda(), target.cuda()

            if small_model_args.cuda and small_model_args.device != -1:
                small_inputs, small_inputs_length, small_target = inputs.cuda(), \
                                                                  inputs_length.cuda(), target.cuda()

            full_model_optimizer.zero_grad()
            small_model_optimizer.zero_grad()
            full_model_logits = full_model(full_inputs, full_inputs_length)
            small_model_logits = small_model(small_inputs, small_inputs_length)
            full_model_loss = softmax_cross_entropy_loss(self_softmax(full_model_logits, big_temperature),
                                                         full_target)
            small_model_loss1 = softmax_cross_entropy_loss(self_softmax(small_model_logits, big_temperature),
                                                           small_target)
            small_model_loss2 = softmax_cross_entropy_loss(self_softmax(small_model_logits, big_temperature),
                                                           full_model_logits)
            small_model_loss = small_model_loss1 + small_model_loss2
            full_model_loss.backward(retain_graph=True)
            small_model_loss.backward(retain_graph=True)
            full_model_optimizer.step()
            small_model_optimizer.step()
            steps += 1

            if steps % full_model_args.log_interval == 0:
                full_model_corrects = (
                            torch.max(full_model_logits, 1)[1].data == torch.max(full_target, 1)[1].data).sum()
                small_model_corrects = (
                            torch.max(small_model_logits, 1)[1].data == torch.max(small_target, 1)[1].data).sum()

                full_model_accuracy = 100 * full_model_corrects / batch.batch_size
                small_model_accuracy = 100 * small_model_corrects / batch.batch_size

                sys.stdout.write(
                    '\rBatch[{}] - full_model_loss: {:.6f}  full_model_acc: {:.4f}%({}/{})'
                    ' - small_model_loss: {:.6f}  small_model_acc: {:.4f}%({}/{})'.format(steps,
                                                                             full_model_loss.item(),
                                                                             full_model_accuracy,
                                                                             full_model_corrects,
                                                                             batch.batch_size,
                                                                             small_model_loss.item(),
                                                                             small_model_accuracy,
                                                                             small_model_corrects,
                                                                             batch.batch_size))

            if steps % full_model_args.test_interval == 0:
                dev_distil_model_joint(full_model, small_model, val_iter, full_model_args, small_model_args)

def dev_distil_model_joint(full_model, small_model, val_iter, full_model_args, small_model_args):
    full_model.eval()
    small_model.eval()
    full_model_corrects, full_model_avg_loss = 0.0, 0.0
    small_model_corrects, small_model_avg_loss = 0.0, 0.0
    small_temperature = 1
    for batch in val_iter:

        (inputs, inputs_length), target = batch.text, batch.label - 1
        target = torch.zeros(full_model_args.batch_size, full_model_args.class_num).scatter_(1, target.view(
            full_model_args.batch_size, 1), 1)

        full_inputs, full_inputs_length, full_target = inputs, inputs_length, target
        small_inputs, small_inputs_length, small_target = inputs, inputs_length, target

        if full_model_args.cuda and full_model_args.device != -1:
            full_inputs, full_inputs_length, full_target = inputs.cuda(), \
                                            inputs_length.cuda(), target.cuda()

        if small_model_args.cuda and small_model_args.device != -1:
            small_inputs, small_inputs_length, small_target = inputs.cuda(), \
                                            inputs_length.cuda(), small_model_args.cuda()

        # logit = model(inputs, inputs_length)
        # loss = F.cross_entropy(logit, target, size_average=False)
        # correct = (torch.max(logit, 1)[1].view(target.size()).data == target.data).sum()
        full_model_logits = full_model(full_inputs, full_inputs_length)
        small_model_logits = small_model(small_inputs, small_inputs_length)
        full_model_loss = softmax_cross_entropy_loss(self_softmax(full_model_logits, small_temperature), full_target)
        small_model_loss1 = softmax_cross_entropy_loss(self_softmax(small_model_logits, small_temperature), small_target)
        small_model_loss2 = softmax_cross_entropy_loss(self_softmax(small_model_logits, small_temperature), full_model_logits)
        small_model_loss = small_model_loss1 + small_model_loss2
        full_model_correct = (torch.max(full_model_logits, 1)[1].data == torch.max(full_target, 1)[1].data).sum()
        small_model_correct = (torch.max(small_model_logits, 1)[1].data == torch.max(small_target, 1)[1].data).sum()

        full_model_avg_loss += full_model_loss
        full_model_corrects += full_model_correct

        small_model_avg_loss += small_model_loss
        small_model_corrects += small_model_correct

    size = len(val_iter.dataset)
    full_model_avg_loss /= size
    full_model_avg_loss /= size

    full_model_accuracy = 100.0 * full_model_corrects / size
    small_model_accuracy = 100.0 * small_model_corrects / size
    full_model.train()
    small_model.train()
    print('\nEvaluation - full_model_loss: {:.6f}  full_model_acc: {:.4f}%({}/{}) '
          'small_model_loss: {:.6f}  small_model_acc: {:.4f}%({}/{}) '.format(full_model_avg_loss,
                                                                     full_model_accuracy,
                                                                     full_model_corrects,
                                                                     size,small_model_avg_loss,
                                                                     small_model_accuracy,
                                                                     small_model_corrects,
                                                                     size))

# cross_entropy1 = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y1, 1e-10, 1.0)))
if __name__ == "__main__":
    # os.environ["CUDA_VISIBLE_DEVICES"] = '0, 1, 2, 3'
    # args, unknown = get_common_args()
    # args.device = -1

    args_full_model, unknown = get_common_args()
    args_full_model.device = 0
    args_full_model.lstm_num_layers = 2
    args_full_model.lstm_hidden_dim = 1200

    args_small_model, unknown = get_common_args()
    args_small_model.device = 1
    args_small_model.lstm_num_layers = 2
    args_small_model.lstm_hidden_dim = 600

    print(args_full_model)
    print(args_small_model)

    train_iter, val_iter = get_dataset_iter(args_full_model, "NewsGroup")
    args_small_model.embed_num = args_full_model.embed_num
    args_small_model.class_num = args_full_model.class_num

    # -1 means cpu, else the gpu index 0,1,2,3
    # args.device = 0
    # print("args : " + str(args))
    # print("unknown args : " + str(unknown))
    #
    # model = LSTMSelfAttention(args)

    full_model = LSTMSelfAttention(args_full_model)
    small_model = LSTMSelfAttention(args_small_model)

    if args_full_model.cuda and args_full_model.device != -1:
        full_model = full_model.cuda()
    if args_small_model.cuda and args_small_model.device != -1:
        small_model = small_model.cuda()

    train_distil_model_joint(full_model, small_model, train_iter, val_iter, args_full_model, args_small_model)

    # train(model, train_iter, val_iter, args)


import requests
import json

genreData = [
  {
    "genre_id": 28,
    "genre_name": "액션"
  },
  {
    "genre_id": 12,
    "genre_name": "모험"
  },
  {
    "genre_id": 16,
    "genre_name": "애니메이션"
  },
  {
    "genre_id": 35,
    "genre_name": "코미디"
  },
  {
    "genre_id": 80,
    "genre_name": "범죄"
  },
  {
    "genre_id": 99,
    "genre_name": "다큐멘터리"
  },
  {
    "genre_id": 18,
    "genre_name": "드라마"
  },
  {
    "genre_id": 10751,
    "genre_name": "가족"
  },
  {
    "genre_id": 14,
    "genre_name": "판타지"
  },
  {
    "genre_id": 36,
    "genre_name": "역사"
  },
  {
    "genre_id": 27,
    "genre_name": "공포"
  },
  {
    "genre_id": 10402,
    "genre_name": "음악"
  },
  {
    "genre_id": 9648,
    "genre_name": "미스터리"
  },
  {
    "genre_id": 10749,
    "genre_name": "로맨스"
  },
  {
    "genre_id": 878,
    "genre_name": "SF"
  },
  {
    "genre_id": 10770,
    "genre_name": "TV 영화"
  },
  {
    "genre_id": 53,
    "genre_name": "스릴러"
  },
  {
    "genre_id": 10752,
    "genre_name": "전쟁"
  },
  {
    "genre_id": 37,
    "genre_name": "서부"
  }
]

final_result = []
with open('movie_genre_final.json', 'w', encoding='utf-8') as f:
    count = 0
    for i in range(1, 500):
        requestData = requests.get(f"https://api.themoviedb.org/3/movie/popular?api_key=8d2390a7f14da4093a0836c65dfb59a2&language=ko-KR&page={i}")
        jsonData = requestData.json()
        results=jsonData["results"]

        for k in range(len(results)):
            for g in results[k]['genre_ids']:
                for gg in range(len(genreData)):
                    if genreData[gg]['genre_id'] == g:
                        g2 = {
                            'movie_id' : count,
                            'genre_id' : gg,
                        }
                        final_result.append(g2)
            count += 1
    json.dump(final_result, f, indent=2, ensure_ascii=False)


import unittest

from chase.wolf import Wolf
from chase.sheep import Sheep
from chase.point import Point

from math import sqrt

class WolfTestCase(unittest.TestCase):
    def test_init(self):
        w = Wolf(1, None)
        self.assertEqual(w.distance, 1)
        self.assertTrue(w.position.x == 0 and w.position.y == 0)

    def test_looking_back(self):
        sheep = [Sheep(10, 1) for x in range(5)]

        for index, _ in enumerate(sheep):
            _.position.set(Point(index + 1, index + 1))

        wolf = Wolf(3, sheep)

        self.assertEqual(wolf.look_back(sheep), (sheep[0], True, sqrt(2)))

        wolf.position.set(Point(0, 1))

        self.assertEqual(wolf.look_back(sheep), (sheep[0], True, 1))

        wolf.position.set(Point(2, 1))

        self.assertEqual(wolf.look_back(sheep), (sheep[0], True, 1))

        wolf.position.set(Point(1, -3))

        self.assertEqual(wolf.look_back(sheep), (sheep[0], False, 4.0))

        wolf.position.set(Point(10, 5))

        self.assertEqual(wolf.look_back(sheep), (sheep[-1], False, 5.0))
        pass

    def test_moving(self):
        sheep = [Sheep(10, 1) for x in range(2)]

        for index, _ in enumerate(sheep):
            _.position.set(Point(index + 1, index + 1))

        wolf = Wolf(3, sheep)

        wolf.move()
        self.assertEqual([wolf.position.x, wolf.position.y], [1, 1])
        self.assertEqual(sheep[0], None)

        sheep = [Sheep(10, 1) for x in range(2)]

        for index, _ in enumerate(sheep):
            _.position.set(Point(index + 1, index + 1))

        wolf = Wolf(1, sheep)
        wolf.move()

        self.assertAlmostEqual(wolf.position.x, sqrt(2) / 2)
        self.assertTrue(sheep[0] is not None)

        sheep = [Sheep(10, 1) for x in range(2)]

        for index, _ in enumerate(sheep):
            _.position.set(Point(index + 1, index + 1))
        wolf = Wolf(1, sheep)
        wolf.position.set(Point(5, 2))
        wolf.move()

        self.assertEqual([wolf.position.x, wolf.position.y], [4, 2])
        self.assertTrue(sheep[1] is not None)
        pass

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


from functools import partial
import tkinter as tk

class App(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master, height=42, width=42)
        self.entry = tk.Entry(self)
        self.entry.focus()
        self.entry.pack()
        self.clear_button = tk.Button(
            self, text="Enviar", command=self.falar)
        self.clear_button.pack()

    def falar(self):
        player = self.entry.get()
        print("Você: " + player)
        self.entry.delete(0, 'end')

def main():
    root = tk.Tk()
    root.title("Início")
    root.geometry("400x400+450+100")
    App(root).pack(expand=True, fill='both')
    root.mainloop()

if __name__ == "__main__":
    main()


from typing import List, Protocol

from adapters.outbound.dynamo_corporate_events_repository import DynamoCorporateEventsRepository
from application.models.earnings_in_assets_event import EarningsInAssetCorporateEvent

class CorporateEventsRepository(Protocol):
    def find_by_emitted_asset(self, emitted_isin: str) -> List[EarningsInAssetCorporateEvent]:
        ...

def get_all_previous_symbols(isin_code: str, corp_events_repository: CorporateEventsRepository) -> List[str]:
    previous_symbols = []
    events = corp_events_repository.find_by_emitted_asset(isin_code)
    for event in events:
        if event.isin_code == isin_code:
            continue
        previous_symbols.append(event.isin_code)
        previous_symbols += get_all_previous_symbols(event.isin_code, corp_events_repository)

    return previous_symbols

if __name__ == '__main__':
    print(get_all_previous_symbols("BREMBRACNOR4", DynamoCorporateEventsRepository()))


from pynput.keyboard import Listener
import logging

# Setup logging
# This will save a list of key presses and key releases as a textfile in the same directory we are in.
for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)
logging.basicConfig(filename="filename.txt", level=logging.DEBUG, format='%(asctime)s: %(message)s')

# This logs the key press and stops when the 's' key is pressed.
def on_press(key):  # The function that's called when a key is pressed
    logging.info("Key pressed: {0}".format(key))
    if key.char == 's':
        listener.stop()

# This logs the key release (can probably just put pass so we don't log it)
def on_release(key):  # The function that's called when a key is released
    logging.info("Key released: {0}".format(key))

print("listening!!!")

with Listener(on_press=on_press, on_release=on_release) as listener:  # Create an instance of Listener
    listener.join()  # Join the listener thread to the main thread to keep waiting for keys


import pygame
import sys
import math
import time
import random

#TASTELE SUNT K;M si A;Z

def linie(screen, x, y, l,color):
    pygame.draw.line(screen, color, [x, y],[x+1 , y+l])

def dreptunghi(screen, x, y, l, w, color):
    pygame.draw.line(screen, color, [x, y], [x + l, y])
    pygame.draw.line(screen, color, [x+ l,y], [x + l,y + w])
    pygame.draw.line(screen, color, [x + l,y + w], [x ,y + w])
    pygame.draw.line(screen, color, [x ,y + w],[x ,y ])

def minge(screen, x, y, r, color, w):
    pygame.draw.circle(screen, color,[x, y], r, w)

def intersects(mx, my, r, left, top, right, bottom):
   if mx < left:
       closestX = left
   else:
       if mx > right:
           closestX = right
       else:
            closestX = mx

   if my < top:
       closestY = top
   else:
       if my > bottom:
           closestY = bottom
       else:
            closestY = my

   dx = closestX - mx
   dy = closestY - my

   return (dx * dx + dy * dy) <= r * r

 #culori RED,GREEN,BLUE
RED = (255 ,0, 0)
WHITE=(255,255,255)
BLUE=(0,0,255)
GREEN=(0,255,0)
BLACK=(0,0,0)

pygame.init()

size=[500, 350]
screen=pygame.display.set_mode(size)

#MINGE

r=7
my=50
mx=250
mdir=2
ui=random.randint(0,360)* math.pi/180

scoreS=0
scoreR=0

pygame.display.set_caption("PONG ")
font=pygame.font.SysFont('Calibri',25,True,False)

won=False

sx=5
rx=475
sy=125
ry=125
sdir=0
rdir=0
done=False
clock=pygame.time.Clock()

pygame.key.set_repeat(1,10)

while not done:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            done=True
        keys = pygame.key.get_pressed()

        if keys[pygame.K_a]:
            if sy>2:
                sy-=2

        if keys[pygame.K_z]:
            if sy<249:
                sy+=2

        if keys[pygame.K_k]:
            if ry>2:
                ry-=2

        if keys[pygame.K_m]:
            if ry<249:
                ry+=2

    screen.fill(WHITE)

    dreptunghi(screen,5,sy,20,100,BLACK)

    textscoreR= font.render("score: " + str(scoreR),True,BLACK)
    screen.blit(textscoreR,[350,325])
    textscoreS= font.render("score: "+ str(scoreS),True,BLACK)
    screen.blit(textscoreS,[87,325])

    if scoreS==5:
        wintextS=font.render("PLAYER1 WINS! ",True,GREEN)
        screen.blit(wintextS,[225,175])
        done=True
        won=True

    if scoreR==5:
        wintextR=font.render("PLAYER2 WINS !",True,GREEN)
        screen.blit(wintextR,[225,175])
        done=True
        won=True

    linie(screen,250,0,350,BLACK)
    dreptunghi(screen,475,ry,20,100,BLACK)
    minge(screen,int(mx),int(my),r,BLUE,0)

    if mx -r <=0:
        scoreR=scoreR+1
        mx=250
        my=50

    if mx + r>=500:
        scoreS=scoreS +1
        mx=250
        my=50

    mx=mx + mdir * math.sin(ui)
    if mx <= 0 + r:
        ui= - ui

    if mx>= 500 - r:
        ui= - ui
    my=my + mdir * math.cos(ui)

    if my <= 0 + r:
        ui= math.pi - ui

    if my >= 350-r:
        ui=math.pi - ui

    if intersects(mx,my,r,sx,sy,sx+20,sy+100):
        ui= math.atan2(my,mx)

    if intersects(mx,my,r,rx,ry,rx+20,ry + 100):
        ui= - math.atan2(my,mx)

        print(scoreS,scoreR)

    pygame.display.flip()
    clock.tick(100)

    if won:
        time.sleep(5)

pygame.quit()
sys.exit()


#User function Template for python3

class Solution:

    def minTime(self, s1, s2, N):

        if s2<s1 :
            s1, s2 = s2, s1
        mc = s2*N

        def getCost(ind) :
            return max(s1*ind, (N-ind)*s2)

        left = 0
        right = N
        while(left <= right) :
            mid = (left+right)//2
            mc = min(mc, getCost(mid))
            if mid*s1 > (N-mid)*s2:
                right = mid -1
            else :
                left = mid + 1

        return mc

#{
#  Driver Code Starts
#Initial Template for Python 3

if __name__ == '__main__':
    t = int(input())
    for _ in range(t):
        S1, S2, N = [int(x) for x in input().split()]

        ob = Solution()
        print(ob.minTime(S1, S2, N))
# } Driver Code Ends


import os
import math
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

np.random.seed(2)

print(tf.__version__)

# Folder path
folder_path = r'/Users/thesauravs/Documents/GitHub/Deep-Learning-from-Scratch/Sinusoidal'
os.chdir(folder_path)

#Loading the dataset
data = pd.read_csv('sine.csv')
data.head()

# Quick look at the joint distribution of a few pairs of columns
sns.pairplot(data[["x", "sin(x)"]], diag_kind="kde")

# To look at overall statistics
data_stats = data.describe()
data_stats.pop('sin(x)')
data_stats = data_stats.transpose()
print(data_stats)

# Split features from labels
train_labels = data.pop('sin(x)')
print(train_labels)
#print(len(data.keys()))

print(data)
# Normalizing the features to train faster
#data = (data - data_stats['mean']) / data_stats['std']
#print(data)

# Build the model
model = keras.Sequential([
        layers.Dense(128, activation='relu', input_shape=[len(data.keys())]),
        layers.Dense(64, activation='relu'),
        layers.Dense(32, activation='relu'),
        layers.Dense(16, activation='relu'),
#        layers.Dense(8, activation='relu'),
#        layers.Dense(4, activation='relu'),
#        layers.Dense(2, activation='relu'),
        layers.Dense(1)
        ])

# Try learning_rate = 0.1, 0.001, 0.0001, 0.00001 and analyse the loss graph
optimizer = keras.optimizers.Adam(learning_rate=0.0001)

model.compile(loss='mse',
              optimizer=optimizer,
              metrics=['mae','mse'])

model.summary()

# The patience parameter is the amount of epochs to check for improvement
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

history = model.fit(data, train_labels,
                    epochs=200,
                    validation_split=0.2,
                    verbose=1,
                    callbacks=[early_stop])

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch

plt.figure()
plt.xlabel('Epoch')
plt.ylabel('Mean Squared Error')
plt.ylim([0, hist['loss'][0]])
plt.plot(hist['epoch'], hist['mse'], label='Train error')
plt.plot(hist['epoch'], hist['val_mse'], label='Val error')
plt.legend()
plt.show()

hist.head(7)
hist.tail(7)

predictions = model.predict(data[:])

plt.scatter(list(data['x']), train_labels, color='g', s=0.05, label='Original')
plt.scatter(list(data['x']), predictions[:], color='r', s=0.05, label='Predicted')
plt.xlabel('X')
plt.ylabel('sin(X)')
plt.title('Sine Wave')
plt.legend(loc='best', fontsize='large')
plt.show()

model.save('sine.h5')


# 1, 1~10까지의 합계를 출력 하시오.  -> 사용자 = 시작/종료 = 합계
'''''
sums = int(input('숫자 입력 : '))
sums2 = int(input('종료 숫자 : '))

nums = sums + sums2
for i in range(sums,sums2):
    #sums += i
    print(f'{sums} + {i} = {sums+i}')
    print('출력 : ',nums)
'''''
hap, even, odd = 0, 0, 0
s = int(input('시작 : '))
e = int(input('종료 : '))
for i in range(s, e + 1):
    hap += i
    if i %2 == 0:
        even += i
    else:
        odd += i
        print('hap', hap)

# 2-1, 사용자로부터 성적을 입력 받아 리스트에 저장 후 저장된 데이터를
# 출력 하시오, 단 시험의 응시자는 달라진다
score = []
m = int(input('점수 : '))
for i in range(m):
    s = int(input('score:'))
    score.append(s)

print('점수 : ')
hap = 0
for i in score:
    hap += i
# for i in range(n)
#       hap += score[i]
avg = hap / len(score)
print('평균 : ', avg)
# 2-2 응시자의 평균을 하세요.
large,small=-1,101
for i in range(m):
    if score[i] > large:
        large = score[i]
    if score[i] < small:
        large = score[i]

print('최대',large)
print('최소',small)


#!/usr/bin/env python3

import numpy
from matplotlib import pyplot

#https://en.wikipedia.org/wiki/Logistic_map
#r: 0 to 1 -> die
#r: 1 to 2 -> quick to (r-1)/r
#r: 2 to 3 -> oscillate to (r-1)/r
#r: 3 to 3.449 -> oscillate between 2 values
#r: 3.450 to 3.544 -> oscillate between 4 values
#r: 3.545 to 3.564 -> oscillate between 8 values
#r: 3.570 to 3.999 -> chaos
#r: 4 and up -> diverge

growth_rates = [0.9, 1.3, 2.9, 3.1, 3.8]
labels = ["r = 0.9 (die)", "r = 1.3 (quick)", "r = 2.9 (slow)",
			 "r = 3.1 (bimodal)", "r = 3.8 (chaos)",]
original_population = 0.3
num_generations = 60
population_multiplier = 20000
population_list_list = []

for growth_rate in growth_rates:
	population_list = [original_population, ]
	old_population = original_population
	for generation_number in range(num_generations):
		new_population = growth_rate * old_population * (1.0 - old_population)
		population_list.append(new_population)
		old_population = new_population
	population_list_list.append(population_list)

#make the graph
for i in range(len(population_list_list)):
	population_list = population_list_list[i]
	label = "r = %.3f"%(growth_rates[i])
	nums = numpy.around(population_list, 5)*population_multiplier
	pyplot.plot(list(range(num_generations+1)), nums, label=labels[i])
pyplot.xlabel("Generation Number")
pyplot.ylabel("Population")
pyplot.legend(bbox_to_anchor=(0.65, 0.3), loc=2, borderaxespad=0.)
pyplot.ylim(ymin=0, ymax=20000)
pyplot.xlim(xmin=0, xmax=54)
#pyplot.savefig("outchaos.png", dpi=300)
pyplot.show()


c = ('\033[m',         # cor 0 = sem cores
     '\033[0;30;41m',  # cor 1 = Vermelho
     '\033[0;30;42m',  # cor 2 = Verde
     '\033[0;30;43m',  # cor 3 = Amarelo
     '\033[0;30;44m',  # cor 4 = Azul
     '\033[0;30;45m',  # cor 5 = Roxo
     '\033[7;30m',  # cor 6 = Branco
    )

def opcao():
   print('\033[0;30;41mDIGITE A OPÇÃO QUE DESEJA CALCULAR:\33[m')
   print('''
            [0] - calcular a plaejado todo
            [1] - calcular area da caixa (laterais, base, chápeu e divisória central (se houver)).
            [2] - calcular o fundo
            [3] - Calular a(s) porta(s)
            [4] - Calcular as gavetas
            [5] - calcular as prateleiras
            [6] - calcular os fiancos.
            [7] - calcular um painel.
        '''.upper())

def medidas(m='SEM MATERIAL', a=0, l=0, p=0):
    print('PRIMEIRO DIGITE AS MEDIDAS DO QUE DESEJA CALCULAR.')
    medida = list()
    copaimed = list()
    while True:
        medida.append(str(input('O TIPO DE MATERIAL : ').strip().upper()))
        medida.append(float(input('DIGITE:A ALTURA EM METROS : '.replace('.', ','))))
        medida.append(float(input('LARGURA EM METROS : '.replace('.', ','))))
        medida.append(float(input('PROFUNDIDADE : '.replace('.', ','))))
        copaimed.append(medida[:])
        medida.clear()
        medidas = copaimed[0][0], copaimed[0][1], copaimed[0][2], copaimed[0][3]
        print(medidas)
        break

def caixa():

        plan = list()
        plancopia = list()
        while True:
            cont = 0
            plan.append(str(input('O TIPO DE MATERIAL : ').strip().upper()))
            plan.append(float(input('DIGITE:A ALTURA EM METROS : '.replace('.', ','))))
            plan.append(float(input('LARGURA EM METROS : '.replace('.', ','))))
            plan.append(float(input('QUANTIDADE : '.replace('.', ','))))
            plancopia.append(plan[:])
            plan.clear()
            area = (((plancopia[0][1] * plancopia[0][2]) * plancopia[0][3]))
            #calc = (((plancopia[0][1] * plancopia[0][2]) * plancopia[0][3])/5.06)
            cont += (area/5.06)
            resp = str(input('TEM MAIS DA MESMA MEDIDA PARA ADICIONAR? [S/N]: '))
            if resp not in 'Nn':
                break
            subtitulos(f'O metro quadrado total da Caixa é: {area:.2f} metros '.upper())
            subtitulos(f'E serão necessários {area/5.06:.2f} CHapas de 2.75 x 1.84 do material {plancopia[0][0]} '.upper())
            break

def fundo():

    plan = list()
    plancopia = list()
    while True:
        cont = 0
        plan.append(str(input('O TIPO DE MATERIAL : ').strip().upper()))
        plan.append(float(input('DIGITE:A ALTURA EM METROS : '.replace('.', ','))))
        plan.append(float(input('LARGURA EM METROS : '.replace('.', ','))))
        plan.append(float(input('QUANTIDADE : '.replace('.', ','))))
        plancopia.append(plan[:])
        plan.clear()
        area = (((plancopia[0][1] * plancopia[0][2]) * plancopia[0][3]))
        # calc = (((plancopia[0][1] * plancopia[0][2]) * plancopia[0][3])/5.06)
        cont += (area / 5.06)
        resp = str(input('TEM MAIS DA MESMA MEDIDA PARA ADICIONAR? [S/N]: '))
        if resp not in 'Nn':
            break
        subtitulos(f'O metro quadrado total da Caixa é: {area:.2f} metros '.upper())
        subtitulos(
            f'E serão necessários {area / 5.06:.2f} CHapas de 2.75 x 1.84 do material {plancopia[0][0]} '.upper())
        break

def titulo(msg, cor=0):
        tam = len(msg) +4
        print('~' * tam)
        print(c[2], end='')
        print(f' {msg}\33[m')
        print('~' * tam)

def subtitulos(msg):
    print(c[5], end='')
    print(f'{msg}\33[m')
    print(c[5], end='')


'''8. What is the return type of arbitrary positional arguments and arbitrary keyword arguments.'''

def positional_(*args):
    results_=0
    for i in args:
        results_ += i
    return results_
print(positional_(1,2,3,4))

def keyword_(**kwargs):
    result=0
    for i in kwargs.values():
        result += i
    return result
print(keyword_(a=1, b=2, c=3, d=4, e=5))


import numpy as np
from PIL import Image

def pad_img_KAR(img, target_w, target_h, pad_value=(124, 116, 104)):
	w, h = img.size
	if w / h == target_w / target_h:
		return img, (0, 0)

	if w < h or w * (target_h / target_w) < h:
		new_w = int(h * (target_w / target_h))
		new_img = Image.new('RGB', (new_w, h), color=pad_value)
		new_img.paste(img, (int((new_w - w) // 2), 0))
		return new_img, (new_w - w, 0)
	else:
		new_h = int(w * (target_h / target_w))
		new_img = Image.new('RGB', (w, new_h), color=pad_value)
		new_img.paste(img, (0, int((new_h - h) // 2)))
		return new_img, (0, new_h - h)

def pad_array_KAR(arr, target_h, target_w, pad_value=np.array([[0]])):
	h, w = arr.shape
	if w / h == target_w / target_h:
		return arr, (0, 0)

	if w < h or w * (target_h / target_w) < h:
		new_w = int(h * (target_w / target_h))
		new_arr = np.ones((h, new_w)) * pad_value
		new_arr[:, int((new_w - w) // 2):int((new_w - w) // 2)+w] = arr
		return new_arr, (0, new_w - w)
	else:
		new_h = int(w * (target_h / target_w))
		new_arr = np.ones((new_h, w)) * pad_value
		new_arr[int((new_h - h) // 2):int((new_h - h) // 2) + h, :] = arr
		return new_arr, (new_h - h, 0)


import sys
import logging
import threading
import time

def ExceptionCatcher(typeErr, value = None, traceback = None, thread = None):
    # sys.__excepthook__(typeErr, value, traceback)
    logging.info(f"{str(threading.currentThread()).split(',')[0][8:]}: Erreur {str(typeErr.exc_value)}")

threading.excepthook = ExceptionCatcher

def Thread1():
    logging.info("Thread 1: starting")
    import Test
    logging.info("Thread 1: finishing")

def Thread2():
    logging.info("Thread 2: starting")
    import Test2
    logging.info("Thread 2: finishing")

if __name__ == "__main__":
    format = "%(asctime)s: %(message)s"
    logging.basicConfig(format=format, level=logging.INFO,
                        datefmt="%H:%M:%S")
    Programme_1 = threading.Thread(target=Thread1, args=())
    Programme_2 = threading.Thread(target=Thread2, args=())

    Programme_1.start()

    Programme_2.start()


"""
Um número inteiro é considerado triangular se for o produto de três
números inteiros consecutivos, como, por exemplo 120 = 4x5x6 . Elabore
um fluxograma e um algoritmo em Portugol que, após lerem em um número
"""

numero = int(input("informe o numero que deseja verificar : "))

a = 0
b = 1
c = 2
while numero >= a:
    valor = a * b * c
    if valor == numero:
        print(f"{a}x{b}x{c}")
        print(numero)
        break
    a += 1
    b += 1
    c += 1


from decimal import Decimal
import sys
from unittest import mock

import _pytest
import pytest
import validators
import keg
import sqlalchemy as sa

import keg_elements.db.utils as dbutils
import kegel_app.model.entities as ents

def test_randemail():
    for length in range(0, 6):
        with pytest.raises(ValueError):
            dbutils.randemail(length)

    def not_so_rand_email(length, char):
        return dbutils.randemail(length, randomizer=lambda n, *args, **kwargs: char * n)

    assert not_so_rand_email(7, 'a') == 'a@a.aaa'
    assert not_so_rand_email(8, 'b') == 'b@bb.bbb'
    assert not_so_rand_email(9, 'c') == 'cc@cc.ccc'

    # Fuzzy testing for an extra dose of confidence
    for length in range(7, 50):
        email = dbutils.randemail(length)
        assert len(email) == length
        assert validators.email(email)

    # Get some confidence of randomness
    assert len(set(dbutils.randemail(50) for _ in range(5))) == 5, \
        'randemail not random (beware non-determinism; try again)'

class TestUpdateCollection(object):

    def setup_method(self, method):
        keg.db.db.session.remove()
        ents.Thing.delete_cascaded()
        ents.RelatedThing.delete_cascaded()

    def test_add(self):
        thing = ents.Thing.fake()
        assert not thing.related_things

        data = [{'name': 'test', 'is_enabled': True}]
        thing.update_collection('related_things', data)

        assert len(thing.related_things) == 1
        related = thing.related_things[0]
        assert related.name == 'test'
        assert related.is_enabled

    def test_edit(self):
        thing = ents.Thing.fake()
        related1_id = ents.RelatedThing.fake(thing=thing, name='a').id
        related2_id = ents.RelatedThing.fake(thing=thing, name='x').id

        data = [
            {'id': related1_id, 'name': 'b', 'is_enabled': False},
            {'id': related2_id, 'name': 'y', 'is_enabled': False},
        ]
        thing.update_collection('related_things', data)

        keg.db.db.session.flush()

        assert len(thing.related_things) == 2
        related1 = thing.related_things[0]
        assert related1.id == related1_id
        assert related1.name == 'b'
        assert not related1.is_enabled

        related2 = thing.related_things[1]
        assert related2.id == related2_id
        assert related2.name == 'y'
        assert not related2.is_enabled

    def test_append_id_none(self):
        thing = ents.Thing.fake()
        related = ents.RelatedThing.fake(thing=thing, name='a', is_enabled=True)

        data = [
            {'is_enabled': False}
        ]
        thing.update_collection('related_things', data)

        assert len(thing.related_things) == 1
        related = thing.related_things[0]

        assert related.name is None
        assert not related.is_enabled

    def test_remove(self):
        thing = ents.Thing.fake()
        ents.RelatedThing.fake(thing=thing, name='a', is_enabled=True)
        assert len(thing.related_things) == 1

        data = []
        thing.update_collection('related_things', data)

        assert len(thing.related_things) == 0

    def test_replace_with_unique_constraint(self):
        thing = ents.Thing.fake()
        other = ents.OtherThing.fake(thing=thing)

        data = [
            {
                'name': 'test',
                'is_enabled': True,
                'unique_field': other.unique_field,
            }
        ]
        thing.update_collection('other_things', data)
        keg.db.db.session.flush()

class TestExceptionHelpers:
    def setup_method(self, _):
        ents.ConstraintTester.delete_cascaded()

    def test_validate_unique_exception_unnamed(self):
        ents.ConstraintTester.fake(unique1=1)
        with pytest.raises(Exception) as exc:
            ents.ConstraintTester.fake(unique1=1)
        assert dbutils.validate_unique_exc(exc.value) is True

        with pytest.raises(Exception) as exc:
            ents.ConstraintTester.fake(check=101)
        assert dbutils.validate_unique_exc(exc.value) is False

    def test_validate_unique_exception_named(self):
        ents.ConstraintTester.fake(unique2=1)
        with pytest.raises(Exception) as exc:
            ents.ConstraintTester.fake(unique2=1)
        assert dbutils.validate_unique_exc(exc.value, 'uq_constraint_tester_unique2') is True

    def test_validate_unique_msg_postgres(self):
        postgres_msg = (
            '(psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint '
            '"uq_constraint_tester_unique2"'
        )
        assert dbutils._validate_unique_msg('postgresql', postgres_msg) is True
        assert dbutils._validate_unique_msg(
            'postgresql',
            postgres_msg,
            'uq_constraint_tester_unique2'
        ) is True

        assert dbutils._validate_unique_msg(
            'postgresql',
            postgres_msg,
            'uq_constraint_tester_unique1'
        ) is False
        assert dbutils._validate_unique_msg('mssql', postgres_msg) is False

    def test_validate_unique_msg_mssql(self):
        mssql_msg = (
            "Violation of UNIQUE constraint 'uq_constraint_tester_unique2'. "
            "Cannot insert duplicate key in object 'dbo.constraint_tester'. "
            'The duplicate key value is (1).'
        )
        assert dbutils._validate_unique_msg('mssql', mssql_msg) is True
        assert dbutils._validate_unique_msg(
            'mssql',
            mssql_msg,
            'uq_constraint_tester_unique2'
        ) is True

        assert dbutils._validate_unique_msg(
            'mssql',
            mssql_msg,
            'uq_constraint_tester_unique1'
        ) is False
        assert dbutils._validate_unique_msg('postgresql', mssql_msg) is False

    def test_validate_unique_msg_sqlite(self):
        sqlite_msg = '(sqlite3.IntegrityError) UNIQUE constraint failed: constraint_tester.unique2'
        assert dbutils._validate_unique_msg('sqlite', sqlite_msg) is True
        assert dbutils._validate_unique_msg(
            'sqlite',
            sqlite_msg,
            'uq_constraint_tester_unique2'
        ) is True

        assert dbutils._validate_unique_msg('postgresql', sqlite_msg) is False

    def test_validate_unique_msg_unsupported(self):
        sqlite_msg = '(sqlite3.IntegrityError) UNIQUE constraint failed: constraint_tester.unique2'
        with pytest.raises(ValueError) as exc:
            dbutils._validate_unique_msg('unknown', sqlite_msg)
        assert str(exc.value) == 'is_unique_exc() does not yet support dialect: unknown'

    @pytest.mark.skipif(sys.version_info.major < 3, reason='requires python 3')
    def test_raises_unique_exception(self):
        ents.ConstraintTester.fake(unique2=1)

        @dbutils.raises_unique_exc('uq_constraint_tester_unique2')
        def make_dup():
            ents.ConstraintTester.fake(unique2=1)

        make_dup()

        @dbutils.raises_unique_exc('uq_constraint_tester_unique2')
        def make_uq():
            ents.ConstraintTester.fake()

        with pytest.raises(_pytest.outcomes.Failed):
            make_uq()

        @dbutils.raises_unique_exc('uq_constraint_tester_unique2')
        def make_ck():
            ents.ConstraintTester.fake(check=101)

        with pytest.raises(AssertionError):
            make_ck()

    def test_is_check_constraint_sqlite(self):
        assert dbutils._is_check_const(
            'sqlite',
            '(sqlite3.IntegrityError) CHECK constraint failed: ck_constraint_tester_check',
            'ck_constraint_tester_check'
        ) is True

        assert dbutils._is_check_const(
            'sqlite',
            '(sqlite3.IntegrityError) UNIQUE constraint failed: constraint_tester.unique2',
            'ck_constraint_tester_check'
        ) is False

    def test_is_check_constraint_mssql(self):
        mssql_msg = (
            'The INSERT statement conflicted with the CHECK constraint '
            '"ck_constraint_tester_check".'
        )
        assert dbutils._is_check_const('mssql', mssql_msg, 'ck_constraint_tester_check') is True

        assert dbutils._is_check_const('mssql', mssql_msg, 'uq_constraint_tester_unique2') is False
        assert dbutils._is_check_const('sqlite', mssql_msg, 'ck_constraint_tester_check') is False

    def test_is_check_constraint_postgres(self):
        postgres_msg = (
            '(psycopg2.errors.CheckViolation) new row for relation "constraint_tester" violates '
            'check constraint "ck_constraint_tester_check"'
        )
        assert dbutils._is_check_const(
            'postgresql',
            postgres_msg,
            'ck_constraint_tester_check'
        ) is True

        assert dbutils._is_check_const(
            'postgresql',
            postgres_msg,
            'uq_constraint_tester_unique2'
        ) is False
        assert dbutils._is_check_const(
            'sqlite',
            postgres_msg,
            'ck_constraint_tester_check'
        ) is False

    def test_is_check_constraint_unsupported(self):
        sqlite_msg = '(sqlite3.IntegrityError) CHECK constraint failed: ck_constraint_tester_check'
        with pytest.raises(ValueError) as exc:
            dbutils._is_check_const('unknown', sqlite_msg, 'ck_constraint_tester_check')
        assert str(exc.value) == 'is_constraint_exc() does not yet support dialect: unknown'

    @pytest.mark.skipif(sys.version_info.major < 3, reason='requires python 3')
    def test_raises_check_exc(self):
        @dbutils.raises_check_exc('ck_constraint_tester_check')
        def make_fail():
            ents.ConstraintTester.fake(check=101)

        make_fail()

        @dbutils.raises_check_exc('ck_constraint_tester_check')
        def make_pass():
            ents.ConstraintTester.fake()

        with pytest.raises(_pytest.outcomes.Failed):
            make_pass()

        @dbutils.raises_check_exc('ck_constraint_tester_check')
        def make_uq():
            ents.ConstraintTester.fake(unique1=1)
            ents.ConstraintTester.fake(unique1=1)

        with pytest.raises(AssertionError):
            make_uq()

# Repeat parameter used to somewhat counteract the non-deterministic nature of the tested function
@pytest.mark.parametrize('repeat', range(1, 20))
@pytest.mark.parametrize('scale,prec,max', [
    (1, 1, Decimal('0.9')),
    (2, 1, Decimal('9.9')),
    (3, 3, Decimal('0.999')),
    (3, 2, Decimal('9.99')),
    (3, 1, Decimal('9.9')),
    (3, 0, Decimal('99.0')),
    (4, 4, Decimal('0.9999')),
    (4, 3, Decimal('9.999')),
    (4, 2, Decimal('99.99')),
    (4, 1, Decimal('99.9')),
    (4, 0, Decimal('99.0')),
])
def test_random_numeric(scale, prec, max, repeat):
    col = sa.Column(sa.Numeric(scale, prec))
    value = dbutils.random_numeric(col)
    assert value <= max
    assert value >= -max

@mock.patch('keg_elements.db.utils.random.uniform', autospec=True, spec_set=True)
def test_random_numeric_respects_magnitude(m_uniform):
    col = sa.Column(sa.Numeric(18, 2), info={'random_magnitude': 100})
    dbutils.random_numeric(col)
    m_uniform.assert_called_once_with(-100, 100)

@mock.patch('keg_elements.db.utils.random.uniform', autospec=True, spec_set=True)
def test_random_numeric_respects_range(m_uniform):
    col = sa.Column(sa.Numeric(18, 2), info={'random_range': (-50, 100)})
    dbutils.random_numeric(col)
    m_uniform.assert_called_once_with(-50, 100)

@mock.patch('keg_elements.db.utils.random.randint', autospec=True, spec_set=True)
def test_random_int_respects_magnitude(m_randint):
    col = sa.Column(sa.Integer, info={'random_magnitude': 100})
    dbutils.random_int(col, (-100, 100))
    m_randint.assert_called_once_with(-100, 100)

@mock.patch('keg_elements.db.utils.random.randint', autospec=True, spec_set=True)
def test_random_int_respects_range(m_randint):
    col = sa.Column(sa.Integer, info={'random_range': (-50, 100)})
    dbutils.random_int(col, (-100, 100))
    m_randint.assert_called_once_with(-50, 100)

@mock.patch('keg_elements.db.utils.random.randint', autospec=True, spec_set=True)
def test_random_int_falls_back_to_default_range(m_randint):
    col = sa.Column(sa.Numeric(18, 2))
    dbutils.random_int(col, (-100, 100))
    m_randint.assert_called_once_with(-100, 100)

@pytest.mark.parametrize(
    'type_,magnitude',
    [
        (sa.SmallInteger, 32767),
        (sa.Integer, 2147483647),
        (sa.BigInteger, 9223372036854775807),
    ]
)
@mock.patch('keg_elements.db.utils.random.randint', autospec=True, spec_set=True)
def test_random_int_by_sa_type(m_randint, type_, magnitude):
    col = sa.Column(type_)
    dbutils.random_int(col, (-100, 100))
    m_randint.assert_called_once_with(-magnitude, magnitude)


#!/usr/bin/env python
#coding=utf-8

import sys
import codecs

reload(sys)
sys.setdefaultencoding("utf-8")

def gen_redis_cmd(ifn, ofn, prefix=None):
    d = {}
    with codecs.open(ifn, "r", "utf-8") as inf:
        while True:
            line = inf.readline()
            if not line:
                break
            line = line.strip()
            if len(line)<=0:
                continue
            for i in range(1, len(line)):
            	word = line[:i]
            	if word not in d:
            		d[word] = 0
            d[line] = 1
    with codecs.open(ofn, "w", "utf-8") as ouf:
        if prefix is not None:
            for word in d:
                ouf.write("set "+prefix+"_"+word+" " + str(d[word])+"\n")
        else:
            for word in d:
                ouf.write("set "+word+" " + str(d[word])+"\n")

if __name__=="__main__":
    if len(sys.argv)<3:
        print("Usage:")
        print("\tpython %s  indir  outdir  [prefix]" % sys.argv[0])
    elif len(sys.argv)==3:
        gen_redis_cmd(sys.argv[1], sys.argv[2])
    else:
        gen_redis_cmd(sys.argv[1], sys.argv[2], sys.argv[3])