import requests
import html
import csv
from contextlib import closing
import matplotlib.pyplot as plt

def derivative(x,y,start,end):
    y_prime = []
    prevX = start
    prevY = end
    for i in range(0,len(x)):
        delta_x = x[i] - prevX
        delta_y = y[i] - prevY
        if (delta_x == 0):
            delta_x = 1
        y_prime.append(delta_y/delta_x)
        prevX = x[i]
        prevY = y[i]
    return y_prime

def getCountryData(country):
    url = "https://covid.ourworldindata.org/data/owid-covid-data.csv"

    with closing(requests.get(url, stream=True)) as r:
        f = (line.decode('utf-8') for line in r.iter_lines())
        reader = csv.reader(f, delimiter=',', quotechar='"')
        data = []
        first = True
        for row in reader:
            if first == True:
                data.append(row)
                first = False
            if row[0] == country:
                data.append(row)
        return data

def plotData(Data):
    plt.plot([day for day in range(0,Data["days"])], Data["data"])
    plt.title(Data["title"])
    # naming the x axis
    plt.xlabel(Data["xlabel"])
    # naming the y axis
    plt.ylabel(Data["ylabel"])

    # function to show the plot
    plt.show()

def main():
    USA = getCountryData("USA")
    my_total_cases = 0
    total = 0
    NC_indx = None
    TC_indx = None
    TC_data = []
    NC_data = []
    days = -1
    for row in USA:
        days += 1
        if row == USA[0]:
            for col in row:
                if col == "new_cases":
                    NC_indx = row.index(col)
                if col == "total_cases":
                    TC_indx = row.index(col)
        else:
            TC_data.append(int(row[TC_indx]))
            NC_data.append(int(row[NC_indx]))
            my_total_cases += int(row[NC_indx])
    TC_dict = {
                "days": days,
                "data": TC_data,
                "title": 'Number of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'Total cases'}
    plotData(TC_dict)
    NC_dict = {
                "days": days,
                "data": NC_data,
                "title": 'New Cases Each Day',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'New cases'}

    plotData(NC_dict)
    Deriv_dict = {
                "days": days,
                "data": derivative([day for day in range(0,days)],TC_data,0,0),
                "title": 'Derivative of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'Derivative'}

    plotData(Deriv_dict)

    Sec_Deriv_dict = {
                "days": days,
                "data": derivative([day for day in range(0,days)],Deriv_dict["data"],0,0),
                "title": '2nd Derivative of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": '2nd Derivative'}

    plotData(Sec_Deriv_dict)

if __name__ == "__main__":
    main()


from rest_framework import serializers
from rest_framework.authtoken.models import Token
from rest_framework.validators import UniqueValidator
from walletservice.models import Wallete, Transactions
from datetime import datetime

class WalletSerializer(serializers.ModelSerializer):
    owner_by = serializers.SerializerMethodField("_owner_")
    status = serializers.SerializerMethodField("_status_")

    def _owner_ (self, obj):
        try:
            token = Token.objects.get(user=obj.owner)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_enable:
            return "enabled"
        else:  return "desabled"

    class Meta:
        model = Wallete
        fields = ['id', 'owner_by', 'status',
                'enabled_at', 'balance', 'disabled_at']

    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None)
        super(WalletSerializer, self).__init__(*args, **kwargs)
        if fields is not None:
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

    def update(self, instance, validated_data):
        is_disabled = validated_data.get("is_disabled")
        if is_disabled == "true":
            instance.is_enable=False
            instance.disabled_at = datetime.now()
        else:
            instance.is_enable=True
            instance.enabled_at = datetime.now()
        instance.save()
        return instance

class DepositSerializer(serializers.ModelSerializer):
    deposited_by = serializers.SerializerMethodField("_deposited_by_")
    status = serializers.SerializerMethodField("_status_")
    deposited_at = serializers.SerializerMethodField("_deposited_at_")
    amount = serializers.CharField(required=True, max_length=255)
    reference_id = serializers.CharField(required=True,
                max_length=100, validators=[
                UniqueValidator(
                queryset=Transactions.objects.filter(type="deposit"),
                message="Reference id already exists")])

    def validate(self, attrs):
        amount = attrs.get('amount')
        if float(amount) <= 0:
            raise serializers.ValidationError(
                "Deposit an amount greater than zero")
        return attrs

    def _deposited_at_ (self, obj):
        try:
            return obj.datetime
        except: return ""

    def _deposited_by_ (self, obj):
        try:
            token = Token.objects.get(user=obj.user)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_success:
            return "Success"
        else:  return "Fail"

    class Meta:
        model = Transactions
        fields = ['id', 'deposited_by', 'status',
                'deposited_at', 'amount', 'reference_id']

    def create(self, validated_data):
        user =  self.context.get('user')
        wallet_obj = self.context.get('wallet_obj')
        amount = validated_data.get("amount")
        reference_id = validated_data.get("reference_id")
        transaction_obj = Transactions.objects.create(amount=amount,
                reference_id=reference_id,
                type='deposit', user=user, wallet=wallet_obj,
                datetime=datetime.now(),
                is_success=True)
        wallet_obj.balance = float(wallet_obj.balance) + float(amount)
        wallet_obj.save()
        return transaction_obj

class WithdrawSerializer(serializers.ModelSerializer):
    withdraw_by = serializers.SerializerMethodField("_withdraw_by_")
    status = serializers.SerializerMethodField("_status_")
    withdraw_at = serializers.SerializerMethodField("_withdraw_at_")
    amount = serializers.CharField(required=True, max_length=255)
    reference_id = serializers.CharField(required=True,
                max_length=100, validators=[
                UniqueValidator(
                queryset=Transactions.objects.filter(
                type="withdraw"),
                message="Reference id already exists")])

    def validate(self, attrs):
        amount = attrs.get('amount')
        wallet_obj = self.context.get('wallet_obj')
        if float(wallet_obj.balance) < float(amount):
            raise serializers.ValidationError(
                "Insufficient balance. Your balance is {balance}".format(
                balance=wallet_obj.balance))
        return attrs

    def _withdraw_at_ (self, obj):
        try:
            return obj.datetime
        except: return ""

    def _withdraw_by_ (self, obj):
        try:
            token = Token.objects.get(user=obj.user)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_success:
            return "Success"
        else:  return "Fail"

    class Meta:
        model = Transactions
        fields = ['id', 'withdraw_by', 'status',
                'withdraw_at', 'amount', 'reference_id']

    def create(self, validated_data):
        user =  self.context.get('user')
        wallet_obj = self.context.get('wallet_obj')
        amount = validated_data.get("amount")
        reference_id = validated_data.get("reference_id")
        transaction_obj = Transactions.objects.create(amount=amount,
                reference_id=reference_id,
                type='withdraw', user=user, wallet=wallet_obj,
                datetime=datetime.now(),
                is_success=True)
        wallet_obj.balance = float(wallet_obj.balance) - float(amount)
        wallet_obj.save()
        return transaction_obj


from PySide import QtGui #@UnresolvedImport
from PySide.QtCore import Qt, QSettings, QSize, QPoint #@UnresolvedImport
from syncplay import utils, constants, version
import sys
import time
import re
import os
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration

class MainWindow(QtGui.QMainWindow):
    def addClient(self, client):
        self._syncplayClient = client
        self.roomInput.setText(self._syncplayClient.getRoom())

    def promptFor(self, prompt=">", message=""):
        #TODO: Prompt user
        return None

    def showMessage(self, message, noTimestamp=False):
        message = unicode(message)
        message = message.replace("&", "&").replace('"', """).replace("<", "<").replace(">", ">")
        message = message.replace("<", "<")
        message = message.replace(">", ">")
        message = message.replace("\n", "
")
        if(noTimestamp):
            self.newMessage(message + "
")
        else:
            self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "
")

    def showUserList(self, currentUser, rooms):
        self._usertreebuffer = QtGui.QStandardItemModel()
        self._usertreebuffer.setColumnCount(2)
        self._usertreebuffer.setHorizontalHeaderLabels(("Room / User","File being played"))
        usertreeRoot = self._usertreebuffer.invisibleRootItem()

        for room in rooms:
            roomitem = QtGui.QStandardItem(room)
            if (room == currentUser.room):
                font = QtGui.QFont()
                font.setWeight(QtGui.QFont.Bold)
                roomitem.setFont(font)
            blankitem = QtGui.QStandardItem("")
            roomitem.setFlags(roomitem.flags()  & ~Qt.ItemIsEditable)
            blankitem.setFlags(blankitem.flags() & ~Qt.ItemIsEditable)
            usertreeRoot.appendRow((roomitem, blankitem))
            for user in rooms[room]:
                useritem = QtGui.QStandardItem(user.username)
                fileitem = QtGui.QStandardItem("")
                if (user.file):
                    fileitem = QtGui.QStandardItem(user.file['name'] + " ("+formatTime(user.file['duration'])+")")
                    if (currentUser.file):
                        sameName = sameFilename(user.file['name'], currentUser.file['name'])
                        sameSize = sameFilesize(user.file['size'], currentUser.file['size'])
                        sameDuration = sameFileduration(user.file['duration'], currentUser.file['duration'])
                        sameRoom = room == currentUser.room
                        differentName = not sameName
                        differentSize = not sameSize
                        differentDuration = not sameDuration
                        if (sameName or sameRoom):
                            if (differentSize and sameDuration):
                                fileitem = QtGui.QStandardItem(user.file['name'] + " ("+formatTime(user.file['duration'])+")" + " (Different size!)")
                            elif (differentSize and differentDuration):
                                fileitem = QtGui.QStandardItem(user.file['name'] + " ("+formatTime(user.file['duration'])+")" + " (Different size and duration!)")
                            elif (differentDuration):
                                fileitem = QtGui.QStandardItem(user.file['name'] + " ("+formatTime(user.file['duration'])+")" + " (Different duration!)")
                            if (sameRoom and (differentName or differentSize or differentDuration)):
                                fileitem.setForeground(QtGui.QBrush(QtGui.QColor('red')))
                else:
                    fileitem = QtGui.QStandardItem("(No file being played)")
                    if (room == currentUser.room):
                        fileitem.setForeground(QtGui.QBrush(QtGui.QColor('blue')))
                if(currentUser.username == user.username):
                    font = QtGui.QFont()
                    font.setWeight(QtGui.QFont.Bold)
                    useritem.setFont(font)
                useritem.setFlags(useritem.flags()  & ~Qt.ItemIsEditable)
                fileitem.setFlags(fileitem.flags()  & ~Qt.ItemIsEditable)
                roomitem.appendRow((useritem, fileitem))

        self.listTreeModel = self._usertreebuffer
        self.listTreeView.setModel(self.listTreeModel)
        self.listTreeView.setItemsExpandable(False)
        self.listTreeView.expandAll()
        self.listTreeView.resizeColumnToContents(0)
        self.listTreeView.resizeColumnToContents(1)

    def roomClicked(self, item):
        while(item.parent().row() != -1):
            item = item.parent()
        self.joinRoom(item.sibling(item.row(), 0).data())

    def userListChange(self):
        self._syncplayClient.showUserList()

    def showDebugMessage(self, message):
        print(message)

    def showErrorMessage(self, message, criticalerror = False):
        message = unicode(message)
        if criticalerror:
            QtGui.QMessageBox.critical(self,"Syncplay", message)
        message = message.replace("&", "&").replace('"', """).replace("<", "<").replace(">", ">")
        message = message.replace("\n", "
")
        message = "" + message + ""
        self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "
")

    def joinRoom(self, room = None):
        if room == None:
            room = self.roomInput.text()
        if room == "":
            if  self._syncplayClient.userlist.currentUser.file:
                room = self._syncplayClient.userlist.currentUser.file["name"]
            else:
                room = self._syncplayClient.defaultRoom
        self.roomInput.setText(room)
        if(room != self._syncplayClient.getRoom()):
            self._syncplayClient.setRoom(room)
            self._syncplayClient.sendRoom()

    def seekPosition(self):
        s = re.match(constants.UI_SEEK_REGEX, self.seekInput.text())
        if(s):
            sign = self._extractSign(s.group('sign'))
            t = utils.parseTime(s.group('time'))
            if(t is None):
                return
            if(sign):
                t = self._syncplayClient.getGlobalPosition() + sign * t
            self._syncplayClient.setPosition(t)

        else:
            self.showErrorMessage("Invalid seek value")

    def undoSeek(self):
        tmp_pos = self._syncplayClient.getPlayerPosition()
        self._syncplayClient.setPosition(self._syncplayClient.playerPositionBeforeLastSeek)
        self._syncplayClient.playerPositionBeforeLastSeek = tmp_pos

    def togglePause(self):
        self._syncplayClient.setPaused(not self._syncplayClient.getPlayerPaused())

    def play(self):
        self._syncplayClient.setPaused(False)

    def pause(self):
        self._syncplayClient.setPaused(True)

    def exitSyncplay(self):
        self._syncplayClient.stop()

    def closeEvent(self, event):
        self.exitSyncplay()
        self.saveSettings()

    def loadMediaBrowseSettings(self):
        settings = QSettings("Syncplay", "MediaBrowseDialog")
        settings.beginGroup("MediaBrowseDialog")
        self.mediadirectory = settings.value("mediadir", "")
        settings.endGroup()

    def saveMediaBrowseSettings(self):
        settings = QSettings("Syncplay", "MediaBrowseDialog")
        settings.beginGroup("MediaBrowseDialog")
        settings.setValue("mediadir", self.mediadirectory)
        settings.endGroup()

    def browseMediapath(self):
        self.loadMediaBrowseSettings()
        options = QtGui.QFileDialog.Options()
        if (os.path.isdir(self.mediadirectory)):
            defaultdirectory = self.mediadirectory
        elif (os.path.isdir(QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.MoviesLocation))):
            defaultdirectory = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.MoviesLocation)
        elif (os.path.isdir(QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.HomeLocation))):
            defaultdirectory = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.HomeLocation)
        else:
            defaultdirectory = ""
        browserfilter = "All files (*)"
        fileName, filtr = QtGui.QFileDialog.getOpenFileName(self,"Browse for media files",defaultdirectory,
                browserfilter, "", options)
        if fileName:
            if sys.platform.startswith('win'):
                fileName = fileName.replace("/","\\")
            self.mediadirectory = os.path.dirname(fileName)
            self.saveMediaBrowseSettings()
            self._syncplayClient._player.openFile(fileName)

    def _extractSign(self, m):
        if(m):
            if(m == "-"):
                return -1
            else:
                return 1
        else:
            return None

    def setOffset(self):
        newoffset, ok = QtGui.QInputDialog.getText(self,"Set offset",
                "Offset (see http://syncplay.pl/guide/ for usage instructions):", QtGui.QLineEdit.Normal,
                "")
        if ok and newoffset != '':
            o = re.match(constants.UI_OFFSET_REGEX, "o " + newoffset)
            if(o):
                sign = self._extractSign(o.group('sign'))
                t = utils.parseTime(o.group('time'))
                if(t is None):
                    return
                if (o.group('sign') == "/"):
                        t =  self._syncplayClient.getPlayerPosition() - t
                elif(sign):
                        t = self._syncplayClient.getUserOffset() + sign * t
                self._syncplayClient.setUserOffset(t)
            else:
                self.showErrorMessage("Invalid offset value")

    def openUserGuide(self):
        if sys.platform.startswith('linux'):
            self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/linux/")
        elif sys.platform.startswith('win'):
            self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/windows/")
        else:
            self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/")

    def drop(self):
        self.close()

    def addTopLayout(self, window):
        window.topSplit = QtGui.QSplitter(Qt.Horizontal)

        window.outputLayout = QtGui.QVBoxLayout()
        window.outputbox = QtGui.QTextEdit()
        window.outputbox.setReadOnly(True)
        window.outputlabel = QtGui.QLabel("Notifications")
        window.outputFrame = QtGui.QFrame()
        window.outputFrame.setLineWidth(0)
        window.outputFrame.setMidLineWidth(0)
        window.outputLayout.setContentsMargins(0,0,0,0)
        window.outputLayout.addWidget(window.outputlabel)
        window.outputLayout.addWidget(window.outputbox)
        window.outputFrame.setLayout(window.outputLayout)

        window.listLayout = QtGui.QVBoxLayout()
        window.listTreeModel = QtGui.QStandardItemModel()
        window.listTreeView = QtGui.QTreeView()
        window.listTreeView.setModel(window.listTreeModel)
        window.listTreeView.doubleClicked.connect(self.roomClicked)
        window.listlabel = QtGui.QLabel("List of who is playing what")
        window.listFrame = QtGui.QFrame()
        window.listFrame.setLineWidth(0)
        window.listFrame.setMidLineWidth(0)
        window.listLayout.setContentsMargins(0,0,0,0)
        window.listLayout.addWidget(window.listlabel)
        window.listLayout.addWidget(window.listTreeView)
        if constants.SHOW_CONTACT_INFO:
            window.contactLabel = QtGui.QLabel()
            window.contactLabel.setWordWrap(True)
            window.contactLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
            window.contactLabel.setLineWidth(1)
            window.contactLabel.setMidLineWidth(0)
            window.contactLabel.setMargin(2)
            window.contactLabel.setText("Have an idea, bug report or feedback? E-mail dev@syncplay.pl, chat via the #Syncplay IRC channel on irc.freenode.net or raise an issue via GitHub. Also check out http://syncplay.pl/ for info, help and updates.")
            window.contactLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
            window.contactLabel.setOpenExternalLinks(True)
            window.listLayout.addWidget(window.contactLabel)
        window.listFrame.setLayout(window.listLayout)

        window.topSplit.addWidget(window.outputFrame)
        window.topSplit.addWidget(window.listFrame)
        window.topSplit.setStretchFactor(0,4)
        window.topSplit.setStretchFactor(1,5)
        window.mainLayout.addWidget(window.topSplit)
        window.topSplit.setSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Expanding)

    def addBottomLayout(self, window):
        window.bottomLayout = QtGui.QHBoxLayout()

        window.addRoomBox(MainWindow)
        window.addSeekBox(MainWindow)
        window.addMiscBox(MainWindow)

        window.bottomLayout.addWidget(window.roomGroup, Qt.AlignLeft)
        window.bottomLayout.addWidget(window.seekGroup, Qt.AlignLeft)
        window.bottomLayout.addWidget(window.miscGroup, Qt.AlignLeft)

        window.mainLayout.addLayout(window.bottomLayout, Qt.AlignLeft)

    def addRoomBox(self, window):
        window.roomGroup = QtGui.QGroupBox("Room")

        window.roomInput = QtGui.QLineEdit()
        window.roomInput.returnPressed.connect(self.joinRoom)
        window.roomButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'door_in.png'), "Join room")
        window.roomButton.pressed.connect(self.joinRoom)
        window.roomLayout = QtGui.QHBoxLayout()
        window.roomInput.setMaximumWidth(150)

        window.roomLayout.addWidget(window.roomInput)
        window.roomLayout.addWidget(window.roomButton)

        window.roomGroup.setLayout(window.roomLayout)
        window.roomGroup.setFixedSize(window.roomGroup.sizeHint())

    def addSeekBox(self, window):
        window.seekGroup = QtGui.QGroupBox("Seek")

        window.seekInput = QtGui.QLineEdit()
        window.seekInput.returnPressed.connect(self.seekPosition)
        window.seekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'clock_go.png'),"Seek to time")
        window.seekButton.pressed.connect(self.seekPosition)

        window.seekLayout = QtGui.QHBoxLayout()
        window.seekInput.setMaximumWidth(50)
        window.seekInput.setText("0:00")

        window.seekLayout.addWidget(window.seekInput)
        window.seekLayout.addWidget(window.seekButton)

        window.seekGroup.setLayout(window.seekLayout)
        window.seekGroup.setFixedSize(window.seekGroup.sizeHint())

    def addMiscBox(self, window):
        window.miscGroup = QtGui.QGroupBox("Other commands")

        window.unseekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'),"Undo seek")
        window.unseekButton.pressed.connect(self.undoSeek)

        window.miscLayout = QtGui.QHBoxLayout()
        window.miscLayout.addWidget(window.unseekButton)
        if constants.MERGE_PLAYPAUSE_BUTTONS == True:
            window.playpauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'),"Toggle pause")
            window.playpauseButton.pressed.connect(self.togglePause)
            window.miscLayout.addWidget(window.playpauseButton)
        else:
            window.playButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_play_blue.png'),"Play")
            window.playButton.pressed.connect(self.play)
            window.playButton.setMaximumWidth(60)
            window.miscLayout.addWidget(window.playButton)
            window.pauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'),"Pause")
            window.pauseButton.pressed.connect(self.pause)
            window.pauseButton.setMaximumWidth(60)
            window.miscLayout.addWidget(window.pauseButton)

        window.miscGroup.setLayout(window.miscLayout)
        window.miscGroup.setFixedSize(window.miscGroup.sizeHint())

    def addMenubar(self, window):
        window.menuBar = QtGui.QMenuBar()

        window.fileMenu = QtGui.QMenu("&File", self)
        window.openAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'folder_explore.png'), "&Open media file")
        window.openAction.triggered.connect(self.browseMediapath)
        window.exitAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'cross.png'), "E&xit")
        window.exitAction.triggered.connect(self.exitSyncplay)
        window.menuBar.addMenu(window.fileMenu)

        window.advancedMenu = QtGui.QMenu("&Advanced", self)
        window.setoffsetAction = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'timeline_marker.png'),"Set &offset")
        window.setoffsetAction.triggered.connect(self.setOffset)
        window.menuBar.addMenu(window.advancedMenu)

        window.helpMenu = QtGui.QMenu("&Help", self)
        window.userguideAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'help.png'), "Open user &guide")
        window.userguideAction.triggered.connect(self.openUserGuide)

        window.menuBar.addMenu(window.helpMenu)
        window.mainLayout.setMenuBar(window.menuBar)

    def addMainFrame(self, window):
        window.mainFrame = QtGui.QFrame()
        window.mainFrame.setLineWidth(0)
        window.mainFrame.setMidLineWidth(0)
        window.mainFrame.setContentsMargins(0,0,0,0)
        window.mainFrame.setLayout(window.mainLayout)

        window.setCentralWidget(window.mainFrame)

    def newMessage(self, message):
        self.outputbox.moveCursor(QtGui.QTextCursor.End)
        self.outputbox.insertHtml(message)
        self.outputbox.moveCursor(QtGui.QTextCursor.End)

    def resetList(self):
        self.listbox.setText("")

    def newListItem(self, item):
        self.listbox.moveCursor(QtGui.QTextCursor.End)
        self.listbox.insertHtml(item)
        self.listbox.moveCursor(QtGui.QTextCursor.End)

    def dragEnterEvent(self, event):
        data = event.mimeData()
        urls = data.urls()
        if (urls and urls[0].scheme() == 'file'):
            event.acceptProposedAction()

    def dropEvent(self, event):
        data = event.mimeData()
        urls = data.urls()
        if (urls and urls[0].scheme() == 'file'):
            if sys.platform.startswith('linux'):
                dropfilepath = unicode(urls[0].path())
            else:
                dropfilepath = unicode(urls[0].path().replace("/","\\"))[1:] # Removes starting slash
            self._syncplayClient._player.openFile(dropfilepath)

    def saveSettings(self):
        settings = QSettings("Syncplay", "MainWindow")
        settings.beginGroup("MainWindow")
        settings.setValue("size", self.size())
        settings.setValue("pos", self.pos())
        settings.endGroup()

    def loadSettings(self):
        settings = QSettings("Syncplay", "MainWindow")
        settings.beginGroup("MainWindow")
        self.resize(settings.value("size", QSize(700, 500)))
        self.move(settings.value("pos", QPoint(200, 200)))
        settings.endGroup()

    def __init__(self):
        super(MainWindow, self).__init__()
        self.QtGui = QtGui
        if sys.platform.startswith('linux'):
            self.resourcespath = utils.findWorkingDir() + "/resources/"
        else:
            self.resourcespath = utils.findWorkingDir() + "\\resources\\"
        self.setWindowTitle("Syncplay v" + version)
        self.mainLayout = QtGui.QVBoxLayout()
        self.addTopLayout(self)
        self.addBottomLayout(self)
        self.addMenubar(self)
        self.addMainFrame(self)
        self.loadSettings()
        self.setWindowIcon(QtGui.QIcon(self.resourcespath + "syncplay.png"))
        self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint)
        self.show()
        self.setAcceptDrops(True)


