#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import math
import json
import re
import time
import logging
import psutil
import configparser
import requests
import shlex
import logging
from PyQt5 import QtCore, QtWidgets, QtGui

try:
    from PyQt5 import QtWebEngineWidgetsas
    webengine_available = 1

except ImportError:
    webengine_available = 0

from qomui import config, update, monitor, plotter

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtWidgets.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtWidgets.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtWidgets.QApplication.translate(context, text, disambig)

class favouriteButton(QtWidgets.QAbstractButton):
    def __init__(self, parent=None):
        super(favouriteButton, self).__init__(parent)
        self.star = QtGui.QPolygonF([QtCore.QPointF(1.0, 0.5)])
        for i in range(5):
            self.star << QtCore.QPointF(0.5 + 0.5 * math.cos(0.8 * i * math.pi),
                                        0.5 + 0.5 * math.sin(0.8 * i * math.pi)
                                        )

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        rect = self.rect()
        palette = self.palette()
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.setPen(QtCore.Qt.NoPen)
        if self.isChecked() == True:
            painter.setBrush(palette.highlight())
        else:
            painter.setBrush(palette.buttonText())
        yOffset = (rect.height() - 25) /2
        painter.translate(rect.x(), rect.y() + yOffset)
        painter.scale(25, 25)
        painter.drawPolygon(self.star, QtCore.Qt.WindingFill)
        painter.translate(1.0, 0.0)

    def enterEvent(self, event):
        self.update()

    def leaveEvent(self, event):
        self.update()

    def sizeHint(self):
        return QtCore.QSize(25, 25)

class ServerWidget(QtWidgets.QWidget):
    server_chosen = QtCore.pyqtSignal(str)
    set_hop_signal = QtCore.pyqtSignal(str)
    changed_favourite_signal = QtCore.pyqtSignal(tuple)

    def __init__ (self, show=None, parent=None):
        super(ServerWidget, self).__init__(parent=None)
        self.hidden = False
        self.fav = 0
        self.show = show
        self.setMouseTracking(True)
        self.setupUi(self)

    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.iconLabel = QtWidgets.QLabel(Form)
        self.iconLabel.setFixedSize(QtCore.QSize(30, 30))
        self.iconLabel.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.iconLabel.setObjectName(_fromUtf8("iconLabel"))
        self.horizontalLayout.addWidget(self.iconLabel)
        self.nameLabel = QtWidgets.QLabel(Form)
        self.nameLabel.setObjectName(_fromUtf8("nameLabel"))
        self.horizontalLayout.addWidget(self.nameLabel)
        self.cityLabel = QtWidgets.QLabel(Form)
        self.cityLabel.setObjectName(_fromUtf8("cityLabel"))
        self.horizontalLayout.addWidget(self.cityLabel)
        self.horizontalLayout.addStretch()
        self.favouriteButton = favouriteButton(Form)
        self.favouriteButton.setVisible(False)
        self.favouriteButton.setCheckable(True)
        self.favouriteButton.setObjectName(_fromUtf8("favouriteButton"))
        self.horizontalLayout.addWidget(self.favouriteButton)
        self.hop_bt = QtWidgets.QPushButton(Form)
        self.hop_bt.setVisible(False)
        self.hop_bt.setObjectName(_fromUtf8("hop_bt"))
        self.horizontalLayout.addWidget(self.hop_bt)
        self.connect_bt = QtWidgets.QPushButton(Form)
        if self.show == None:
            self.connect_bt.setVisible(False)
        self.connect_bt.setObjectName(_fromUtf8("connect_bt"))
        self.horizontalLayout.addWidget(self.connect_bt)
        QtCore.QMetaObject.connectSlotsByName(Form)
        self.connect_bt.clicked.connect(self.signal)
        self.hop_bt.clicked.connect(self.hop_signal)
        self.favouriteButton.toggled.connect(self.fav_change)

    def setText(self, name, provider, country, city, button = "connect", fav = 0):
        self.name = name
        self.provider = provider
        self.city = city
        self.fav = fav

        if self.provider != "bypass":

            try:
                self.iconLabel.setPixmap(country)

            except TypeError:
                flag = '{}/flags/{}.png'.format(config.ROOTDIR, country)
                if not os.path.isfile(flag):
                    flag = '{}/flags/Unknown.png'.format(config.ROOTDIR)
                pixmap = QtGui.QPixmap(flag).scaled(25, 25,
                                                    transformMode=QtCore.Qt.SmoothTransformation
                                                    )
                self.iconLabel.setPixmap(pixmap)
        else:
            icon = QtGui.QIcon.fromTheme(country)
            self.iconLabel.setPixmap(icon.pixmap(25,25))

        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        bold_font.setPointSize(11)

        if self.fav == "on":
            self.favouriteButton.setChecked(True)

        self.nameLabel.setFont(bold_font)
        self.nameLabel.setText(self.name)
        self.cityLabel.setText(self.city)

        try:
            self.connect_bt.setText(_translate("Form", button, None))

        except AttributeError:
            pass

        try:
            self.hop_bt.setText(_translate("Form", "hop", None))

        except AttributeError:
            pass

    def hide_button(self, choice=None):
        self.choice = choice
        #self.horizontalLayout.removeWidget(self.hop_bt)
        self.hop_bt = None

        if choice == 1:
            self.connect_bt.setVisible(False)
            self.horizontalLayout.removeWidget(self.connect_bt)
            self.connect_bt = None

    def enterEvent(self, event):
        if self.show == None:

            try:
                self.connect_bt.setVisible(True)

            except AttributeError:
                pass

            try:
                self.hop_bt.setVisible(True)
            except AttributeError:
                pass

            self.cityLabel.setVisible(False)

            if self.fav != 0:
                self.favouriteButton.setVisible(True)

    def leaveEvent(self, event):
        if self.show == None:

            try:
                self.connect_bt.setVisible(False)

            except AttributeError:
                pass

            try:
                self.hop_bt.setVisible(False)

            except AttributeError:
                pass

            self.cityLabel.setVisible(True)
            self.favouriteButton.setVisible(False)

    def signal(self):
        self.server_chosen.emit(self.name)

    def display_latency(self, latency):
        self.latency = latency

        if self.city != "":
            self.cityLabel.setText("{} - {}".format(self.city, self.latency))

        else:
            self.cityLabel.setText(latency)

    def setHidden(self, state):
        self.hidden = state

    def isHidden(self):
        return self.hidden

    def hop_signal(self):
        self.set_hop_signal.emit(self.name)

    def fav_change(self, change):
        self.changed_favourite_signal.emit((self.name, change))

    def sizeHint(self):
        return QtCore.QSize(100, 50)

class HopWidget(QtWidgets.QWidget):
    clear = QtCore.pyqtSignal()

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

    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(100, 100)
        self.setAutoFillBackground(True)
        self.setBackgroundRole(self.palette().Base)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.hopLabel = QtWidgets.QLabel(Form)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.hopLabel.setFont(bold_font)
        self.verticalLayout.addWidget(self.hopLabel)
        self.activeHopWidget = ServerWidget()
        self.verticalLayout.addWidget(self.activeHopWidget)
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
        self.activeHopWidget.server_chosen.connect(self.signal)

    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Form", None))
        self.hopLabel.setText(_translate("Form", "Current selection for first hop:", None))

    def setText(self, server_dict):
        try:
            city = server_dict["city"]

        except KeyError:
            city = None

        self.activeHopWidget.setText(server_dict["name"], server_dict["provider"],
                               server_dict["country"], city, button="clear")

        self.activeHopWidget.hide_button(0)

    def signal(self):
        self.clear.emit()

class ProgressBarWidget(QtWidgets.QWidget):
    abort = QtCore.pyqtSignal(str)

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

    def setupUi(self, ProgessBarWidget):
        self.horizontalLayout = QtWidgets.QHBoxLayout(ProgessBarWidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.taskLabel = QtWidgets.QLabel(ProgessBarWidget)
        self.taskLabel.setObjectName(_fromUtf8("taskLabel"))
        bold_font = QtGui.QFont()
        bold_font.setPointSize(13)
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.taskLabel.setFont(bold_font)
        self.horizontalLayout.addWidget(self.taskLabel)
        self.waitBar = QtWidgets.QProgressBar(ProgessBarWidget)
        self.waitBar.setObjectName(_fromUtf8("waitBar"))
        self.horizontalLayout.addWidget(self.waitBar)
        self.cancelButton = QtWidgets.QPushButton(ProgessBarWidget)
        self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
        self.horizontalLayout.addWidget(self.cancelButton)

        self.cancelButton.clicked.connect(self.cancel)
        self.waitBar.setRange(0, 0)

    def setText(self, text, action=None):
        self.action = action
        self.cancelButton.setText("cancel")
        if action == "upgrade":
            self.cancelButton.setVisible(False)
        self.taskLabel.setText(_translate("ProgessBarWidget", text, None))

    def cancel(self):
        self.abort.emit(self.action)

class ActiveWidget(QtWidgets.QWidget):
    disconnect = QtCore.pyqtSignal()
    reconnect = QtCore.pyqtSignal()
    check_update = QtCore.pyqtSignal()

    def __init__ (self, text, parent=None):
        super(ActiveWidget, self).__init__(parent)
        self.setupUi(self)
        self.text = text
        self.bypass = None

    def setupUi(self, ConnectionWidget):
        ConnectionWidget.setObjectName(_fromUtf8("ConnectionWidget"))
        self.vLayoutActive = QtWidgets.QVBoxLayout(ConnectionWidget)
        self.vLayoutActive.setObjectName(_fromUtf8("vLayoutActive"))
        self.hLayoutActive = QtWidgets.QHBoxLayout()
        self.hLayoutActive.setObjectName(_fromUtf8("hLayoutActive"))
        self.statusLabel = QtWidgets.QLabel(ConnectionWidget)
        bold_font = QtGui.QFont()
        bold_font.setPointSize(12)
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.statusLabel.setFont(bold_font)
        self.statusLabel.setObjectName(_fromUtf8("statusLabel"))
        self.vLayoutActive.addWidget(self.statusLabel)
        bold_font.setPointSize(11)
        self.hopCountryLabel = QtWidgets.QLabel(ConnectionWidget)
        self.hopCountryLabel.setFixedSize(30,30)
        self.hopCountryLabel.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.hopCountryLabel.setVisible(False)
        self.hLayoutActive.addWidget(self.hopCountryLabel)
        self.hopNameLabel = QtWidgets.QLabel(ConnectionWidget)
        self.hopNameLabel.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.hopNameLabel.setFont(bold_font)
        self.hopNameLabel.setVisible(False)
        self.hLayoutActive.addWidget(self.hopNameLabel)
        self.ServerWidget = ServerWidget(show=True, parent=ConnectionWidget)
        self.hLayoutActive.addWidget(self.ServerWidget)
        self.vLayoutActive.addLayout(self.hLayoutActive)

        self.ServerWidget.server_chosen.connect(self.signal)
        QtCore.QMetaObject.connectSlotsByName(ConnectionWidget)

    def setText(self, server_dict, hop_dict, tun, tun_hop=None, bypass=None):
        self.statusLabel.setText(self.text)
        self.tun = tun
        self.tun_hop = tun_hop
        self.bypass = bypass
        self.statusLabel.setText(self.text)
        city = self.city_port_label(server_dict)
        self.ServerWidget.setText(server_dict["name"], server_dict["provider"],
                               server_dict["country"], city, button="disconnect")

        if hop_dict is not None:
            flag = '{}/flags/{}.png'.format(config.ROOTDIR, hop_dict["country"])
            if not os.path.isfile(flag):
                flag = '{}/flags/Unknown.png'.format(config.ROOTDIR)
            pixmap = QtGui.QPixmap(flag).scaled(25, 25,
                                                transformMode=QtCore.Qt.SmoothTransformation
                                                )
            self.hopCountryLabel.setPixmap(pixmap)
            hop_text = hop_dict["name"] + "    " + chr(10145)
            self.hopNameLabel.setText(hop_text)
            self.hopCountryLabel.setVisible(True)
            self.hopNameLabel.setVisible(True)

        else:
            self.hopCountryLabel.setVisible(False)
            self.hopNameLabel.setVisible(False)

        self.ServerWidget.hide_button(0)

    def reconnect_signal(self):
        self.reconnect.emit()

    def city_port_label(self, server_dict):
        try:
            protocol = server_dict["protocol"]
            port = server_dict["port"]

        except KeyError:
            protocol = ""
            port = ""

        try:
            city = server_dict["city"]
            if city != "":
                (city) = "{} -".format(city)

        except KeyError:
            city = ""

        return "{} {} {}".format(city, protocol, port)

    def signal(self):
        self.disconnect.emit()

class LineWidget(QtWidgets.QWidget):

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

    def setupUi(self, LineWidget):
        self.setAutoFillBackground(True)
        self.setFixedHeight(1)
        #self.setBackgroundRole(self.palette().Highlight)

class StatusOffWidget(QtWidgets.QWidget):
    def __init__ (self, parent=None):
        super(StatusOffWidget, self).__init__(parent=None)
        self.setupUi(self)

    def setupUi(self, Form):
        Form.setObjectName("Form")
        self.vLayoutStatus = QtWidgets.QVBoxLayout(Form)
        self.vLayoutStatus.setObjectName("vLayoutStatus")
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.offLabel = QtWidgets.QLabel(Form)
        self.offLabel.setObjectName("offLabel")
        self.offLabel.setFont(font)
        self.vLayoutStatus.addWidget(self.offLabel)
        self.vLayoutStatus.addSpacing(40)
        self.qIconLabel = QtWidgets.QLabel(Form)
        self.qIconLabel.setObjectName("qIconLabel")
        self.qIconLabel.setMinimumSize(300,300)
        self.qIconLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.vLayoutStatus.addWidget(self.qIconLabel)
        self.vLayoutStatus.addSpacing(40)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.offLabel.setText(_translate("Form", "You are currently not connected to any VPN server "))
        icon = QtGui.QIcon.fromTheme("qomui_off")
        self.qIconLabel.setPixmap(icon.pixmap(300,300))

class ColoredRect(QtWidgets.QFrame):
    def __init__ (self, color, parent=None):
        super(ColoredRect, self).__init__(parent)
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(color)
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Window, brush)
        self.setPalette(palette)
        self.setFixedSize(10,10)
        self.setAutoFillBackground(True)

