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

"""
Module implementing MainWindow.
"""
import os
import json
import time
import sqlite3
from PyQt5.Qt import *
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import *
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery
from PyQt5.QtGui import *

from Ui_UI_Main import *
from Ui_showPhoto import *

myDictExif = {}
myDictOcr = {}
DNDict = {}

class MainWindow(QMainWindow):
    """
    Class documentation goes here.
    """
    databasePath = '.\\photoIndex.db'
    photoPath1 = r'.\\'
    shortPath1 = '1\\'
    photoPath2 = r'.\\'
    shortPath2 = '2\\'
    rootPath = '.'
    path1List = []
    path2List = []
    cursor = None
    conn = None
    comboxList1 = ['','完全匹配', '表达式']
    comboxList2 = ['','phpto', 'video', 'GIFph']
    comboxList3 = ['', 'tiny small', 'small', 'tiny middle', 'middle', 'large', 'super large']
    comboxList4 = ['', 'panoramas', 'super panoramas', 'square']
    comboxList5 = ['', 'creationTime', 'modificationTime', 'accessTime']
    comboxList6 = ['之前','之后']
    comboxList7 = ['','laptop', 'book', 'refrigerator', 'tvmonitor', 'person', 'wine_glass', 'bed', 'teddy_bear', 'chair', 'cat', 'backpack', 'pottedplant', 'broccoli', 'sports_ball', 'bench', 'keyboard', 'bird', 'car', 'bus', 'truck', 'aeroplane', 'scissors', 'dog', 'vase', 'tie', 'clock', 'remote', 'umbrella', 'handbag', 'toothbrush', 'spoon', 'cell_phone', 'diningtable', 'pizza', 'boat', 'bottle', 'cup', 'bowl', 'mouse', 'hair_drier', 'microwave', 'surfboard', 'cake', 'stop_sign', 'horse', 'kite', 'sheep', 'frisbee', 'suitcase', 'sofa', 'donut', 'tennis_racket', 'baseball_bat', 'oven', 'motorbike', 'knife', 'giraffe', 'cow', 'toilet', 'bicycle', 'carrot', 'banana', 'fork', 'bear', 'train', 'baseball glove', 'apple', 'traffic_light', 'sandwich', 'orange', 'skateboard', 'parking_meter', 'skis', 'fire_hydrant', 'zebra']
    comboxList7Temp = ['name','path','laptop', 'book', 'refrigerator', 'tvmonitor', 'person', 'wine_glass', 'bed', 'teddy_bear', 'chair', 'cat', 'backpack', 'pottedplant', 'broccoli', 'sports_ball', 'bench', 'keyboard', 'bird', 'car', 'bus', 'truck', 'aeroplane', 'scissors', 'dog', 'vase', 'tie', 'clock', 'remote', 'umbrella', 'handbag', 'toothbrush', 'spoon', 'cell_phone', 'diningtable', 'pizza', 'boat', 'bottle', 'cup', 'bowl', 'mouse', 'hair_drier', 'microwave', 'surfboard', 'cake', 'stop_sign', 'horse', 'kite', 'sheep', 'frisbee', 'suitcase', 'sofa', 'donut', 'tennis_racket', 'baseball_bat', 'oven', 'motorbike', 'knife', 'giraffe', 'cow', 'toilet', 'bicycle', 'carrot', 'banana', 'fork', 'bear', 'train', 'baseball glove', 'apple', 'traffic_light', 'sandwich', 'orange', 'skateboard', 'parking_meter', 'skis', 'fire_hydrant', 'zebra']
    comboxList8 = ['name', 'type', 'suffix', 'path', 'height', 'weight','creationTime', 'modificationTime', 'accessTime', 'GPSInfoPlace', 'cameraMaker', 'cameraModel']
    comboxList8Temp = ['name', 'type', 'suffix', 'path', 'ocr', 'height', 'weight','size_type','widthHeight_type','creationTime', 'modificationTime', 'accessTime', 'GPSInfoPlace', 'cameraMaker', 'cameraModel']
    comboxList9 = ['升序', '降序']
    comboxList10 = ['','大于', '小于']
    exeString = ''
    exeStringWhereTemp = ''
    exeStringOrderByTemp = ''
    resultAll = []
    resultAllcount = 0
    resultAllLeft = 0
    resultAllRight = 0
    pageConAble = False
    pageNow = 0
    pageAll = 0
    resultNow = [] #是一个列表字典嵌套，len一般小于等于5，同来保存当前显示的0~5张图的所有信息，resultNow[0]['path']这么用
    resultNowString = [] #是将resultNow中字典的内容转换成字符串后保存的地方
    m_flag=False #用于拖动窗口，此处不初始化的话，需要进入窗口之后先点击一下空白处，而不能直接点下拉框
    redoAndUndo = []
    redoAndUndoCurrentIndex = -1

    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.ui=Ui_MainWindow()        #创建UI对象
        self.ui.setupUi(self)      #构造UI界面
        #self.setWindowOpacity(0.9) # 设置窗口透明度
        self.setProperty('canMove', True)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
        self.ui.label_15.setText('by Water - v0.6')
        self.ui.pushButton_icon.setIcon(QIcon('./icons/shui.png'))
        self.ui.pushButton_zxh.setIcon(QIcon('./icons/zuixiaohua.png'))
        self.ui.pushButton_zdh.setIcon(QIcon('./icons/zuidahua.png'))
        self.ui.pushButton_close.setIcon(QIcon('./icons/guanbi.png'))
        self.ui.pushButton_cx.setIcon(QIcon('./icons/chexiao.png'))
        self.ui.pushButton_cx.clicked.connect(self.chexiao)
        self.ui.pushButton_cx.setEnabled(False)
        self.ui.pushButton_cz.setIcon(QIcon('./icons/chongzuo.png'))
        self.ui.pushButton_cz.clicked.connect(self.chongzuo)
        self.ui.pushButton_cz.setEnabled(False)
#        self.ui.pushButton_show0.setIcon(QIcon('./icons/empty.png'))
#        self.ui.pushButton_show1.setIcon(QIcon('./icons/empty.png'))
#        self.ui.pushButton_show2.setIcon(QIcon('./icons/empty.png'))
#        self.ui.pushButton_show3.setIcon(QIcon('./icons/empty.png'))
#        self.ui.pushButton_show4.setIcon(QIcon('./icons/empty.png'))
        for i in range(0):#此处会导致所有传出参数都为最后一个temp 所以弃用了
            temp = eval("self.ui.pushButton_show{}".format(i))
            temp.setContextMenuPolicy(Qt.CustomContextMenu)
            temp.customContextMenuRequested.connect(lambda:self.showMenu(i))
        self.ui.pushButton_show0.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.pushButton_show0.customContextMenuRequested.connect(lambda:self.showMenu(0))
        self.ui.pushButton_show1.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.pushButton_show1.customContextMenuRequested.connect(lambda:self.showMenu(1))
        self.ui.pushButton_show2.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.pushButton_show2.customContextMenuRequested.connect(lambda:self.showMenu(2))
        self.ui.pushButton_show3.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.pushButton_show3.customContextMenuRequested.connect(lambda:self.showMenu(3))
        self.ui.pushButton_show4.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.pushButton_show4.customContextMenuRequested.connect(lambda:self.showMenu(4))
        self.clearShowButton()
        self.ui.pushButton_show4.setToolTip('ToolTip test')
        self.ui.pushButton_close.installEventFilter(self)
        #self.ui.pushButton_close.clicked.connect(self.close)
        self.ui.pushButton_zxh.clicked.connect(self.showMinimized)
        #self.ui.pushButton_zdh.clicked.connect(self.showMaximized)
        self.ui.pushButton_process.released.connect(self.doIt)

        self.ui.textEdit.setUndoRedoEnabled(True)
        #self.ui.textEdit.redoAvailable.connect(self.textEditorChanged)
        #self.ui.textEdit.undoAvailable.connect(self.textEditorChanged)
        #self.ui.textEditor.textChanged.connect(self.textEditorChanged)
        self.ui.comboBox.addItems(self.comboxList1)
        self.ui.comboBox.currentIndexChanged.connect(lambda:self.likeComplet(1))
        self.ui.comboBox_2.addItems(self.comboxList2)
        self.ui.comboBox_3.addItems(self.comboxList1)
        self.ui.comboBox_3.currentIndexChanged.connect(lambda:self.likeComplet(3))
        self.ui.comboBox_4.addItems(self.comboxList1)
        self.ui.comboBox_4.currentIndexChanged.connect(lambda:self.likeComplet(4))
        self.ui.comboBox_5.addItems(self.comboxList10)
        self.ui.comboBox_5.currentIndexChanged.connect(lambda:self.heightWeightCom(5))
        self.ui.comboBox_6.addItems(self.comboxList10)
        self.ui.comboBox_6.currentIndexChanged.connect(lambda:self.heightWeightCom(6))
        self.ui.comboBox_7.addItems(self.comboxList3)
        self.ui.comboBox_8.addItems(self.comboxList4)
        self.ui.comboBox_9.addItems(self.comboxList5)
        self.ui.comboBox_10.addItems(self.comboxList6)
        self.ui.comboBox_11.addItems(self.comboxList1)
        self.ui.comboBox_11.currentIndexChanged.connect(lambda:self.likeComplet(11))
        self.ui.comboBox_12.addItems(self.comboxList1)
        self.ui.comboBox_12.currentIndexChanged.connect(lambda:self.likeComplet(12))
        self.ui.comboBox_13.addItems(self.comboxList1)
        self.ui.comboBox_13.currentIndexChanged.connect(lambda:self.likeComplet(13))
        self.ui.comboBox_14.addItems(self.comboxList7)
        self.ui.comboBox_14.currentIndexChanged.connect(lambda:self.heightWeightCom(9))
        self.ui.comboBox_15.addItems(self.comboxList8)
        self.ui.comboBox_15.currentTextChanged.connect(self.sortByChanged)
        self.comboBox_15Now = 8
        self.ui.comboBox_16.addItems(self.comboxList9)
        self.ui.comboBox_16.currentTextChanged.connect(self.sortByChanged)
        self.ui.dateEdit.setDate(QDate.currentDate())
        self.ui.dateEdit.setCalendarPopup(True)
        self.setStyleSheet()
        self.ui.pushButton_icon.installEventFilter(self)
        self.ui.dateEdit.dateChanged.connect(self.onDateChanged)
        self.ui.pushButton_search.released.connect(self.generateExeString)
        self.ui.pushButton_clear.released.connect(self.clearAll)
        self.clipboard = QApplication.clipboard()
        self.contextMenu = QMenu(self)
        self.ui.pushButton_show0.released.connect(lambda:self.oneClickToView(0))
        self.ui.pushButton_show1.released.connect(lambda:self.oneClickToView(1))
        self.ui.pushButton_show2.released.connect(lambda:self.oneClickToView(2))
        self.ui.pushButton_show3.released.connect(lambda:self.oneClickToView(3))
        self.ui.pushButton_show4.released.connect(lambda:self.oneClickToView(4))

        self.initMenu()

        #qApp.processEvents()
        #self.initDatabase()
        self.initDatabase2()