import sys
import os
sys.path.append(os.path.join(os.getcwd(),".."))
sys.path.append(os.getcwd())
import tensorflow as tf
import os
import Config
from MTCNN4Iris import DSV4MTCNN
from MTCNN4Iris.IrisONet import IrisONet

if __name__ == "__main__":
    # 运行目录
    experiment_dir = "experiments/onet"
    config = Config.Config("{0}/config.json".format(experiment_dir))
    config.show()
    # session
    sess = tf.Session()
    # 数据集
    train_data = DSV4MTCNN.DSV4MTCNN(sess, config.iris_position_json_file, config.iris_images_dir, config.pos_iou, config.neg_iou)
    # 网络
    onet = IrisONet(sess,config,experiment_dir)
    # restore
    try:
        onet.restore(os.path.join(os.path.join(experiment_dir,"model")))
    except:
        print("[!]无法restore")
    cur_step = 0
    learning_rate = config.learning_rate
    while cur_step< config.total_training_steps:
        if cur_step < 2000:
            learning_rate =1e-4
        else:
            learning_rate =1e-5
        batch = train_data.getBatchForONet(config.batch_size,config.pos_region_each_image, config.neg_region_each_image)
        assert len(batch[0]) == config.batch_size ," {0} != {1}".format(len(batch[0]), config.batch_size)
        loss,cur_step = onet.train(batch[0],batch[1],batch[2],learning_rate)

        print("[*] Step[{0}] loss{1} ".format(cur_step,loss))
        # 每隔 save_every_steps ，保存一次模型
        if cur_step % config.save_every_steps == 0:
            onet.save(os.path.join(experiment_dir,"model/step"),cur_step)