class StatusOnWidget(QtWidgets.QWidget):
    reconnect = QtCore.pyqtSignal()
    check_update = QtCore.pyqtSignal()

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

    def setupUi(self, Form):
        Form.setObjectName("Form")
        self.vLayoutStatus = QtWidgets.QVBoxLayout(Form)
        self.vLayoutStatus.setObjectName("vLayoutStatus")
        self.ipv4Label = QtWidgets.QLabel(Form)
        self.ipv4Label.setObjectName("ipv4Label")
        self.vLayoutStatus.addWidget(self.ipv4Label)
        self.ipv6Label = QtWidgets.QLabel(Form)
        self.ipv6Label.setObjectName("ipv6Label")
        self.vLayoutStatus.addWidget(self.ipv6Label)
        self.vLayoutStatus.addSpacing(10)
        if webengine_available == 1:
            self.webView = QtWebEngineWidgets.QWebEngineView(Form)
            self.webView.setUrl(QtCore.QUrl("about:blank"))
            self.webView.setObjectName("webView")
            self.webView.setMinimumSize(300,300)
            self.webView.setMaximumSize(16000, 16000)
            self.vLayoutStatus.addWidget(self.webView)
            self.hLayoutStatus = QtWidgets.QHBoxLayout()
            self.hLayoutStatus.setObjectName("hLayoutStatus")
            self.locButton = QtWidgets.QPushButton(Form)
            self.locButton.setObjectName("locButton")
            self.hLayoutStatus.addWidget(self.locButton)
            self.ipleakButton = QtWidgets.QPushButton(Form)
            self.ipleakButton.setObjectName("ipleakButton")
            self.hLayoutStatus.addWidget(self.ipleakButton)
            self.vLayoutStatus.addLayout(self.hLayoutStatus)
            self.vLayoutStatus.addSpacing(25)
            self.locButton.clicked.connect(self.show_location)
            self.ipleakButton.clicked.connect(self.show_ipleak)

        self.netHeader = QtWidgets.QLabel(Form)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.netHeader.setFont(font)
        self.netHeader.setObjectName("netHeader")
        self.netHeader.setVisible(False)
        self.vLayoutStatus.addWidget(self.netHeader)
        self.hLayoutStatus_2 = QtWidgets.QHBoxLayout()
        self.hLayoutStatus_2.setObjectName("hLayoutStatus_2")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.hLayoutStatus_2.addItem(spacerItem)
        font.setPointSize(9)
        font.setBold(False)
        self.intLabel = QtWidgets.QLabel(Form)
        self.intLabel.setObjectName("intLabel")
        self.intLabel.setFont(font)
        self.hLayoutStatus_2.addWidget(self.intLabel)
        self.timeLabel = QtWidgets.QLabel(Form)
        self.timeLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.timeLabel.setObjectName("timeLabel")
        self.timeLabel.setFont(font)
        self.hLayoutStatus_2.addWidget(self.timeLabel)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.hLayoutStatus_2.addItem(spacerItem1)
        self.vLayoutStatus.addLayout(self.hLayoutStatus_2)
        self.netGraph = plotter.PlotArea(Form)
        self.netGraph.setObjectName("netGraph")
        self.netGraph.setMinimumSize(100,100)
        self.vLayoutStatus.addWidget(self.netGraph)
        self.hLayoutStatus_3 = QtWidgets.QHBoxLayout()
        self.hLayoutStatus_3.setObjectName("hLayoutStatus_3")
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.hLayoutStatus_3.addItem(spacerItem2)
        self.downRect = ColoredRect(QtGui.QColor(255,127,42,255), parent=Form)
        self.hLayoutStatus_3.addWidget(self.downRect)
        self.downLabel = QtWidgets.QLabel(Form)
        self.downLabel.setObjectName("downLabel")
        self.downLabel.setFont(font)
        self.hLayoutStatus_3.addWidget(self.downLabel)
        self.upRect = ColoredRect(QtGui.QColor(44,162,216,255), parent=Form)
        self.hLayoutStatus_3.addWidget(self.upRect)
        self.upLabel = QtWidgets.QLabel(Form)
        self.upLabel.setObjectName("upLabel")
        self.upLabel.setFont(font)
        self.hLayoutStatus_3.addWidget(self.upLabel)
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.hLayoutStatus_3.addItem(spacerItem3)
        self.vLayoutStatus.addLayout(self.hLayoutStatus_3)
        self.vLayoutStatus.addSpacing(25)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.ipv4Label.setText(_translate("Form", "<b>External IPv4 address:</b> "))
        self.ipv6Label.setText(_translate("Form", "<b>External IPv6 address:</b> "))
        self.netHeader.setText(_translate("Form", "Network statistics"))
        self.intLabel.setText(_translate("Form", "<b>Network Inferface:</b> "))
        self.timeLabel.setText(_translate("Form", "<b>Uptime:</b> "))
        self.downLabel.setText(_translate("Form", "<b>Download:</b>"))
        self.upLabel.setText(_translate("Form", "<b>Upload:</b>"))

        if webengine_available == 1:
            self.locButton.setText(_translate("Form", "Location"))
            self.ipleakButton.setText(_translate("Form", "ipleak.net"))

    def monitor_conn(self, interface, server):
        self.server = server
        self.intLabel.setText("<b>Network Inferface:</b> {}".format(interface))
        self.calcThread = monitor.TunnelMon(interface, None, tun_hop=None)
        self.calcThread.time.connect(self.update_time)
        self.calcThread.stat.connect(self.update_chart)
        self.calcThread.ip.connect(self.show_ext_ip)
        self.calcThread.start()

    def show_ext_ip(self, ip_data):
        self.ip_data = ip_data
        self.ipv4Label.setText("<b>External IPv4 address:</b> {}".format(self.ip_data["ip4"]))
        self.ipv6Label.setText("<b>External IPv6 address:</b> {}".format(self.ip_data["ip6"]))

        if webengine_available == 1:
            if self.ip_data["lon"] == 0 and self.ip_data["lat"] == 0:
                self.show_location_failed()
            else:
                self.show_location()

        else:
            logging.error("Import Error: QtWebEngine is not available")

    def show_location(self):
        formatting = {"lat":self.ip_data["lat"], "lon":self.ip_data["lon"], "server":self.server}
        loc_html = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>Location</title>
            <link rel = "stylesheet" href = "https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"/>
            <script src = "https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
        </head>
        <body>
            <div id = "map" style = "width: 98w; height: 98vh"></div>
            <script>
                var lat = {lat}
                var lon = {lon}
                var mapOptions = {{
                    center: [lat, lon],
                    zoom: 6
                }}
                var map = new L.map('map', mapOptions);
                var marker = L.marker([lat, lon]).addTo(map);
                marker.bindPopup("<b>{server}</b><br>lat: {lat} lon: {lon}");
                var osmAttrib='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a>'
                var layer = new L.TileLayer(
                    'http://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', {{
                    attribution: osmAttrib,
                    maxZoom: 18
                    }});
                map.addLayer(layer);
            </script>
        </body>
        </html>
        """.format(**formatting)
        self.webView.setVisible(True)
        self.webView.setHtml(loc_html)

    def show_location_failed(self):
        loc_html = """
        <html>
        <body>
            <h1>Sorry, failed to determine location :(</h1>
        </body>
        </html>
        """
        self.webView.setVisible(True)
        self.webView.setHtml(loc_html)

    def show_ipleak(self):
        self.webView.setUrl(QtCore.QUrl("https://ipleak.net/#dnsdetection_title"))

    def reset_html(self):
        if webengine_available == 1:
            self.webView.setHtml(None)

    def update_time(self, t):
        self.timeLabel.setText("<b>Uptime:</b> {}".format(t))

    def update_chart(self, update):
        self.netGraph.addPoint(update[2], update[0])
        DLrate = round(update[0] / 128, 2)
        DLacc = update[1]
        ULrate = round(update[2] / 128, 2)
        ULacc = update[3]
        unit_acc_up = "Mb"
        unit_acc_down = "Mb"

        if DLacc / 1024 >= 1:
            DLacc = DLacc / 1024
            unit_acc_down = "Gb"

        if ULacc / 1024 >= 1:
            ULacc = ULacc / 1024
            unit_acc_up = "Gb"

        self.downLabel.setText("<b>Download:</b> {} {} - {} Mbps".format(round(DLacc, 2), unit_acc_down, DLrate))
        self.upLabel.setText("<b>Upload:</b> {} {} - {} Mbps".format(round(ULacc, 2), unit_acc_up, ULrate))

    def reconnect_signal(self):
        self.reconnect.emit()

    def check_for_update(self):
        self.check_update.emit()

class FirewallEditor(QtWidgets.QDialog):
    fw_change = QtCore.pyqtSignal(dict)
    options = [
            "block_lan",
            "preserve_rules",
            "fw_gui_only"
            ]

    def __init__ (self, settings, parent=None):
        super(FirewallEditor, self).__init__(parent)
        try:
            with open('{}/firewall.json'.format(config.ROOTDIR), 'r') as fload:
                self.firewall_dict = json.load(fload)
        except FileNotFoundError:
            with open('{}/firewall_default.json'.format(config.ROOTDIR), 'r') as fload:
                self.firewall_dict = json.load(fload)

        self.config_dict = settings
        self.setupUi(self)
        self.display_rules()

    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(600, 700)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.headerLabel = QtWidgets.QLabel(Form)
        bold_font = QtGui.QFont()
        bold_font.setPointSize(12)
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.headerLabel.setFont(bold_font)
        self.headerLabel.setObjectName(_fromUtf8("headerLabel"))
        self.verticalLayout.addWidget(self.headerLabel)
        self.block_lan_check = QtWidgets.QCheckBox()
        self.block_lan_check.setObjectName(_fromUtf8("headerLabel"))
        self.verticalLayout.addWidget(self.block_lan_check)
        self.fw_gui_only_check = QtWidgets.QCheckBox()
        self.fw_gui_only_check.setObjectName(_fromUtf8("headerLabel"))
        self.verticalLayout.addWidget(self.fw_gui_only_check)
        self.preserve_rules_check = QtWidgets.QCheckBox()
        self.preserve_rules_check.setObjectName(_fromUtf8("headerLabel"))
        self.verticalLayout.addWidget(self.preserve_rules_check)
        self.warnLabel = QtWidgets.QLabel(Form)
        self.warnLabel.setObjectName(_fromUtf8("warnLabel"))
        self.verticalLayout.addWidget(self.warnLabel)
        self.line = QtWidgets.QFrame(Form)
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName(_fromUtf8("line"))
        self.verticalLayout.addWidget(self.line)
        self.ipv4Label = QtWidgets.QLabel(Form)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.ipv4Label.setFont(bold_font)
        self.ipv4Label.setObjectName(_fromUtf8("ipv4_on_lbl"))
        self.verticalLayout.addWidget(self.ipv4Label)
        self.ipv4Edit = QtWidgets.QPlainTextEdit(Form)
        self.ipv4Edit.setObjectName(_fromUtf8("ipv4_on_edit"))
        self.verticalLayout.addWidget(self.ipv4Edit)
        self.ipv6Label = QtWidgets.QLabel(Form)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.ipv6Label.setFont(bold_font)
        self.ipv6Label.setObjectName(_fromUtf8("ipv6_on_lbl_2"))
        self.verticalLayout.addWidget(self.ipv6Label)
        self.ipv6Edit = QtWidgets.QPlainTextEdit(Form)
        self.ipv6Edit.setObjectName(_fromUtf8("ipv6_on_edit"))
        self.verticalLayout.addWidget(self.ipv6Edit)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.horizontalLayout.addStretch()
        self.restoreButton = QtWidgets.QPushButton(Form)
        self.restoreButton.setObjectName(_fromUtf8("saveButton"))
        self.horizontalLayout.addWidget(self.restoreButton)
        self.saveButton = QtWidgets.QPushButton(Form)
        self.saveButton.setObjectName(_fromUtf8("saveButton"))
        self.horizontalLayout.addWidget(self.saveButton)
        self.cancelButton = QtWidgets.QPushButton(Form)
        self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
        self.horizontalLayout.addWidget(self.cancelButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.retranslateUi(Form)
        self.set_options()
        QtCore.QMetaObject.connectSlotsByName(Form)
        self.cancelButton.clicked.connect(self.cancel)
        self.saveButton.clicked.connect(self.save_rules)
        self.restoreButton.clicked.connect(self.restore)

    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Edit firewall", None))
        self.headerLabel.setText(_translate("Form", "Configure firewall", None))
        self.warnLabel.setText(_translate("Form", "Warning: Only for advanced users ", None))
        self.block_lan_check.setText(_translate("Form", "Block lan/private networks", None))
        self.fw_gui_only_check.setText(_translate("Form", "Activate firewall only when gui is running", None))
        self.preserve_rules_check.setText(_translate("Form", "Preserve pre-existing firewall rules", None))
        self.ipv4Label.setText(_translate("Form", "IPv4 rules", None))
        self.ipv6Label.setText(_translate("Form", "IPv6 rules", None))
        self.saveButton.setText(_translate("Form", "Save", None))
        self.saveButton.setIcon(QtGui.QIcon.fromTheme("dialog-ok"))
        self.cancelButton.setText(_translate("Form", "Cancel", None))
        self.cancelButton.setIcon(QtGui.QIcon.fromTheme("dialog-no"))
        self.restoreButton.setText(_translate("Form", "Restore defaults", None))
        self.restoreButton.setIcon(QtGui.QIcon.fromTheme("view-refresh"))

    def set_options(self):
        for option in self.options:
            try:
                if self.config_dict[option] == 1:
                    getattr(self, "{}_check".format(option)).setCheckState(2)
                else:
                    getattr(self, "{}_check".format(option)).setCheckState(0)

            except KeyError:
                getattr(self, "{}_check".format(option)).setCheckState(0)

    def display_rules(self):
        for rule in self.firewall_dict["ipv4rules"]:
            self.ipv4Edit.appendPlainText(' '.join(rule))

        for rule in self.firewall_dict["ipv6rules"]:
            self.ipv6Edit.appendPlainText(' '.join(rule))

    def restore(self):
        self.ipv4Edit.clear()
        self.ipv6Edit.clear()

        with open('{}/firewall_default.json'.format(config.ROOTDIR), 'r') as fload:
            self.firewall_dict = json.load(fload)

        self.display_rules()

    def save_rules(self):
        new_ipv4_rules = []
        new_ipv6_rules = []

        for line in self.ipv4Edit.toPlainText().split("\n"):
                new_ipv4_rules.append(shlex.split(line))

        for line in self.ipv6Edit.toPlainText().split("\n"):
                new_ipv6_rules.append(shlex.split(line))

        self.firewall_dict["ipv4rules"] = new_ipv4_rules
        self.firewall_dict["ipv6rules"] = new_ipv6_rules

        with open ("{}/firewall_temp.json".format(config.HOMEDIR), "w") as firedump:
                json.dump(self.firewall_dict, firedump)

        for option in self.options:
            if getattr(self, "{}_check".format(option)).checkState() == 2:
                self.config_dict[option] = 1
            else:
                self.config_dict[option] = 0

        self.hide()
        self.fw_change.emit(self.config_dict)

    def cancel(self):
        self.hide()

class AppSelector(QtWidgets.QDialog):
    app_chosen = QtCore.pyqtSignal(tuple)

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

    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(600, 700)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.installedLabel = QtWidgets.QLabel(Form)
        self.verticalLayout.addWidget(self.installedLabel)
        self.appListWidget = QtWidgets.QListWidget(Form)
        self.verticalLayout.addWidget(self.appListWidget)
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Choose an application", None))
        self.installedLabel.setText(_translate("Form",
                                               "Applications installed on your system:",
                                               None
                                               ))

    def get_desktop_files(self):
        self.bypassAppList = []
        directories = ["{}/.local/share/applications".format(os.path.expanduser("~")),
                       "/usr/share/applications",
                       "/usr/local/share/applications"
                       ]

        for d in directories:
            try:
                for f in os.listdir(d):
                    if f.endswith(".desktop"):
                        desktop_file = os.path.join(d, f)
                        c = configparser.ConfigParser()
                        c.read(desktop_file)

                        try:

                            if c["Desktop Entry"]["NoDisplay"] == "true":
                                pass

                            else:
                                name = c["Desktop Entry"]["Name"]
                                icon = c["Desktop Entry"]["Icon"]
                                logging.debug("Adding {} to bypass app list".format(name))
                                self.bypassAppList.append((name, icon, desktop_file))

                        except KeyError:
                            name = c["Desktop Entry"]["Name"]
                            icon = c["Desktop Entry"]["Icon"]
                            logging.debug("Adding {} to bypass app list".format(name))
                            self.bypassAppList.append((name, icon, desktop_file))
            except Exception as e:
                logging.error(e)
                logging.error("Failed to add {} to bypass app list".format(name))

        self.bypassAppList = sorted(self.bypassAppList)
        self.pop_AppList()

    def pop_AppList(self):
        self.appListWidget.clear()
        for entry in self.bypassAppList:
            item = QtWidgets.QListWidgetItem()
            self.appListWidget.addItem(item)
            item.setText(entry[0])
            item.setIcon(QtGui.QIcon.fromTheme(entry[1]))
        self.appListWidget.itemClicked.connect(self.chosen)

    def chosen(self):
        self.app_chosen.emit(self.bypassAppList[self.appListWidget.currentRow()])
        self.hide()

class ModifyServer(QtWidgets.QDialog):
    modified = QtCore.pyqtSignal(dict)

    def __init__ (self, key=None, server_info=None, parent=None):
        super(ModifyServer, self).__init__(parent)
        self.key = key
        self.server_info = server_info
        self.config_change = 0
        self.provider = self.server_info["provider"]
        self.setupUi(self)
        self.load_config_file()

    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(419, 480)
        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
        self.verticalLayout.setObjectName("verticalLayout")
        self.nameLabel = QtWidgets.QLabel(Dialog)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.nameLabel.setFont(bold_font)
        self.nameLabel.setObjectName("nameLabel")
        self.verticalLayout.addWidget(self.nameLabel)
        self.nameEdit = QtWidgets.QLineEdit(Dialog)
        self.nameEdit.setObjectName("nameEdit")
        self.verticalLayout.addWidget(self.nameEdit)
        self.iconLabel = QtWidgets.QLabel(Dialog)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.iconLabel.setFont(bold_font)
        self.iconLabel.setObjectName("iconLabel")
        self.verticalLayout.addWidget(self.iconLabel)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.countryEdit = QtWidgets.QLineEdit(Dialog)
        self.countryEdit.setObjectName("countryEdit")
        self.horizontalLayout.addWidget(self.countryEdit)
        self.countryHintLabel = QtWidgets.QLabel(Dialog)
        self.countryHintLabel.setObjectName("countryHintLabel")
        self.horizontalLayout.addWidget(self.countryHintLabel)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.line = QtWidgets.QFrame(Dialog)
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.verticalLayout.addWidget(self.line)
        self.configLabel = QtWidgets.QLabel(Dialog)
        bold_font = QtGui.QFont()
        bold_font.setBold(True)
        bold_font.setWeight(75)
        self.configLabel.setFont(bold_font)
        self.configLabel.setObjectName("configLabel")
        self.verticalLayout.addWidget(self.configLabel)
        self.changeAllBox = QtWidgets.QCheckBox(Dialog)
        self.changeAllBox.setCheckable(True)
        self.changeAllBox.setChecked(True)
        self.changeAllBox.setObjectName("changeAllBox")
        self.verticalLayout.addWidget(self.changeAllBox)
        self.configBrowser = QtWidgets.QTextEdit(Dialog)
        self.configBrowser.setObjectName("configBrowser")
        self.verticalLayout.addWidget(self.configBrowser)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.retranslateUi(Dialog)
        self.changeAllBox.toggled.connect(self.block_option)
        self.buttonBox.accepted.connect(self.accept_change)
        self.buttonBox.rejected.connect(self.reject_change)
        self.configBrowser.textChanged.connect(self.config_changed)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Edit server"))
        self.nameLabel.setText(_translate("Dialog", "Name:"))
        self.nameEdit.setText(self.server_info["name"])
        self.iconLabel.setText(_translate("Dialog", "Country:"))
        self.countryHintLabel.setText(_translate("Dialog", "Preferably use country codes\n"
                                                 "Example: US for United States"))
        self.countryEdit.setText(self.server_info["country"])
        self.configLabel.setText(_translate("Dialog", "Edit Configuration File:"))
        self.changeAllBox.setText(_translate("Dialog",
                                             "Apply changes to all configuration files of {}".format(self.provider)))

    def block_option(self, state):
        if self.provider in config.SUPPORTED_PROVIDERS and state is False:
            self.changeAllBox.setChecked(True)

    def load_config_file(self):
        try:
            if self.server_info["tunnel"] == "WireGuard":
                self.configBrowser.setVisible(False)
                self.configLabel.setVisible(False)
                self.changeAllBox.setVisible(False)
                self.resize(419, 150)

            else:
                self.display_config()

        except KeyError:
            self.display_config()

    def display_config(self):
        if self.provider in config.SUPPORTED_PROVIDERS:
            conf = "{}/{}/openvpn.conf".format(config.ROOTDIR, self.provider)

        else:
            conf = "{}/{}".format(config.ROOTDIR, self.server_info["path"])

        splt = os.path.splitext(conf)
        mod = "{}_MOD.{}".format(splt[0], splt[1])
        if os.path.exists(mod):
            conf = mod

        with open (conf, "r") as config_edit:
            self.old_config = config_edit.readlines()
            for line in self.old_config:
                self.configBrowser.append(line.split("\n")[0])

    def config_changed(self):
        self.config_change = 1

    def reject_change(self):
        self.hide()

    def accept_change(self):
        change_all = 0
        self.server_info["name"] = self.nameEdit.text()
        country_change = self.countryEdit.text()

        if len(country_change) == 2:
            country = update.country_translate(country_change)
            if country == "Unknown":
                country = country_change

        else:
            country = country_change

        self.server_info["country"] = country

        if self.config_change == 1:
            new_config = []
            remote_index = 0
            new_config = self.configBrowser.toPlainText().split("\n")
            for index, line in enumerate(new_config):

                if line.startswith("remote "):
                    remote_index = index

                line_format = "{}\n".format(line)
                new_config[index] = line_format
            if new_config != self.old_config:

                if self.provider in config.SUPPORTED_PROVIDERS:
                    temp_file = "{}_config".format(self.provider)

                else:
                    temp_file = self.server_info["path"].split("/")[1]

                temp_folder = "{}/temp".format(config.HOMEDIR)

                if not os.path.exists(temp_folder):
                    os.makedirs(temp_folder)

                with open("{}/{}".format(temp_folder, temp_file), "w") as update_config:
                    update_config.writelines(new_config)

        else:
            remote_index = 0
            new_config = []

        if self.changeAllBox.isChecked() == True:
            change_all = 1

        change_dict = {"info_update" : self.server_info, "key" : self.key,
                       "config_change" : new_config,
                       "index" : remote_index, "apply_all" : change_all
                       }

        self.modified.emit(change_dict)
        self.hide()


"""
Under development, this file has no usage yet, please don't even try to use it.
"""

from aioredis import Redis
from fastapi import APIRouter

router = APIRouter()

class API:
    """
    A helper class for interacting with redis and moderating users.
    This does NOT work yet, it's under development.
    """

    def __init__(self):
        self.debug = False
        self.redis = Redis(host="redis", port=6379, decode_responses=True)

        self.req = str | None  # ip address to ban

    async def ban_user(self, duration: int = 120):
        """Bans a user from using the API temporally, by default using 120 seconds."""
        self.redis.set(self.req, "banned", duration)

    async def unban_user(self):
        """When user gets unbanned they will have access to the API again."""
        self.redis.delete(self.req)

    async def key_exists(self, key: str) -> bool:
        """
        Check if the given key exists in the redis database.
        :param key: The key to be used in the
        redis database.
        :return: boolean.
        """
        exists = await self.redis.exists(key)
        return exists

banned = {}

@router.post("/ban/{ip}")
async def ban_user(ip: str):
    """Ban a user from using the API."""
    if ip not in banned:
        banned[ip] = True
        return {"message": f"User with IP {ip} banned."}

@router.delete("/unban/{ip}")
async def unban_user(ip: str):
    """Unban a user from using the API."""
    if ip in banned:
        banned[ip] = False
        return {"message": f"User with IP {ip} unbanned."}
    else:
        return {"message": "IP not found"}

@router.get("/check/{ip}")
async def check_user(ip: str):
    """Check if a user is banned or not."""
    return {"message": banned.get(ip, False)}

@router.get("/list")
async def list_banned():
    """List all banned users."""
    return banned

@router.get("/clear")
async def clear_banned():
    """Clear all banned users."""
    banned.clear()
    return {"message": "Cleared."}


import os
import click
import json
import time
import glob

import numpy as np
import torchvision.transforms as T

from .utils import rotate_page
from .consts import MODEL_VERSION, MODEL_CONFIGS
from .utils import (
    set_logger,
    data_dir,
    load_model_params,
    imsave,
    read_img,
    pil_to_numpy,
    plot_for_debugging,
)
from .datasets import StdDataModule
from .trainer import PlTrainer, resave_model
from .model import gen_model
from . import CnStd

_CONTEXT_SETTINGS = {"help_option_names": ['-h', '--help']}

logger = set_logger(log_level='INFO')
DEFAULT_MODEL_NAME = 'db_shufflenet_v2_small'

@click.group(context_settings=_CONTEXT_SETTINGS)
def cli():
    pass

@cli.command('train')
@click.option(
    '-m',
    '--model-name',
    type=click.Choice(MODEL_CONFIGS.keys()),
    default=DEFAULT_MODEL_NAME,
    help='模型名称。默认值为 %s' % DEFAULT_MODEL_NAME,
)
@click.option(
    '-i',
    '--index-dir',
    type=str,
    required=True,
    help='索引文件所在的文件夹，会读取文件夹中的 train.tsv 和 dev.tsv 文件',
)
@click.option('--train-config-fp', type=str, required=True, help='训练使用的json配置文件')
@click.option(
    '-r', '--resume-from-checkpoint', type=str, default=None, help='恢复此前中断的训练状态，继续训练'
)
@click.option(
    '-p',
    '--pretrained-model-fp',
    type=str,
    default=None,
    help='导入的训练好的模型，作为初始模型。优先级低于"--restore-training-fp"，当传入"--restore-training-fp"时，此传入失效',
)
def train(
    model_name, index_dir, train_config_fp, resume_from_checkpoint, pretrained_model_fp
):
    """训练文本检测模型"""
    train_config = json.load(open(train_config_fp))
    fpn_type = train_config.get('fpn_type', 'fpn')
    kwargs = dict(
        rotated_bbox=train_config['rotated_bbox'],
        auto_rotate_whole_image=train_config.get('auto_rotate_whole_image', False),
        pretrained_backbone=True,
        fpn_type=fpn_type,
    )
    if 'db_shufflenet_v2' in model_name:
        kwargs['pretrained_backbone'] = False
    if 'resized_shape' in train_config:
        kwargs['input_shape'] = train_config['resized_shape']
    model = gen_model(model_name, **kwargs)
    logger.info(model)
    logger.info(model.cfg)
    expected_img_shape = model.cfg['input_shape']

    train_transform = T.Compose(  # MUST NOT include `Resize`
        [
            T.RandomInvert(p=0.1),
            T.RandomPosterize(bits=4, p=0.05),
            T.RandomAdjustSharpness(sharpness_factor=0.05, p=0.1),
            T.ColorJitter(brightness=0.05, contrast=0.05, saturation=0.05, hue=0.05),
            T.RandomEqualize(p=0.05),
            T.RandomApply([T.GaussianBlur(kernel_size=3)], p=0.05),
        ]
    )
    val_transform = None

    data_mod = StdDataModule(
        index_dir=index_dir,
        resized_shape=expected_img_shape[1:],
        preserve_aspect_ratio=train_config['preserve_aspect_ratio'],
        data_root_dir=train_config['data_root_dir'],
        train_transforms=train_transform,
        val_transforms=val_transform,
        batch_size=train_config['batch_size'],
        num_workers=train_config['num_workers'],
        pin_memory=train_config['pin_memory'],
        debug=train_config.get('debug', False),
    )

    # train_ds = data_mod.train
    # for i in range(100):
    #     visualize_example(train_ds[i], 'debugs/train-1-%d' % i)
    #     visualize_example(train_ds[i], 'debugs/train-2-%d' % i)
    #     visualize_example(train_ds[i], 'debugs/train-3-%d' % i)
    # val_ds = data_mod.val
    # for i in range(10):
    #     visualize_example(val_ds[i], 'debugs/val-1-%d' % i)
    #     visualize_example(val_ds[i], 'debugs/val-2-%d' % i)
    #     visualize_example(val_ds[i], 'debugs/val-2-%d' % i)
    # return

    trainer = PlTrainer(
        train_config, ckpt_fn=['cnstd', 'v%s' % MODEL_VERSION, model_name, fpn_type]
    )

    if pretrained_model_fp is not None:
        load_model_params(model, pretrained_model_fp)

    trainer.fit(
        model, datamodule=data_mod, resume_from_checkpoint=resume_from_checkpoint
    )

def visualize_example(example, fp_prefix):
    image = example['image']
    imsave(image, '%s-image.jpg' % fp_prefix, normalized=True)

    def _vis_bool(img, fp):
        img *= 255
        imsave(img, fp, normalized=False)

    _vis_bool(example['gt'].transpose(1, 2, 0), '%s-gt.jpg' % fp_prefix)
    _vis_bool(np.expand_dims(example['mask'], -1), '%s-mask.jpg' % fp_prefix)
    _vis_bool(
        np.expand_dims(example['thresh_map'], -1), '%s-thresh-map.jpg' % fp_prefix
    )
    _vis_bool(
        np.expand_dims(example['thresh_mask'], -1), '%s-thresh-mask.jpg' % fp_prefix
    )

@cli.command('predict')
@click.option(
    '-m',
    '--model-name',
    type=click.Choice(MODEL_CONFIGS.keys()),
    default=DEFAULT_MODEL_NAME,
    help='模型名称。默认值为 %s' % DEFAULT_MODEL_NAME,
)
@click.option(
    '-p',
    '--pretrained-model-fp',
    type=str,
    default=None,
    help='使用训练好的模型。默认为 `None`，表示使用系统自带的预训练模型',
)
@click.option(
    "-r", "--rotated-bbox", is_flag=True, help="是否检测带角度（非水平和垂直）的文本框。默认为 `True`"
)
@click.option(
    "--resized-shape",
    type=str,
    default='768,768',
    help='格式："height,width"; 预测时把图片resize到此大小再进行预测。两个值都需要是32的倍数。默认为 `768,768`',
)
@click.option(
    "--box-score-thresh", type=float, default=0.3, help="检测结果只保留分数大于此值的文本框。默认值为 `0.3`"
)
@click.option(
    "--preserve-aspect-ratio",
    type=bool,
    default=True,
    help="resize时是否保留图片原始比例。默认值为 `True`",
)
@click.option(
    "--context",
    help="使用cpu还是 `gpu` 运行代码，也可指定为特定gpu，如`cuda:0`。默认为 `cpu`",
    type=str,
    default='cpu',
)
@click.option("-i", "--img-file-or-dir", help="输入图片的文件路径或者指定的文件夹")
@click.option(
    "-o", "--output-dir", default='./predictions', help="检测结果存放的文件夹。默认为 `./predictions`"
)
def predict(
    model_name,
    pretrained_model_fp,
    rotated_bbox,
    resized_shape,
    box_score_thresh,
    preserve_aspect_ratio,
    context,
    img_file_or_dir,
    output_dir,
):
    """预测单个文件，或者指定目录下的所有图片"""
    std = CnStd(
        model_name,
        model_fp=pretrained_model_fp,
        rotated_bbox=rotated_bbox,
        context=context,
    )

    resized_shape = list(map(int, resized_shape.split(',')))  # [H, W]
    if len(resized_shape) == 1:
        resized_shape.append(resized_shape[0])

    # process image
    if os.path.isfile(img_file_or_dir):
        img_list = [img_file_or_dir]
    elif os.path.isdir(img_file_or_dir):
        fnames = glob.glob1(img_file_or_dir, "*g")
        img_list = [os.path.join(img_file_or_dir, fn) for fn in fnames]
    else:
        raise TypeError(
            'param "image_dir": %s is neither a file or a dir' % img_file_or_dir
        )

    start_time = time.time()
    std_out = std.detect(
        img_list,
        resized_shape=tuple(resized_shape),
        preserve_aspect_ratio=preserve_aspect_ratio,
        box_score_thresh=box_score_thresh,
    )
    time_cost = time.time() - start_time
    logger.info(
        '%d files are detected by cnstd, total time cost: %f, mean time cost: %f'
        % (len(img_list), time_cost, time_cost / len(img_list))
    )

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    for idx, img_fp in enumerate(img_list):
        angle = std_out[idx]['rotated_angle']
        pil_img = read_img(img_fp)
        img = pil_to_numpy(pil_img).transpose((1, 2, 0)).astype(np.uint8)
        rotated_img = np.ascontiguousarray(rotate_page(img, -angle))

        fname = os.path.basename(img_fp).rsplit('.', maxsplit=1)[0]
        prefix_fp = os.path.join(output_dir, fname)
        plot_for_debugging(
            rotated_img, std_out[idx]['detected_texts'], box_score_thresh, prefix_fp
        )

    try:
        from cnocr import CnOcr

        ocr = CnOcr()

        logger.info('use cnocr to predict texts from the FIRST image, as an example')
        cropped_img_list = [
            box_info['cropped_img'] for box_info in std_out[0]['detected_texts']
        ]
        start_time = time.time()
        ocr_out = ocr.ocr_for_single_lines(cropped_img_list, batch_size=1)
        time_cost = time.time() - start_time
        logger.info(
            '%d cropped text boxes are recognized by cnocr, total time cost: %f, mean time cost: %f'
            % (len(cropped_img_list), time_cost, time_cost / len(cropped_img_list))
        )
        logger.info('ocr result: %s' % str(ocr_out))
    except ModuleNotFoundError as e:
        logger.warning(e)

@cli.command('resave')
@click.option('-i', '--input-model-fp', type=str, required=True, help='输入的模型文件路径')
@click.option('-o', '--output-model-fp', type=str, required=True, help='输出的模型文件路径')
def resave_model_file(
    input_model_fp, output_model_fp,
):
    """训练好的模型会存储训练状态，使用此命令去掉预测时无关的数据，降低模型大小"""
    resave_model(input_model_fp, output_model_fp, map_location='cpu')

if __name__ == '__main__':
    cli()


#Write your function here
def exponents(bases, powers):
  answer = []
  for base in bases:
    for power in powers:
      answer.append(base ** power)
  return answer

#Uncomment the line below when your function is done
print(exponents([2, 3, 4], [1, 2, 3]))


from collections import Counter
import sys
input = sys.stdin.readline

n,m=map(int,input().split())

arr=[input().rstrip() for _ in range(n)]

s=""
for col in range(m):
    t=[]
    for row in range(n):
        t.append(arr[row][col])
    a=sorted(Counter(t).items(),key=lambda x:(-x[1],x[0]))
    s+=a[0][0]

total=0
for i in arr:
    cnt=0
    for ind,j in enumerate(i):
        if j!=s[ind]:
            cnt+=1
    total+=cnt
print(s)
print(total)


import copy
import struct
from typing import Tuple, Any

from .base import Header, Protocol, DataObject, NotSupportedError

"""

References:
    https://tools.ietf.org/html/rfc1035
"""
_FMT_DNS_FIXED_HDR = '>HHHHHH'
_STRUCT_DNS_FIXED_HDR = struct.Struct(_FMT_DNS_FIXED_HDR)
_QR_MAP = {0: 'query', 1: 'response'}
_OPCODE_MAP = {
    0: 'QUERY',
    1: 'IQUERY',
    2: 'STATUS'
}

_RCODE_MAP = {
    0: 'No error condition',
    1: 'Format error',
    2: 'Server failure',
    3: 'Name error',
    4: 'Not Implemented',
    5: 'Refused'
}

_Q_TYPE_MAP = {
    1: 'A',
    2: 'NS',
    3: 'NS',
    4: 'MF',
    5: 'CNAME',
    6: 'SOA',
    7: 'MB',
    8: 'MG',
    9: 'MR',
    10: 'NULL',
    11: 'WKS',
    12: 'PTR',
    13: 'HINFO',
    14: 'MINFO',
    15: 'MX',
    16: 'TXT',
    28: 'AAAA',
    252: 'AXFR',
    253: 'MAILB',
    254: 'MALA',
    255: 'ANY'
}

_Q_CLASS_MAP = {
    1: 'IN',  # Internet
    2: 'CS',  # CSNET
    3: 'CH',  # CHAOS
    4: 'HS',  # Hesiod
    255: 'ANY'
}

def describe_q_type(typ: int):
    if typ in _Q_TYPE_MAP:
        return _Q_TYPE_MAP[typ]
    return f'Unknown {typ}'

def describe_q_class(kls: int):
    if kls in _Q_CLASS_MAP:
        return _Q_CLASS_MAP[kls]
    return f'Unknown {kls}'

class DNSHeader(Header):
    def __init__(self):
        self.identifier = 0
        self.qr = 0
        self.opcode = 0
        self.authoritative_answer = 0
        self.truncation = 0
        self.recursion_desired = 0
        self.recursion_available = 0
        self.z = 0
        self.response_code = 0
        self.question_count = 0
        self.answer_count = 0
        self.authority = 0
        self.additional_info = 0

    def describe(self) -> dict:
        dct = copy.copy(self.__dict__)
        dct['qr'] = _QR_MAP[self.qr]
        dct['opcode'] = _OPCODE_MAP.get(self.opcode, 'reserved')
        return dct

class DNSQuery(DataObject):

    def __init__(self):
        self.q_name = ''
        self.q_type = 0
        self.q_class = 0

    def describe(self) -> dict:
        return {

        }

class DNSResourceRecord(DataObject):

    def __init__(self):
        pass

    def describe(self) -> dict:
        pass

def _parse_domain_name(data: bytes):
    idx = 0
    domain_lst = []
    while True:
        length = data[idx]
        idx += 1
        if length == 0:
            break
        domain_lst.append(data[idx:idx + length].decode())
        idx += length
    return '.'.join(domain_lst), idx

class DNS(Protocol):

    def unpack_data(self, data: bytes) -> Tuple[Header, Any]:
        identifier, id2, question, answer, auth, addition = _STRUCT_DNS_FIXED_HDR.unpack(data[:12])
        hdr = DNSHeader()
        hdr.identifier = identifier
        hdr.response_code = id2 & 0xf
        id2 >>= 4
        hdr.z = id2 & 0x7
        id2 >>= 3
        hdr.recursion_available = id2 & 0x1
        id2 >>= 1
        hdr.recursion_desired = id2 & 0x1
        id2 >>= 1
        hdr.truncation = id2 & 0x1
        id2 >>= 1
        hdr.authoritative_answer = id2 & 0x1
        id2 >>= 1
        hdr.opcode = id2 & 0xf
        id2 >>= 4
        hdr.qr = id2 & 0x1
        hdr.question_count = question
        hdr.answer_count = answer
        hdr.authority = auth
        hdr.additional_info = addition
        raw_payload = data[12:]
        payload_list = []
        idx = 0
        for _ in range(hdr.question_count):
            qry = DNSQuery()
            name, length = _parse_domain_name(raw_payload)
            qry.q_name = name
            idx += length
            qry.q_type, qry.q_class = struct.unpack('>HH', raw_payload[idx:idx + 4])
            payload_list.append(qry)
            idx += 4

        for _ in range(hdr.answer_count):
            payload = DNSResourceRecord()
            if raw_payload[idx] >> 6 != 3:
                raise NotSupportedError(raw_payload[idx])
            offset, payload.r_type, payload.r_class, \
                payload.ttl, payload.rd_length = struct.unpack('>HHHIH', raw_payload[idx:idx + 12])
            offset &= 0x3fff
            name, _ = _parse_domain_name(data[offset:])
            idx += 12
            payload.name = name
            payload.r_data = raw_payload[idx:idx + payload.rd_length]
            idx += payload.rd_length
            payload_list.append(payload)
        return hdr, payload_list


import tensorflow as tf
import collections
import numpy as np

def index(tensor, index_tensor):
    one_hot_indices = tf.reshape(tf.one_hot(index_tensor, tf.shape(tensor)[1], 1., 0., axis=-1),
                                 [-1, tf.shape(tensor)[1], 1])
    return tf.squeeze(tf.batch_matmul(tf.reshape(tensor, [-1, 1, tf.shape(tensor)[1]]), one_hot_indices))

def nonzero_gradients(gradients):
    return [(tf.maximum(grad, 1e-10), var) for grad, var in gradients]

def mean_gradients(gradients):
    return [(sum([gradient[var_i][0] for gradient in gradients]) / num_sample_episodes, gradients[0][var_i][1])
            for var_i in range(len(gradients[0]))]

def gradient_op(grad1, grad2, op):
    return [(op(grad_element1, grad_element2), var1)
            for (grad_element1, var1), (grad_element2, var2) in zip(grad1, grad2)]

class GradientWrapper:
    def __init__(self, gradient):
        self._gradient = gradient

    def get(self):
        return self._gradient

    def nonzero(self):
        return GradientWrapper(nonzero_gradients(self._gradient))

    def __radd__(self, other):
        if other == 0:
            return self
        return other.__add__(self)

    def __add__(self, other):
        if type(other) is GradientWrapper:
            return GradientWrapper(gradient_op(self._gradient, other._gradient, lambda x, y: x + y))
        else:
            return GradientWrapper([(grad + other, var) for grad, var in self._gradient])

    def __rsub__(self, other):
        return other.__sub__(self)

    def __sub__(self, other):
        if type(other) is GradientWrapper:
            return GradientWrapper(gradient_op(self._gradient, other._gradient, lambda x, y: x - y))
        else:
            return GradientWrapper([(grad - other, var) for grad, var in self._gradient])

    def __mul__(self, other):
        if type(other) is GradientWrapper:
            return GradientWrapper(gradient_op(self._gradient, other._gradient, lambda x, y: x * y))
        else:
            return GradientWrapper([(grad * other, var) for grad, var in self._gradient])

    def __truediv__(self, other):
        if type(other) is GradientWrapper:
            return GradientWrapper(gradient_op(self._gradient, other._gradient, lambda x, y: x / y))
        else:
            return GradientWrapper([(grad / other, var) for grad, var in self._gradient])

class GradientVector:
    _VariableDescriptor = collections.namedtuple('_VariableDescriptor', ['range', 'var'])

    def __init__(self, gradient, batch=False):
        self._gradient = gradient
        self._batch = batch

        flattened_gradient = []
        self._descriptors = []
        current_index = 0
        for grad, var in gradient:
            if grad is not None:
                dim = np.prod(var.get_shape()).value
                if batch:
                    flattened_gradient.append(tf.reshape(grad, shape=[-1, dim]))
                else:
                    flattened_gradient.append(tf.reshape(grad, shape=[-1]))
                self._descriptors.append(self._VariableDescriptor((current_index, current_index + dim), var))
                current_index += dim

        self.flattened_gradient = tf.concat(0, flattened_gradient)

    @property
    def reshaped_gradient(self):
        gradient = []
        for variable_descriptor in self._descriptors:
            if self._batch:
                variable_gradient = self.flattened_gradient[:, variable_descriptor.range[0]:variable_descriptor.range[1]]
                variable_gradient = tf.reshape(variable_gradient, shape=[None] + variable_descriptor.var.get_shape())
            else:
                variable_gradient = self.flattened_gradient[variable_descriptor.range[0]:variable_descriptor.range[1]]
                variable_gradient = tf.reshape(variable_gradient, shape=variable_descriptor.var.get_shape())
            gradient.append((variable_gradient, variable_descriptor.var))
        return gradient

    def new(self, flat_gradient, batch):
        batch = self._batch if batch is None else batch
        new_gradient = type(self).__new__(type(self))
        new_gradient.flattened_gradient = flat_gradient
        new_gradient._descriptors = self._descriptors
        new_gradient._batch = batch
        return new_gradient

def scope_collection(scope='', collection=tf.GraphKeys.TRAINABLE_VARIABLES):
    return tf.get_collection(collection, tf.get_variable_scope().name + "/?" + scope)

def copy_parameters(source_scope, target_scope):
    ops = []
    parent_scope = tf.get_variable_scope().name
    parent_scope_name_length = len(parent_scope) + 1
    if parent_scope_name_length == 1:
        parent_scope_name_length = 0
    for variable in scope_collection(source_scope):
        with tf.variable_op_scope([], target_scope, reuse=True):
            ops.append(tf.get_variable(variable.name[parent_scope_name_length + len(source_scope) + 1:].
                                       split(':', 1)[0]).assign(variable))
    return ops

def vector_gradient(f, inputs, max_dim, optimizer):
    inputs = [tf.reshape(input, [-1, 1]) if len(input.get_shape()) == 1 else input for input in inputs ]
    input_padded = [tf.pad(input, [[0, max_dim-tf.shape(input)[0]], [0, 0]]) for input in inputs]
    y = f(*input_padded)
    grad = []
    for i in range(max_dim):
        grad.append(optimizer.compute_gradients(tf.gather(tf.reshape(y, [max_dim, -1]), i)))

    return [(None if grad_0 is None else tf.gather(tf.pack([grad[j][i][0] for j in range(max_dim)]), tf.range(tf.shape(inputs[0])[0])), var) for i, (grad_0, var) in enumerate(grad[0])]

def least_squares(X, y, method='svd', regularize=0):
    if method == 'matrix_solve':
        XTX = tf.matmul(tf.transpose(X), X) + tf.diag(regularize * tf.ones([tf.shape(X)[1]]))
        XTy = tf.matmul(tf.transpose(X), tf.reshape(y, shape=[-1, 1]))
        return tf.matrix_solve(XTX, XTy)
    elif method == 'svd':
        assert regularize == 0
        s, u, v = tf.svd(X)
        s_inv = 1/s
        return tf.matmul(tf.matmul(tf.matmul(v, tf.diag(s_inv), transpose_a=True), u, transpose_b=True),
                         tf.reshape(y, shape=[-1, 1]))
    else:
        assert False

def var_name(var):
    return var.name.split('/')[-1].split(':')[0]

def test_parameter_vector_descriptor():
    from examples.lander.networks import build_policy_network
    import debug
    sess = tf.InteractiveSession()
    state = tf.placeholder(tf.float32, shape=[None, 4])
    network = build_policy_network(state)
    optimizer = tf.train.GradientDescentOptimizer(0.1)
    gradient = optimizer.compute_gradients(tf.log(network))
    wrapper = GradientVector(gradient)
    wrapper.flattened_gradient *= 2
    op = debug.print_gradient(tf.no_op(), gradient)
    op = debug.print_gradient(op, wrapper.reshaped_gradient)
    tf.initialize_all_variables().run()
    op.run(feed_dict={state: [[4, 3, 1, 2]]})

def test_least_squares():
    sess = tf.InteractiveSession()
    X = tf.placeholder(tf.float32, shape=[None, 1])
    y = tf.placeholder(tf.float32, shape=[None])
    tf.initialize_all_variables().run()
    for method in ['matrix_solve', 'svd']:
        p = least_squares(X, y, method=method)
        print(p.eval(feed_dict={X: [[1], [3], [5]], y: [4.02, 11.95, 19.98]}))

if __name__ == '__main__':
    test_least_squares()
    # test_parameter_vector_descriptor()


from app.node import Node
from app.core.config import settings

from .tasks.create_replications import associate_nodes_to_replication
from .tasks.calculate_distribution import validate_alive_nodes_number, split_capacity

class Initialization:

    def __init__(self):
        pass

    def _nodes_registry(self):
        return [
            Node(node_host)
            for node_host in settings.LIST_OF_NODE_HOSTS
        ]

    def run(self):
        nodes = self._nodes_registry()
        valid_nodes = validate_alive_nodes_number(nodes)
        split_capacity(**valid_nodes)
        associate_nodes_to_replication(valid_nodes["available_nodes"])
        for node in valid_nodes["available_nodes"]:
            print(f"{node.host} -> {node.replication_node.host}")
        return nodes


import os
import threading
from PIL import Image, UnidentifiedImageError

num_done = 0  # number of pics converted
pics_to_do = 0  # total number of pics to do

def resize_image(image_name):
    global num_done
    global pics_to_do
    try:
        # Original Image
        im = Image.open(image_name)
        width, height = im.size

        # New Image
        newim = Image.new(im.mode, (max(width, height), max(width, height)), (255, 255, 255, 0))
        new_width, new_height = newim.size

        # combine
        coords_to_paste = (int((new_width - width) / 2), 0)
        newim.paste(im, coords_to_paste)

        new_name = image_name[:image_name.find('.')] + "_square.png"
        newim.save('converted/' + new_name, 'PNG')

        # notify user and update num_done
        num_done += 1
        print(str(num_done) + '/' + str(pics_to_do) + ' completed')
    except PermissionError:
        print('ERROR: Missing Permissions for image "' + image_name + '"')
        # update pics_to_do
        pics_to_do -= 1
    except UnidentifiedImageError:
        print('ERROR: Not a valid image: "' + image_name + '"')
        # update pics_to_do
        pics_to_do -= 1

# May add filters if required
def get_images():
    return os.listdir()

def main():
    print('Creating converted folder')
    try:
        os.mkdir('converted')
    except FileExistsError:
        pass

    print('Files Found:')
    images = [i for i in get_images() if i not in ['convert.exe', 'converted']]
    print(images)
    global pics_to_do
    pics_to_do = len(images)

    print('Start Converting Images')
    # Init threads
    threads = []
    for image in images:
        t = threading.Thread(target=resize_image, args=(image,))
        threads.append(t)
        t.start()

    # wait for threads to close
    for t in threads:
        t.join()

    input("Done. Press Enter to exit")

if __name__ == '__main__':
    main()


import requests
import sys
import io
from lxml import etree
import os

def build_new_field(new_field_path):
    #     # 创建文件夹
    isExists = os.path.exists(new_field_path)
    # 判断结果
    if not isExists:
        # 如果不存在则创建目录
        # 创建目录操作函数
        os.makedirs(new_field_path)
        print(new_field_path + ' 创建成功')
    else:
        # 如果目录存在则不创建，并提示目录已存在
            print(new_field_path + ' 目录已存在')

# 目标网址
url = 'http://m.umei.cc/tags/'

# 请求头
headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'Cookie': 'Hm_lvt_19d597dda6fff717a20d276fa907bd17=1579874963,1579962492; Hm_lpvt_19d597dda6fff717a20d276fa907bd17=1579964664',
    'Host': 'm.umei.cc',

    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4021.2 Safari/537.36',
}

while True:
    # 得到网页数据
    response = requests.get(url, headers=headers).content.decode('utf-8')
    # 用lxml进行提取数据
    html = etree.HTML(response)
    lis = html.xpath('/html/body/div[4]/div/a')
    url_head = 'http://m.umei.cc/'
    field_path = 'd:\\data'  # 要保存文件夹位置
    for li in lis:
        href = li.get('href')
        title = li.get('title')
        # print(href,title)
        spelling_url = url_head + href  # 拼写网址头+爬取href等于完整网址
        # print(spelling_url)
        response1 = requests.get(url=spelling_url, headers=headers).content.decode('utf-8')
        html1 = etree.HTML(response1)
        lis1 = html1.xpath('/html/body/div[8]/ul/li/a')
        for li1 in lis1:
            href1 = li1.get('href')  # 爬取图片组网址
            alt = li1.xpath('./img')[0].get('alt')  # 爬取图片组标题
            src = li1.xpath('./img')[0].get('lazysrc')  # 爬取图片封面地址
            # print(alt, href1, src, "提取成功！")
            all_path = field_path + '\\' + alt  # 绝对地址+爬取alt（标题）
            build_new_field(new_field_path=all_path)
            # 打开已经新建文件夹并新建文件
            All_path = all_path + '\\'
            # print(All_path)
            # img = requests.get(url=src,headers=headers).content
            # with open(f'{All_path}封面.jpg', 'wb')as f:
            #   f.write(img)
            #  print("下载着……\t", alt, "\t下载成功!!!")
            for j in range(1,20):
                url1 = href1
                if j > 1:
                    url1 = url1[:-4] + '_' + str(j)+'.htm'
                print(url1)
                response2 = requests.get(url=url1).content.decode('utf-8')
                html = etree.HTML(response2)
                lis2 = html.xpath('//*[@id="ArticleBox"]/p/a/img')

                for li2 in lis2:
                    src1 = li2.get('src')  # 图片组里面的某一个网址
                    print(alt,j,src1)
                    img = requests.get(url=src1)
                    if img.status_code == 200:
                        with open(f'{All_path}{str(j)}.jpg', 'wb')as f:
                            f.write(img.content)
                            print(f"第{str(j)}张标题为{alt}的图片", "下载成功!!!")
                    else:
                        with open(f'{field_path}\\日志.txt', 'a+')as f:
                            f.writelines(f"错误记录：{j}, {alt}, {url1}, {src1}")
                            print(src1, "此网址不存在!!!")


#!/usr/bin/python

from __future__ import print_function

#import paho.mqtt.client as paho

import board
import neopixel
import time
import random
import Adafruit_DHT
from relay_lib_seeed import *
import datetime

import schedule
import os

broker = "broker.hivemq.com"
port = 1883

LED_NO = 120
pixels = neopixel.NeoPixel(board.D21, LED_NO)
DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 8

start_pump1 = datetime.time(8, 2, 0)
end_pump1 = datetime.time(8, 3, 0)
start_pump2 = datetime.time(18, 0, 0)
end_pump2 = datetime.time(18, 1, 0)

start_off_led = datetime.time(0, 0, 0)
end_off_led = datetime.time(3, 0 ,0)

def mqtt_init():
    client1 = paho.Client("vert_farm_control")
    client1.on_publish = on_publish
    client1.connect(broker, port)
    ret = client1.publish("vert_farm/kzaman", "on")

def take_picture():
    os.system('fswebcam -r 1280x720 -S 3 --jpeg 50 --save /home/pi/vert_farm/cam/%Y-%m-%d_%H%M%S.jpg')

def get_humid_temp():
    humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
    if humidity is not None and temperature is not None:
        print("Temp={0:0.1f}*C Humidity={1:0.1f}%".format(temperature, humidity))
    else:
        print("Failed to retrieve data from humidity sensor")
        return None, None
    return humidity, temperature

def on_led():
    print("Led is on")
    for i in range(LED_NO):
        pixels[i] = (255, 255, 255)

def off_led():
    print("Led is off")
    for i in range(LED_NO):
        pixels[i] = (0, 0, 0)

def on_relay(relay_no):
    relay_on(relay_no)

def off_relay(relay_no):
    relay_off(relay_no)

def time_in_range(start, end, x):
    if start <= end:
        return start <= x <= end
    else:
        return start <= x or x <= end
def on_publish(clent, userdata,result):
    pass

def process_loop():
    schedule.run_pending()
    current_time = datetime.datetime.now().time()

    get_humid_temp()

    if (time_in_range(start_off_led, end_off_led, current_time)):
        off_led()
    else:
        on_led()

    if time_in_range(start_pump1, end_pump1, current_time) or time_in_range(start_pump2, end_pump2, current_time):
        on_relay(1)
    else:
        off_relay(1)

    time.sleep(60)

if __name__ == "__main__":
    schedule.every(3).hours.do(take_picture)
    while True:
        try:
            process_loop()
        except KeyboardInterrupt:
            print("Exiting application")
            relay_all_off()
            off_led()
            sys.exit(0)


import os

# List of file extensions to exclude (adjust as needed)
exclude_extensions = ["txt", "md"]

# Get the current working directory
current_directory = os.getcwd()

# Iterate through the files in the directory
for filename in os.listdir(current_directory):
    if os.path.isfile(filename):
        # Get the file extension
        file_extension = filename.split(".")[-1]

        # Check if the extension is in the exclude list
        if file_extension in exclude_extensions:
            print(f"Excluding file: {filename}")
        else:
            # Make the file executable
            os.chmod(filename, os.stat(filename).st_mode | 0o111)
            print(f"Made executable: {filename}")


#! python3
from socket import socket
from threading import Thread
from secure import Secure
from Crypto.Cipher import PKCS1_OAEP

HOST = "localhost"
PORT = 9999

class Client():
    def __init__(self, listenCallback):
        self.listenCallback = listenCallback
        self.s = socket()
        self.s.connect((HOST, PORT))
        self.secure = Secure()
        self.serverKey = None
        Thread(target=self.listen, daemon=True).start()

    def listen(self):
        while True:
            data = self.s.recv(4096)
            if data.startswith(b">>>"):
                print("Received server key")
                self.serverKey = self.secure.fromDer(data[3:])
                self.serverCipher = PKCS1_OAEP.new(self.serverKey)
                self.s.send(b">>>" + self.secure.publicKey.exportKey("DER"))
                print("Sent own key")
            else:
                deciphered = self.secure.privateCipher.decrypt(data)
                if not deciphered.startswith(b">>"):
                    print("Invalid packet from server")
                    return
                deciphered = deciphered[2:]
                if deciphered == b"PING":
                    self.send(b"PONG")
                    print("PING -> PONG")
                else:
                    self.listenCallback(deciphered)
                    print(deciphered)

    def send(self, data):
        ciphered = self.serverCipher.encrypt(b">>" + data)
        self.s.send(ciphered)

if __name__ == "__main__":
    from main import run
    run()


#----------------------------------------------------
# This file is quoted from EPI-DLMH
#----------------------------------------------------
import itertools
import numpy as np
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences

def sentence2word(str_set):
    word_seq=[]
    for sr in str_set:
        tmp=[]
        for i in range(len(sr)-5):
            if('N' in sr[i:i+6]):
                tmp.append('null')
            else:
                tmp.append(sr[i:i+6])
        word_seq.append(' '.join(tmp))
    return word_seq

def word2num(wordseq,tokenizer,MAX_LEN):
    sequences = tokenizer.texts_to_sequences(wordseq)
    numseq = pad_sequences(sequences, maxlen=MAX_LEN)
    return numseq

def sentence2num(str_set,tokenizer,MAX_LEN):
    wordseq=sentence2word(str_set)
    numseq=word2num(wordseq,tokenizer,MAX_LEN)
    return numseq

def get_tokenizer():
    f= ['a','c','g','t']
    c = itertools.product(f,f,f,f,f,f)
    res=[]
    for i in c:
        temp=i[0]+i[1]+i[2]+i[3]+i[4]+i[5]
        res.append(temp)
    res=np.array(res)
    NB_WORDS = 4097
    tokenizer = Tokenizer(num_words=NB_WORDS)
    tokenizer.fit_on_texts(res)
    acgt_index = tokenizer.word_index
    acgt_index['null'] = 0
    return tokenizer

def get_data(enhancers,promoters):
    tokenizer=get_tokenizer()
    MAX_LEN=3000
    X_en=sentence2num(enhancers,tokenizer,MAX_LEN)
    MAX_LEN=2000
    X_pr=sentence2num(promoters,tokenizer,MAX_LEN)

    return X_en,X_pr

names = ['GM12878', 'HUVEC', 'HeLa-S3', 'IMR90', 'K562', 'NHEK','all']
name = names[4]
train_dir='./data2/%s/train/'%name
imbltrain='./data2/%s/imbltrain/'%name
test_dir='./data2/%s/test/'%name
Data_dir='./data2/%s/'%name

import os
os.makedirs(train_dir, exist_ok=True)
os.makedirs(imbltrain, exist_ok=True)
os.makedirs(test_dir, exist_ok=True)
os.makedirs(Data_dir, exist_ok=True)

print ('Experiment on %s dataset' % name)

print ('Loading seq data1...')
enhancers_tra=open(train_dir+'%s_enhancer.fasta'%name,'r').read().splitlines()[1::2]
promoters_tra=open(train_dir+'%s_promoter.fasta'%name,'r').read().splitlines()[1::2]
y_tra=np.loadtxt(train_dir+'%s_label.txt'%name)

im_enhancers_tra=open(imbltrain+'%s_enhancer.fasta'%name,'r').read().splitlines()[1::2]
im_promoters_tra=open(imbltrain+'%s_promoter.fasta'%name,'r').read().splitlines()[1::2]
y_imtra=np.loadtxt(imbltrain+'%s_label.txt'%name)

enhancers_tes=open(test_dir+'%s_enhancer_test.fasta'%name,'r').read().splitlines()[1::2]
promoters_tes=open(test_dir+'%s_promoter_test.fasta'%name,'r').read().splitlines()[1::2]
y_tes=np.loadtxt(test_dir+'%s_label_test.txt'%name)

print('balanced')
print('pos_samples:'+str(int(sum(y_tra))))
print('neg_samples:'+str(len(y_tra)-int(sum(y_tra))))
print('imblanced')
print('pos_samples:'+str(int(sum(y_imtra))))
print('neg_samples:'+str(len(y_imtra)-int(sum(y_imtra))))
print('test')
print('pos_samples:'+str(int(sum(y_tes))))
print('neg_samples:'+str(len(y_tes)-int(sum(y_tes))))

X_en_tra,X_pr_tra=get_data(enhancers_tra,promoters_tra)
X_en_imtra,X_pr_imtra=get_data(im_enhancers_tra,im_promoters_tra)
X_en_tes,X_pr_tes=get_data(enhancers_tes,promoters_tes)

np.savez(Data_dir+'%s_train.npz'%name,X_en_tra=X_en_tra,X_pr_tra=X_pr_tra,y_tra=y_tra)
np.savez(Data_dir+'im_%s_train.npz'%name,X_en_tra=X_en_imtra,X_pr_tra=X_pr_imtra,y_tra=y_imtra)
np.savez(Data_dir+'%s_test.npz'%name,X_en_tes=X_en_tes,X_pr_tes=X_pr_tes,y_tes=y_tes)


def part1(grid):
    width = len(grid)
    height = width # assume width == height

    visible_trees: list[tuple] = []

    # from left
    for x in range(0, height):
        highest = -1
        for y in range(0, width):
            if grid[x][y] > highest:
                visible_trees.append((x,y))
                highest = grid[x][y]

    # from above
    for x in range(0, height):
        highest = -1
        for y in range(0, width):
            if grid[y][x] > highest:
                visible_trees.append((y,x))
                highest = grid[y][x]

    # from right
    for x in reversed(range(0, height)):
        highest = -1
        for y in reversed(range(0, width)):
            if grid[x][y] > highest:
                visible_trees.append((x,y))
                highest = grid[x][y]

    # from below
    for x in reversed(range(0, height)):
        highest = -1
        for y in reversed(range(0, width)):
            if grid[y][x] > highest:
                visible_trees.append((y,x))
                highest = grid[y][x]

    visible_trees_set = set(visible_trees)
    print("part1:", len(visible_trees_set))
    return visible_trees_set

def part2(grid, visible_trees):
    grid_width = len(grid)
    grid_height = len(grid)

    def sightline_points(tree_col,tree_row):
        current_height = grid[tree_row][tree_col]

        col = tree_col
        row = tree_row
        # left
        sightline_left = 0
        while 1:
            col -= 1
            if col < 0:
                break
            sightline_left += 1
            h = grid[row][col]
            if h >= current_height:
                break

        # right
        col = tree_col
        row = tree_row
        sightline_right = 0
        while 1:
            col += 1
            if col >= grid_width:
                break
            sightline_right += 1
            h = grid[row][col]
            if h >= current_height:
                break

        # up
        col = tree_col
        row = tree_row
        sightline_up = 0
        while 1:
            row -= 1
            if row < 0:
                break

            sightline_up += 1
            h = grid[row][col]
            if h >= current_height:
                break

        # down
        col = tree_col
        row = tree_row
        sightline_down = 0
        while 1:
            row += 1
            if row >= grid_height:
                break

            sightline_down += 1
            h = grid[row][col]
            if h >= current_height:
                break

        return sightline_down * sightline_up * sightline_left * sightline_right

    highest_score = 0
    for tree in visible_trees:
        score = sightline_points(tree[1], tree[0]) # accidentally used X as row, should be Y...
        if score > highest_score:
            highest_score = score

    print(f"Part2: {highest_score}")

lines = []
with open("inputs/day8", "r") as f:
    lines = [l.strip() for l in f.readlines()]

grid = []

for l in lines:
    row = []
    for c in l:
        row.append(int(c))
    grid.append(row)

visible_trees = part1(grid)
part2(grid, visible_trees)


from random import randint

DESCRIPTION = "What number is missing in the progression?"

MIN_PROGRESSION_LENGTH = 5
MAX_PROGRESSION_LENGTH = 10
MIN_START_NUMBER = 1
MAX_START_NUMBER = 20
MIN_STEP_PROGRESSION = 1
MAX_STEP_PROGRESSION = 7

def get_game():
    progression_length = randint(MIN_PROGRESSION_LENGTH, MAX_PROGRESSION_LENGTH)
    start_number = randint(MIN_START_NUMBER, MAX_START_NUMBER)
    step = randint(MIN_STEP_PROGRESSION, MAX_STEP_PROGRESSION)
    end_number = start_number + progression_length * step

    progression = list(range(start_number, end_number, step))
    hide_number_index = randint(0, progression_length - 1)

    correct_answer = str(progression[hide_number_index])
    progression[hide_number_index] = ".."
    question = " ".join(str(number) for number in progression)

    return question, correct_answer


"""user_id in recipe

Revision ID: e8e6492f5c17
Revises: f8ae18d53b2f
Create Date: 2022-04-25 16:31:27.411305

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'e8e6492f5c17'
down_revision = 'f8ae18d53b2f'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('my_recipes')
    op.add_column('recipe', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'recipe', 'user', ['user_id'], ['id'])
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint(None, 'recipe', type_='foreignkey')
    op.drop_column('recipe', 'user_id')
    op.create_table('my_recipes',
    sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('recipe_id', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.ForeignKeyConstraint(['recipe_id'], ['recipe.id'], name='my_recipes_recipe_id_fkey'),
    sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='my_recipes_user_id_fkey'),
    sa.PrimaryKeyConstraint('id', name='my_recipes_pkey')
    )
    # ### end Alembic commands ###


import numpy as np
import pandas as pd
import joblib
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt

class KNN():

    def __init__(self, filePath=None, noOfRows=0,noOfColumns=0):
        if filePath:
            print("file is readed")
            self.dataset = pd.read_csv(filePath)
            if noOfRows == 0 and noOfColumns == 0:
                self.data = self.dataset.iloc[:, :].values
            elif noOfRows != 0 and noOfColumns == 0:
                self.data = self.dataset.iloc[:noOfRows, :].values
            elif noOfRows == 0 and noOfColumns != 0:
                self.data = self.dataset.iloc[:, :noOfColumns].values
            else:
                self.data = self.dataset.iloc[:noOfRows, :noOfColumns].values
            print(self.data.shape)

    def createModel(self,distancesThreshold,no_neighbors=5 , OutputFileName=""):
        nbrs = NearestNeighbors(n_neighbors=no_neighbors)
        nbrsModel = nbrs.fit(self.data)
        n_neighbors = nbrs.n_neighbors
        n_features_in_= nbrs.n_features_in_
        n_samples_fit_ = nbrs.n_samples_fit_
        distances, indexes = nbrs.kneighbors(self.data)
        distances_mean = distances.mean(axis=1)
        if distancesThreshold != 0:
            th = distancesThreshold
        else :
            th = self.CalculateThDistanse(distances_mean)
        print(th)
        labels = [1 if i > th else 0 for i in distances_mean]
        locValue: int = len(self.dataset.columns)
        self.dataset.insert(loc=locValue, column='KNN OUTPUT', value=labels)
        OutputFile = f"SKlearn/outlierdetection/outputFiels/{OutputFileName}output.csv"
        plt.figure(figsize=(15, 7))
        plt.plot(distances.mean(axis=1))
        plt.savefig(r"SKlearn/clustring/images/" + str(OutputFileName))
        plt.clf()
        self.dataset.to_csv(OutputFile, index=False)

        return nbrsModel,labels,n_neighbors,n_features_in_,n_samples_fit_,th

    def saveModel(self,nbrsModel,filename):
        filename = filename
        joblib.dump(nbrsModel, filename)

    def CalculateThDistanse(self, distances_mean):
        q3, q1 = np.percentile(distances_mean, [75, 25])
        iqr = q3 - q1
        upper_limit = q3 + (1.5 * iqr)
        return upper_limit


n, m = map(int, input().split())
coins = [int(input()) for _ in range(n)]

dp = [10001] * 10001

for coin in coins:
    dp[coin] = 1

for i in range(n):
    for j in range(coins[i], m+1):
        if dp[j - coins[i]] != 10001:
            dp[j] = min(dp[j], dp[j - coins[i]] + 1)

if dp[m] == 1001:
    print(-1)
else:
    print(dp[m])

Q5.효율적인화폐구성.py


__author__ = 'Piia Hartikka 013866037'

import pygame
from pygame.locals import *
import sys
from queue import Empty
from datetime import datetime
import pathlib

HEARTBEAT_INTERVAL = 5

class Game(object):
    def __init__(self, server_message_queue, command_queue):
        self.server_message_queue = server_message_queue
        self.command_queue = command_queue
        self.WINDOW_WIDTH = 400
        self.WINDOW_HEIGHT = 300

        self.WHITE = (255, 255, 255)
        self.BLUE = (0, 0, 255)
        self.GREEN = (0, 255, 0)
        self.background = pygame.image.load('assets/background_image.png')

        self.BLOCK = 10
        self.x = 200
        self.y = 200
        self.last_sent = datetime.now()

        self.game_state = []

        pygame.init()
        pygame.display.set_caption('Game client')
        self.screen = pygame.display.set_mode((self.WINDOW_WIDTH, self.WINDOW_HEIGHT), 0, 32)
        self.screen.fill(self.WHITE)
        self.clock = pygame.time.Clock()

    def start(self):
        while True:
            self.clock.tick(60)
            self.send_heartbeat()
            self.update_game_state()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    return
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.locals.K_UP:
                        self.y -= self.BLOCK
                    elif event.key == pygame.locals.K_DOWN:
                        self.y += self.BLOCK
                    elif event.key == pygame.locals.K_RIGHT:
                        self.x += self.BLOCK
                    elif event.key == pygame.locals.K_LEFT:
                        self.x -= self.BLOCK
                    else:
                        continue
                    self.write_command()
            self.draw()
            pygame.display.update()

    def send_heartbeat(self):
        now = datetime.now()
        if (now - self.last_sent).total_seconds() > HEARTBEAT_INTERVAL:
            print("Sending heartbeat")
            self.write_command()

    def draw(self):
        #self.screen.fill(self.WHITE)
        self.screen.blit(self.background, (0,0))
        for coords in self.game_state:
            rectangle = pygame.Rect(coords, (self.BLOCK, self.BLOCK))
            pygame.draw.rect(self.screen, self.GREEN, rectangle)
        self.draw_me_like_one_of_your_french_girls()

    def draw_me_like_one_of_your_french_girls(self):
        rectangle = pygame.Rect((self.x, self.y), (self.BLOCK, self.BLOCK))
        pygame.draw.rect(self.screen, self.BLUE, rectangle)

    def update_game_state(self):
        last_game_state = None

        try:
            while True:
                last_game_state = self.server_message_queue.get_nowait()
        except Empty:
            pass

        if last_game_state != None:
            self.game_state = last_game_state

    def write_command(self):
        self.last_sent = datetime.now()
        self.command_queue.put((self.x, self.y))


from difflib import Differ
import os

file_folder1 ="C:/Users/24547/Git/nelnet-cisco-ivr/FMS_Velocity_IVR_Java_ph/src/com/fms/velocity/auth"
file_folder_2 = "C:/Users/24547\Git/nelnet-cisco-ivr/FMS_Velocity_IVR_Java/src/com/fms/velocity/auth"

for filename in os.listdir(file_folder1):
    file1 = os.path.join(file_folder1, filename)
    file2 = os.path.join(file_folder_2, filename)
    fileNameSplit = filename.split(".")
    print(file1)
    print(file2)
    if os.path.exists(file2):
        with open(file1) as file_1, open(file2) as file_2:
            differ = Differ()
            for line in differ.compare(file_1.readlines(), file_2.readlines()):
                #apped the diff to a file
                if line.startswith('-'):
                    with open(f"diff/{fileNameSplit[0]}_diff.txt", "a") as diff_file:
                        diff_file.write(line)

    else:
        print(f"{file2} does not exist, skipping...")

    """
    Code	Meaning
    ‘-‘     line unique to sequence 1
    ‘+’     line unique to sequence 2
    ‘ ‘     line common to both sequences
    ‘?’     line not present in either input sequence
    """


from flask import Flask, render_template, request,url_for
from flask_fontawesome import FontAwesome
from flask_sqlalchemy import SQLAlchemy
from send_mail import send_mail

app = Flask(__name__)

ENV = 'env'

if ENV=='env':
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///booking.db'

    app.config['SECRET_KEY'] = 'thisisasecret'
    app.debug=True
else:
    app.debug = False
    app.config['SQLALCHEMY_DATABASE_URI'] = ''

fa = FontAwesome(app)
db = SQLAlchemy(app)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

class Feedback(db.Model):
    __tablename__ = 'feedback'
    id = db.Column(db.Integer, primary_key=True)
    customer = db.Column(db.String(200), unique=True)
    email = db.Column(db.String(200), unique=True)
    guest = db.Column(db.Integer)
    room= db.Column(db.String(200))
    arrival = db.Column(db.String(200))
    departure=db.Column(db.String(200))
    comments = db.Column(db.Text())

    def __init__(self, customer, email, guest, room, arrival, departure, comments):
        self.customer = customer
        self.email = email
        self.guest = guest
        self.room = room
        self.arrival = arrival
        self.departure = departure
        self.comments = comments

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/submit', methods=['POST'])
def submit():
    if request.method == 'POST':
        customer = request.form['customer']
        email=request.form['email']
        guest=request.form['guest']
        room=request.form['room']
        arrival=request.form['arrival']
        departure=request.form['departure']
        comments=request.form['comments']
        if customer == '' or guest == '' or arrival == '':
            return render_template('index.html', message= 'Please enter requird fields')
        if db.session.query(Feedback).filter(Feedback.customer == customer).count() == 0:
            data = Feedback(customer, email, guest, room, arrival, departure, comments)
            db.session.add(data)
            db.session.commit()
            send_mail(customer, email, guest, room, arrival, departure, comments)
            return render_template('success.html')
        return render_template('index.html', message= 'You have already reserved room at our hotel')

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


from collections import deque

bracket_list = [ (i, j) for i in range(5) for j in range(i+1, 6)]

def search(win_list) :
  q = deque([[0, win_list.copy()]])

  while q :
    idx, cur_list = q.popleft()
    if idx == 15 :
      if is_valid_winning(cur_list) :
        return 1
      continue

    a, b = bracket_list[idx]

    for k in range(3) :
      if cur_list[3*a+k] and cur_list[3*b+2-k] :
        next_list = cur_list.copy()
        next_list[3*a+k] -= 1
        next_list[3*b+2-k] -= 1
        q.append([idx+1, next_list])

  return 0

def is_valid_winning(lst) :
  for left in lst :
    if left != 0 :
      return False
  return True

def solve() :
  result = list()
  for _ in range(4) :
    win_list = list(map(int, input().split()))
    result.append(search(win_list))

  print(*result)

solve()


from shared.infrastructure.dependency_injection.app import App
from users.application.queries.get_user_result import GetUserResult
from users.domain.errors.error import ErrorMessage
from users.infrastructure.repositories.user_respository import UserRepository
from users.infrastructure.tokens.user_token_service import UserTokenService
from shared.domain.exceptions.bad_request import BadRequestException

class GetUserHandler(object):
    def __init__(
        self,
        user_repository: UserRepository = App().container.UserRepository(),
        user_token_service: UserTokenService = App().container.UserTokenService(),
    ):
        self.user_repository = user_repository
        self.user_token_service = user_token_service

    def handle(self, query):
        user = self.user_repository.find_by_id(query.id)

        if(user is None):
            raise BadRequestException(
                ErrorMessage.USER_NOT_FOUND.value)

        properties = user.toProperties()

        return GetUserResult(name=properties["name"], email=properties["email"], age=properties["age"])


# Inicialización de variables
sueldo_diario = 0
dias_trabajados = 0

# Solicitar nombre del empleado
nombre = input("Ingresa tu nombre: ")

# Bucle para asegurar una cantidad válida de días trabajados
while True:
    dias_trabajados = int(input("Días trabajados "))
    if dias_trabajados > 15:
        print("No puede ser mayor a 15, porque es quincenal los pagos")
    else:
        break

# Bucle para asegurar un sueldo diario válido
while True:
    sueldo_diario = float(input("Sueldo diario"))
    if sueldo_diario == 0:
        print("Ve a la profeco, no te pueden pagar 0")
    else:
        break

# Calcular el sueldo quincenal
sueldo_quincenal = dias_trabajados * sueldo_diario

# Imprimir resultado
print(f"{nombre} tu sueldo quincenalmente: ${sueldo_quincenal}")


from utils import aoc

def decrypt(nums: list[int], steps: int = 1) -> int:
    indices = list(range(len(nums)))

    for i in indices * steps:
        j = indices.index(i)
        indices.pop(j)
        indices.insert((j + nums[i]) % len(indices), i)

    zero = indices.index(nums.index(0))
    return sum(
        nums[indices[(zero + offset) % len(nums)]] for offset in (1000, 2000, 3000)
    )

if __name__ == "__main__":
    file = aoc.get_input("20")

    nums = [int(x) for x in file]
    print(decrypt(nums))

    nums = [int(x) * 811589153 for x in file]
    print(decrypt(nums, 10))


#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

def mcd (L):
    L=[a,b]

    while r!= 0:
        a=b
        b=r
        r=a%b
    return b

L= [6,98]
mcd (L)