#        self.ani = QPropertyAnimation(self.ui.pushButton_icon)
#        self.ani.setStartValue(QSize(48, 30))
#        self.ani.setEndValue(QSize(1, 1))
#        self.ani.setDuration(3000)
#        self.ani.start()

    def chexiao(self):
        if len(self.redoAndUndo) and self.redoAndUndoCurrentIndex>0:
            self.redoAndUndoCurrentIndex -= 1
            self.ui.textEdit.setText(self.redoAndUndo[self.redoAndUndoCurrentIndex])
            self.ui.pushButton_cz.setEnabled(True)
        if self.redoAndUndoCurrentIndex<=0:
            self.ui.pushButton_cx.setEnabled(False)

    def chongzuo(self):
        if self.redoAndUndoCurrentIndex < len(self.redoAndUndo)-1:
            self.redoAndUndoCurrentIndex += 1
            self.ui.textEdit.setText(self.redoAndUndo[self.redoAndUndoCurrentIndex])
            self.ui.pushButton_cx.setEnabled(True)
        if self.redoAndUndoCurrentIndex == len(self.redoAndUndo)-1:
            self.ui.pushButton_cz.setEnabled(False)

    def updateRedoAndUndo(self, nowString):
        if self.redoAndUndoCurrentIndex == len(self.redoAndUndo)-1:
            self.redoAndUndo.append(nowString)
            self.redoAndUndoCurrentIndex += 1
        elif self.redoAndUndoCurrentIndex < len(self.redoAndUndo)-1:
            self.redoAndUndo = self.redoAndUndo[:self.redoAndUndoCurrentIndex+1]
            self.redoAndUndo.append(nowString)
            self.redoAndUndoCurrentIndex = len(self.redoAndUndo)-1
        if len(self.redoAndUndo) and self.redoAndUndoCurrentIndex>0:
            self.ui.pushButton_cx.setEnabled(True)
        if self.redoAndUndoCurrentIndex < len(self.redoAndUndo)-1:
            self.ui.pushButton_cz.setEnabled(True)
        pass

    def copyThisPhoto(self):
        if self.copyWhich>=0:
            try:
                tempPhoto = QPixmap(self.rootPath+self.resultNow[self.copyWhich]['path'])
                self.clipboard.setPixmap(tempPhoto)
                print('复制成功')
            except IndexError:
                print("复制失败：这里没有图片")

    def showThisPhotoInExplorer(self):
        if self.copyWhich>=0:
            try:
                tempPath = self.rootPath+self.resultNow[self.copyWhich]['path']
                os.system("explorer.exe /select,%s" % tempPath)
            except IndexError:
                print("定位失败：这里没有图片")

    def openThisPhoto(self):
        if self.copyWhich>=0:
            try:
                tempPath = self.rootPath+self.resultNow[self.copyWhich]['path']
                os.startfile(tempPath)
            except IndexError:
                print("打开失败：这里没有图片")

    def viewThisPhoto(self):
        if self.copyWhich>=0:
            try:
                tempPath = self.rootPath+self.resultNow[self.copyWhich]['path']
                showInSubWindow(tempPath)
            except IndexError:
                print("查看失败：这里没有图片")
            except Exception as e:
                print(e)

    def showMenu(self, index):
        #print(QCursor.pos())
        self.copyWhich = index
        self.contextMenu.exec_(QCursor.pos())

    def initMenu(self):
        self.copyThisPhotoMenu = self.contextMenu.addAction("复制 (至剪贴板)")
        self.copyThisPhotoMenu.triggered.connect(self.copyThisPhoto)
        self.copyWhich = -1
        self.showThisPhotoInExplorerMenu = self.contextMenu.addAction("定位 (到所在文件夹)")
        self.showThisPhotoInExplorerMenu.triggered.connect(self.showThisPhotoInExplorer)
        self.openThisPhotoMenu = self.contextMenu.addAction("打开 (使用系统默认方式)")
        self.openThisPhotoMenu.triggered.connect(self.openThisPhoto)
        self.viewThisPhotoMenu = self.contextMenu.addAction("查看 (在新建的窗口)")
        self.viewThisPhotoMenu.triggered.connect(self.viewThisPhoto)

    def oneClickToView(self,index): #v0.6.2 feature 1
        self.copyWhich = index
        self.openThisPhoto()

    def testFun(self):
        a = QPixmap('d:\\test.jpg')
        self.clipboard.setPixmap(a)

    def resultButtonWhichOn(self):
        pass

    def showResult(self):
        self.clearShowButton()
        #self.resultNow
        resultNowLen = len(self.resultNow)
        #print(resultNowLen)
        #print(self.resultNowString)
        print('loading...')
        if resultNowLen > 5:
            raise Exception('showResult函数传入参数数组长度不能超过5')
        else:
            for i in range(resultNowLen):
                realPath = self.rootPath + self.resultNow[i]['path']
#                sheetString = '''
#QPushButton{background-image: url(:{});}
#QPushButton:hover{background-image: url(:{}) -10 -10 -10 -10;}'''.format(realPath, realPath)
#                eval("tempButton = self.ui.pushButton_show{}".format(i))
#                tempButton.setStyleSheet(sheetString)
                tempButton = eval("self.ui.pushButton_show{}".format(i))
                tempButton.setIcon(QIcon(realPath))
                tempButton.setToolTip(self.resultNowString[i])
            for i in range(resultNowLen,5): #v0.6.2 bug2
                tempButton = eval("self.ui.pushButton_show{}".format(i))
                tempButton.setToolTip("")
        print('finish')
        if not self.pageConAble:
            self.pageConAble = True
            self.ui.pushButton_firstPage.clicked.connect(lambda:self.whichPage('first'))
            self.ui.pushButton_upPage.clicked.connect(lambda:self.whichPage('up'))
            self.ui.pushButton_downPage.clicked.connect(lambda:self.whichPage('down'))
            self.ui.pushButton_lastPage.clicked.connect(lambda:self.whichPage('last'))

    def clearShowButton(self):
        self.ui.pushButton_show0.setIcon(QIcon('./icons/shui.png'))
        self.ui.pushButton_show1.setIcon(QIcon('./icons/shui.png'))
        self.ui.pushButton_show2.setIcon(QIcon('./icons/shui.png'))
        self.ui.pushButton_show3.setIcon(QIcon('./icons/shui.png'))
        self.ui.pushButton_show4.setIcon(QIcon('./icons/shui.png'))
        pass

    def clearShowResult(self):
        self.resultNow = []
        self.resultNowString = []
        pass

    def doIt(self):
        self.exeString = self.ui.textEdit.toPlainText()
        try:
            self.cursor.execute(self.exeString)
        except Exception as e:
            QMessageBox.critical(self, "Something Wrong", e.args[0], QMessageBox.Yes)
        else:
            self.resultAll = self.cursor.fetchall()
            #print(type(self.resultAll))
            self.resultAllcount = len(self.resultAll)
            QMessageBox.information(self, '语句执行成功','共查询到'+str(self.resultAllcount)+'条结果',QMessageBox.Yes)
            self.updateRedoAndUndo(self.exeString)
            if self.resultAllcount >= 5:
                self.resultAllLeft = 0
                self.resultAllRight = 4
            elif self.resultAllcount == 0:
                self.resultAllLeft = 0
                self.resultAllRight = 0
                return
            else:
                self.resultAllLeft = 0
                self.resultAllRight = self.resultAllcount-1
            #print(str(self.resultAllLeft)+' '+str(self.resultAllRight)+' '+str(self.resultAllcount))
            #self.getResultNow() #因为whichPage会调用getResultNow()，所以这里替换掉是因为这样做可以让每次执行查询之后回到第一页，而不是保留上一次的页码数而使得可能越界v0.6.1
            self.whichPage('first')

    def getResultNow(self):
        self.clearShowResult()
        for j in range(self.resultAllLeft, self.resultAllRight+1):
            #print(self.resultAll)
            if self.comboBox_15Now == 7:#photoObject :path in cloumn index 1
                tempDict = {}#突然发现 如果手速够快可以当程序在这个循环的时候突然改变Now值，后面应该就会出bug
                tempString = ''
                for i in range(len(self.comboxList7Temp)):
                    keyTemp = self.comboxList7Temp[i]
                    valueTemp = self.resultAll[j][i]
                    tempDict[keyTemp] = valueTemp
                    if valueTemp is not None:
                        if not isinstance(valueTemp, str):
                            tempString += (keyTemp + ' : ' + str(valueTemp)+'\n')
                        else:
                            tempString += (keyTemp + ' : ' + valueTemp+'\n')
                self.resultNow.append(tempDict)
                self.resultNowString.append(tempString)
            elif self.comboBox_15Now == 8:#photo :path in colum index 3
                tempDict = {}
                tempString = ''
                for i in range(len(self.comboxList8Temp)):
                    keyTemp = self.comboxList8Temp[i]
                    valueTemp = self.resultAll[j][i]
                    tempDict[keyTemp] = valueTemp
                    if keyTemp == 'ocr' and (valueTemp is not None):
                        keyTemp.replace('\n','')
                        keyTemp.replace('\t','')
                        keyTemp.replace(' ','')
                        tempString += (keyTemp + ' : ' + valueTemp[:10]+'...\n')
                    elif valueTemp is not None:
                        if not isinstance(valueTemp, str):
                            tempString += (keyTemp + ' : ' + str(valueTemp)+'\n')
                        else:
                            tempString += (keyTemp + ' : ' + valueTemp+'\n')
                self.resultNow.append(tempDict)
                self.resultNowString.append(tempString)
        #print(self.resultNow)
        self.showResult()

    def whichPage(self, whichButton):
        a = self.resultAllcount//5
        b = self.resultAllcount%5
        if b == 0:
            self.pageAll = a
        else:
            self.pageAll = a+1
        if self.pageAll == 1 and self.resultAllRight-self.resultAllLeft+1 == self.resultAllcount: #比较万能，无论是下面的哪种写法都可以用这句
            self.pageNow = 0 #v0.6.2 bug3
            pass
        elif whichButton=='first':
            self.pageNow = 0
        elif whichButton=='last':
            self.pageNow = self.pageAll - 1
        elif whichButton=='up':
            if self.pageNow > 0:
                self.pageNow -= 1
        elif whichButton=='down':
            if self.pageNow < self.pageAll - 1:
                self.pageNow += 1
        self.resultAllLeft = self.pageNow*5
        if self.pageNow == self.pageAll - 1:
            self.resultAllRight = self.resultAllLeft+(self.resultAllcount-1)%5
        else:
            self.resultAllRight = self.resultAllLeft+4
        print(str(self.resultAllLeft)+' '+str(self.resultAllRight)+' '+str(self.resultAllcount))
        print(self.pageNow)