from django.urls import path

from . import views

app_name = 'job'

urlpatterns = [
    # 任务列表
    path('jobs/', views.jobs_view, name='jobs'),

    # 任务详情
    path('jobs/<int:job_id>/detail/', views.job_detail_view, name='job_detail'),

    # 删除任务
    path('jobs/ajax/delete/', views.job_delete_view, name='job_delete'),

    # 回调更新任务信息
    path('remote_update/<int:job_id>/', views.jobs_remote_update_view, name='remote_update'),
]


"""Deletes the files with provided extensions under a directory that are older than
provided number of days"""
import os, time

root = r'C:\Temp\SeleniumPythonFramework'
file_extensions_to_remove = ('.log', '.png') # tuple
how_many_days_old_logs_to_remove = 1
removed_files = []

for dirpath, dirnames, filenames in os.walk(root):
	print(f"Checking Folder: {dirpath}")
	folder_path = dirpath

	now = time.time()

	for file in os.listdir(folder_path):
	    file_full_path = os.path.join(folder_path,file)
	    if os.path.isfile(file_full_path) and file.endswith(file_extensions_to_remove):
	        #Delete files older than x days
	        if os.stat(file_full_path).st_mtime < now - how_many_days_old_logs_to_remove * 86400:
	             os.remove(file_full_path)
	             print ("File Removed : " , file_full_path)
	             removed_files.append(file_full_path)

print(f"{len(removed_files)} files were removed from {root}")
print(removed_files)


from flask import Flask, flash, render_template, request, redirect, url_for
from werkzeug import secure_filename
from Jjson import *
import os
import datetime

Upload_Folder = './stored'
ALLOWED_EXTENSIONS = set(['txt'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = Upload_Folder

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def main() -> 'html':
    return render_template('main.html')

@app.route('/upload', methods=['POST'])
def upload() -> 'html':
    Uploadtime = datetime.datetime.now()
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        # if user does not select file, browser also
        # submit a empty part without filename
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            n = os.path.getsize(filename) / 1024.0
            n = round(n, 3)

            if c.find_one():
                for x in c.find():
                    if filename == x["FileName"]:
                        if n == x["DataSize"]:
                            arr = c.find_one({'FileName': filename})
                            count = 0
                            return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"], size=arr["DataSize"])
                    else:
                        count = 1
                if(count == 1):
                    insert(filename, n, Uploadtime)
                    for x in c.find():
                        print(x["FileName"])
                        arr = c.find_one({'FileName': filename})
                    return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"],
                                       size=arr["DataSize"])
            else:
                insert(filename, n, Uploadtime)
                for x in c.find():
                    print(x["FileName"])
                arr = c.find_one({'FileName': filename})
                return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"], size=arr["DataSize"])
        return render_template('main.html')

@app.route('/history', methods=['POST'])
def history()->'html':
    ar = []
    for x in c.find():
        ar.append(x["FileName"])
    print(ar)
    arra = {}
    for x in ar:
        arra[x] = c.find_one({'FileName': x})
    for x in arra:
        print(arra[x]["DATE"])
    return render_template('history.html', NAMEARRAY=ar, DATAARRAY=arra)

@app.route('/result2/<filename>', methods=['GET'])
def result2(filename)->'html':
    arr = c.find_one({'FileName': filename})
    return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"],
                           size=arr["DataSize"])

def insert(filename, n, Uploadtime):
    wordData = openfile(Upload_Folder, filename)
    print(wordData)

    post = {"FileName": filename, "DataSize": n, "DATE": Uploadtime,
            "DATA": wordData}
    db.word.insert(post, check_keys=False)

app.secret_key = 'thisismysecretsecretsecretkey'

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


import csv
import matplotlib.pyplot as plt
import numpy as np
import json
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.ensemble import RandomForestClassifier

def getdays(date1):
	year1 = int(date1[0] + date1[1] + date1[2] + date1[3])
	month1 = int(date1[4] + date1[5])
	date1 = int(date1[6] + date1[7])

	answer = 365*year1 + 30*month1 + date1
	return answer

def getmonth(date1):
	month1 = int(date1[4] + date1[5])
	return month1

# Reorders all csv files to fixed column ordering and loads to a ndarray
def create_add_year_matches(input_path, output_path):

	with open(input_path, 'r') as infile, open(output_path, 'w') as outfile:
	    # Output dict needs a list for new column ordering
	    fieldnames = ['tourney_id', #0
	                  'tourney_name', #1
	                  'surface', #2
	                  'draw_size', #3
	                  'tourney_level', #4
	                  'tourney_date', #5
	                  'match_num', #6
	                  'winner_id', #7
	                  'winner_seed', #8
	                  'winner_entry', #9
	                  'winner_name', #10
	                  'winner_hand', #11
	                  'winner_ht', #12
	                  'winner_ioc', #13
	                  'winner_age', #14
	                  'winner_rank', #15
	                  'winner_rank_points', #16
	                  'loser_id', #17
	                  'loser_seed', #18
	                  'loser_entry', #19
	                  'loser_name', #20
	                  'loser_hand', #21
	                  'loser_ht', #22
	                  'loser_ioc', #23
	                  'loser_age', #24
	                  'loser_rank', #25
	                  'loser_rank_points', #26
	                  'score', #27
	                  'best_of', #28
	                  'round', #29
	                  'minutes', #30
	                  'w_ace', #31
	                  'w_df', #32
	                  'w_svpt', #33
	                  'w_1stIn', #34
	                  'w_1stWon', #35
	                  'w_2ndWon', #36
	                  'w_SvGms', #37
	                  'w_bpSaved', #38
	                  'w_bpFaced', #39
	                  'l_ace', #40
	                  'l_df', #41
	                  'l_svpt', #42
	                  'l_1stIn', #43
	                  'l_1stWon', #44
	                  'l_2ndWon', #45
	                  'l_SvGms', #46
	                  'l_bpSaved', #47
	                  'l_bpFaced'] #48

	    writer = csv.DictWriter(outfile, fieldnames=fieldnames)
	    # reorder the header first
	    writer.writeheader()
	    for row in csv.DictReader(infile):
	        # writes the reordered rows to the new file
	        writer.writerow(row)

	inputs = np.loadtxt(output_path, dtype=np.dtype(str), delimiter=',', skiprows=1)
	return inputs

with open('atp_matches_1997.csv', 'r') as infile, open('reordered_atp_matches_1997.csv', 'w') as outfile:
    # output dict needs a list for new column ordering
    fieldnames = ['tourney_id', 'tourney_name', 'surface', 'draw_size', 'tourney_level', 'tourney_date', 'match_num', 'winner_id', 'winner_seed', 'winner_entry', 'winner_name', 'winner_hand', 'winner_ht', 'winner_ioc', 'winner_age', 'winner_rank', 'winner_rank_points' ,'loser_id', 'loser_seed'	,'loser_entry', 'loser_name', 'loser_hand', 'loser_ht' , 'loser_ioc', 'loser_age', 'loser_rank', 'loser_rank_points', 'score', 'best_of' ,'round', 'minutes', 'w_ace', 'w_df', 'w_svpt', 'w_1stIn', 'w_1stWon', 'w_2ndWon', 'w_SvGms', 'w_bpSaved', 'w_bpFaced', 'l_ace', 'l_df', 'l_svpt', 'l_1stIn', 'l_1stWon', 'l_2ndWon', 'l_SvGms', 'l_bpSaved', 'l_bpFaced']

    writer = csv.DictWriter(outfile, fieldnames=fieldnames)
    # reorder the header first
    writer.writeheader()
    for row in csv.DictReader(infile):
        # writes the reordered rows to the new file
        writer.writerow(row)

inputs = np.loadtxt("reordered_atp_matches_1997.csv", dtype=np.dtype(str), delimiter=',', skiprows=1)

for i in range(1998, 2019):
	input_path = 'atp_matches_' + str(i) + '.csv'
	output_path = 'reordered_atp_matches' + str(i) + '.csv'

	inputs_temp = create_add_year_matches(input_path, output_path)
	inputs = np.concatenate((inputs, inputs_temp))

for i in range(2010, 2018):
	input_path = 'atp_matches_qual_chall_' + str(i) + '.csv'
	output_path = 'reordered_atp_matches_qual_chall_matches' + str(i) + '.csv'

	inputs_temp = create_add_year_matches(input_path, output_path)
	inputs = np.concatenate((inputs, inputs_temp))

for i in range(2019, 2020):
	input_path = 'atp_matches_' + str(i) + '.csv'
	output_path = 'reordered_atp_matches' + str(i) + '.csv'

	inputs_temp = create_add_year_matches(input_path, output_path)
	inputs = np.concatenate((inputs, inputs_temp))

print(inputs.shape)

print(inputs[1])

num_rows, num_cols = inputs.shape
print(num_rows, num_cols)

print(inputs[0])

# Sanity checking tourney_id

ct = 0

for i in range(num_rows):
	if(inputs[i][0] == ""):
		ct = ct + 1

print(ct)

#Sanity checking tourney_name

ct = 0

for i in range(num_rows):
	if(inputs[i][1] == ""):
		ct = ct + 1

print(ct)

# Sanity checking surface and creating dict of surfaces

ct = 0
tc = 0
none_surfaces_rows = list()

for i in range(num_rows):
	if(inputs[i][2] == ""):
		ct = ct + 1
		none_surfaces_rows.append(i)

	if(inputs[i][2] == "None"):
		tc = tc + 1
		none_surfaces_rows.append(i)

inputs = np.delete(inputs, none_surfaces_rows, 0)

print(ct)
print(tc)

ct = 0
surfaces = dict()
size = 0

num_rows, num_cols = inputs.shape

for i in range(num_rows):
	if(inputs[i][2] == ""):
		ct = ct + 1
	else:
		if inputs[i][2] not in surfaces:
			surfaces[inputs[i][2]] = size
			size = size + 1

print(ct)
print(surfaces)

# Sanity checking draw_size

ct = 0
tc = 0
draw_sizes = dict()
size = 0

for i in range(num_rows):
	if(inputs[i][3] == ""):
		ct = ct + 1

	else:
		if inputs[i][3] not in draw_sizes:
			draw_sizes[inputs[i][3]] = size
			size = size + 1

print(draw_sizes)

print(ct)

# Drop tourey_name column
#inputs = np.delete(inputs, 1, axis=1)

# Drop draw_size column
#inputs = np.delete(inputs, 3, axis=1)

# Drop tourey_level column
#inputs = np.delete(inputs, 4, axis=1)

# Drop match_num column
#inputs = np.delete(inputs, 6, axis=1)

# Drop winner_name column
#inputs = np.delete(inputs, 10, axis=1)

# Drop loser_name column
#inputs = np.delete(inputs, 20, axis=1)

# Drop winner_ioc column - country of winner
#inputs = np.delete(inputs, 13, axis=1)

# Drop loser_ioc column - country of loser
#inputs = np.delete(inputs, 23, axis=1)

# Drop score
#inputs = np.delete(inputs, 27, axis=1)

# Sanity checking and sanitizing month from time of match

ct = 0

for i in range(num_rows):
	if(inputs[i][5] == ""):
		ct = ct + 1

print(ct)

# Sanity checking winner_id

ct = 0
federer_win = 0

for i in range(num_rows):
	if(inputs[i][7] == ""):
		ct = ct + 1

	if(inputs[i][17] == ""):
		ct = ct + 1

	if(inputs[i][7] == "103819"):
		federer_win = federer_win + 1

print(ct) # It comes out to be 0\
print(federer_win)

# Sanitizing winner_seed

ct = 0
federer_win = 0

for i in range(num_rows):
	if(inputs[i][8] == ""):
		ct = ct + 1
		inputs[i][8] = '40'

	if(inputs[i][18] == ""):
		ct = ct + 1
		inputs[i][18] = '40'

	if(not inputs[i][8].isdigit()):
		ct = ct + 1
		inputs[i][8] = '40'

	if(not inputs[i][18].isdigit()):
		ct = ct + 1
		inputs[i][18] = '40'

print(ct)

# Sanitizing winner_entry

ct = 0
federer_win = 0
entries = dict()
entry_type = 0

for i in range(num_rows):
	if inputs[i][9].lower() not in entries:
		entries[inputs[i][9].lower()] = entry_type
		entry_type = entry_type + 1

	if inputs[i][19].lower() not in entries:
		entries[inputs[i][19].lower()] = entry_type
		entry_type = entry_type + 1

	inputs[i][9] = entries[inputs[i][9].lower()]
	inputs[i][19] = entries[inputs[i][19].lower()]

print(entries)

# Sanitizing winner_hand - can only be left or right handed

for i in range(num_rows):
	if inputs[i][11].lower() == 'l':
		inputs[i][11] = '0'
	else:
		inputs[i][11] = '1'

	if inputs[i][21].lower() == 'l':
		inputs[i][21] = '0'
	else:
		inputs[i][21] = '1'

# Sanitizing winner_ht
# Making all winners without a height as height = -1

ct = 0

for i in range(num_rows):
	if inputs[i][12].lower() == "":
		ct = ct + 1
		inputs[i][12] = '-1'

	if inputs[i][22].lower() == "":
		ct = ct + 1
		inputs[i][22] = '-1'

# Too many players without a height - so just going to take difference in height as feature
# and make it 0 when input doesn't have it
print(ct)

# Sanitizing winner_age

ct = 0
total = 0.0
total_matches = 0

for i in range(num_rows):
	if inputs[i][14].lower() == "":
		ct = ct + 1
		inputs[i][14] = "26.08"
	else:
		total = total + float(inputs[i][14])
		total_matches = total_matches + 1

	if inputs[i][24].lower() == "":
		ct = ct + 1
		inputs[i][24] = "26.08"
	else:
		total = total + float(inputs[i][24])
		total_matches = total_matches + 1

# Seems like 26 is the average age of the winner
print(total/total_matches)

# Seems like 18 winners overall don't have an age - default to 26
print(ct)

# Sanitizing winner_rank and loser_rank - if no rank then replacing with 2000 which refers to a very high rank which
# represents the last rank

ct = 0

for i in range(num_rows):
	if(inputs[i][15] == ""):
			inputs[i][15] = 2000
			rank_1 = 2000
	else:
			rank_1 = int(inputs[i][15])

	if(inputs[i][25] == ""):
			inputs[i][25] = 2000
			rank_2 = 2000
	else:
			rank_2 = int(inputs[i][25])

	if(rank_1 < rank_2):
		ct = ct + 1

print(ct*100/num_rows)

benchmark_higher_rankings = ct*100/num_rows

# Sanitizing winner_rank points - if rankings points is empty replacing with 0

ct = 0

for i in range(num_rows):
	if(inputs[i][16] == ""):
		ct = ct + 1
		inputs[i][16] = 0

	if(inputs[i][26] == ""):
		ct = ct + 1
		inputs[i][26] = 0

print(ct)

# Sanity checking score

ct1 = 0
ct2 = 0
walkover_matches = list()

for i in range(num_rows):
	if(inputs[i][27] == ""):
		ct1 = ct1 + 1
		walkover_matches.append(i)
	if(inputs[i][27].lower() == "w/o"):
		ct2 = ct2 + 1
		walkover_matches.append(i)

print(ct1)
print(ct2)

inputs = np.delete(inputs, walkover_matches, 0)

num_rows, num_cols = inputs.shape

# Sanity checking best_of

ct = 0

for i in range(num_rows):
	if(inputs[i][28] == ""):
		ct = ct + 1

print(ct)

# Sanity checking and converting rounds to numbers

ct = 0
rounds = {'Q1' : -3, 'Q2' : -2, 'Q3': -3, 'R128': 0, 'RR': 0, 'BR': 0, 'R64': 1, 'R32': 2, 'R16': 3, 'QF': 4, 'SF': 5, 'F': 6}
type_rounds = 0

for i in range(num_rows):
	if(inputs[i][29] == ""):
		ct = ct + 1
	else:
		inputs[i][29] = rounds[inputs[i][29].upper()]

print(num_rows)
print(rounds)
print(ct)

# Sanity checking minutes

ct = 0
no_minutes = list()

for i in range(num_rows):
	if(inputs[i][30] == ""):
		ct = ct + 1
		no_minutes.append(i)

# Lots of rows without minutes
print(ct)

inputs = np.delete(inputs, no_minutes, 0)

num_rows, num_cols = inputs.shape

# Sanity checking all numerical features of the match - double faults, aces, first serve, etc.
#and deleting all rows that have any missing

ct = 0
missing_values = list()

for i in range(num_rows):
	for j in range(31, 49):
		if(inputs[i][j] == ""):
			ct = ct + 1
			missing_values.append(i)

print(ct)

inputs = np.delete(inputs, missing_values, 0)

num_rows, num_cols = inputs.shape

print(num_rows) #63770 rows in total

career_stats_winner = np.zeros((num_rows, 49))
career_stats_loser = np.zeros((num_rows, 49))
career_stats_winner_total = np.zeros((num_rows, 49))
career_stats_loser_total = np.zeros((num_rows, 49))

x = 0

player_id_stats_overall_sum = [dict() for x in range(num_cols)]
player_id_stats_overall_count = [dict() for x in range(num_cols)]
player_name = dict()

delete_list = []

count_2019 = 0

for i in range(num_rows):
	if inputs[i][5][0] == '2' and inputs[i][5][1] == '0' and inputs[i][5][2] == '1' and inputs[i][5][3] == '9' and getmonth(inputs[i][5]) > 6:
		count_2019+=1

# Delete davis cup matches in prediction - they are generally extremely hard to predict
# If Davis Cup matches needs to be predicted the most likely best way to do is to have a different model for davis cup
for i in range(num_rows - count_2019, num_rows):
	if "davis" in inputs[i][1].lower():
		delete_list.append(i)

inputs = np.delete(inputs, delete_list, 0)

num_rows, num_cols = inputs.shape

count_2019 = 0

for i in range(num_rows):
	if inputs[i][5][0] == '2' and inputs[i][5][1] == '0' and inputs[i][5][2] == '1' and inputs[i][5][3] == '9' and getmonth(inputs[i][5]) > 6:
		count_2019+=1

X_inputs = np.zeros((2*(num_rows - count_2019), 51))
Y_inputs = np.zeros(2*(num_rows - count_2019))

X_prediction = np.zeros((2*count_2019, 51))
Y_prediction = np.zeros(2*count_2019)

print(count_2019)

matches_won_lost = dict()

head_to_head = dict()
head_to_head_surface = dict()
matches_won_lost_surface = dict()

rank_count = dict()
rank_total = dict()
rankings_points_total = dict()

form = dict()
form_surface = dict()

tournament_form_win = dict()
tournament_form_count = dict()

common_head_to_head = dict()
total_no_head_to_head = 0