#下面这种写法好累人啊，未完成，放弃了，因为找到了更好写的
#        elif whichButton=='first':
#            self.resultAllLeft = 0
#            if self.resultAllcount >= 5:
#                self.resultAllRight = 4
#            elif self.resultAllcount == 0:
#                self.resultAllRight = 0
#            else:
#                self.resultAllRight = self.resultAllcount-1
#        elif whichButton=='last':
#            if b== 0:
#                self.resultAllLeft = (a-1)*5
#            else:
#                self.resultAllLeft = a*5
#            self.resultAllRight = (self.resultAllcount-1)%5
#        elif whichButton=='up':
#            if self.resultAllLeft == 0:
#                pass
#        elif whichButton=='down':
#            if self.resultAllRight - self.resultAllLeft <=4:
#                pass
#-----------------------------------------------------------到这里
        self.getResultNow()

    def generateExeString(self):
        #print(self.comboBox_15Now)
        if self.executeString():
            if self.chooseObject and not self.chooseObjectWrong:
                self.where = 'photoObject'
                if self.comboBox_15Now == 8:
                    self.comboBox_15Now = 7
                    self.ui.comboBox_15.clear()
                    self.ui.comboBox_15.addItem('name')
                    self.ui.comboBox_15.addItems(self.comboxList7[1:])
            else:
                self.where = 'photo'
                if self.comboBox_15Now == 7:
                    self.comboBox_15Now = 8
                    self.ui.comboBox_15.clear()
                    self.ui.comboBox_15.addItems(self.comboxList8)
            self.sortBy()
            self.exeString = '''select *
from {}
where {}
order by {}'''.format(self.where,self.exeStringWhereTemp, self.exeStringOrderByTemp)
            self.ui.textEdit.setText(self.exeString)
            self.doIt()
        else:
            print('未生成表达式')

    def sortByChanged(self):
        self.sortBy()
        self.exeString = '''select *
from {}
where {}
order by {}'''.format(self.where,self.exeStringWhereTemp, self.exeStringOrderByTemp)
        self.ui.textEdit.setText(self.exeString)

    def clearAll(self):
        a = QMessageBox.warning(self, "are you sure？", "确定要清空？", QMessageBox.Yes | QMessageBox.No)
        if a == QMessageBox.Yes:
            index = 0
            text = ''
            self.ui.lineEdit.setText(text)
            for i in range(2, 10):
                eval("self.ui.lineEdit_{}.setText('{}')".format(i, text))
            self.ui.comboBox.setCurrentIndex(index)
            for i in range(2, 10):
                eval("self.ui.comboBox_{}.setCurrentIndex({})".format(i, index))
            for i in range(11, 15):
                eval("self.ui.comboBox_{}.setCurrentIndex({})".format(i, index))

    def heightWeightCom(self, a):
        if 5 == a and '' == self.ui.lineEdit_4.text():
            self.ui.lineEdit_4.setText('0')
        if 6 == a and '' == self.ui.lineEdit_5.text():
            self.ui.lineEdit_5.setText('0')
        if 9 == a and '' == self.ui.lineEdit_9.text():
            self.ui.lineEdit_9.setText('0.6')
        if 9 == a and 0 == self.ui.comboBox_14.currentIndex():
            self.ui.lineEdit_9.setText('')

    def likeComplet(self, a):
        if 1 == a and '' == self.ui.lineEdit.text() and self.ui.comboBox.currentText() == '表达式':
            self.ui.lineEdit.setText('%%')
        if 3 == a and '' == self.ui.lineEdit_2.text() and self.ui.comboBox_3.currentText() == '表达式':
            self.ui.lineEdit_2.setText('%%')
        # v0.6.2 bug1 以上
        if 4 == a and '' == self.ui.lineEdit_3.text() and self.ui.comboBox_4.currentText() == '表达式':
            self.ui.lineEdit_3.setText('%%')
        if 11 == a and '' == self.ui.lineEdit_6.text() and self.ui.comboBox_11.currentText() == '表达式':
            self.ui.lineEdit_6.setText('%%')
        if 12 == a and '' == self.ui.lineEdit_7.text() and self.ui.comboBox_12.currentText() == '表达式':
            self.ui.lineEdit_7.setText('%%')
        if 13 == a and '' == self.ui.lineEdit_8.text() and self.ui.comboBox_13.currentText() == '表达式':
            self.ui.lineEdit_8.setText('%%')

    def sortBy(self):
        self.exeStringOrderByTemp = ''
        sortByColumn = self.ui.comboBox_15.currentText()
        isDesc = self.ui.comboBox_16.currentText()
        if isDesc == '升序':
            self.exeStringOrderByTemp = '{}'.format(sortByColumn)
        elif isDesc == '降序':
            self.exeStringOrderByTemp = '{} desc'.format(sortByColumn)

    def executeString(self):
        self.exeStringDictWay = {}
        self.exeStringDict = {}
        self.exeStringDict['name'] = self.ui.lineEdit.text()
        self.exeStringDictWay['nameWay'] = self.ui.comboBox.currentText()
        self.exeStringDictWay['type'] = self.ui.comboBox_2.currentText()
        self.exeStringDict['suffix'] = self.ui.lineEdit_2.text()
        self.exeStringDictWay['suffixWay'] = self.ui.comboBox_3.currentText()
        self.exeStringDict['ocr'] = self.ui.lineEdit_3.text()
        self.exeStringDictWay['ocrWay'] = self.ui.comboBox_4.currentText()
        self.exeStringDict['height'] = self.ui.lineEdit_4.text()
        self.exeStringDictWay['heightWay'] = self.ui.comboBox_5.currentText()
        self.exeStringDict['weight'] = self.ui.lineEdit_5.text()
        self.exeStringDictWay['weightWay'] = self.ui.comboBox_6.currentText()
        self.exeStringDictWay['size_type'] = self.ui.comboBox_7.currentText()
        self.exeStringDictWay['widthHeight_type'] = self.ui.comboBox_8.currentText()
        self.exeStringDictWay['timeStampWay'] = self.ui.comboBox_9.currentText()
        self.exeStringDict['timeStamp'] = self.ui.dateEdit.date().toString(Qt.ISODate)
        self.exeStringDict['timeStampBeAf'] = self.ui.comboBox_10.currentText()
        self.exeStringDict['GPSInfoPlace'] = self.ui.lineEdit_6.text()
        self.exeStringDictWay['GPSInfoPlaceWay'] = self.ui.comboBox_11.currentText()
        self.exeStringDict['cameraMaker'] = self.ui.lineEdit_7.text()
        self.exeStringDictWay['cameraMakerWay'] = self.ui.comboBox_12.currentText()
        self.exeStringDict['cameraModel'] = self.ui.lineEdit_8.text()
        self.exeStringDictWay['cameraModelWay'] = self.ui.comboBox_13.currentText()
        self.exeStringDict['object'] = self.ui.lineEdit_9.text()
        self.exeStringDictWay['objectWay'] = self.ui.comboBox_14.currentText()
        #print(self.exeStringDict.keys())
        self.count = 0
        #self.firstCome = False
        self.exeStringWhereTemp = ''
        self.chooseObject = False
        for key in self.exeStringDictWay.keys():
            value = self.exeStringDictWay.get(key)
            #print(key, end=' ')
            #print(type(self.exeStringDict.get(key.split('Way')[0])))
            if value != '':
                self.count += 1
                #print(value)
                if 1 == self.count:
                    if '完全匹配' == value:
                        self.exeStringWhereTemp += ("("+key.split('Way')[0]+" = \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif '表达式' == value:
                        self.exeStringWhereTemp += ("("+key.split('Way')[0]+" like \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif '大于' == value:
                        self.exeStringWhereTemp += ("("+key.split('Way')[0]+" > "+self.exeStringDict.get(key.split('Way')[0])+")")
                    elif '小于' == value:
                        self.exeStringWhereTemp += ("("+key.split('Way')[0]+" < "+self.exeStringDict.get(key.split('Way')[0])+")")
                    elif 'timeStampWay' == key:
                        if '之前' == self.exeStringDict.get('timeStampBeAf'):
                            self.exeStringWhereTemp += ("("+self.exeStringDictWay['timeStampWay']+" < \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                        if '之后' == self.exeStringDict.get('timeStampBeAf'):
                            self.exeStringWhereTemp += ("("+self.exeStringDictWay['timeStampWay']+" > \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif 'type' == key or 'widthHeight_type' == key or 'size_type' == key:
                        self.exeStringWhereTemp += ("("+key+" = \'"+value+"\')")

                elif self.count > 1:
                    if '完全匹配' == value:
                        self.exeStringWhereTemp += (' and ('+key.split('Way')[0]+" = \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif '表达式' == value:
                        self.exeStringWhereTemp += (' and ('+key.split('Way')[0]+" like \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif '大于' == value:
                        self.exeStringWhereTemp += (" and ("+key.split('Way')[0]+" > "+self.exeStringDict.get(key.split('Way')[0])+")")
                    elif '小于' == value:
                        self.exeStringWhereTemp += (" and ("+key.split('Way')[0]+" < "+self.exeStringDict.get(key.split('Way')[0])+")")
                    elif 'timeStampWay' == key:
                        if '之前' == self.exeStringDict.get('timeStampBeAf'):
                            self.exeStringWhereTemp += (" and ("+self.exeStringDictWay['timeStampWay']+" < \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                        if '之后' == self.exeStringDict.get('timeStampBeAf'):
                            self.exeStringWhereTemp += (" and ("+self.exeStringDictWay['timeStampWay']+" > \'"+self.exeStringDict.get(key.split('Way')[0])+"\')")
                    elif 'type' == key or 'widthHeight_type' == key or 'size_type' == key:
                        self.exeStringWhereTemp += (" and ("+key+" = \'"+value+"\')")
                #print(key.split('Way')[0])
                #print(self.exeStringDict.get(key.split('Way')[0]))
            if 'objectWay' == key:
                if self.exeStringWhereTemp == '':
                    self.chooseObjectWrong = False
                else:
                    self.chooseObjectWrong = True
                if '' != self.exeStringDict['object']:
                    self.chooseObject = True
                    if '' == self.exeStringWhereTemp:
                        self.exeStringWhereTemp += ("("+value+" > "+self.exeStringDict['object'] +")")
        #print(self.count)
        #print(self.exeStringWhereTemp)
        #print(len(self.exeStringDictWay.keys()))
        if(0 == self.count):
            QMessageBox.information(self, "emmmm", "没有输入查询项", QMessageBox.Yes)
            return False
        if self.chooseObjectWrong and self.chooseObject:
            QMessageBox.information(self, "warning", "暂时只支持单独按物体查询", QMessageBox.Yes)
            return False
        return True

    def onDateChanged(self, data):
        pass
        #print(self.ui.dateEdit.date())

    def enterEvent(self,QEvent):
        #print('鼠标进入')
        self.setMouseTracking(False)#在MainWindow中不可用

    def leaveEvent(self,QEvent):
        #print('鼠标离开')
        self.setMouseTracking(False)

#    def mouseMoveEvent(self, event):#当鼠标按下拖动时触发
        #if event.buttons() == Qt.NoButton:
        #print((event.pos().x(), event.pos().y()))
#        pass

    def mouseDoubleClickEvent(self, event):
        print(event)

    def mousePressEvent(self, event):
        if event.button()==QtCore.Qt.LeftButton:
            self.m_flag=True
            self.m_Position=event.globalPos()-self.pos() #获取鼠标相对窗口的位置
            event.accept()
            #self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))  #更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if QtCore.Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos()-self.m_Position)#更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag=False
        #self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    def eventFilter(self, object, event):
        if self.ui.pushButton_close == object and event.type() == QEvent.MouseButtonRelease:
            #'pushButton_close' == object.objectName()
            self.closeDatabase()
            self.close()
        #if object == self.calendarWidget:
        #print('active eventFilter')
        if event.type() == QEvent.HoverMove:
            #print(('button ', event.pos().x(), event.pos().y()))
            #print(object.objectName())
            return True
        elif event.type() == QEvent.MouseMove:
            print('点击')
            return True
            #print(('calendar', event.pos().x(), event.pos().y()))
        #return False
        return QWidget.eventFilter(self, object, event)

    def initDatabase2(self):
        self.conn = sqlite3.connect(self.databasePath)
        self.cursor = self.conn.cursor()

    def closeDatabase(self):
        self.cursor.close()
        self.conn.commit()
        self.conn.close()

    def initDatabase(self):
        db=''
        if not self.connectDatabase(db):
            return False
        #self.initTable()

    def connectDatabase(self, db):
        db = QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName(self.databasePath)
        if not db.open():
            print('连接数据库失败')
            return False
        else:
            return True

    def initTable(self):
        self.path1List = os.listdir(self.photoPath1)
        self.path2List = os.listdir(self.photoPath2)
        #ocr字典
        with open(r'X:\IPhone4s\IPhone4S\test.txt','r',encoding = 'utf-8') as f:
            content = f.read()
        self.myDictOcr = json.loads(content)
        #exif字典
        with open(r'X:\IPhone4s\IPhone4S\testExif.txt','r',encoding = 'utf-8') as f:
            s = f.read()
        global myDictExif
        myDictExif = eval(s)
        #DNdone字典
        with open(r'X:\IPhone4s\IPhone4S\DNdone.txt','r',encoding = 'utf-8') as f:
            content = f.read()
        global DNDict
        DNDict = json.loads(content)
        #self.startInsert(self.path1List, self.shortPath1, self.photoPath1)
        #self.startInsert(self.path2List, self.shortPath2, self.photoPath2)
        #self.updateGPSInfo('GPSInfoDecodeFormat', 'GPSInfoPlace')
        #self.updateGPSInfo('Make', 'cameraMaker')
        #self.updateGPSInfo('Model', 'cameraModel')
        #self.updateGPSInfo(['Make','Model'], ['cameraMaker','cameraModel'])
        #self.initPhotoObject()

    def initPhotoObject(self):
        '''
        从DNdone中获取数据
        '''
        self.initPhotoObjectColumn()
        query = QSqlQuery()
        keysDN = DNDict.keys()
        '''
        {
            objectName1:
                            {
                                path1 : float
                                path2 : float
                                ......
                            }
            objectName2:{......}
            ......
        }
        '''
        for objectName in keysDN:
            objectName = objectName.replace(' ','_')
            if DNDict.get(objectName):
                pathCon = DNDict.get(objectName)
            else:
                continue
            pathConKeys = pathCon.keys()
            for pa in pathConKeys:
                confidence = pathCon.get(pa)
                sqlExe = "insert into photoObject (name,path,{}) values('{}','{}',{})".format(objectName, pa.split('\\')[1], pa, confidence)
                if query.exec(sqlExe):
                    #print('success')
                    pass
                else:
                    print(pa+' '+'objectName'+' insert failed')
                    sqlExe = "update photoObject set {}={} where path='{}'".format(objectName, confidence, pa)
                    if query.exec(sqlExe):
                        print('but update success')
                        pass
                    else:
                        print(pa+' '+'objectName'+' update failed')

    def initPhotoObjectColumn(self):
        '''
        根据DNdone创建列
        '''
        query = QSqlQuery()
        keysDN = DNDict.keys()
        print(str(len(keysDN))+' 项')
        for key in keysDN:
            key = key.replace(' ','_')
            sqlExe = "alter table photoObject add column {} FLOAT".format(key)
            #alter table photoObject add column laptop FLOAT;
            if query.exec(sqlExe):
                #print('success')
                pass
            else:
                print(key+' failed')

    def updateGPSInfo(self, fromExif, whereDatabase):
        '''
        一个参数是存储在exif文件中的字典键名，一个是photo表的对应列名称
        暂时只能取出exif文件中的一级内容，写个递归就可以处理多级的问题了
        版本1：
            self.updateGPSInfo('Make', 'cameraMaker')
            self.updateGPSInfo('Model', 'cameraModel')
        只测试过版本1，版本2还未测试，毋庸置疑后者处理多个内容比执行多个前者要方便
        版本2：
            self.updateGPSInfo(['Make','Model'], ['cameraMaker','cameraModel'])
        '''
        if len(fromExif) != len(whereDatabase):
            return
        query = QSqlQuery()
        keyList = myDictExif.keys()
        for key in keyList:
            value = myDictExif.get(key)
            for e, w in zip(fromExif, whereDatabase):
                if value.get(e):
                    GPS = value[e]
                    #print(key+GPS)
                    sqlExe = "update photo set {}='{}' where path='{}'".format(w, GPS, key )
                    if query.exec(sqlExe):
                        #print('success')
                        pass
                    else:
                        print(pa+' failed')

    def startInsert(self, pathList, shortPath, photoPath):
        '''
        开始读取ocr数据，exif数据，以及创建数据库所需的其他数据
        '''
        query = QSqlQuery()
        #开始写入
        for name in pathList:
            #获取suffix
            suf = name.split('.')[1]
            #获取type
            if suf.upper() in ['PNG', 'JPG','HEIC', 'JPEG']:
                type = 'phpto' # 后知后觉 这个单词拼错了 于是打算不改了 让它成为特色
            elif suf.upper() in ['MOV', 'MP4']:
                type = 'video'
            elif suf.upper() == 'GIF':
                type = 'GIFph'
            else:
                continue
            #获取path
            pa = shortPath+name
            #获取ocr
            try:
                ocr = self.myDictOcr.get(pa)
            except:
                ocr = ''
            #获取 3 时间
            cT, mT, aT = self.fileCMATime(photoPath+name)
            #获取宽高以及两种尺寸type
            global myDictExif
            if myDictExif.get(pa):
                if myDictExif.get(pa).get('size'):
                    w = myDictExif.get(pa).get('size')[0]
                    h = myDictExif.get(pa).get('size')[1]
                else:
                    w = 0
                    h = 0
                if myDictExif.get(pa).get('size_type'):
                    size_type = myDictExif.get(pa).get('size_type')
                else:
                    size_type = ''
                if myDictExif.get(pa).get('widthHeight_type'):
                    widthHeight_type = myDictExif.get(pa).get('widthHeight_type')
                else:
                    widthHeight_type = ''
            else:
                w = 0
                h = 0
                size_type = ''
                widthHeight_type = ''
            sqlExe = "insert into photo values('{}','{}','{}','{}','{}',{},{},'{}','{}','{}','{}','{}')".format(name, type, suf, pa, ocr, h, w, size_type, widthHeight_type,cT, mT, aT)
            #print(str(h)+' '+str(w)+' '+size_type+' '+widthHeight_type)
            if query.exec(sqlExe):
                #print('success')
                pass
            else:
                print(pa+' failed')

    def fileCMATime(self, filePath):
        '''
        获取文件的三个时间数据
        '''
        fileInfo = os.stat(filePath)
        cTime = self.secondsToStr(fileInfo.st_ctime) #这是一个以(毫)秒为单位的时间
        mTime = self.secondsToStr(fileInfo.st_mtime)
        aTime = self.secondsToStr(fileInfo.st_atime)
        return cTime, mTime, aTime

    def secondsToStr(self, seconds):
        '''
        将以秒为单位的数据转换成字符串
        '''
        x = time.localtime(seconds)  # 时间元组
        return time.strftime("%Y-%m-%d %X", x) # 时间元组转为字符

    def setStyleSheet(self):
        '''
        首先，layout没有setStyleSheet的方法，QWidget有
        其次，待qt designer设计完成之后，需要修改一点代码
            因为在写的时候没有创建QWidget，再让它的布局设置为表格布局，而是直接在mainWidget上不断嵌套表格布局
            导致不能分块设置qss样式，虽然可以直接在mainWidget上设置，但是指定具体名称又很麻烦
            经实验，得到了一个后期修改方法，ui文件编译后以此法修改即可(换言之，修改会被编译覆盖)
            代码原本是
                self.gridLayout_main.addWidget(self.gridLayout, 0, 0, 1, 2) #这一句一般会在下面一点
            现在则需要先创建一个QWidget
                self.g1Widget = QtWidgets.QWidget()
                self.g1Widget.setObjectName("g1Widget")
            之后再把布局设置到这个QWidget里面
                self.g1Widget.setLayout(self.gridLayout)
            然后改成把这个QWidget添加到主布局中（之前是把布局添加到主布局中）
                self.gridLayout_main.addWidget(self.g1Widget, 0, 0, 1, 2)
            这样就可以在g1Widget上setStyleSheet了
        啊，不愧是我（叉会儿腰）
        '''
#        with open("./qss/my.qss") as f:
#            self.ui.centralWidget.setStyleSheet(f.read())
        with open("./qss/myUp.qss") as f:
            self.ui.upWidget.setStyleSheet(f.read())
        with open("./qss/myLeft.qss") as f:
            self.ui.leftWidget.setStyleSheet(f.read())
        with open("./qss/myRight.qss") as f:
            self.ui.rightWidget.setStyleSheet(f.read())

if __name__ =="__main__":
    import sys
    app = QApplication(sys.argv)
    aMainWindow = MainWindow()
    aMainWindow.show()
    sys.exit(app.exec_())


import random

from fabric import Connection
from patchwork.files import append, exists, directory

REPO_URL = 'https://github.com/eailfly/superlist.git'
REMOTE_USER = 'vagrant'
SITE_NAME = 'superlits-staging.example.org'
PACKAGE = ['vim', 'git', 'python3-venv', 'nginx']

def _install_the_nessary_package(c, package):
    c.sudo(f'apt install {package} -y', echo=True)

def _create_directory_structure_if_necessary(c, site_folder):
    for subfolder in ('database', 'static', 'virtualenv', 'source'):
        directory(c, f'{site_folder}/{subfolder}')

def _get_latest_source(c, source_folder):
    if exists(c, source_folder + '/.git'):
        c.run(f'cd {source_folder} && git fetch')
    else:
        c.run(f'git clone {REPO_URL} {source_folder}')
    current_commit = c.local('git log -n 1 --format=%H')
    c.run(f'cd {source_folder} && git reset --hard {current_commit.stdout}')

def _update_settings(c, source_folder, host):
    settings_path = source_folder + '/superlists/settings.py'
    c.run(f"sed -i 's/DEBUG = True/DEBUG = False/' {settings_path}")
    c.run(f"sed -i 's/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = [\"127.0.0.1\"]/' {settings_path}")
    secret_key_file = source_folder + '/superlists/secret_key.py'
    if not exists(c, secret_key_file):
        chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
        key = ''.join(random.SystemRandom().choice(chars) for _ in range(50))
        append(c, secret_key_file, f'SECRET_KEY = "{key}"')
    append(c, settings_path, '\nfrom .secret_key import SECRET_KEY')

def _update_virtualenv(c, source_folder):
    virtualenv_folder = source_folder + '/../virtualenv'
    if not exists(c, virtualenv_folder + '/bin/pip'):
        c.run(f'python3 -m venv {virtualenv_folder}')
    c.run(f'{virtualenv_folder}/bin/pip install -r {source_folder}/requirements.txt')

def _update_static_files(c, source_folder):
    c.run(f'cd {source_folder}'
          f' && ../virtualenv/bin/python manage.py collectstatic --noinput')

def _update_database(c, source_folder):
    c.run(f'cd {source_folder}'
          f' && ../virtualenv/bin/python manage.py migrate --noinput')

def _set_webservers(c):
    c.put('nginx.template.conf')
    c.put('gunicorn-superlists-staging.service')
    c.sudo('mv nginx.template.conf /etc/nginx/sites-available/superlists')
    c.sudo('chown root.root /etc/nginx/sites-available/superlists')
    c.sudo('ln -s /etc/nginx/sites-available/superlists /etc/nginx/sites-enabled/superlists')
    c.sudo('rm /etc/nginx/sites-enabled/default')
    c.sudo('mv gunicorn-superlists-staging.service /etc/systemd/system/')
    c.sudo('chown root.root /etc/systemd/system/gunicorn-superlists-staging.service')
    c.sudo('systemctl daemon-reload')
    c.sudo('systemctl start nginx')
    c.sudo('systemctl start gunicorn-superlists-staging')

def deploy(c):
    # site_folder = f'/home/{REMOTE_USER}/sites/superlits-staging.example.org'
    # source_folder = site_folder + '/source'
    # package = ' '.join(PACKAGE)
    # _install_the_nessary_package(c, package)
    # _create_directory_structure_if_necessary(c, site_folder)
    # _get_latest_source(c, source_folder)
    # _update_settings(c, source_folder, SITE_NAME)
    # _update_virtualenv(c, source_folder)
    # _update_static_files(c, source_folder)
    # _update_database(c, source_folder)
    _set_webservers(c)

if __name__ == '__main__':
    connection = Connection(host='127.0.0.1',
                            user=REMOTE_USER,
                            port=2222,
                            connect_kwargs={
                                'key_filename': '../.vagrant/machines/default/virtualbox/private_key'
                            },
                            )
    deploy(connection)
    connection.close()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.4'
#       jupytext_version: 1.1.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # s_high_freq_tick_time [<img src="https://www.arpm.co/lab/icons/icon_permalink.png" width=30 height=30 style="display: inline;">](https://www.arpm.co/lab/redirect.php?code=s_high_freq_tick_time&codeLang=Python)
# For details, see [here](https://www.arpm.co/lab/redirect.php?permalink=ExerTickTEvol).

# +
import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt

from arpym.tools import trade_quote_processing, add_logo
# -

# ## [Input parameters](https://www.arpm.co/lab/redirect.php?permalink=s_high_freq_tick_time-parameters)

i_0 = 0  # index of window's starting time for quotes
i_1 = 1249  # index of window's last time for quotes

# ## [Step 0](https://www.arpm.co/lab/redirect.php?permalink=s_high_freq_tick_time-implementation-step00): Load data

# +
path = '../../../databases/global-databases/high-frequency/\
db_US_10yr_Future_quotestrades/'
quotes = pd.read_csv(path + 'quotes.csv', index_col=0, parse_dates=True)
trades = pd.read_csv(path + 'trades.csv', index_col=0, parse_dates=True)

dates_quotes = pd.to_datetime(quotes.index).date
t0 = pd.to_datetime(quotes.index)

time_quotes = np.zeros(len(t0))
for i in range(len(time_quotes)):
    time_quotes[i] = t0[i].timestamp()
p_bid = np.array(quotes.loc[:, 'bid'])  # best bids
p_ask = np.array(quotes.loc[:, 'ask'])  # best asks
h_bid = np.array(quotes.loc[:, 'bsiz'])  # bid sizes
h_ask = np.array(quotes.loc[:, 'asiz'])  # ask sizes

dates_trades = pd.to_datetime(trades.index).date
t_k0 = pd.to_datetime(trades.index)  # time vector of trades
time_trades = np.zeros(len(t_k0))
for i in range(len(time_trades)):
    time_trades[i] = t_k0[i].timestamp()
p_last = np.array(trades.loc[:, 'price'])  # last transaction values
delta_q = np.array(trades.loc[:, 'siz'])  # flow of traded contracts' sizes
delta_sgn = np.array(trades.loc[:, 'aggress'])  # trade sign flow
match = np.array(trades.loc[:, 'mtch'])  # match events
# -

# ## [Step 1](https://www.arpm.co/lab/redirect.php?permalink=s_high_freq_tick_time-implementation-step01): Process the time series

# +
time_quotes, _, _, _, _, _, time_trades, _, p_last,\
    _, _, _ = trade_quote_processing(time_quotes, dates_quotes,
                                     h_ask, p_ask, h_bid,
                                     p_bid, time_trades, dates_trades, p_last,
                                     delta_q, delta_sgn, match)

time_quotes = time_quotes.flatten()

# index of the first trade within the time window
k_0 = np.where(time_trades >= time_quotes[i_0])[0][0]
# index of the last trade within the time window
k_1 = np.where(time_trades <= time_quotes[i_1])[0][-1]

# last transaction value within the time window as a function of tick time
p_last_k = p_last[k_0: k_1+1]
# number of trades within the time window as a function of tick time
k_t = np.arange(1, len(p_last_k)+1)
# -

# ## Plots

# +
plt.style.use('arpm')
trans_time = []
for i in range(k_0, k_1+1):
    trans_time.append(datetime.fromtimestamp(time_trades[i]))
trans_time = np.array(trans_time)

# axes settings
pgrid_min = min(p_last_k)-0.001
pgrid_max = max(p_last_k)+0.001
pgrid = np.linspace(pgrid_min, pgrid_max, 5)
kgrid_min = min(k_t)
kgrid_max = max(k_t)+1
kgrid = np.linspace(kgrid_min, kgrid_max, 5, dtype=int)

fig, _ = plt.subplots(2, 2)

# top-left plot
plt.subplot(221)
plt.ticklabel_format(useOffset=False)
plt.yticks(pgrid)
plt.axis([min(trans_time), max(trans_time), pgrid_min, pgrid_max])
plt.ylabel('Transaction Price')
plt.xlabel('Wall Clock Time')
plt.title('Time evolution')

for k in range(len(k_t) - 1):
    plt.plot([trans_time[k], trans_time[k+1]],
             [p_last_k[k], p_last_k[k]], lw=1, color='r')
plt.scatter(trans_time, p_last_k, c='r', s=5)

plt.grid(True)

# top-right plot
plt.subplot(222)
plt.ticklabel_format(useOffset=False)
plt.xticks(kgrid)
plt.yticks(pgrid)
plt.axis([kgrid_min, kgrid_max, pgrid_min, pgrid_max])
plt.ylabel('Transaction Price')
plt.xlabel('Tick Time')
plt.title('Tick Time Activity Evolution')

for k in range(len(k_t) - 1):
    plt.plot([k_t[k], k_t[k+1]], [p_last_k[k], p_last_k[k]], lw=1, color='r')

plt.scatter(k_t, p_last_k, marker='.', s=5, color='r')
plt.grid(True)

# bottom-left plot
plt.subplot(223)
plt.yticks(kgrid)
plt.axis([min(trans_time), max(trans_time), kgrid_min, kgrid_max])
plt.ylabel('Number of trades')
plt.xlabel('Wall Clock Time')
for k in range(len(k_t) - 1):
    plt.plot([trans_time[k], trans_time[k+1]], [k_t[k], k_t[k]], lw=1,
             color='b')
plt.scatter(trans_time, k_t, marker='.', s=5, color='b')
plt.grid(True)

# bottom-right plot
plt.subplot(224)
plt.yticks(kgrid)
plt.axis([kgrid_min, kgrid_max, kgrid_min, kgrid_max])
plt.ylabel('Number of trades')
plt.xlabel('Tick Time')
plt.plot(k_t, k_t, lw=1, color='b')
plt.grid(True)
add_logo(fig, size_frac_x=1/8)
plt.tight_layout()


# x=rock y=paper z=scissors
beats = {"X":"Z","Y":"X","Z":"Y"}
scores = {"X":1,"Y":2,"Z":3}

score = 0
with open("input.txt") as f:
    for strat in f.read().split("\n"):
        strat = strat.replace("A","X")
        strat = strat.replace("B","Y")
        strat = strat.replace("C","Z")

        split = strat.split(" ")
        win = beats[split[1]] == split[0]
        lose = beats[split[0]] == split[1]
        draw = split[1] == split[0]

        rscore = scores[split[1]]
        if win == True:
            rscore += 6
        elif draw == True:
            rscore += 3

        print(split,win,lose,draw,rscore)
        score += rscore

print(score)


# -*- coding: utf-8 -*-
import scrapy
from scrapy.utils.response import open_in_browser

from scrapy.linkextractors import LinkExtractor

from dataslap_jobs.items import JobItem
from dataslap_jobs.pipelines import ProcessIndeed
from scrapy.loader import ItemLoader

import re
from datetime import datetime,tzinfo,timedelta

from pytz import timezone
import pytz

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy.sql import select
import itertools

from dataslap_jobs.models import *

class IndeedSpider(scrapy.Spider):
    name = "indeed"
    allowed_domains = ["indeed.com"]
    start_urls = ["https://www.indeed.com"]
    search_terms = ["data scientist", "web scraping", "data aggregation"]
    locations = ["New York, NY", "Boston, MA"]
    full_search = list(itertools.product(search_terms, locations))

    avoid_page = []
    avoid_job = []
    duplicate_counter = 0
    duplicate_count_limit = 300
    follow_pagination = True

    custom_settings = {
        'ITEM_PIPELINES': {
            'dataslap_jobs.pipelines.ProcessIndeed': 300,
            'dataslap_jobs.pipelines.RecordJob': 400
        }
    }

    script = """
    function main(splash, args)

        function focus(sel)
            splash:select(sel):focus()
        end

        function wait_to_load(time)
            local initial_check = true
            local initial_html = splash:html()

            while initial_check do
                assert(splash:wait(time))
                local new_html = splash:html()
                if (initial_html == new_html) then
                    initial_check = false
                else
                    initial_html = new_html
                end
            end
        end

				wait_to_load(2)
				assert(splash:go(args.url))
        wait_to_load(2)

        return {
        html = splash:html()
        }
    end
    """

    def parse(self, response):
        for search_term in self.full_search:
            yield scrapy.FormRequest.from_response(
                response,
                formdata={"q" : search_term[0],
                            "l" : search_term[1]},
                callback = self.after_search,
                dont_filter = True
            )

    def after_search(self, response):

        next_page = LinkExtractor(allow=(),
                                  restrict_xpaths='//div[@class="pagination"]',
                                  unique=True).extract_links(response)

        job_links = LinkExtractor(allow=(),
                                  restrict_xpaths='//div[@data-jk]//a[@data-tn-element="jobTitle"]',
                                  unique=True).extract_links(response)

        job_links = [
            job_link.url for job_link in job_links if job_link.url not in self.avoid_job]
        next_page = [
            next_link.url for next_link in next_page if next_link.url not in self.avoid_page]

        for next_link in next_page:
            if self.follow_pagination:
                if next_link not in self.avoid_page:
                    self.avoid_page.append(next_link)
                    next_page_request = scrapy.Request(
                        next_link, callback=self.after_search)
                yield next_page_request

        for job_link in job_links:
            if self.duplicate_counter < self.duplicate_count_limit:
                job_link_request = scrapy.Request(
                    job_link, callback=self.parse_job)
                yield job_link_request
            else:
                self.follow_pagination = False

    def parse_job(self, response):
        url_exists = session_test.query(exists().where(Url_entry.url==response.url)).scalar()
        if not url_exists:
            self.duplicate_counter = 0
            job = ItemLoader(item = JobItem(), response = response)
            job.add_value("url", response.url)

            job.add_xpath(
                "job_company", '//*[@class="company" and preceding-sibling::*[@class="jobtitle"]]//text()')

            job.add_xpath("job_position", '//*[@class="jobtitle"]//text()')
            job.add_xpath("job_text", '//*[@id="job_summary"]//text()')

            job.add_xpath("location", '//div[@data-tn-component]//*[@class="location"]//text()')
            job.add_value('country', "United States")

            extracted = response.xpath('//*[@class = "result-link-bar"]//*[@class = "date"]//text()').extract()
            extracted = "".join(extracted)

            if re.findall("hour", extracted) or re.findall("day", extracted):
                if re.findall("hour", extracted):
                    hours_num = re.findall("\d+", extracted)
                    hours_num = "".join(hours_num)
                    date_output = datetime.now(timezone('US/Eastern')) - timedelta(hours=int(hours_num))
                    job.add_value('date_added', date_output)
                elif re.findall("day", extracted):
                    days_num = re.findall("\d+", extracted)
                    days_num = "".join(days_num)
                    date_output = datetime.now(timezone('US/Eastern')) - timedelta(days=int(days_num))
                    job.add_value('date_added', date_output)

                days_since_posted = (datetime.now(timezone('US/Eastern')) - date_output).days

                job.add_value('date_scraped', datetime.now(timezone('US/Eastern')))

                job.add_value('source', "indeed")

                # job.add_value('page_source_html', response.body)
                job.add_xpath("page_source_text", '//text()')

                if days_since_posted < 28:

                    external_check = response.xpath('//div[@id = "apply-button-container"]//a//@href').extract()
                    if external_check:
                        external_url = "https://www.indeed.com" + "".join(external_check)
                        job.add_value('external_url', external_url)

                        yield scrapy.Request(external_url, self.check_external, meta={
                            'job': job,
                            'splash': {
                                'args': {
                                    'lua_source': self.script,
                                    'html': 1,
                                    },
                                'endpoint': 'execute'}}, dont_filter=True)
                    else:
                        item = job.load_item()
                        yield(item)
        else:
            self.duplicate_counter += 1

    def check_external(self, response):
        job = response.meta['job']
        # job.add_value('page_external_source_html', str(response.body))
        job.add_xpath("page_external_source_text", '//text()')
        item = job.load_item()
        # yield({"pew================": response.body.encode('UTF-8')})

        yield(item)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('billing', '0009_auto_20160705_1256'),
    ]

    operations = [
        migrations.CreateModel(
            name='InvoiceLine',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('payment_for_date', models.DateField(verbose_name='Date payment is for')),
                ('quantity', models.IntegerField(verbose_name='Quantity')),
                ('unit_price_ex_tax', models.DecimalField(verbose_name='Unit price excl. tax (Euro)', max_digits=10, decimal_places=2)),
            ],
        ),
        migrations.CreateModel(
            name='InvoiceRun',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('start_date', models.DateField(verbose_name='Invoice period start date')),
                ('end_date', models.DateField(verbose_name='Invoice period end date')),
                ('invoice_date', models.DateField(verbose_name='Invoice date')),
                ('description', models.TextField(verbose_name='Description', blank=True)),
                ('status', models.CharField(default=b'NEW', max_length=20, verbose_name='Status', choices=[(b'NEW', 'New'), (b'EXPORTING', 'Export in progress'), (b'EXPORTED', 'Exported')])),
            ],
        ),
        migrations.RemoveField(
            model_name='productpayment',
            name='assigned_product',
        ),
        migrations.RemoveField(
            model_name='productpayment',
            name='pricing_used',
        ),
        migrations.AddField(
            model_name='assignedproduct',
            name='next_invoice_date',
            field=models.DateField(null=True, verbose_name='Date of next payment', blank=True),
        ),
        migrations.DeleteModel(
            name='ProductPayment',
        ),
        migrations.AddField(
            model_name='invoiceline',
            name='assigned_product',
            field=models.ForeignKey(verbose_name='Assigned product', to='billing.AssignedProduct'),
        ),
        migrations.AddField(
            model_name='invoiceline',
            name='invoice_run',
            field=models.ForeignKey(related_name='items', verbose_name='Invoice run', to='billing.InvoiceRun'),
        ),
    ]


import os
import bottle
from bottle import Bottle, template, static_file
from pony.orm.integration.bottle_plugin import PonyPlugin

from controllers import surat

path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
templates_dir = os.path.join(dir_path, 'views')
if templates_dir not in bottle.TEMPLATE_PATH:
    bottle.TEMPLATE_PATH.insert(0, templates_dir)

app = Bottle()
pony_plugin = PonyPlugin()
app.install(pony_plugin)

def setup_route(application):
    application.route('/static/<filename:path>', callback=send_static)
    application.route('/', callback=index)
    application.route('/favicon.ico', 'GET', callback=favicon)
    application.route('/surat', 'GET', callback=surat.semua_surat)
    application.route('/surat/new', ['GET', 'POST'], callback=surat.surat_baru)
    application.route('/surat/<id>', 'GET', callback=surat.info_surat)
    application.route('/surat/<id>/edit', 'GET', callback=surat.edit_surat)
    application.route('/surat/<id>/delete', 'GET', callback=surat.delete_surat)

def send_static(filename):
    return static_file(filename, root=os.path.join(os.path.dirname(__file__), 'static'))

def favicon():
    return send_static('favicon.ico')

def index():
    return template('index')

if __name__ == "__main__":
    setup_route(app)
    app.run(debug=True, reloader=True)


from typing import NamedTuple, Sequence, Tuple, Optional

import numpy as np
from scipy.linalg import expm
from scipy.special import legendre
from scipy.signal import cont2discrete

import jax
import jax.numpy as jnp
import flax.linen as nn

class LMUCell(nn.Module):
    """Legendre Memory Unit (LMU) Cell"""

    input_size: int
    hidden_size: int
    memory_size: int
    theta: int
    dt: float = 1.0
    learn_a: bool = False
    learn_b: bool = False

    def setup(self):
        A, B = self.calc_AB()
        self.A = self.param("A", lambda _: self.calc_AB()[0]) if self.learn_a else A
        self.B = self.param("B", lambda _: self.calc_AB()[1]) if self.learn_b else B

        iz, hz, mz = self.input_size, self.hidden_size, self.memory_size

        self.e_x = self.param(
            "e_x", nn.initializers.lecun_uniform(), (self.input_size, 1)
        )
        self.e_h = self.param(
            "e_h", nn.initializers.lecun_uniform(), (self.hidden_size, 1)
        )
        self.e_m = self.param(
            "e_m", nn.initializers.lecun_uniform(), (self.memory_size, 1)
        )

        self.W_in = self.param("W_in", nn.initializers.xavier_normal(), (iz, hz))
        self.W_h = self.param("W_h", nn.initializers.xavier_normal(), (hz, hz))
        self.W_m = self.param("W_m", nn.initializers.xavier_normal(), (mz, hz))
        self.h = self.variable("state", "h", lambda: jnp.zeros((self.hidden_size)))
        self.m = self.variable("state", "m", lambda: jnp.zeros((self.memory_size)))

    def calc_AB(self):
        Q = np.arange(self.memory_size, dtype=np.float64).reshape(-1, 1)
        R = (2 * Q + 1) / self.theta
        i, j = np.meshgrid(Q, Q, indexing="ij")

        A = R * np.where(i < j, -1, (-1.0) ** (i - j + 1))  # (memory_size, memory_size)
        B = R * ((-1.0) ** Q)  # (memory_size, 1)
        C = np.ones((1, self.memory_size))
        D = np.zeros((1,))

        A, B, C, D, _ = cont2discrete((A, B, C, D), self.dt, method="zoh")

        return A, B.T

    def __call__(self, x: jnp.array):
        # compute input to the memory block
        u = x @ self.e_x + self.h.value @ self.e_h + self.m.value @ self.e_m  # (1,)

        # compute new memory state
        self.m.value = self.m.value @ self.A + u @ self.B  # (memory_size,)

        # compute new hidden state
        self.h.value = jnp.tanh(x @ self.W_in + self.h.value @ self.W_h + self.m.value @ self.W_m)  # (hidden_size,)

        return self.h.value

class LDNCell(nn.Module):
    """Legendre Delay Network Cell
    Thanks to: https://github.com/neuromorphs/ant21-legendre/blob/main/notebooks/Basic%20LMU%20implementation.ipynb
    """

    size_in: int
    q: int = 1
    theta: int = 4
    decay: float = 0.5
    dt: float = 1

    def _calculate_initial(self) -> Tuple[jnp.ndarray, jnp.ndarray]:
        # Do Aaron's math to generate the matrices A and B so that
        #  dx/dt = Ax + Bu will convert u into a legendre representation over a window theta
        #  https://github.com/arvoelke/nengolib/blob/master/nengolib/synapses/analog.py#L536
        A = jnp.zeros((self.q, self.q))
        B = jnp.zeros((self.q, 1))
        for i in range(self.q):
            B = B.at[i].set((-1.0) ** i * (2 * i + 1))
            for j in range(self.q):
                A = A.at[i, j].set(
                    (2 * i + 1) * (-1 if i < j else (-1.0) ** (i - j + 1))
                )
        return A / self.theta, B / self.theta

    def _calc_expm(self, A):
        return expm(A * self.dt)

    def setup(self):
        A, B = self._calculate_initial()
        # Handle the fact that we're discretizing the time step
        #  https://en.wikipedia.org/wiki/Discretization#Discretization_of_linear_state_space_models
        result_shape = jax.ShapeDtypeStruct(A.shape, jnp.float32)
        self.Ad = jax.pure_callback(self._calc_expm, result_shape, A)
        self.Bd = jnp.dot(jnp.dot(jnp.linalg.inv(A), (self.Ad - jnp.eye(self.q))), B)

    def __call__(self, x: jnp.array, state: Optional[jnp.ndarray] = None):
        if state is None:
            state = jnp.zeros((self.q, self.size_in))

        # this code will be called every timestep
        new_state = (self.Ad @ state) + (self.Bd @ x[None, :])
        return new_state.T.flatten(), new_state

class LDNCellCompact(nn.Module):
    """Legendre Delay Network Cell
    Thanks to: https://github.com/neuromorphs/ant21-legendre/blob/main/notebooks/Basic%20LMU%20implementation.ipynb
    """

    size_in: int
    q: int = 1
    theta: int = 4
    decay: float = 0.5
    dt: float = 1

    def _calculate_initial(self) -> Tuple[jnp.ndarray, jnp.ndarray]:
        # Do Aaron's math to generate the matrices A and B so that
        #  dx/dt = Ax + Bu will convert u into a legendre representation over a window theta
        #  https://github.com/arvoelke/nengolib/blob/master/nengolib/synapses/analog.py#L536
        A = jnp.zeros((self.q, self.q))
        B = jnp.zeros((self.q, 1))
        for i in range(self.q):
            B = B.at[i].set((-1.0) ** i * (2 * i + 1))
            for j in range(self.q):
                A = A.at[i, j].set(
                    (2 * i + 1) * (-1 if i < j else (-1.0) ** (i - j + 1))
                )
        return A / self.theta, B / self.theta

    def _calc_expm(self, A):
        return expm(A * self.dt)

    @nn.compact
    def __call__(self, x: jnp.ndarray, state: Optional[jnp.ndarray] = None):
        A = self.param("A", lambda _: self._calculate_initial()[0])
        B = self.param("B", lambda _: self._calculate_initial()[1])

        if state is None:
            state = jnp.zeros((self.q, self.size_in))

        # Handle the fact that we're discretizing the time step
        #  https://en.wikipedia.org/wiki/Discretization#Discretization_of_linear_state_space_models
        result_shape = jax.ShapeDtypeStruct(A.shape, jnp.float32)
        Ad = jax.pure_callback(self._calc_expm, result_shape, A)
        Bd = jnp.dot(jnp.dot(jnp.linalg.inv(A), (Ad - jnp.eye(self.q))), B)

        # this code will be called every timestep
        new_state = (Ad @ state) + (Bd @ x[None, :])
        return new_state.T.flatten(), new_state


def sum_difference():
    mylist = [x for x in range(0,101)]
    sum = 0
    for x in mylist:
        sum = sum + x
        sum1 = sum**2

    sum2 = 0
    mylist2 = [ x**2 for x in range(0,101)]
    for y in mylist2:
        sum2 = sum2 + y

    return sum1 - sum2

print(sum_difference())


from collections import defaultdict

import en_core_web_md
from flair.data import Sentence
from sklearn.feature_extraction import DictVectorizer
from common import SPAN
import numpy as np
from tqdm import tqdm
from flair.embeddings import TransformerWordEmbeddings

class RelationsVectorizer:
    def __init__(self, i2sentence, op_relations, embedding_type='', dv=None):

        self.features = self.get_features(i2sentence, op_relations)
        self.remove_redundant_features()
        self.normalize_features()

        if not dv:
            self.dv = DictVectorizer()
            self.f_vectors = self.dv.fit_transform(self.features).toarray()
        else:
            self.dv = dv
            self.f_vectors = self.dv.transform(self.features).toarray()
        if embedding_type != '':
            print("load embedding!")
            self.embedding_vectorizer = WeVectorizer(op_relations, embedding_type)
            self.e_vectors = self.embedding_vectorizer.vectors
            self.vectors = self.merge_vectors(self.f_vectors, self.e_vectors)
        else:
            self.vectors = self.f_vectors

    def normalize_features(self):
        sent_max = max([f["dist_sent"] for f in self.features])
        tree_max = max([f["dist_tree"] for f in self.features])
        for f in self.features:
            f["dist_sent"] /= sent_max
            f["dist_tree"] /= tree_max

    def merge_vectors(self, feat_vectors, embedding_vectors):
        merged = []
        for f_vec, e_vec in zip(feat_vectors, embedding_vectors):
            merged.append(np.concatenate([f_vec, e_vec]))
        return np.array(merged)

    def remove_redundant_features(self):
        stat = self.create_features_stat()
        for f_dict in self.features:
            for f_name, f_val in f_dict.items():
                f_stat = stat[f_name][f_val]
                if (f_name == "dist_sent" and (f_val < 4 or f_val > 20)) or \
                        (f_name == "dist_tree" and (f_val < 3 or f_val > 10)):
                    f_dict[f_name] = 0
                if f_name not in ["dist_sent", "dist_tree"] and f_stat < 15:
                    f_dict[f_name] = "OTHER"

    def create_features_stat(self):
        stat = defaultdict(lambda: defaultdict(int))
        for f in self.features:
            for f_name, f_val in f.items():
                stat[f_name][f_val] += 1

        for f_name, f_stat in stat.items():
            stat[f_name] = {k: v for k, v in sorted(f_stat.items(), key=lambda item: item[1], reverse=True)}

        return stat

    def get_features(self, i2sentences, relations):
        features = []
        for relation in relations:
            feature = self.get_relation_features(relation, i2sentences[relation[0]])
            features.append(feature)
        return features

    def get_relation_features(self, relation, sentence):
        features = {}
        for f_feature in [self.f_pre_pos, self.f_after_pos, self.f_distance_in_sentence, self.f_distance_in_tree,
                          self.f_cur_pos]:
            f_feature(features, relation[1], relation[2], sentence)
        return features

    def f_pre_pos(self, features, person, org, sentence):
        person_start_index = person[SPAN][0]
        if person_start_index != 0:
            features["pre_person_pos"] = sentence.analyzed[person_start_index - 1].pos_
        else:
            features["pre_person_pos"] = "START"

        org_start_index = org[SPAN][0]
        if org_start_index != 0:
            features["pre_org_pos"] = sentence.analyzed[org_start_index - 1].pos_
        else:
            features["pre_org_pos"] = "START"

        return features

    def f_cur_pos(self, features, person, org, sentence):
        person_start_index = person[SPAN][0]
        features["cur_person_pos"] = sentence.analyzed[person_start_index].pos_

        org_start_index = org[SPAN][0]
        features["cur_org_pos"] = sentence.analyzed[org_start_index].pos_
        return features

    def f_after_pos(self, features, person, org, sentence):
        person_end_index = person[SPAN][1]
        try:
            if person_end_index != len(sentence.analyzed.doc) - 1:
                features["after_person_pos"] = sentence.analyzed[person_end_index + 1].pos_
            else:
                features["after_person_pos"] = "END"
        except Exception as error:
            pass

        org_end_index = org[SPAN][1]
        if org_end_index != len(sentence.analyzed.doc) - 1:
            features["after_org_pos"] = sentence.analyzed[org_end_index + 1].pos_
        else:
            features["after_org_pos"] = "END"

    def f_distance_in_sentence(self, features, person, org, sentence):
        person_start_index = person[SPAN][0]
        org_start_index = org[SPAN][0]
        features["dist_sent"] = abs(person_start_index - org_start_index)

    def f_distance_in_tree(self, features, person, org, sentence):
        person_start_index = person[SPAN][0]
        person_end_index = person[SPAN][1]
        org_start_index = org[SPAN][0]
        cur_head = sentence.analyzed[org_start_index]
        dist = 1
        # all_deps = defaultdict(int)
        while cur_head.dep_ != "ROOT" and (person_start_index > cur_head.i or cur_head.i > person_end_index):
            dist += 1
            cur_head = cur_head.head
        #     all_deps[f"dep_{cur_head.dep_}"] += 1
        #
        # if cur_head.dep_ != "ROOT":
        #     all_deps[f"dep_{cur_head.dep_}"] += 1
        #     features.update(all_deps)

        if cur_head.dep_ == "ROOT":
            features["dist_tree"] = 0
        else:
            features["dist_tree"] = dist

class WeVectorizer:

    def __init__(self,  op_relations, vectorizer='spacy'):
        if vectorizer == 'spacy':
            self.vectorizer = en_core_web_md.load()
        else:
            self.vectorizer = TransformerWordEmbeddings('roberta-base')
        self.vectors = self.vectorizer_data(op_relations)

    def _vectorizer_data(self, relations):
        vecs = []
        for sent_id, per_cand, org_cand, sent_raw  in tqdm(relations):
            sent = sent_raw.strip("().\n")
            org = org_cand['text']
            per = per_cand['text']
            sent_clean = sent.replace(org, "").replace(per, "")
            vecs.append(self.vec_sent(sent_clean, per, org))
        vecs = np.array(vecs)
        return vecs

    def vectorizer_data(self, relations):
        vecs = []
        for sent_id, per_cand, org_cand, sent_raw in tqdm(relations):
            sent = sent_raw.strip("().\n")
            sent = Sentence(sent)
            self.vectorizer.embed(sent)
            vecs.append(sent[0].embedding.cpu().detach().numpy())
        vecs = np.array(vecs)
        return vecs

    def vec_sent(self, sent, per_candidate, org_candidate):
        toks = [t for t in self.vectorizer(sent) if not any([t.is_space, t.is_punct, t.is_stop, t.is_currency]) and t.has_vector]
        sent_vecs = np.array([t.vector for t in toks]).mean(axis=0)
        per_vec = self.vectorize_ent(per_candidate)
        org_vec = self.vectorize_ent(org_candidate)
        res = np.concatenate([sent_vecs, per_vec, org_vec])
        return res

    def vectorize_ent(self, org_candidate):
        return np.array([t.vector for t in self.vectorizer(org_candidate)]).mean(axis=0)


# coding=utf-8

"""Zonal statistics on a raster layer."""

import logging

from qgis.analysis import QgsZonalStatistics
from qgis.core import QgsFeatureRequest

from safe.definitions.fields import exposure_count_field, total_field
from safe.definitions.layer_purposes import (
    layer_purpose_aggregate_hazard_impacted)
from safe.definitions.processing_steps import zonal_stats_steps
from safe.gis.sanity_check import check_layer
from safe.gis.vector.reproject import reproject
from safe.gis.vector.tools import (
    copy_layer,
    copy_fields,
    remove_fields,
    rename_fields,
    create_memory_layer,
    create_field_from_definition)
from safe.utilities.gis import qgis_version
from safe.utilities.i18n import tr
from safe.utilities.profiling import profile

__copyright__ = "Copyright 2016, The InaSAFE Project"
__license__ = "GPL version 3"
__email__ = "info@inasafe.org"
__revision__ = '1a0dd4852cc92d080bf32eb73bc0487259083a8c'

LOGGER = logging.getLogger('InaSAFE')

@profile
def zonal_stats(raster, vector):
    """Reclassify a continuous raster layer.

    Issue https://github.com/inasafe/inasafe/issues/3190

    The algorithm will take care about projections.
    We don't want to reproject the raster layer.
    So if CRS are different, we reproject the vector layer and then we do a
    lookup from the reprojected layer to the original vector layer.

    :param raster: The raster layer.
    :type raster: QgsRasterLayer

    :param vector: The vector layer.
    :type vector: QgsVectorLayer

    :return: The output of the zonal stats.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = zonal_stats_steps['output_layer_name']

    exposure = raster.keywords['exposure']
    if raster.crs().authid() != vector.crs().authid():
        layer = reproject(vector, raster.crs())

        # We prepare the copy
        output_layer = create_memory_layer(
            output_layer_name,
            vector.geometryType(),
            vector.crs(),
            vector.fields()
        )
        copy_layer(vector, output_layer)
    else:
        layer = create_memory_layer(
            output_layer_name,
            vector.geometryType(),
            vector.crs(),
            vector.fields()
        )
        copy_layer(vector, layer)

    input_band = layer.keywords.get('active_band', 1)
    analysis = QgsZonalStatistics(
        layer,
        raster,
        'exposure_',
        input_band,
        QgsZonalStatistics.Sum)
    result = analysis.calculateStatistics(None)
    LOGGER.debug(tr('Zonal stats on %s : %s' % (raster.source(), result)))

    output_field = exposure_count_field['field_name'] % exposure
    if raster.crs().authid() != vector.crs().authid():
        output_layer.startEditing()
        field = create_field_from_definition(
            exposure_count_field, exposure)

        output_layer.addAttribute(field)
        new_index = output_layer.fields().lookupField(field.name())
        old_index = layer.fields().lookupField('exposure_sum')
        for feature_input, feature_output in zip(
                layer.getFeatures(), output_layer.getFeatures()):
            output_layer.changeAttributeValue(
                feature_input.id(), new_index, feature_input[old_index])
        output_layer.commitChanges()
        layer = output_layer
    else:
        fields_to_rename = {
            'exposure_sum': output_field
        }
        if qgis_version() >= 21600:
            rename_fields(layer, fields_to_rename)
        else:
            copy_fields(layer, fields_to_rename)
            remove_fields(layer, list(fields_to_rename.keys()))
        layer.commitChanges()

    # The zonal stats is producing some None values. We need to fill these
    # with 0. See issue : #3778
    # We should start a new editing session as previous fields need to be
    # committed first.
    layer.startEditing()
    request = QgsFeatureRequest()
    expression = '\"%s\" is None' % output_field
    request.setFilterExpression(expression)
    request.setFlags(QgsFeatureRequest.NoGeometry)
    index = layer.fields().lookupField(output_field)
    for feature in layer.getFeatures():
        if feature[output_field] is None:
            layer.changeAttributeValue(feature.id(), index, 0)
    layer.commitChanges()

    layer.keywords = raster.keywords.copy()
    layer.keywords['inasafe_fields'] = vector.keywords['inasafe_fields'].copy()
    layer.keywords['inasafe_default_values'] = (
        raster.keywords['inasafe_default_values'].copy())

    key = exposure_count_field['key'] % raster.keywords['exposure']

    # Special case here, one field is the exposure count and the total.
    layer.keywords['inasafe_fields'][key] = output_field
    layer.keywords['inasafe_fields'][total_field['key']] = output_field

    layer.keywords['exposure_keywords'] = raster.keywords.copy()
    layer.keywords['hazard_keywords'] = vector.keywords[
        'hazard_keywords'].copy()
    layer.keywords['aggregation_keywords'] = (
        vector.keywords['aggregation_keywords'])
    layer.keywords['layer_purpose'] = (
        layer_purpose_aggregate_hazard_impacted['key'])

    layer.keywords['title'] = output_layer_name

    check_layer(layer)
    return layer


class Stack() :
    def __init__(self):
        self.data = []

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

    def is_empty(self):
        if len(self.data) == 0:
            return True
        else:
            return False

    def push(self, element):
        self.data.append(element)

    def pop(self):
        if self.is_empty() :
            return 'Stack is empty'
        else:
            return self.data.pop()

    def top(self):
        if self.is_empty():
            return 'Stack is empty'
        else:
            return self.data[-1]

s = Stack()
s.push(10)
s.push(20)
print('Stack :', s.data)
print('Is - Empty :', s.is_empty())
print('Length:', len(s))
print('Popped:', s.pop())
print('Popped:', s.pop())
print('Is - Empty :', s.is_empty())
print('Popped:', s.pop())
print('Top:', s.top())
s.push(10)
s.push(20)
s.push(30)
s.push(40)
print('Stack: ', s.data)
print('TOP:', s.top())


from math import atan2, cos, exp, log, sin
from typing import Self

class CNum:
    real_part: float = 0.0
    imaginary_part: float = 0.0

    def __init__(self, real_part: float = 0.0, imaginary_part: float = 0.0):
        self.imaginary_part = float(imaginary_part)
        self.real_part = float(real_part)

    def __str__(self) -> str:
        if self.real_part >= 0.0 and self.imaginary_part >= 0.0:
            return f'{self.real_part} + {self.imaginary_part} * i'
        if self.real_part < 0.0 and self.imaginary_part < 0.0:
            return f'-{abs(self.real_part)} - {abs(self.imaginary_part)} * i'
        if self.real_part < 0.0:
            return f'-{abs(self.real_part)} + {self.imaginary_part} * i'
        return f'{self.real_part} - {abs(self.imaginary_part)} * i'

    def __add__(self, other: Self | int | float) -> Self:
        if not (isinstance(other, float) or isinstance(other, int) or isinstance(other, CNum)):
            raise TypeError()

        if isinstance(other, CNum):
            return CNum(
                self.real_part + other.real_part,
                self.imaginary_part + other.imaginary_part
            )

        return CNum(self.real_part + other, self.imaginary_part)

    def __sub__(self, other: Self | float | int) -> Self:
        if not (isinstance(other, float) or isinstance(other, int) or isinstance(other, CNum)):
            raise TypeError()
        if isinstance(other, CNum):
            return CNum(
                self.real_part - other.real_part,
                self.imaginary_part - other.imaginary_part
            )

        return CNum(self.real_part - other, self.imaginary_part)

    def __mul__(self, other: Self | float | int) -> Self:
        if not (isinstance(other, float) or isinstance(other, int) or isinstance(other, CNum)):
            raise TypeError()

        if isinstance(other, CNum):
            new_real_part = (
                    self.real_part
                    * other.real_part
                    - self.imaginary_part
                    * other.imaginary_part
            )

            new_imaginary_part = (
                    self.real_part
                    * other.imaginary_part
                    + self.imaginary_part
                    * other.real_part
            )

            return CNum(new_real_part, new_imaginary_part)

        return CNum(other * self.real_part, other * self.imaginary_part)

    def __truediv__(self, other: Self | float | int) -> Self:
        if not (isinstance(other, float) or isinstance(other, int) or isinstance(other, CNum)):
            raise TypeError()

        if isinstance(other, CNum):
            if other.real_part and other.imaginary_part:
                raise ZeroDivisionError()

            divider = (
                    other.real_part ** 2
                    + other.imaginary_part ** 2
            )
            new_real_part = ((
                                     self.real_part
                                     * other.real_part
                                     + self.imaginary_part
                                     * other.imaginary_part
                             ) / divider
                             )
            new_imaginary_part = ((
                                          self.imaginary_part
                                          * other.real_part
                                          - self.real_part
                                          * other.imaginary_part
                                  ) / divider
                                  )

            return CNum(new_real_part, new_imaginary_part)

        if other:
            raise ZeroDivisionError()

        return CNum(self.real_part / other, self.imaginary_part / other)

    def __radd__(self, other: Self) -> Self:
        return self + other

    def __rsub__(self, other: Self | float | int) -> Self:
        return -self + other

    def __rmul__(self, other: Self | float | int) -> Self:
        return self * other

    def __abs__(self) -> float:
        return (self.real_part ** 2 + self.imaginary_part ** 2) ** 0.5

    def __eq__(self, other: Self) -> bool:
        return self.real_part == other.real_part and self.imaginary_part == other.imaginary_part

    def __ne__(self, other: Self) -> bool:
        return self.real_part != other.real_part or self.imaginary_part != other.imaginary_part

    def __pow__(self, power: int | float | Self, modulo=None) -> Self:
        if not (isinstance(power, float) or isinstance(power, int) or isinstance(power, CNum)):
            raise TypeError()

        if isinstance(power, float) or isinstance(power, int):
            return abs(self) * CNum(cos(power * self.get_fi()), sin(power * self.get_fi()))

        return (self.__get_power_for_pow(power)).get_exp()

    def __neg__(self) -> Self:
        return CNum(-self.real_part, -self.imaginary_part)

    def get_log(self):
        return CNum(log(abs(self)), self.get_fi())

    def get_exp(self) -> Self:
        return exp(self.real_part) * CNum(cos(self.imaginary_part), sin(self.imaginary_part))

    def get_fi(self) -> float:
        return atan2(self.imaginary_part, self.real_part)

    def __get_power_for_pow(self, other: Self) -> Self:
        return self.get_log() * other

    @staticmethod
    def get_cnum_from_str(c_num: str) -> list[float]:
        sign: int = 1
        tmp = ''
        n = 0
        answer: list[float] = [0.0, 0.0]
        for elem in c_num:
            if elem in '1234567890.':
                tmp += elem
                continue

            if elem == "i" and answer[0] == 0:
                n = 1

            if elem == "i" and tmp == "" and '*' not in c_num:
                tmp = 1.0

            if elem in 'i-+*' and tmp != '':
                answer[n] = float(tmp) * sign
                tmp = ''
                n += 1
                sign = 1

            if elem == '-':
                sign = -1

        if tmp != '':
            answer[0] = float(c_num)
        return answer

    def update_c_num(self, c_num: str):
        if 'i' in c_num:
            self.real_part, self.imaginary_part = self.get_cnum_from_str(c_num)[0], self.get_cnum_from_str(c_num)[1]
        else:
            self.real_part = float(c_num)
            self.imaginary_part = 0.0


scores = []

for i in range(1,6):
    scores.append(int(input('enter test score: ' + str(i) + ': ')))

def determine_grade(score):
    if score > 89 and score < 101:
        return 'A'
    elif score > 79 and score < 90:
        return 'B'
    elif score > 69 and score < 80:
        return 'C'
    elif score > 59 and score < 70:
        return 'D'
    elif score < 60:
        return 'F'
for score in scores:
    print(determine_grade(score))

def calc_avarage(scores):
    totaal = 0
    for score in scores:
        totaal += score
    avarage = totaal/5
    return avarage
print(calc_avarage(scores))