for i in range(num_rows):
	player_id_winner = inputs[i][7]
	player_id_loser = inputs[i][17]

	# Start of Tournament level form

	if (player_id_winner, inputs[i][0][5:]) not in tournament_form_win:
		tournament_form_win[(player_id_winner, inputs[i][0][5:])] = 0
		tournament_form_count[(player_id_winner, inputs[i][0][5:])] = 0

	if (player_id_loser, inputs[i][0][5:]) not in tournament_form_win:
		tournament_form_win[(player_id_loser, inputs[i][0][5:])] = 0
		tournament_form_count[(player_id_loser, inputs[i][0][5:])]  = 0

	tournament_form_win[(player_id_winner, inputs[i][0][5:])] += 1
	tournament_form_win[(player_id_loser, inputs[i][0][5:])] += 0

	tournament_form_count[(player_id_winner, inputs[i][0][5:])] += 1
	tournament_form_count[(player_id_loser, inputs[i][0][5:])] += 1

	if i < num_rows - count_2019:
		X_inputs[2*i][44] = tournament_form_win[(player_id_winner, inputs[i][0][5:])] - 1 - tournament_form_win[(player_id_loser, inputs[i][0][5:])]
		X_inputs[2*i][45] = tournament_form_count[(player_id_winner, inputs[i][0][5:])] - tournament_form_count[(player_id_loser, inputs[i][0][5:])]

		temp11 = 1
		temp12 = 1

		if tournament_form_count[(player_id_winner, inputs[i][0][5:])] != 1:
			temp11 = tournament_form_count[(player_id_winner, inputs[i][0][5:])]
		if tournament_form_count[(player_id_loser, inputs[i][0][5:])]  != 1:
			temp12 = tournament_form_count[(player_id_loser, inputs[i][0][5:])]

		X_inputs[2*i][46] = ((tournament_form_win[(player_id_winner, inputs[i][0][5:])] - 1)*100/temp11) - ((tournament_form_win[(player_id_loser, inputs[i][0][5:])])*100/temp12)

		X_inputs[2*i+1][44] =  -X_inputs[2*i][44]
		X_inputs[2*i+1][45] = -X_inputs[2*i][45]
		X_inputs[2*i+1][46] = -X_inputs[2*i][46]
	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))

		X_prediction[x1][44] = tournament_form_win[(player_id_winner, inputs[i][0][5:])] - 1 - tournament_form_win[(player_id_loser, inputs[i][0][5:])]
		X_prediction[x1][45] = tournament_form_count[(player_id_winner, inputs[i][0][5:])] - tournament_form_count[(player_id_loser, inputs[i][0][5:])]

		temp11 = 1
		temp12 = 1

		if tournament_form_count[(player_id_winner, inputs[i][0][5:])] != 1:
			temp11 = tournament_form_count[(player_id_winner, inputs[i][0][5:])]
		if tournament_form_count[(player_id_loser, inputs[i][0][5:])]  != 1:
			temp12 = tournament_form_count[(player_id_loser, inputs[i][0][5:])]

		X_prediction[x1][46] = ((tournament_form_win[(player_id_winner, inputs[i][0][5:])] - 1)*100/temp11) - ((tournament_form_win[(player_id_loser, inputs[i][0][5:])])*100/temp12)

		X_prediction[x1+1][44] =  -X_prediction[x1][44]
		X_prediction[x1+1][45] = -X_prediction[x1][45]
		X_prediction[x1+1][46] = -X_prediction[x1][46]

	# End of Tournament level form

	# Start of overall form

	if player_id_winner not in form:
		form[player_id_winner] = []

	form[player_id_winner].append((1, inputs[i][5]))

	if player_id_loser not in form:
		form[player_id_loser] = []

	form[player_id_loser].append((0, inputs[i][5]))

	total_winner_5 = -1
	total_winner_10 = -1
	total_winner_15 = -1
	total_winner_25 = -1

	total_loser_5 = -1
	total_loser_10 = -1
	total_loser_15 = -1
	total_loser_25 = -1

	winner_win_5 = 0
	winner_win_10 = 0
	winner_win_15 = 0
	winner_win_25 = 0

	loser_win_5 = 0
	loser_win_10 = 0
	loser_win_15 = 0
	loser_win_25 = 0

	for (a1, a2) in reversed(form[player_id_winner]):
		if total_winner_5 == -1:
			total_winner_5 = 0
		else:
			if total_winner_5 < 5:
				winner_win_5 = winner_win_5 + a1
				total_winner_5 += 1

	for (a1, a2) in reversed(form[player_id_winner]):
		if total_winner_10 == -1:
			total_winner_10 = 0
		else:
			if total_winner_10 < 10:
				winner_win_10 = winner_win_10 + a1
				total_winner_10 += 1

	for (a1, a2) in reversed(form[player_id_winner]):
		if total_winner_15 == -1:
			total_winner_15 = 0
		else:
			if total_winner_15 < 15:
				winner_win_15 = winner_win_15 + a1
				total_winner_15 += 1

	for (a1, a2) in reversed(form[player_id_winner]):
		if total_winner_25 == -1:
			total_winner_25 = 0
		else:
			if total_winner_25 < 25:
				winner_win_25 = winner_win_25 + a1
				total_winner_25 += 1

	for (a1, a2) in reversed(form[player_id_loser]):
		if total_loser_5 == -1:
			total_loser_5 = 0
		else:
			if total_loser_5 < 5:
				loser_win_5 = loser_win_5 + a1
				total_loser_5 += 1

	for (a1, a2) in reversed(form[player_id_loser]):
		if total_loser_10 == -1:
			total_loser_10 = 0
		else:
			if total_loser_10 < 10:
				loser_win_10 = loser_win_10 + a1
				total_loser_10 += 1

	for (a1, a2) in reversed(form[player_id_loser]):
		if total_loser_15 == -1:
			total_loser_15 = 0
		else:
			if total_loser_15 < 15:
				loser_win_15 = loser_win_15 + a1
				total_loser_15 += 1

	for (a1, a2) in reversed(form[player_id_loser]):
		if total_loser_25 == -1:
			total_loser_25 = 0
		else:
			if total_loser_25 < 25:
				loser_win_25 = loser_win_25 + a1
				total_loser_25 += 1

	if i < num_rows - count_2019:
		X_inputs[2*i][36] = winner_win_5 - loser_win_5
		X_inputs[2*i][37] = winner_win_10 - loser_win_10
		X_inputs[2*i][38] = winner_win_15 - loser_win_15
		X_inputs[2*i][39] = winner_win_25 - loser_win_25

		X_inputs[2*i+1][36] = loser_win_5 - winner_win_5
		X_inputs[2*i+1][37] = loser_win_10 - winner_win_10
		X_inputs[2*i+1][38] = loser_win_15 - winner_win_15
		X_inputs[2*i+1][39] = loser_win_25 - winner_win_25

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))

		X_prediction[x1][36] = winner_win_5 - loser_win_5
		X_prediction[x1][37] = winner_win_10 - loser_win_10
		X_prediction[x1][38] = winner_win_15 - loser_win_15
		X_prediction[x1][39] = winner_win_25 - loser_win_25

		X_prediction[x1+1][36] = loser_win_5 - winner_win_5
		X_prediction[x1+1][37] = loser_win_10 - winner_win_10
		X_prediction[x1+1][38] = loser_win_15 - winner_win_15
		X_prediction[x1+1][39] = loser_win_25 - winner_win_25

	# End of overall form

	# Start of last 1 month form overall

	total_winner_1 = -1
	total_loser_1 = -1
	winner_win_1 = 0
	loser_win_1 = 0

	for (a1, a2) in reversed(form[player_id_winner]):
		if total_winner_1 == -1:
			total_winner_1 = 0
		else:
			if getdays(inputs[i][5]) - getdays(a2) < 30 and getdays(inputs[i][5]) - getdays(a2) >= 0:
				winner_win_1 = winner_win_1 + a1
				total_winner_1 += 1
				#print(getdays(inputs[i][5]) - getdays(a2), a2, inputs[i][5], i, 1, total_winner_1)
			else:
				break

	for (a1, a2) in reversed(form[player_id_loser]):
		if total_loser_1 == -1:
			total_loser_1 = 0
		else:
			if getdays(inputs[i][5]) - getdays(a2) < 30 and getdays(inputs[i][5]) - getdays(a2) >= 0:
				loser_win_1 = loser_win_1 + a1
				total_loser_1 += 1
				#print(getdays(inputs[i][5]) - getdays(a2), a2, inputs[i][5], i, 5, total_loser_1)
			else:
				break

	if i < num_rows - count_2019:
		X_inputs[2*i][47] = winner_win_1 - loser_win_1
		X_inputs[2*i+1][47] = loser_win_1 - winner_win_1
		X_inputs[2*i][48] = total_winner_1 - total_loser_1
		X_inputs[2*i+1][48] = total_loser_1 - total_winner_1

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))

		X_prediction[x1][47] = winner_win_1 - loser_win_1
		X_prediction[x1+1][47] = loser_win_1 - winner_win_1
		X_prediction[x1][48] = total_winner_1 - total_loser_1
		X_prediction[x1+1][48] = total_loser_1 - total_winner_1

	# End of last 1 month form overall
	# I tried adding 3, 6 and 12 month forms as well - it didn't seem to help - in fact made the prediction worse

	# Start of surface level form

	if player_id_winner not in form_surface:
		form_surface[(player_id_winner, inputs[i][2])] = []

	form_surface[(player_id_winner, inputs[i][2])].append((1, inputs[i][5]))

	if player_id_loser not in form_surface:
		form_surface[(player_id_loser, inputs[i][2])] = []

	form_surface[(player_id_loser, inputs[i][2])].append((0, inputs[i][5]))

	total_winner_5 = -1
	total_winner_10 = -1
	total_winner_15 = -1
	total_winner_25 = -1

	total_loser_5 = -1
	total_loser_10 = -1
	total_loser_15 = -1
	total_loser_25 = -1

	winner_win_5 = 0
	winner_win_10 = 0
	winner_win_15 = 0
	winner_win_25 = 0

	loser_win_5 = 0
	loser_win_10 = 0
	loser_win_15 = 0
	loser_win_25 = 0

	for (a1, a2) in reversed(form_surface[(player_id_winner, inputs[i][2])]):
		if total_winner_5 == -1:
			total_winner_5 = 0
		else:
			if total_winner_5 < 5:
				winner_win_5 = winner_win_5 + a1
				total_winner_5 += 1

	for (a1, a2) in reversed(form_surface[(player_id_winner, inputs[i][2])]):
		if total_winner_10 == -1:
			total_winner_10 = 0
		else:
			if total_winner_10 < 10:
				winner_win_10 = winner_win_10 + a1
				total_winner_10 += 1

	for (a1, a2) in reversed(form_surface[(player_id_winner, inputs[i][2])]):
		if total_winner_15 == -1:
			total_winner_15 = 0
		else:
			if total_winner_15 < 15:
				winner_win_15 = winner_win_15 + a1
				total_winner_15 += 1

	for (a1, a2) in reversed(form_surface[(player_id_winner, inputs[i][2])]):
		if total_winner_25 == -1:
			total_winner_25 = 0
		else:
			if total_winner_25 < 25:
				winner_win_25 = winner_win_25 + a1
				total_winner_25 += 1

	for (a1, a2) in reversed(form_surface[(player_id_loser, inputs[i][2])]):
		if total_loser_5 == -1:
			total_loser_5 = 0
		else:
			if total_loser_5 < 5:
				loser_win_5 = loser_win_5 + a1
				total_loser_5 += 1

	for (a1, a2) in reversed(form_surface[(player_id_loser, inputs[i][2])]):
		if total_loser_10 == -1:
			total_loser_10 = 0
		else:
			if total_loser_10 < 10:
				loser_win_10 = loser_win_10 + a1
				total_loser_10 += 1

	for (a1, a2) in reversed(form_surface[(player_id_loser, inputs[i][2])]):
		if total_loser_15 == -1:
			total_loser_15 = 0
		else:
			if total_loser_15 < 15:
				loser_win_15 = loser_win_15 + a1
				total_loser_15 += 1

	for (a1, a2) in reversed(form_surface[(player_id_loser, inputs[i][2])]):
		if total_loser_25 == -1:
			total_loser_25 = 0
		else:
			if total_loser_25 < 25:
				loser_win_25 = loser_win_25 + a1
				total_loser_25 += 1

	if i < num_rows - count_2019:
		X_inputs[2*i][40] = winner_win_5 - loser_win_5
		X_inputs[2*i][41] = winner_win_10 - loser_win_10
		X_inputs[2*i][42] = winner_win_15 - loser_win_15
		X_inputs[2*i][43] = winner_win_25 - loser_win_25

		X_inputs[2*i+1][40] = loser_win_5 - winner_win_5
		X_inputs[2*i+1][41] = loser_win_10 - winner_win_10
		X_inputs[2*i+1][42] = loser_win_15 - winner_win_15
		X_inputs[2*i+1][43] = loser_win_25 - winner_win_25

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))

		X_prediction[x1][40] = winner_win_5 - loser_win_5
		X_prediction[x1][41] = winner_win_10 - loser_win_10
		X_prediction[x1][42] = winner_win_15 - loser_win_15
		X_prediction[x1][43] = winner_win_25 - loser_win_25

		X_prediction[x1+1][40] = loser_win_5 - winner_win_5
		X_prediction[x1+1][41] = loser_win_10 - winner_win_10
		X_prediction[x1+1][42] = loser_win_15 - winner_win_15
		X_prediction[x1+1][43] = loser_win_25 - winner_win_25

	# End of surface level form

	# Start of Overall win loss

	p1, p2 = (0, 0)
	b1, b2 = (0, 0)

	if player_id_winner not in matches_won_lost:
		matches_won_lost[player_id_winner] = (1, 0)
		(p1, p2) = (0, 0)
	else:
		(a1, a2) = matches_won_lost[player_id_winner]
		matches_won_lost[player_id_winner] = (a1 + 1, a2)
		(p1, p2) = (a1, a2)

	if player_id_loser not in matches_won_lost:
		matches_won_lost[player_id_loser] = (0, 1)
		(b1, b2) = (0, 0)
	else:
		(a1, a2) = matches_won_lost[player_id_loser]
		matches_won_lost[player_id_loser] = (a1, a2 + 1)
		(b1, b2) = (a1, a2)

	if((p1 + p2) != 0):
		temp1 = (p1*100/(p1+p2))
	else:
		temp1 = 0

	if((b1 + b2) != 0):
		temp2 = (b1*100/(b1+b2))
	else:
		temp2 = 0

	if i < num_rows - count_2019:
		X_inputs[2*i][25] = p1 - b1
		X_inputs[2*i+1][25] = b1 - p1

		X_inputs[2*i][26] =  temp1 - temp2
		X_inputs[2*i+1][26] = temp2 - temp1

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
		X_prediction[x1][25] = p1 - b1
		X_prediction[x1+1][25] = b1 - p1

		X_prediction[x1][26] = temp1 - temp2
		X_prediction[x1+1][26] = temp2 - temp1

# End of Overall win loss

# Start of section for win loss based on surface

	p1, p2 = (0, 0)
	b1, b2 = (0, 0)

	if (player_id_winner, inputs[i][2]) not in matches_won_lost_surface:
		matches_won_lost_surface[(player_id_winner, inputs[i][2])] = (1, 0)
		(p1, p2) = (0, 0)
	else:
		(a1, a2) = matches_won_lost_surface[(player_id_winner, inputs[i][2])]
		matches_won_lost_surface[(player_id_winner, inputs[i][2])] = (a1 + 1, a2)
		(p1, p2) = (a1, a2)

	if (player_id_loser, inputs[i][2]) not in matches_won_lost_surface:
		matches_won_lost_surface[(player_id_loser, inputs[i][2])] = (0, 1)
		(b1, b2) = (0, 0)
	else:
		(a1, a2) = matches_won_lost_surface[(player_id_loser, inputs[i][2])]
		matches_won_lost_surface[(player_id_loser, inputs[i][2])] = (a1, a2 + 1)
		(b1, b2) = (a1, a2)

	if((p1 + p2) != 0):
		temp1 = (p1*100/(p1+p2))
	else:
		temp1 = 0

	if((b1 + b2) != 0):
		temp2 = (b1*100/(b1+b2))
	else:
		temp2 = 0

	if i < num_rows - count_2019:
		X_inputs[2*i][33] = p1 - b1
		X_inputs[2*i+1][33] = b1 - p1

		X_inputs[2*i][34] =  temp1 - temp2
		X_inputs[2*i+1][34] = temp2 - temp1

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
		X_prediction[x1][33] = p1 - b1
		X_prediction[x1+1][33] = b1 - p1

		X_prediction[x1][34] = temp1 - temp2
		X_prediction[x1+1][34] = temp2 - temp1

# End of section for win loss based on surface

# Start of Overall Head to Head

	if (player_id_winner, player_id_loser) not in head_to_head:
		head_to_head[(player_id_winner, player_id_loser)] = (1, 0)
		head_to_head[(player_id_loser, player_id_winner)] = (0, 1)
		if i < num_rows - count_2019:
			X_inputs[2*i][15] = 1
			X_inputs[2*i+1][15] = -1
		else:
			x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
			total_no_head_to_head = total_no_head_to_head + 1
			print(inputs[i][10], inputs[i][20])
			X_prediction[x1][15] = 1
			X_prediction[x1+1][15] = -1

	else:
		(a1, a2) = head_to_head[(player_id_winner, player_id_loser)]

		if i < num_rows - count_2019:
			X_inputs[2*i][15] = a1 - a2
			X_inputs[2*i+1][15] = a2 - a1
		else:
			x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
			X_prediction[x1][15] = a1 - a2
			X_prediction[x1+1][15] = a2 - a1

		head_to_head[(player_id_winner, player_id_loser)] = (a1 + 1, a2)
		head_to_head[(player_id_loser, player_id_winner)] = (a2, a1 + 1)

# End of Overall Head to Head

# Start of Common Opponent Head to Head

	if player_id_winner not in common_head_to_head:
		common_head_to_head[player_id_winner] =  {player_id_loser: (0, 0)}

	if player_id_loser not in common_head_to_head:
		common_head_to_head[player_id_loser] = {player_id_winner: (0, 0)}

	if player_id_loser not in common_head_to_head[player_id_winner]:
		common_head_to_head[player_id_winner][player_id_loser] = (0, 0)

	if player_id_winner not in common_head_to_head[player_id_loser]:
		common_head_to_head[player_id_loser][player_id_winner] = (0, 0)

	(x11, y11) = common_head_to_head[player_id_winner][player_id_loser]
	(x22, y22) = common_head_to_head[player_id_loser][player_id_winner]
	common_head_to_head[player_id_winner][player_id_loser] = (x11+1, y11)
	common_head_to_head[player_id_loser][player_id_winner] = (x22, y22+1)

	new_head_to_head_winner = (0, 0)
	new_head_to_head_loser = (0, 0)

	for player_id in common_head_to_head[player_id_winner]:
		if player_id in common_head_to_head[player_id_loser]:
			(temp1, temp2) = common_head_to_head[player_id_winner][player_id]
			t1, t2 = new_head_to_head_winner
			new_head_to_head_winner = t1 + temp1, t2 + temp2

	for player_id in common_head_to_head[player_id_loser]:
		if player_id in common_head_to_head[player_id_winner]:
			(temp1, temp2) = common_head_to_head[player_id_loser][player_id]
			t1, t2 = new_head_to_head_loser
			new_head_to_head_loser = t1 + temp1, t2 + temp2

	temp1, temp2 = new_head_to_head_winner
	temp3, temp4 = new_head_to_head_loser

	temp5 = 0
	temp6 = 0

	if(temp1 + temp2) != 0:
		temp5 = ((temp1*100)/(temp1+temp2))

	if(temp3 + temp4) != 0:
		temp6 = ((temp3*100)/(temp3+temp4))

	if i < num_rows - count_2019:
		X_inputs[2*i][49] = temp1 - temp3
		X_inputs[2*i][49] =  temp5 - temp6
		X_inputs[2*i+1][50] = temp3 - temp1
		X_inputs[2*i+1][50] = temp6 - temp5

	else:
		x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
		X_prediction[x1][49] = temp1 - temp3
		X_prediction[x1][49] = temp5 - temp6
		X_prediction[x1+1][50] = temp3 - temp1
		X_prediction[x1+1][50] = temp6 - temp5

# End of Common Opponent Head to Head

# Start of surface level head to head

	if (player_id_winner, player_id_loser, inputs[i][2]) not in head_to_head_surface:
		if i < num_rows - count_2019:
			X_inputs[2*i][35] = 0
			X_inputs[2*i+1][35] = 0
		else:
			x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
			X_prediction[x1][35] = 0
			X_prediction[x1+1][35] = 0

		head_to_head_surface[(player_id_winner, player_id_loser, inputs[i][2])] = (1, 0)
		head_to_head_surface[(player_id_loser, player_id_winner, inputs[i][2])] = (0, 1)
	else:
		(a1, a2) = head_to_head_surface[(player_id_winner, player_id_loser, inputs[i][2])]

		if i < num_rows - count_2019:
			X_inputs[2*i][35] = a1 - a2
			X_inputs[2*i+1][35] = a2 - a1
		else:
			x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
			X_prediction[x1][35] = a1 - a2
			X_prediction[x1+1][35] = a2 - a1

		head_to_head_surface[(player_id_winner, player_id_loser, inputs[i][2])] = (a1 + 1, a2)
		head_to_head_surface[(player_id_loser, player_id_winner, inputs[i][2])] = (a2, a1 + 1)

# End of surface level head to head

	for j in range(31, 40):
		if player_id_winner not in player_id_stats_overall_count[j-31]:

			career_stats_winner[i][j] = 0
			career_stats_winner_total[i][j] = 0

			player_id_stats_overall_count[j-31][player_id_winner] = 1
			player_id_stats_overall_sum[j-31][player_id_winner] = int(inputs[i][j])
			player_name[player_id_winner] = inputs[i][10]
		else:
			career_stats_winner[i][j] = player_id_stats_overall_sum[j-31][player_id_winner]/player_id_stats_overall_count[j-31][player_id_winner]
			career_stats_winner_total[i][j] = player_id_stats_overall_sum[j-31][player_id_winner]

			player_id_stats_overall_count[j-31][player_id_winner] = player_id_stats_overall_count[j-31][player_id_winner] + 1
			player_id_stats_overall_sum[j-31][player_id_winner] = player_id_stats_overall_sum[j-31][player_id_winner] + int(inputs[i][j])
			player_name[player_id_winner] = inputs[i][10]

	for j in range(40, 49):
		if player_id_loser not in player_id_stats_overall_count[j-40]:

			career_stats_loser[i][j] = 0
			career_stats_loser_total[i][j] = 0

			player_id_stats_overall_count[j-40][player_id_loser] = 1
			player_id_stats_overall_sum[j-40][player_id_loser] = int(inputs[i][j])
			player_name[player_id_loser] = inputs[i][20]
		else:
			career_stats_loser[i][j] = player_id_stats_overall_sum[j-40][player_id_loser]/player_id_stats_overall_count[j-40][player_id_loser]
			career_stats_loser_total[i][j] = player_id_stats_overall_sum[j-40][player_id_loser]

			player_id_stats_overall_count[j-40][player_id_loser] = player_id_stats_overall_count[j-40][player_id_loser] + 1
			player_id_stats_overall_sum[j-40][player_id_loser] = player_id_stats_overall_sum[j-40][player_id_loser] + int(inputs[i][j])
			player_name[player_id_loser] = inputs[i][20]

		if i < num_rows - count_2019:
			X_inputs[2*i][j-40] = career_stats_winner[i][j-9] - career_stats_loser[i][j]
			X_inputs[2*i+1][j-40] = career_stats_loser[i][j] - career_stats_winner[i][j-9]
			X_inputs[2*i][j-24] = career_stats_winner_total[i][j-9] - career_stats_loser_total[i][j]
			X_inputs[2*i+1][j-24] = career_stats_loser_total[i][j] - career_stats_winner_total[i][j-9]

		else:
			x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
			X_prediction[x1][j-40] = career_stats_winner[i][j-9] - career_stats_loser[i][j]
			X_prediction[x1+1][j-40] = career_stats_loser[i][j] - career_stats_winner[i][j-9]
			X_prediction[x1][j-24] = career_stats_winner_total[i][j-9] - career_stats_loser_total[i][j]
			X_prediction[x1+1][j-24] = career_stats_loser_total[i][j] - career_stats_winner_total[i][j-9]

	#15, 16, 25, 26

	if player_id_winner not in rank_count:
		rank_count[player_id_winner] = 1
		rank_total[player_id_winner] = inputs[i][15]
		rankings_points_total[player_id_winner] = inputs[i][16]
	else:
		rank_count[player_id_winner] += 1
		rank_total[player_id_winner] += inputs[i][15]
		rankings_points_total[player_id_winner] += inputs[i][16]

	if player_id_loser not in rank_count:
		rank_count[player_id_loser] = 1
		rank_total[player_id_loser] = inputs[i][25]
		rankings_points_total[player_id_loser] = inputs[i][26]
	else:
		rank_count[player_id_loser] += 1
		rank_total[player_id_loser] += inputs[i][25]
		rankings_points_total[player_id_loser] += inputs[i][26]

	# 26, 25, 24, 22, 21, 18 - 16, 15, 14, 12, 11, 8
	k = 9

	for j in range(18, 27):
		if j != 19 and j != 20 and j != 23:
			if i < num_rows - count_2019:
				X_inputs[2*i][k] = float(inputs[i][j-10])
				X_inputs[2*i][k+18] = float(inputs[i][j])
				X_inputs[2*i+1][k] = float(inputs[i][j])
				X_inputs[2*i+1][k+18] = float(inputs[i][j-10])

				if j == 22 and (int(inputs[i][j-10]) == -1 or int(inputs[i][j]) == -1):
					X_inputs[2*i][k] = 0
					X_inputs[2*i][k+18] = 0
					X_inputs[2*i+1][k] = 0
					X_inputs[2*i+1][k+18] = 0
				k += 1
			else:
				x1 = int(2*i - 2*int(num_rows) + 2*int(count_2019))
				X_prediction[x1][k] = float(inputs[i][j-10])
				X_prediction[x1][k+18] = float(inputs[i][j])
				X_prediction[x1+1][k] = float(inputs[i][j])
				X_prediction[x1+1][k+18] = float(inputs[i][j-10])

				if j == 22 and (int(inputs[i][j-10]) == -1 or int(inputs[i][j]) == -1):
					X_prediction[x1][k] = 0
					X_prediction[x1][k+18] = 0
					X_prediction[x1+1][k] = 0
					X_prediction[x1+1][k+18] = 0

				k += 1

	if i < num_rows - count_2019:
		Y_inputs[2*i] = 1
		Y_inputs[2*i+1] = 0
	else:
		x1 = 2*i - 2*int(num_rows) + 2*int(count_2019)
		Y_prediction[x1] = 1
		Y_prediction[x1+1] = 0

clf = LogisticRegression(multi_class='ovr', random_state=0, solver='liblinear', penalty='l2').fit(X_inputs, Y_inputs)
training_prediction = clf.predict_proba(X_prediction)

np.savetxt("training_data.csv", X_inputs, delimiter=",")

total = count_2019
right = 0

print(training_prediction.shape)

for i in range(count_2019):
	(a, b) = training_prediction[2*i]
	(c, d) = training_prediction[2*i+1]

	if a < b and c > d:
		predicted = 1
	else:
		if a > b and c < d:
			predicted = 0
		else:
			if a + d < b + c:
				predicted = 1
			else:
				predicted = 0

	if Y_prediction[2*i] == predicted:
		right = right + 1

print(total)
print(right)
print(right*100/total)

training_prediction_1 = clf.predict(X_inputs)

total = 2*(num_rows - count_2019)
right = 0

for i in range(2*(num_rows - count_2019)):
	if Y_inputs[i] == training_prediction_1[i]:
		right = right + 1

print(total)
print(right)
print(right*100/total)

print(total_no_head_to_head)

# it was 59.5% with 9 features which were just stats,
# with ranking, seed, ranking points, basically values known pre-match which describe the player - improved to 62.5%
#62.654205607476634 - l1 penalty
# lbfgs - l2 - 62.57943925233645

#clf = svm.SVC(kernel='linear')
#clf.fit(X_inputs, Y_inputs)

#svm.SVC(kernel='linear')
#svm.SVC(kernel='rbf')
#svm.SVC(kernel=‘sigmoid’)
#svm.SVC(kernel=‘poly')
#logistic regression - penaltystr, ‘l1’, ‘l2’, ‘elasticnet’ or ‘none’, optional (default=’l2’)

#predictions_svm_svc = clf.predict(X_prediction)

#right = 0

#for i in range(2*count_2019):
#	if Y_prediction[i] == predictions_svm_svc[i]:
#		right = right + 1

#print(total)
#print(right)
#print(right*100/total)

# Sanity testing whether the total number of aces of Federer calculated the real aces - it matches!!
for player_id in player_id_stats_overall_count[0]:
	if "Federer" in player_name[player_id]:
		print(player_name[player_id], player_id_stats_overall_sum[0][player_id], player_id_stats_overall_count[0][player_id])


# -*- coding: utf-8 -*-

"""
Module implementing EnterOperatorID.
"""
import PyQt4.QtGui, PyQt4.QtCore, sys
import VayaMfgTool
import Ui_VayaMfgMainWin

from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QDialog
from PyQt4.QtCore import pyqtSignature

from Ui_IdInput import Ui_EnterOperatorID

class EnterOperatorID(QDialog, Ui_EnterOperatorID):
    """
    Class documentation goes here.
    """
    def __init__(self, parent = None):
        """
        Constructor
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)

    @pyqtSignature("")
    def on_pushButton_clicked(self):
        app = PyQt4.QtGui.QApplication(sys.argv)
        ui = Ui_VayaMfgMainWin.Ui_MainWindow() #should use local class
        ui.show()
        sys.exit(app.exec_())

    @pyqtSignature("")
    def on_pushButton_2_clicked(self):
        sys.exit(app.exec_())

if __name__ == "__main__":
    app = PyQt4.QtGui.QApplication(sys.argv)
    ui = EnterOperatorID()
    ui.show()
    sys.exit(app.exec_())


'''
                                        Author:xtncsg（想听你唱首歌）
                                        create；2019-04-18
                                        update；2019-04-19
                                        bug:输入闹钟时间的时候，不能直接把输入框里面的数字全都删除
                                        unknown:ctypes 蜂鸣器
                                                StringVar()绑定变量
                                                局部函数里使用全局变量要global说明
                                                massagebox弹窗的自动关闭
                                                好像没有 RGB(255,255,255)这样生成颜色的宏
                                                同一个标签变量，不能两次放置，只会显示一次
                                                bind() 事件处理的绑定
                                                root.quit 和 root.destroy 的区别
'''

# from tkinter import*   并不鼓励使用from Tkinter import * 说是失去命名空间同时导致名字冲突
import tkinter
from datetime import datetime
import tkinter.messagebox as ms
import time
from threading import Thread
import  ctypes    # 关于系统蜂鸣器的库
player = ctypes.windll.kernel32  # 都是字母 l

# 生成全局窗口
root = tkinter.Tk()
root.title("闹钟定制")
# root.minsize(width = 800,height = 640)
root.geometry("1000x580") # 还可以继续缩小的窗口,中间是英文 x
# root.resizable(width = 1,height = 0)    设置窗口是否可以改变大小

game = tkinter.Label(root,text = "设置好闹钟时间后，若显示为ON则闹钟已经成功开启",height = 5,width = 50,bg = "#33FF00",fg = "#FF0000",font = 6)
game.place(x = 320,y = 5)

'''    必须要先生成窗口，才能绑定变量，因为StringVar 这个类里面，有一个成员函数 __init__(self, master=None, value=None, name=None)，
它的参数MASTER can be given as master widget.    '''

# 获取当前时间
# print(type(datetime.now()))  <class 'datetime.datetime'>
current_hour = datetime.now().hour
current_minute = datetime.now().minute
current_second = datetime.now().second
# print(type(curent_hour))  <class 'int'>

# 能自动刷新的字符串变量，可用set和get方法进行传值和取值
now_hour = tkinter.StringVar(value = current_hour)
now_minute = tkinter.StringVar(value = current_minute)
now_second = tkinter.StringVar(value = current_second)
# print(now_hour)         PY_VAR0
# print(type(now_hour))   <class 'tkinter.StringVar'>

clock_flag = False

# 与按键 ON/OFF 绑定的启动闹钟函数
def boot_clock():
    # global 说明这里的变量与外面的全局变量是一样的
    global clock_flag  #  local variable 'clock_flag' referenced before assignment
    clock_flag = not clock_flag

    clock_hour = int(hour_entry.get())  # 获取输入框里面的时间
    clock_minute = int(minute_entry.get())
    clock_second = int(second_entry.get())
    # print(type(clock_hour))  <class 'str'>

    if(clock_hour >= 24 or clock_minute >= 60 or clock_second >=60):
        ms.showerror("错误","闹钟时间设置错误\n请重新设置")
        # sys.exit(0)  这样整个程序就退出了，还是用 else 吧
    else:
         if(clock_flag):
            ms.showinfo("闹钟已经开启","闹钟将在{}时{}分{}秒时启动\n请注意躲避".format(clock_hour,clock_minute,clock_second))
            # showinfo(),showerror(),showwarning()
            confirm["text"] = "ON"
         else:
            confirm["text"] = "OFF"

# 响铃函数
def ring():
    for i in range(10):
        player.Beep(2000,1000)  # 频率和毫秒

# 时间匹配时，闹钟开始运行
def clock_start():
    Thread(target = ring).start()
    ms.showwarning("闹钟进行","闹钟开始了，大家快跑啊")
# 这里创建线程，要不然弹窗不关闭，就不会响铃

def timer():
    while(1):
        hour_num = int(now_hour.get()) # 获取当前时间
        minute_num = int(now_minute.get())
        second_num = int(now_second.get())
        # print(type(hour_num))  <class 'str'>

        # 非纯数字组成的字符串强转为整型会报错：ValueError: invalid literal for int() with base 10
        # 所以在输入框输入数字的时候，不能一下子把原来的数字都删掉，这样就变成空字符串了
        clock_hour = int(hour_entry.get())  # 获取输入框里面的时间
        clock_minute = int(minute_entry.get())
        clock_second = int(second_entry.get())
        # print(type(clock_hour))  <class 'str'>

        second_num += 1
        if second_num == 60:
            minute_num +=1
            second_num = 0
            if minute_num == 60:
                hour_num += 1
                minute_num =0
                if hour_num == 24:
                    hour_num = 0
        now_hour.set("%02d"%hour_num)  # 指定格式更新数据
        now_minute.set("%02d"%minute_num)
        now_second.set("%02d"%second_num)

        if(clock_flag == True and hour_num == clock_hour and minute_num == clock_minute and second_num == clock_second):
            Thread(target = clock_start).start()
        # 这里创建线程，要不然闹钟开始的时候，时钟就不走了
        # 时间每隔一秒刷新一次
        time.sleep(1)   # 单位是秒

if __name__ == '__main__':
    # 用 RGB 生成颜色
    # current_time = tkinter.Label(root,width = 10,height = 1,text = "现在时间：",font = 3,bg = RGB(20,184,152))

    # "#33FF00"十六进制表示的颜色字符串，R,G,B各占一个字节
    current_time = tkinter.Label(root,width = 10,height = 1,text = "现在时间：",font = 3,bg = "#33FF00",fg = "#FF3333")
    current_time.place(x = 10,y = 5)

    current_time_hour = tkinter.Label(root,width = 2,height = 1,textvariable = now_hour,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_hour.place(x = 140,y = 5)

    tmp_1 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_1.place(x = 165,y = 5)

    current_time_minute = tkinter.Label(root,width = 2,height = 1,textvariable = now_minute,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_minute.place(x = 190,y = 5)

    # 必须要生成两个临时标签，要不然只会放置一次
    tmp_2 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_2.place(x = 215,y = 5)

    current_time_second = tkinter.Label(root,width = 2,height = 1,textvariable = now_second,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_second.place(x = 240,y = 5)

    clock_set = tkinter.Label(root,width = 10,height = 1,text = "设置闹钟：",font = 3,bg = "#FFFF00",fg = "#FF3333")
    clock_set.place(x = 10,y = 80)

    '''Entry 窗口是没有 height 属性的
    Entry等控件中的参数是关键字参数，其由键-值组成。关键字参数是在传递构成中不必按照顺序传递
    必须要提供”传递参数名=传递参数值”形式的参数，而传递过程中也转变为dict的键值对map关系。
    参数里面的 root 是 master，entry 控件的父控件，也就是放置 entry 的控件 '''

    hour_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")   # show = '*'
    hour_entry.place(x = 140,y = 80)

    tmp_3 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_3.place(x = 165,y = 80)

    minute_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")
    minute_entry.place(x = 190,y = 80)

    tmp_4 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_4.place(x = 215,y = 80)

    second_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")
    second_entry.place(x = 240,y = 80)

    hour_entry.insert("end","00")  # 必须要指明插入的位置
    minute_entry.insert("end","00")
    second_entry.insert("end","00")

    # command 绑定事件好像只能鼠标左键单击,command 绑定的是一个回调函数
    confirm = tkinter.Button(root,font = 3,bg = "#66CC33",fg= "#FF3300",height = 1,width = 10,activebackground = "#0000FF",text = "OFF",command = boot_clock)
    confirm.place(x = 400,y = 200)

    quit = tkinter.Button(root,font = 3,bg = "#66CC33",fg= "#FF3300",height = 1,width = 10,activeforeground = "#0000FF",text = "退出程序",command = root.destroy)
    # root.destroy 会很快关闭，root.quit 关闭的就很慢
    quit.place(x = 400,y = 300)

    '''confirm.bind( "<Button-1>",start()) 如果不加括号的话，start() takes 0 positional arguments but 1 was given
    用bind() 绑定的时候，没有发生事件也会自动调用 start() 函数
    回调函数与函数：fun与fun（） 作为参数时表示的意义不同，fun作为参数表示是函数，fun（）作为参数时表示一个值 '''

    clock_t = Thread(target = timer)   # 创建线程的时候，这里不能有括号
    clock_t.start()
    # 启动主窗口消息循环
    root.mainloop()


#!/usr/bin/env python3

import shutil

from pathlib import Path
from typing import List

from core.challenge import Challenge
from core.setting import Setting
from .utils.lock_file import LockFile

class Benchmark(Setting):
    """Benchmark"""

    def __init__(self, debug: bool = False, **kwargs):
        super(Benchmark, self).__init__(name="Benchmark", **kwargs)
        self.paths = self.configuration.bench_paths
        self.challenges = None
        self.verbose = True
        self.debug = debug
        self._init_log_file(folder=Path("benchmark", str(self.seed)),
                            file=Path("benchmark.log"))
        self.get_challenges()

    def _get_challenge_info(self, name):
        challenge = self.get_challenge(name)

        if challenge is not None:
            return challenge.get_info()

        return None

    def init_challenge(self, tool_name: str, challenge_name: str, remove_patch: bool = False) -> Challenge:
        wd = Path(self.configuration.paths.working_dir, f"{tool_name}_{challenge_name}_{self.seed}")
        lock = LockFile(self.configuration.paths.root, self.configuration.lock_file)
        cmd_str = self.checkout(working_directory=wd, challenge_name=challenge_name, remove_patch=remove_patch)

        if wd.exists():
            shutil.rmtree(wd)
        try:
            lock.wait_lock()
            lock()
            out, err = super().__call__(cmd_str=cmd_str,
                                        msg=f"Checking out challenge {challenge_name} to {wd}.\n")
        finally:
            lock.unlock()

        if not err:
            return Challenge(challenge_name, wd)

        return Challenge("", "")

    def get_challenges(self):
        if not self.challenges:
            out, err = super().__call__(cmd_str=f"{self.paths.program} catalog",
                                        msg="Querying benchmarks challenges")

            self.challenges = out.splitlines()

        return self.challenges

    def checkout(self, working_directory: Path, challenge_name: str, remove_patch: bool = False) -> Challenge:
        cmd_str = f"{self.paths.program} checkout -wd {working_directory} -cn {challenge_name}"

        if self.debug:
            cmd_str += " -v"

        if remove_patch:
            cmd_str += " -rp"

        return cmd_str

    def compile(self, challenge: Challenge, instrumented_files: List[str] = None, preprocess=False, regex: str = None,
                prefix: str = None, log_file: str = None, fix_files: List[str] = None, cpp_files: bool = False,
                separate: bool = False):
        cmd_str = f"{self.paths.program} compile -wd {challenge.working_dir} -cn {challenge.name}"
        cmd_flags = ""

        if instrumented_files:
            inst_files_str = ' '.join(instrumented_files)
            cmd_flags += f" -ifs {inst_files_str}"

        if fix_files:
            fix_files_str = ' '.join(fix_files)
            cmd_flags += f" -ffs {fix_files_str}"

        if cpp_files:
            cmd_flags += f" -cpp"

        if regex:
            cmd_flags += f" -r {regex}"

        if prefix:
            cmd_flags += f" -pf {prefix}"

        if log_file:
            cmd_flags += f" -l {log_file}"

        if self.debug:
            cmd_str += " -v"

        if preprocess:
            out, err = super().__call__(cmd_str=cmd_str + cmd_flags,
                                        msg=f"Compiling {challenge.name}.\n")

            if out:
                return out
            return err

        if separate:
            return cmd_str, cmd_flags

        return cmd_str + cmd_flags

    def test(self, challenge: Challenge, tests: List[str] = None, pos_tests: bool = False, neg_tests: bool = False,
             exit_fail: bool = False, write_fail: bool = False, out_file: str = None, coverage: dict = None,
             regex: str = None, prefix: str = None, log_file: str = None, neg_pov: bool = False):
        cmd_str = f"{self.paths.program} test -wd {challenge.working_dir} -cn {challenge.name}"

        if tests:
            tests_str = ' '.join(tests)
            cmd_str += f" -tn {tests_str}"
        elif pos_tests:
            cmd_str += " --pos_tests"
        elif neg_tests:
            cmd_str += " --neg_tests"

        if exit_fail:
            cmd_str += " -ef"

        if write_fail:
            cmd_str += " -wf"

        if neg_pov:
            cmd_str += " -np"

        if out_file:
            cmd_str += f" -of {out_file}"

        if regex:
            cmd_str += f" -r {regex}"

        if prefix:
            cmd_str += f" -pf {prefix}"

        if log_file:
            cmd_str += f" -l {log_file}"

        if self.debug:
            cmd_str += " -v"

        if coverage:
            cmd_str += " " + ' '.join([f"--{opt} {arg}" for opt, arg in coverage.items()])
            out, err = super().__call__(cmd_str=cmd_str, msg=f"Testing {challenge.name}.\n")

            if out:
                return out
            return err

        return cmd_str

    def prefix(self, challenge: Challenge):
        out, err = super().__call__(
            cmd_str=f"{self.paths.program} info -t prefix -wd {challenge.working_dir} -cn {challenge.name}",
            msg=f"Querying {challenge.name}'s prefix.\n")

        if not err:
            return out.splitlines()[0]

        return ""

    def patch(self, challenge_name: str):
        out, err = super().__call__(cmd_str=f"{self.paths.program} patch -cn {challenge_name}")

        if err:
            return ""

        return out

    def count_tests(self, challenge: Challenge):
        out, err = super().__call__(cmd_str=f"{self.paths.program} info -t count_tests -wd {challenge.working_dir} " +
                                            f"-cn {challenge.name}",
                                    msg=f"Querying {challenge.name}'s tests count.\n")

        if not err:
            return out.splitlines()[0].split(" ")

        return 0, 0


'''
'''

import numpy as np
import math
from f_plot_formats import plot1D

def pulsar_DM_compensation_roll(matrix_0, freq_points, fmin, fmax, df, TimeRes, pulsarPeriod, DM0, save_intermediate_data, customDPI):
    '''
    Plots 1D plots of variable
    '''
    dt = np.zeros((freq_points), dtype = 'float')                # time of shifting channel to dedisperse
    for i in range (freq_points):
        dt[i] = (DM0 / 2.410331) * ((10000./math.pow((fmin + df * i), 2)) - (10000./math.pow(fmax, 2)))
    shiftPar = np.zeros((freq_points), dtype = 'int')            # number of steps to shift each row
    for i in range (freq_points):
        shiftPar[i] = -1 * round(pulsarPeriod * (dt[i] / pulsarPeriod - math.floor(dt[i] / pulsarPeriod)) / TimeRes)
        matrix_0[i] = np.roll(matrix_0[i], shiftPar[i])

    return matrix_0, shiftPar


import re

def unique(lst):
    return [lst[0]] + [y for x, y in zip(lst, lst[1:]) if x != y]

class EMString:
    # Encodable mutable string
    def __init__(self, string, encoding=None, debug=False):
        self.debug = debug
        self.encoding = encoding or []
        self.external = string
        self.internal = self.encode(string)

    def sub(self, pattern, sub):
        # perform substitutions on words separately
        old = new = self.internal
        try:
            new = ' '.join(
                [pattern.sub(sub, string) for string in
                    new.split(' ')])
        except AttributeError:
            new = ' '.join(
                [re.sub(pattern, sub, string) for string in
                    new.split(' ')])
        if old != new:
            self.internal = new
            self.external = self.decode(new)
        return self.external

    def encode(self, string):
        for code in self.encoding:
            string = string.replace(*code)
        return string

    def decode(self, string):
        if not self.debug:
            string = self.nodigits(string)
        for code in self.encoding[::-1]:
            string = string.replace(*code[::-1])
        return string

    def nodigits(self, word):
        return re.sub(r'\d', '', word)

    def __str__(self):
        return self.external

class Evolver:
    def __init__(self, replacements=None, debug=False):
        replacements = replacements or []
        self.debug = debug
        self.replacements = [
            (re.compile(pattern), string) for
            pattern, string in replacements
        ]

    def evolution(self, word, replacement):
        return str(word.sub(*replacement))

    def evolve(self, word):
        output = [str(word)]
        for i, replacement in enumerate(self.replacements):
            evolution = self.evolution(word, replacement)
            output += [evolution]
        return output

class HighToDemoticLulani:
    def __init__(self, debug=False):
        self.rewrites = [
            ('’', "'"),
            ('·', '.'),
            ('ʔ', "''"),
            ('ö', 'O'),
            ('ü', 'U'),
            ('ž', 'Z'),
            ('à', 'A'),
            ('ì', 'I'),
            ('ù', '^'),
            ('ò', '('),
            ('è', 'E'),
            ('ȍ', ')'),  # o with double grave
            ('ȕ', '*'),  # u with double grave
            ('ˈ', '1'),
            ('ˌ', '2')]
        self.consonants = r'[pbvtdDcjkg\'mnqrlfsxhNLHy]'
        self.vowels = r'[aiuoeOU.]'
        self.stresses = self.setup_stresses([
            (r'((C)\2)', r'\g<1>2'),
            (r'(VC+)(V)$', r'\g<1>2\2'),
            (r'(2VC+)2', r'\1'),
            (r'(C)(VC+VC+2)', r'\g<1>2\2')])
        self.sandhi = self.setup_sandhi([
            (r'(?<=[pbtdcjkgmnNqlLrfvDsx])[hH]', ''),
            (r'[hH](?=[pbtdcjkgmnNqlLrfvDsx])', ''),
            (r'[hH]([hH])', r'\1'),
            (r'([pbtdcjkg])[mnNq]', self.prenasal_assimilation),
            (r'sf|mn|pt', self.protect_cluster),
            (r'p(?=[bdjgm])|(?<=[bdjg])p', 'b'),
            (r't(?=[bdjgn])|(?<=[bdjg])t', 'd'),
            (r'c(?=[bdjgN])|(?<=[bdjg])c', 'j'),
            (r'k(?=[bdjgq])|(?<=[bdjg])k', 'g'),
            (r'[pbtdcjkg]([pbtdcjkg])', r'\1\1'),
            (r'([td])([fv])', r'\2\1'),
            ('tx', 'c'),
            ('dx', 'j'),
            (r'c(?=[lLr])', 't'),
            (r'j(?=[lLr])', 'd'),
            (r'(?<=[cj])[fsx]|(?<=D)[cj]|[fvsx](?=[cj])', ''),
            (r'[mnNq]([pbmtdncjNkgq])', self.nasal_assimilation),
            (r'n(?=[xLy])|(?<=x)n', 'N'),
            (r'N(?=[slr])|(?<=[fvD])[mnNq]|(?<=s)N', 'n'),
            (r'L(?=[tdnlscjNLx])', 'l'),
            (r'v(?=[ptk])', 'f'),
            (r'f(?=[bdg])', 'v'),
            (r'(?<=D)[pbkg]', 'D'),
            (r'([D])([td])', r'\2\1'),
            ('tD', 'tT'),
            (r'([vD])[fsx]', r'\1\1'),
            (r'[fsx]([fsx])', r'\1\1'),
            # remove /y/ after palatals, and quotes
            ('\'|(?<=[cjxNL])y', '')])
        replacements = [
            # lowering of back vowels before peripherals
            (r'u(?=[pbmfkgqhH])', 'o'),
            (r'([nl\'hbdgptck])\1', self.geminate_shift),
            (r'([auo])(?=.{1,2}i)', self.umlaut),
            (r'(([stdnl])\2?)(?=i)', self.palatalise),
            (r'.*', self.stress),
            (r'(?<=.)h(?=2)', '\''),  # elision of syllable final /h/
            (r'(?<=2a)\'(?=[aeuoUO])', 'y'),  # fortify glottal stop
            (r'(?<=2a)\'(?=[i])', 'w'),  # fortify glottal stop
            (r'2([iuUoO])\'', self.fortify_vowel),
            (r'([aiuoeOU.]([pbtdDcjkg\'mnqrlfsxhNLHy])2)[aiuoeOU.](\2)',
             r'\1.\3'),  # middot
            (r'((\w)\2)2i', r'\2'),  # kappita ==> kapta
            (r'([pbvtdDcjkg\'mnqrlfsxhNLHyw])\1', r'\1'),  # degemination
            (r'(?<!2)([aieouOU])\'2*([aieouOU])',
             self.simplify_vowel_cluster),
            (r'2([ae.])', ''),  # remove unstressed open vowels
            # (r'2', ''), # remove stress marks
            (r'.*', self.simplify_consonant_cluster),
            (r'^[mnNq](?=[pbmftdDcjkgnqsxNLH])', 'm'),
            (r'^[lL](?=[pbmftdDcjkgnqsxNLH])', 'l'),
            (r'^((\w)\2)', r'\2'),  # degeminate initials
            (r'[cj]([cj])', r'\1'),  # degeminate affricates
            (r'([aiueUoO])2\1,*', r'\1'),  # shorten long vowel
            (r'([aiueUoO])([pbmfvtdDcjkgnqsxNLH]+2[aiueUoO][pbmfvtdDcjkgnqsxNLH]+[aiueUoO]*$)',
             self.stress_antepenult),  # stress antepenultimate closed syllable when appropriate
            (r'(2[aiueUoO][pbmfvtdDcjkgnqsxNLH]+)([aiueUoO])$',
             self.stress_antepenult),  # re-write final semivowels
            (r'(?<=[^i])y$', 'i'),  # re-write final semivowels
            (r'w$', 'u'),
            (r'U$', 'O'),
            ('dd', 'd.d'),
            ('D', 'dd'),
            ('L', 'll'),
            ('N', 'nn'),
            ('H', 'hh'),
        ]
        self.evolver = Evolver(replacements, debug)
        self.debug = debug

    def evolve(self, text):
        return unique(self.evolver.evolve(
            EMString(text, self.rewrites, self.debug)
        ))

    def geminate_shift(self, regex):
        return {
            'n': 'N', 'l': 'L', '\'': 'y', 'h': 'H',
            'b': 'v', 'd': 'D', 'g': 'r', 'p': 'b',
            't': 'd', 'c': 'j', 'k': 'g',
        }[regex.group(1)] * 2

    def umlaut(self, regex):
        return dict(a='e', u='U', o='O')[regex.group(1)]

    def palatalise(self, regex):
        return dict(
            s='x', t='c', d='j', n='N', l='L'
        )[regex.group(2)] * len(regex.group(1))

    def simplify_vowel_cluster(self, regex):
        first, second = [regex.group(x) for x in range(1, 3)]
        if (first + second).lower() in ('au', 'ao'):
            return second.upper()
        if (first + second).lower() in ('ae', 'aa', 'ia', 'iu'):
            return first + 'y2' + second
        if (first + second).lower() in ('ui', 'oi'):
            return first + 'w2' + second
        return first

    def fortify_vowel(self, regex):
        if regex.group(1) == 'i':
            return 'y'
        return 'w'

    def prenasal_assimilation(self, regex):
        plosive = regex.group(1)
        return plosive + dict(
            p='m', b='m',
            t='n', d='n',
            c='N', j='N',
            k='q', g='q'
        )[plosive]

    def nasal_assimilation(self, regex):
        other = regex.group(1)
        return dict(
            p='m', b='m', m='m',
            t='n', d='n', n='n',
            c='N', j='N', N='N',
            k='q', g='q', q='q'
        )[other] + other

    def protect_cluster(self, regex):
        return '{0}\'{1}'.format(*regex.group(0))

    def setup_stresses(self, stresses):
        return [(re.compile(pattern.replace(
                'C', self.consonants).replace(
            'V', self.vowels)
        ), string) for pattern, string in stresses]

    def stress(self, regex):
        word = regex.group(0)
        for stress in (0, 1, 2):
            pattern, string = self.stresses[stress]
            word = pattern.sub(string, word)
        old = ''
        while old != word:
            old = word
            for stress in (3, 2):
                pattern, string = self.stresses[stress]
                word = pattern.sub(string, word)
        return word

    def setup_sandhi(self, sandhi):
        return [(re.compile(pattern), string) for pattern, string in sandhi]

    def simplify_consonant_cluster(self, regex):
        cluster = regex.group(0)
        for sandhi in self.sandhi:
            pattern, string = sandhi
            cluster = pattern.sub(string, cluster)
        return cluster

    def stress_antepenult(self, regex):
        vowels = dict(a='A', e='E', i='I', o='(', O=')',
                      u='^', U='*')
        try:
            return vowels[regex.group(1)]
        except IndexError:
            return vowels[regex.group(0)]


# -*- coding: utf-8 -*-
"""PySistem configuration file"""

import os

# Work directory. Leave as is
DIR = os.path.dirname(os.path.realpath(__file__))

# Storage
STORAGE = os.path.join(DIR, 'storage')

SECRET_KEY = b'\nB\xd3\xa7\x9f\xd6r\x03a&R\x85\x84\xea\x0c\xab\x1eU4\x18O\xad\xda\xed'
DEBUG = False
# Allowed languages
LANGUAGES = {
    'en': 'English',
    'ru': 'Русский'
}
# Database to use
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(DIR, 'pysistem.db')
# For debugging
#SQLALCHEMY_ECHO = True

# Auto-created directories. Leave as is
CREATE_DIRS = (
    'checkers_bin',
    'submissions_bin'
)

# Extra paths to search compilers in
PATH_EXTRA = []

# How often check submissions
CHECK_THREAD_TIME = 1

# Do check submissions?
# Note: using this option may be unstable with Gunicorn
LAUNCH_CHECK_THREAD = True

# Maximum upload size
MAX_CONTENT_LENGTH = 16 * 1024 * 1024

# Maximum compilation time, in seconds
COMPILE_TIME_LIMIT = 15