import json

def show_menu():
    print('\n---')
    print('Example code snippets menu')
    print('1 - Load data from a JSON file')
    print('2 - Load data from a JSON string')
    print('3 - Write data to a JSON file')
    print('4 - Write data to a JSON string')
    print('5 - Write data to a JSON file with indentation')
    print('S - Stop the program')
    print('---')
    menu_item = input('Select menu item: ')
    print()
    if menu_item not in ['S', 's']:
        if menu_item == '1':
            load_data_from_json_file()
        elif menu_item == '2':
            load_data_from_json_string()
        elif menu_item == '3':
            write_data_to_a_json_file()
        elif menu_item == '4':
            write_data_to_json_string()
        elif menu_item == '5':
            write_data_to_a_json_file_with_indentation()
        else:
            print('Invalid menu selection. Please try again.')
        show_menu()

def load_data_from_json_file():
    # Declare the data dictionary before the with statement,
    # so that we can access it after the file has closed.
    recipes_data = {}
    with open('recipes-original.json') as file:
        recipes_data = json.load(file)

    # Iterate through each of the recipes in the "recipes" list in the data
    # and print details of each recipe
    recipes = recipes_data['recipes']
    for recipe in recipes:
        # Get the values of name and serves attributes, assign to variables for printing
        name = recipe['name']
        serves = recipe['serves']
        print(f'---\n{name}, serves: {serves}\n')

        # Prints all of the ingredient children data, from ingredients list
        ingredients = recipe['ingredients']
        for ingredient in ingredients:
            print(f' * {ingredient}')
        print(f'---\n')

def load_data_from_json_string():
    # Create a string that has data about countries in JSON format
    data = '{"countries": [' + \
        '{"name": "Estonia", "population_millions": 1.3, "neighbours": ["Latvia", "Russia"]},' + \
        '{"name": "Belarus", "population_millions": 9.5, "neighbours": ["Lithuania", "Latvia", "Poland", "Russia", "Ukraine"]}' + \
        ']}'
    print(f'String to parse as JSON data: {data}')

    # Load the JSON string into a dictionary
    data_dict = json.loads(data)
    print(f"Loaded the JSON data into a dictionary")

    countries = data_dict['countries']
    for country in countries:
        # Assign name and population to variables for printing
        name = country['name']
        population = country['population_millions']
        print(f'\nCountry: {name}')
        print(f'Population (in millions): {population}\n')

        # Iterate through the neighbouring countries for the country
        print('Neighbours:')
        neighbours = country['neighbours']
        for neighbour in neighbours:
            print(f'* {neighbour}')
        print('---')

def write_data_to_a_json_file():
    # Create a dictionary of lists for writing to json file
    favourite_recipes = {
        'recipes': [
            {
                'name': 'Nachos',
                'serves': 4,
                'ingredients': [
                    '8 cherry tomatoes', '100g natural corn chips',
                    '2/3 cup Hommus', '1/4 cup fresh parsley'
                ]
            },
            {
                'name': 'Mushroom Risotto',
                'serves': 4,
                'ingredients': [
                    '2 cups mushrooms, sliced', '1 cup Arborio rice',
                    '4 cups vegetable stock', '1 cup grated Parmesan cheese'
                ]
            }
        ]
    }
    number_of_recipes = len(favourite_recipes['recipes'])

    # Open a file and write the dictionary of lists to file in json format
    with open('favourite-recipes.json', 'w') as file:
        json.dump(favourite_recipes, file)
    print(f'Wrote {number_of_recipes} recipes to a json file')

def write_data_to_json_string():
    # Create a dictionary with data for two countries
    countries_data = {
        'countries': [
            {
                'name': 'Latvia',
                'population_in_millions': 1.9,
                'countries': ['Belarus', 'Estonia', 'Lithuania', 'Russia']
            },
            {
                'name': 'Finland',
                'population_in_millions': 5.5,
                'countries': ['Norway', 'Russia', 'Sweden']
            }
        ]
    }
    # Write the countries data to a string in JSON format
    countries_string = json.dumps(countries_data)
    print('String created with json.dumps printed below:\n')
    print(countries_string)

def write_data_to_a_json_file_with_indentation():
    # Open a json file with recipes that has no indentation
    recipe_data = {}
    with open('recipes-no-format.json') as file:
        recipe_data = json.load(file)

    # Create a json file and write the recipes data with indentation (note the indent argument)
    with open('recipes-indentation.json', 'w') as file:
        json.dump(recipe_data, file, indent=4)
    print("\nWrote the data to the 'recipes-indentation.json' file, with indent of 4 spaces.\n")

# Mainline of the program
show_menu()


import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import os

from notepad import Writer, Notepad
from ta_test8_6 import Figure_Canvas
from report4 import tab_widget
from datewrong import dateWrong

sys.path.append('C:\\Users\\user\\Desktop\\lastest(8.19)\\game')
import tetris
from tetris import Tetris
import Snake
from Snake import MyApp

class firstWindow(QWidget):

    def setupUi(self,MainWindow):
        sshFile="orange.qss"
        with open(sshFile,"r") as fh:
            self.setStyleSheet(fh.read())

        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1024, 768)
        #MainWindow.setStyleSheet("#MainWindow { border-image: url(./icon/trader2.png) 0 0 0 0 stretch stretch; }")
        self.setWindowIcon(QIcon('./icon/icon.png'))

        self.show()

    def fade(self):

        if self.fileMenu.title()=="商品":
            self.fileMenu.setTitle("Item")
            self.addAction.setText("Add Item")
            self.setAction.setText("Item Setting")
            self.fileMenu2.setTitle("Strategy")
            self.writeAction.setText("Edit")
            self.checkAction.setText("View")
            self.chooseAction.setText("Choose")
            self.fileMenu3.setTitle("Performance Report")
            self.reportAction.setText("Show")
            self.fileMenu4.setTitle("Order")
            self.exchangeAction.setText("Stock Exchange")
            self.orderAction.setText("Make Order")
            self.fileMenu5.setTitle("Advanced")
            self.fileMenu6.setTitle("Language Setting")
            self.fileMenu7.setTitle("Game")
            self.gameAction.setText("Tetris")
            self.snakeAction.setText("Snake eating")

    def fadeout(self):
        if self.fileMenu.title()=="Item":
            self.fileMenu.setTitle("商品")
            self.addAction.setText("新增商品")
            self.setAction.setText("設定商品")
            self.fileMenu2.setTitle("交易策略")
            self.writeAction.setText("編寫")
            self.checkAction.setText("查看")
            self.chooseAction.setText("選擇")
            self.fileMenu3.setTitle("檢視績效報告")
            self.reportAction.setText("策略績效報告")
            self.fileMenu4.setTitle("下單接口")
            self.exchangeAction.setText("選擇證券交易所")
            self.orderAction.setText("下單")
            self.fileMenu5.setTitle("進階")
            self.fileMenu6.setTitle("設定語言")
            self.fileMenu7.setTitle("遊戲")
            self.gameAction.setText("俄羅斯方塊")
            self.snakeAction.setText("貪吃蛇")

    def re(self):
        path = "C:\\Users\\user\\Desktop\\lastest(8.19)\\cache"
        listR = []
        for dirPath, dirNames, fileNames in os.walk (path):
            fileNames = [ fi for fi in fileNames if  fi.endswith(".csv") ]
            for f in fileNames:
                listR.append(f)

        for r in range(len(listR)):
            if int(listR[r][0])>=1:
                self.reportwindow = tab_widget()
                self.reportwindow.show()
                #tab_widget()
                break

            elif len(listR) == -1:
                if self.fileMenu.title()=="Item":
                    self.dwrongmsg = dateWrong("NS-C",1)  #no strategy choose
                else:
                    self.dwrongmsg = dateWrong("NS-C")
                self.dwrongmsg.show()

    def se(self):
        path = "C:\\Users\\user\\Desktop\\lastest(8.19)\\cache"

        listC = []
        for dirPath, dirNames, fileNames in os.walk (path):
            fileNames = [ fi for fi in fileNames if  fi.endswith(".csv") ]
            for f in fileNames:
                listC.append(f.replace(".csv",""))

        if len(listC)>=1:
            print (listC)
            self.choosewindow = chooseWindow()
            self.choosewindow.show()
        else:
            if self.fileMenu.title()=="Item":
                self.dwrongmsg = dateWrong("NI-C",1)
            else:
                self.dwrongmsg = dateWrong("NI-C")  #no item choose
            self.dwrongmsg.show()

    def ae(self):
        if self.fileMenu.title()=="Item":
            self.addwindow = addWindow(1)
        else:
            self.addwindow = addWindow()
        self.addwindow.show()

    def we(self):       #init editor and compiler
        self.writewindow = Writer()
        self.writewindow.show()

    def Russia(self):
        self.abc =Tetris()
        self.abc.show()

    def EAT(self):
        self.eat = MyApp()
        self.eat.show()

    def initUI(self):

        self.addAction = QAction(QIcon('./icon/add.png'), '新增商品', self)
        self.addAction.setShortcut('Alt+F1')
        self.addAction.setStatusTip('從內部資料庫新增商品')
        self.addAction.triggered.connect(self.ae)

        self.setAction = QAction(QIcon('./icon/set.png'), '設定商品', self)
        self.setAction.setShortcut('Alt+F2')
        self.setwindow = setWindow()
        self.setAction.triggered.connect(self.setwindow.show)
        self.setAction.setStatusTip('設定目前商品的細項')

        #第二個按鈕裡面的東西
        self.writeAction = QAction(QIcon('./icon/write.png'), '編寫', self)
        self.writeAction.setShortcut('Alt+W')
        self.writeAction.triggered.connect(self.we)
        self.writeAction.setStatusTip('手動編寫交易策略')

        self.checkAction = QAction(QIcon('./icon/check.png'), '查看', self)
        self.checkAction.setShortcut('Alt+C')
        self.checkwindow = checkWindow()
        self.checkAction.triggered.connect(self.checkwindow.show)
        self.checkAction.setStatusTip('查看內建的交易策略')

        self.chooseAction = QAction(QIcon('./icon/check.png'), '選擇', self)
        self.chooseAction.setShortcut('Alt+C')

        self.chooseAction.triggered.connect(self.se)
        self.chooseAction.setStatusTip('查看內建的交易策略')
        #第三個按鈕
        self.reportAction = QAction(QIcon('./icon/report.png'), '策略績效報告', self)
        self.reportAction.setShortcut('Alt+R')
        self.reportAction.setStatusTip('檢視此次交易策略之績效報告')
        self.reportAction.triggered.connect(self.re)
        #第四個按鈕
        self.exchangeAction = QAction(QIcon('./icon/exchange.png'), '選擇證券交易所', self)
        self.exchangewindow = exchangeWindow()
        self.exchangeAction.setShortcut('Alt+X')
        self.exchangeAction.triggered.connect(self.exchangewindow.show)
        self.exchangeAction.setStatusTip('選擇欲交易之證券交易所')

        self.orderAction = QAction(QIcon('./icon/order.png'), '下單', self)
        self.tradewindow = tradeWindow()
        self.orderAction.setShortcut('Alt+O')
        self.orderAction.triggered.connect(self.tradewindow.show)
        self.orderAction.setStatusTip('與證券交易所進行交易')
        #第五個按鈕

        self.Language = QAction('繁體中文', self)
        self.Language.setShortcut('Alt+8')
        self.Language.triggered.connect(self.fadeout)
        self.Language2 = QAction('English', self)
        self.Language2.setShortcut('Alt+9')
        self.Language2.triggered.connect(self.fade)

        self.gameAction = QAction('俄羅斯方塊', self)
        self.gameAction.triggered.connect(self.Russia)

        self.snakeAction = QAction('貪吃蛇', self)
        self.snakeAction.triggered.connect(self.EAT)

        self.statusBar()
        menubar = self.menuBar()
        menubar.setStyleSheet("font-size: 12pt")

        self.fileMenu = menubar.addMenu('商品')
        self.fileMenu2 = menubar.addMenu('交易策略')
        self.fileMenu3 = menubar.addMenu('檢視績效報告')
        self.fileMenu4 = menubar.addMenu('下單接口')
        self.fileMenu5 = menubar.addMenu('進階')
        self.fileMenu6 = self.fileMenu5.addMenu('設定語言')
        self.fileMenu7 = self.fileMenu5.addMenu('遊戲')

        self.fileMenu.addActions([self.addAction,self.setAction])
        self.fileMenu2.addActions([self.writeAction,self.checkAction,self.chooseAction])
        self.fileMenu3.addAction(self.reportAction)
        self.fileMenu4.addActions([self.exchangeAction,self.orderAction])
        self.fileMenu6.addActions([self.Language,self.Language2])
        self.fileMenu7.addActions([self.gameAction,self.snakeAction])

        self.setWindowTitle('iTrader ver2.0')
        self.createContextMenu()
        self.show()

    def createContextMenu(self):

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showContextMenu)

        self.contextMenu = QMenu(self)
        self.actionA = self.contextMenu.addAction("新增商品")
        self.actionB = self.contextMenu.addAction("編寫交易策略")
        self.actionC = self.contextMenu.addAction("選擇交易策略")
        self.actionD = self.contextMenu.addAction("檢視績效報表")
        self.actionA.triggered.connect(self.ae)
        self.actionB.triggered.connect(self.we)
        self.actionC.triggered.connect(self.se)
        self.actionD.triggered.connect(self.re)

    def showContextMenu(self, pos):

        self.contextMenu.move(self.pos() + pos)
        self.contextMenu.show()

class slaveWindow(QWidget):
    def __init__(self, parent = None):
        super(slaveWindow, self).__init__(parent)

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

class slaveWindow2(QWidget):
    def __init__(self, parent = None):
        super(slaveWindow2, self).__init__(parent)

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

class addWindow(QTabWidget):
    def __init__(self,*args, parent = None):
        super(addWindow, self).__init__(parent)
        self.setWindowTitle('新增商品')
        #self.setFixedSize(500, 300)
        self.setGeometry(600,300,700,400)

        self.listWidget = QListWidget(self)

        item = QtWidgets.QListWidgetItem()

        if len(args) == 0:          # delimiter
            item.setText('商品'+'\t'*2+'說明\n'+'-'*53)
            self.start = QLabel("起始",self)
            self.end = QLabel("結束",self)
            self.k = QLabel("K線週期",self)

        else:
            self.setWindowTitle('Add item')
            item.setText('item'+'\t'*2+'Description\n'+'-'*53)
            self.start = QLabel("Strat",self)
            self.end = QLabel("End",self)
            self.k = QLabel("K-Line",self)

        item.setFlags(QtCore.Qt.NoItemFlags)        # item should not be selectable
        self.listWidget.addItem(item)
        self.listWidget.addItems(["%-20s%10s"%("中石化","中國石油化工股份有限公司"), \
            "%-20s%10s"%("台泥","台灣水泥1101")])
        self.listWidget.setFixedSize(330,200)

        self.listWidget2 = QListWidget(self)
        self.listWidget2.addItems(["aa","bb"])
        self.listWidget2.setFixedSize(280,200)

        self.listWidget3 = QListWidget(self)

        self.listWidget3.addItems(["cc","dd"])
        self.listWidget3.setFixedSize(280,200)

        if len(args) == 0:
            self.addTab(self.listWidget,"股票")
            self.addTab(self.listWidget2,"期貨")
            self.addTab(self.listWidget3,"指數")
        else:
            self.addTab(self.listWidget,"stock")
            self.addTab(self.listWidget2,"futures")
            self.addTab(self.listWidget3,"index")
        self.year = QComboBox(self)
        self.month = QComboBox(self)
        self.day = QComboBox(self)
        self.year2 = QComboBox(self)
        self.month2 = QComboBox(self)
        self.day2 = QComboBox(self)
        self.scope = QLineEdit(self)
        self.Tcount = QComboBox(self)

        self.year.addItems([str(x) for x in range(1998,2018)])
        self.month.addItems([str(y) for y in range(1,13)])
        self.day.addItems([str(z) for z in range(1,32)])
        self.year2.addItems([str(a) for a in range(1998,2018)])
        self.month2.addItems([str(b) for b in range(1,13)])
        self.day2.addItems([str(c) for c in range(1,32)])

        self.scope.setPlaceholderText("default:1")  #時間週期輸入框，設定字體大小
        f = self.scope.font()
        f.setPointSize(12)
        self.scope.setFont(f)

        self.Tcount.addItems(["日","周","月"])
        self.Tcount.resize(40,27.5)

        self.start.move(350,100)    #起始時間標籤
        self.year.move(400, 100)
        self.month.move(500, 100)
        self.day.move(600, 100)

        self.end.move(350,150)  #結束時間標籤
        self.year2.move(400,150)
        self.month2.move(500,150)
        self.day2.move(600,150)

        self.k.move(350,200)
        self.scope.move(430,200)
        self.Tcount.move(600,200)

        self.subbutton = QPushButton('確認',self)
        self.subbutton.move(400, 350)
        backbutton = QPushButton('back \n返回 \nリターン \nбуцах',self)
        backbutton.move(550, 300)

        self.lineedit = QLineEdit(self)
        model = QStringListModel()
        model.setStringList(['中石化', '台泥', '竺元','aa','bb','cc'\
            ,'dd'])

        completer = QCompleter()
        completer.setModel(model)
        self.lineedit.setCompleter(completer)
        self.lineedit.setFixedWidth(200)
        self.lineedit.setPlaceholderText("search by name")
        f = self.lineedit.font()
        f.setPointSize(12)
        self.lineedit.setFont(f)
        self.lineedit.move(350, 50)

        self.subbutton.clicked.connect(lambda:self.compare(self.currentIndex())) # 比較如果時間不符跳警示窗
        backbutton.clicked.connect(self.close)

        self.bigtimer()
        self.space = self.lineedit.text()

    def bigtimer(self):
        try:
            self.listWidget.selectedItems()[0].text()
            self.timer()
        except:
            QTimer.singleShot(10, self.smalltimer)
    def smalltimer(self):

        if self.lineedit.text() != self.space:
            self.realtimer()
        else:
            QTimer.singleShot(10, self.bigtimer)
    def timer(self):
        try:
            self.listWidget.selectedItems()[0].text()
            self.clear_text()
            self.realtimer()
        except:
            QTimer.singleShot(10, self.timer)

    def realtimer(self):

        if self.lineedit.text() != self.space:
            self.clear(self.listWidget)
            self.timer()
        else:
            QTimer.singleShot(10, self.realtimer)

    def clear(self,listwidget):

        listwidget.clearSelection()

    def clear_text(self):
        self.lineedit.clear()

    def compare(self,index):
        a = None
        itemlist = (['中石化', '台泥', '竺元','aa','bb','cc','dd'])
        if index == 0:
            mylist = self.listWidget
        elif index == 1:
            mylist = self.listWidget2
        elif index == 2:
            mylist = self.listWidget3

        for i in mylist.selectedItems():
            a = i.text()[:3].replace(" ","")

        if a == None and self.lineedit.text() == "":
            self.dwrongmsg = dateWrong("NE") # no enter
            print ("沒選擇啦嫩")
            self.dwrongmsg.show()

        elif a == None and self.lineedit.text() not in itemlist:
            self.dwrongmsg = dateWrong("NI")  #no item
            print("沒有這項產品")
            self.dwrongmsg.show()

        elif int(self.year.currentText()) > int(self.year2.currentText()):
            self.dwrongmsg = dateWrong("T")   #time error
            print ("date wrong1")
            self.dwrongmsg.show()
        elif int(self.year.currentText()) == int(self.year2.currentText()) and int(self.month.currentText()) >= \
            int(self.month2.currentText()):
            self.dwrongmsg = dateWrong("T")
            print ("date wrong2")
            self.dwrongmsg.show()

        else:
            print ("date right")
            self.tt(index)
            self.close()

    def tt(self,index):
        if index == 0:
            try:
                self.num = str(self.listWidget.selectedItems()[0].text()[:3].replace(" ",""))
            except:
                self.num = self.lineedit.text()
        elif index == 1:
            self.num = str(self.listWidget2.currentItem().text()[:3].replace(" ",""))
        elif index == 2:
            self.num = str(self.listWidget3.currentItem().text()[:3].replace(" ",""))

        #file = open("./cache/fuckfile.txt","w",encoding = 'utf8')
        #file.write(self.num)
        print("stockcombo is "+self.num)
        if self.scope.text()=="":    #如果沒有輸入時間週期，跑預設的1
            self.num2=1
        else:
            self.num2 = int(self.scope.text())
        self.a = str(self.year.currentText())+"-"+str(self.month.currentText())+"-"+str(self.day.currentText())
        self.b = str(self.year2.currentText())+"-"+str(self.month2.currentText())+"-"+str(self.day2.currentText())
        if self.Tcount.currentText() == "日":
            self.tc = self.num2* 1

        elif self.Tcount.currentText() == "周":
            self.tc = self.num2* 7

        else:
            self.tc = self.num2* 30
        print("self.num="+self.num)
        print("self.a="+self.a)
        print("self.b="+self.b)
        print("self.tc="+str(self.tc))
        self.kline(self.num,self.a,self.b,self.tc)

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

    def onActivated(self, text):

        self.lbl.setText(text)
        self.lbl.adjustSize()

    def kline(self,num,a,b,tc):

        self.dr = Figure_Canvas()
        #實例化一个FigureCanvas
        self.dr.test(num,a,b,tc)  # 畫圖
        self.dr.show()

class futureWindow(QWidget):
    def __init__(self, parent = None):
        super(futureWindow, self).__init__(parent)
        self.setFixedSize(800, 600)
        self.setWindowTitle('股票清單')

class optionWindow(QWidget):
    def __init__(self, parent = None):
        super(optionWindow, self).__init__(parent)
        self.setFixedSize(200, 200)
        self.setWindowTitle('選擇權清單')
        self.lbl = QLabel("Ubuntu", self)

        optioncombo = QComboBox(self)
        optioncombo.addItem("Ubuntu")
        optioncombo.addItem("Mandriva")
        optioncombo.addItem("Fedora")
        optioncombo.addItem("Arch")
        optioncombo.addItem("Gentoo")

        optioncombo.move(50, 50)
        self.lbl.move(50, 100)

        optioncombo.activated[str].connect(self.onActivated)

        subbutton = QPushButton('確認',self)
        subbutton.move(50, 150)
        subbutton.clicked.connect(self.close)

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

    def onActivated(self, text):

        self.lbl.setText(text)
        self.lbl.adjustSize()

class setWindow(QWidget):
    def __init__(self, parent = None):
        super(setWindow, self).__init__(parent)
        self.setFixedSize(800, 600)
        self.setWindowTitle('設定商品')

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

class chooseWindow(QTabWidget):
    def __init__(self, parent = None):
        super(chooseWindow, self).__init__(parent)
        style = """QTabWidget::tab-bar{
        alignment: right;
        }QTabWidget::pane{border: 1px solid #eeeeee;}"""

        self.setStyleSheet(style)

        self.setFixedSize(600, 300)
        self.setWindowTitle('選擇交易策略')
        self.lbl2 = QLabel("txf2")
        #self.strategycombo = QComboBox(self)
        self.strategylist = QListWidget(self)
        self.strategylist.addItems(["atr","bollinger","cross","cumret","highlow",\
            "hurst","linebreak","linreg","ma","macd","ratio","roc","rsi","stats","stoch",\
            "vwap"])

        self.strategylist.setFixedSize(200,220)
        self.MSL = QListWidget(self)
        self.MSL.setFixedSize(200,220)
        self.MSL.move(200,200)

        listA = []
        for dirPath, dirNames, fileNames in os.walk \
        ("C:\\Users\\user\\Desktop\\lastest(8.19)\\strategy\\User"):
            fileNames = [ fi for fi in fileNames if  fi.endswith(".md") ]
            for f in fileNames:
                listA.append(f.replace(".md",""))

        self.MSL.addItems(listA)

        tab = QWidget()
        typetablayout = QGridLayout(tab)
        typetablayout.addWidget(self.strategylist)
        typetablayout.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)

        tab2 = QWidget()
        t2layout = QGridLayout(tab2)
        t2layout.addWidget(self.MSL)
        t2layout.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)

        self.addTab(tab,"內建")
        self.addTab(tab2,"使用者")

        self.IL = QListWidget(self)
        self.IL.setFixedSize(240,160)
        self.IL.move(50,35)

        path = "C:\\Users\\user\\Desktop\\lastest(8.19)\\cache"
        listI = []
        for dirPath, dirNames, fileNames in os.walk (path):
            fileNames = [ fi for fi in fileNames if  fi.endswith(".csv") ]
            for f in fileNames:
                listI.append(f[2:].replace(".csv",""))

        self.IL.addItems(listI)

        strategybutton = QPushButton('確認',self)
        strategybutton.move(120, 220)
        strategybutton.resize(70,50)

        self.bigtimer()
        strategybutton.clicked.connect(self.compare)
        #strategybutton.clicked.connect(self.close)

    def bigtimer(self):
        try:
            self.strategylist.selectedItems()[0].text()
            QTimer.singleShot(10, self.timer)
        except:
            QTimer.singleShot(10, self.smalltimer)

    def smalltimer(self):

        try:
            self.MSL.selectedItems()[0].text()
            QTimer.singleShot(10, self.realtimer)
        except:
            QTimer.singleShot(10, self.bigtimer)

    def timer(self):
        try:
            self.strategylist.selectedItems()[0].text()
            self.clear(self.MSL)
            self.realtimer()
        except:
            QTimer.singleShot(10, self.timer)
    def realtimer(self):

        try:
            self.MSL.selectedItems()[0].text()
            self.clear(self.strategylist)
            self.timer()
        except:
            QTimer.singleShot(10, self.realtimer)

    def clear(self,listwidget):
        listwidget.clearSelection()

    def compare(self):
        a = None; b = None; c = None
        for i in self.strategylist.selectedItems():
            a = i.text()

        for j in self.MSL.selectedItems():
            b = j.text()

        for x in self.IL.selectedItems():
            c = x.text()

        if c == None:
            self.dwrongmsg = dateWrong("NI-C")
            self.dwrongmsg.show()

        elif a == None and b ==None:
            self.dwrongmsg = dateWrong("NS")
            self.dwrongmsg.show()

        else:
            try:
                self.pyalgostrategy(c,self.strategylist.selectedItems()[0].text())
                self.close()
            #except Exception as e:
            #    print(str(e))
            except:
                self.pyalgostrategy(c,"my"+self.MSL.selectedItems()[0].text())
                self.close()
    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

    def pyalgostrategy(self,name,strategyname):
        if strategyname =="ma":
            f = open("./cache/%s.txt"%(name),'w')
            f.write('ma'+'\n'+'150')
        elif strategyname =="macd":
            f = open("./cache/%s.txt"%(name),'w')
            f.write('macd'+'\n'+'12'+'\n'+'26'+'\n'+'9')
        elif strategyname =="rsi":
            f = open("./cache/%s.txt"%(name),'w')
            f.write('rsi'+'\n'+'14'+'\n'+'6')
        elif strategyname[:2] == "my":
            f = open("./cache/%s.txt"%(name),'w')
            f.write('%s'%(strategyname))
            #print("相信使用者的%s"%(strategyname))
        path = "C:\\Users\\user\\Desktop\\lastest(8.19)\\cache"
        listI = []
        for dirPath, dirNames, fileNames in os.walk (path):
            fileNames = [ fi for fi in fileNames if  fi.endswith(".csv") ]
            for f in fileNames:
                listI.append(f.replace(".csv",""))

        for i in range(len(listI)):
                if listI[i].find(name) != -1:
                    a = listI[i]

        b = str(int(a[0])+1)+a[1:]
        #print("87:"+a)
        #print("8787:"+b)
        #print("rename %s.csv %s.csv"%(a,b))
        path = "C:\\Users\\user\\Desktop\\lastest(8.19)\\cache"

        os.system("rename %s\\%s.csv %s.csv"%(path,a,b))

    def onActivated(self, text):

        self.lbl2.setText(text)
        self.lbl2.adjustSize()
class checkWindow(QWidget):
    def __init__(self, parent = None):
        super(checkWindow, self).__init__(parent)
        self.setFixedSize(800, 600)
        self.setWindowTitle('內建交易策略')

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

class exchangeWindow(QWidget):
    def __init__(self, parent = None):
        super(exchangeWindow, self).__init__(parent)
        self.setFixedSize(800, 600)
        self.setWindowTitle('選擇證券交易所')
        self.lbl = QLabel("Ubuntu", self)

        stockcombo = QComboBox(self)

        stockcombo.addItems(["a","b","c"])

        stockcombo.move(50, 50)
        self.lbl.move(50, 100)

        stockcombo.activated[str].connect(self.onActivated)

        subbutton = QPushButton('確認',self)
        subbutton.move(50, 150)
        subbutton.clicked.connect(self.close)

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

    def onActivated(self, text):

        self.lbl.setText(text)
        self.lbl.adjustSize()

class tradeWindow(QWidget):
    def __init__(self, parent = None):
        super(tradeWindow, self).__init__(parent)
        self.setFixedSize(800, 600)
        self.setWindowTitle('下單交易')

    def main():
        app = QApplication(sys.argv)
        mainwindow = MainWindow()
        mainwindow.show()

class MainWindow(QMainWindow, firstWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.initUI()
    #def closeEvent(self, event):
    #    os.system("del /F/S/Q cache")
    #清除cache

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


from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
from modules.status_response import transition

app = Flask(__name__)
app.config.from_object(__name__)

@app.route("/", methods=['GET', 'POST'])
def route():
    """Respond to incoming calls with a simple text message."""
    from_number = request.values.get('From', None)
    body = request.values.get('Body', None)
    resp = MessagingResponse()
    message = "You sent: " + body + " from " + from_number
    # resp.message(message)
    # send.send_sms(from_number, body)
    transition(from_number, body)
    # return str(resp)
    return '200'
    # resp = MessagingResponse()
    # message = "You sent: " + body + " from " + from_number
    # resp.message(message)
    # return str(resp)

if __name__ == "__main__":
    app.run()


import requests, sys, os, boto3, time
from html.parser import HTMLParser

class GameInfoParser(HTMLParser):

    def __init__(self):
        super().__init__()

    def feed(self, data):
        self.release_date = "unknown"
        self.user_score = "unknown"
        self.num_user_ratings = "0"
        self.__state = 0
        super().feed(data)

    def handle_starttag(self, tag, attrs):

        if self.__state == 0:
            # look through attributes and check for:
            # itemprop="datePublished", href=ending in "/user-reviews"
            for attr in attrs:
                if attr[0] == "itemprop" and attr[1] == "datePublished":
                    self.__state = 1
                elif attr[0] == "href" and attr[1].endswith("/user-reviews"):
                    self.__state = 4

        elif self.__state == 2:
            if tag == "div": self.__state = 3

    def handle_data(self, data):
        if self.__state == 0:
            if data.strip().lower() == "user score":
                self.__state = 2

        elif self.__state == 1:
            self.release_date = data.strip()
            self.__state = 0

        elif self.__state == 3:
            if self.user_score == "unknown":
                self.user_score = data.strip()
            self.__state = 0

        elif self.__state == 4:
            self.__state = 0

            # check for "123 ratings", record the "123"
            words = data.strip().split(' ')
            if len(words) == 2:
                if words[1].lower() == "ratings":
                    self.num_user_ratings = words[0]

class GameListParser(HTMLParser):

    def __init__(self):
        super().__init__()

    def feed(self, data):
        self.url = []
        self.title = []
        self.metascore = []
        self.__state = 0
        super().feed(data)

    def handle_starttag(self, tag, attrs):

        if self.__state == 0:
            if tag == "div":
                # look through attributes and check for class="product_condensed"
                for attr in attrs:
                    if attr[0] == "class" and attr[1] == "product_condensed":
                        self.__state = 1

        elif self.__state == 1:
            if tag == "li":
                # look for "class" attribute that contains "game_product"
                for attr in attrs:
                    if attr[0] == "class" and "game_product" in attr[1]:
                        self.__state = 2

        elif self.__state == 2:
            if tag == "a":
                for attr in attrs:
                    if attr[0] == "href":
                        self.url.append("http://www.metacritic.com" + attr[1].strip())
                        self.__state = 3

        elif self.__state == 4:
            if tag == "div":
              # look for "class" attribute that contains "metascore_w"
              for attr in attrs:
                    if attr[0] == "class" and "metascore_w" in attr[1]:
                        self.__state = 5

    def handle_data(self, data):
        if self.__state == 3:
            self.title.append(data.strip())
            self.__state = 4

        elif self.__state == 5:
            self.metascore.append(data.strip())
            self.__state = 1

class WebPages_List:

    def __init__(self):
        self.__web_pages_list = [
            ["strategy", "http://www.metacritic.com/browse/games/genre/date/strategy/pc?view=condensed&page=", 0, 34],
            ["action", "http://www.metacritic.com/browse/games/genre/date/action/pc?view=condensed&page=", 0, 48],
            ["adventure", "http://www.metacritic.com/browse/games/genre/date/adventure/pc?view=condensed&page=", 0, 23],
            ["first person shooters", "http://www.metacritic.com/browse/games/genre/date/first-person/pc?view=condensed&page=", 0, 22],
            ["flight", "http://www.metacritic.com/browse/games/genre/date/flight/pc?view=condensed&page=", 0, 2],
            ["platformer", "http://www.metacritic.com/browse/games/genre/date/platformer/pc?view=condensed&page=", 0, 4],
            ["puzzle", "http://www.metacritic.com/browse/games/genre/date/puzzle/pc?view=condensed&page=", 0, 1],
            ["racing", "http://www.metacritic.com/browse/games/genre/date/racing/pc?view=condensed&page=", 0, 7],
            ["real-time strategy", "http://www.metacritic.com/browse/games/genre/date/real-time/pc?view=condensed&page=", 0, 16],
            ["role-playing games", "http://www.metacritic.com/browse/games/genre/date/role-playing/pc?view=condensed&page=", 0, 20],
            ["simulation", "http://www.metacritic.com/browse/games/genre/date/simulation/pc?view=condensed&page=", 0, 12],
            ["sports", "http://www.metacritic.com/browse/games/genre/date/sports/pc?view=condensed&page=", 0, 7],
            ["third-person shooter", "http://www.metacritic.com/browse/games/genre/date/third-person/pc?view=condensed&page=", 0, 9],
            ["turn-based strategy", "http://www.metacritic.com/browse/games/genre/date/turn-based/pc?view=condensed&page=", 0, 9]
        ]

        self.__index_offset = [0]
        # __index_offset[i] = starting task number of __web_pages_list[i]
        # __index_offset[i] = __index_offset[i-1] + __web_pages_list[i-1][3] + 1
        last_index = len(self.__web_pages_list) - 1
        for i in range(1, last_index + 1):
            new_index = self.__index_offset[i-1] + self.__web_pages_list[i-1][3] + 1
            self.__index_offset.append(new_index)

        # total number of tasks there are
        self.__length = self.__index_offset[last_index] + self.__web_pages_list[last_index][3] + 1

    def length(self):
        """Return the total number of web pages."""
        return self.__length

    def get_task(self, n):
        """Return the genre and address of the n-th web page."""
        # find the right genre for task number 'n'
        # n should be between self.__index_offset[genre_index] and
        # self.__index_offset[genre_index] + self.__web_pages_list[genre_index][3]
        genre_index = 0
        while self.__index_offset[genre_index] + self.__web_pages_list[genre_index][3] < n:
            genre_index += 1

        page_number = n - self.__index_offset[genre_index]

        return (self.__web_pages_list[genre_index][0], # genre
                self.__web_pages_list[genre_index][1] + str(page_number)) # web URL

def main(bucket_name, file_name, start_task_index, end_task_index):
    """Process the web pages, from index 'start_task_index'
    to 'end_task_index'. The result will be uploaded to AWS S3 at
    'bucket_name' and 'file_name' as a tab delimited file."""

    # create local text file - output will be written here and
    # later uploaded to S3
    f = open(file_name, mode = "w")

    # measure how long this process takes
    start_time = time.time()

    # parsers
    list_parser = GameListParser() # for web page containing list of games
    info_parser = GameInfoParser() # for web page containing info on one game

    # process web pages
    web_pages_list = WebPages_List()
    for i in range(start_task_index, end_task_index + 1):
        (genre, game_list_url) = web_pages_list.get_task(i)

        # status update
        print("Processing", genre, game_list_url)

        # extract list of games from game_list_url
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0'}
        response = requests.get(game_list_url, headers=headers)
        list_parser.feed(response.text)

        # at this point, the list of games on this particular page are
        # in list_parser.url, list_parser.title, list_parser.metascore lists

        # the straight forward way to loop over j is:
        # for j in range(0, len(list_parser.url)):

        # However, the "requests.get(...)" call appears to fail
        # randomly, every few hundred web pages. So a retry mechanism
        # is necessary.

        num_pages = len(list_parser.url)
        num_retries = 0
        j = 0
        while j < num_pages:
            # extract information about the j-th game
            response = requests.get(list_parser.url[j], headers=headers)
            info_parser.feed(response.text)

            # check for possible errors
            error = False
            if info_parser.release_date == "unknown" or \
                info_parser.user_score == "unknown":
                # the web site uses "tbd" for insufficient user_score, while
                # my code currently defaults to "unknown"
                print("possible error @ web page #" + str(i),
                      "game #" + str(j), genre, "game", list_parser.title[j],
                      "due to release date or user_score being 'unknown'")
                error = True

            if error and (num_retries < 2):
                num_retries = num_retries + 1
                print("Retrying to process the web page.")

            else:
                # no error - write results to text file
                # format: genre, title, meta score, release_date, user_score,
                # num_user_ratings
                f.write(genre + '\t' + list_parser.title[j] + '\t'
                        + list_parser.url[j]  + '\t' + list_parser.metascore[j]
                        + '\t' + info_parser.release_date
                        + '\t' + info_parser.user_score + '\t'
                        + info_parser.num_user_ratings + '\n')
                j = j + 1

            time.sleep(2) # slow down to avoid trouble??

    f.close()

    # upload local text file
    s3 = boto3.client('s3')
    s3.upload_file(file_name, bucket_name, file_name)

    # clean up local text file
    os.remove(file_name)

    print("Task completed in", int(time.time() - start_time),
          "seconds.")

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("""Arguments required:
            bucket_name - results will be uploaded to this AWS S3 bucket
            file_name - results will appear as this file in AWS S3
            start_task_index - the index of the first web page to process
            end_task_index - the index of the last web page to process""")
        print()
        print("Example: python web_scrape.py louis2018 data002_004.tsv 2 4")
        sys.exit()

    main(sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4]))


from django.shortcuts import get_object_or_404
from rest_framework import viewsets, status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework_simplejwt.tokens import AccessToken

from api.permissions import IsAdminOrSuperUser
from api.serializers import (TokenSerializer, UsersSerializer)
from users.models import User
from django.contrib.auth.tokens import default_token_generator

from rest_framework.filters import SearchFilter
from .filters import TitlesFilter
from .permissions import IsAdminOrSuperUser, IsAdminOrReadOnly
from django.db.models import Avg #Для рейтинга

from api_yamdb.services import send_confirmation_code

from django.shortcuts import render
from .serializers import CategorySerializer, GenreSerializer, TitleListSerializer, TitleCreateSerializer
from reviews.models import Category, Comment, Genre, Review, Title
from rest_framework import permissions

class UserSignupView(GenericAPIView):
    serializer_class = UsersSerializer
    permission_classes = (AllowAny,)

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user, _ = User.objects.get_or_create(**serializer.validated_data)
        confirmation_code = default_token_generator.make_token(user)
        send_confirmation_code(
            email=user.email,
            confirmation_code=confirmation_code
        )
        return Response(serializer.data, status=status.HTTP_200_OK)

class UserGetTokenView(GenericAPIView):
    serializer_class = TokenSerializer
    permission_classes = (AllowAny,)

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        username = serializer.validated_data.get('username')
        confirmation_code = serializer.validated_data.get('confirmation_code')
        user = get_object_or_404(User, username=username)

        if not default_token_generator.check_token(user, confirmation_code):
            return Response({'confirmation_code': 'неверный код'},
                            status=status.HTTP_400_BAD_REQUEST)
        return Response({'token': str(AccessToken.for_user(user))},
                        status=status.HTTP_200_OK)

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UsersSerializer
    permission_classes = (IsAdminOrSuperUser,)
    lookup_field = 'username'

    @action(
        detail=False,
        methods=('GET', 'PATCH'),
        url_path='me',
        permission_classes=(IsAuthenticated,),
        serializer_class=UsersSerializer
    )
    def me(self, request):
        if request.method == 'PATCH':
            serializer = self.get_serializer(request.user, request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        serializer = self.get_serializer(request.user)
        return Response(serializer.data, status=status.HTTP_200_OK)

class CategoryViewSet(viewsets.ModelViewSet):
    """Категории. GET, POST, DEL."""
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    search_fields = ('name',)
    filter_backends = [SearchFilter]
    lookup_field = 'slug'
    permission_classes = (IsAdminOrReadOnly,)

class GenreViewSet(viewsets.ModelViewSet):
    """Жанр. GET, POST, DEL."""
    queryset = Genre.objects.all()
    serializer_class = GenreSerializer
    search_fields = ('name',)
    filter_backends = [SearchFilter]
    lookup_field = 'slug'
    permission_classes = (IsAdminOrReadOnly,)

class TitleViewSet(viewsets.ModelViewSet):
    """Произведения.GET, POST, PATCH, DEL."""
    queryset = Title.objects.annotate(rating=Avg('reviews__score')).all()
    filter_class = TitlesFilter
    permission_classes = (IsAdminOrReadOnly,)
    # serializer_class = TitleListSerializer
    def get_serializer_class(self):
        if self.request.method in permissions.SAFE_METHODS:
            return TitleListSerializer
        return TitleCreateSerializer


import itertools
def longest_repetition(chars):
    if chars=='':
        return ('',0)
    arr=[]
    for x,y in itertools.groupby(chars):
         arr.append(''.join(y))
    max=len(arr[0])
    maxi=arr[0][0]
    for i in range(len(arr)):
        if len(arr[i])>max:
            max=len(arr[i])
            maxi=arr[i][0]
    return(maxi,max)


from django.urls import path, include
from competence import views
from competence import views_bundles
# from competence import api
# from competence.api import views as apiviews

app_name="competence"
urlpatterns = [
    # path('', views.CompetenceList.as_view(), name="competence"),
    path('', views.competenceList, name="competence"),
    path('api/', include('competence.api.urls')),

    path('create/', views.competenceCreate, name="create"),
    path('test2/', views.comptest2, name="comptest2"),
    path('table/', views.table_comp, name="table-comp"),
    path('table/<int:pk>/', views.table_qty, name="table_qty"),

    # path('endpoints/', views.get_endpoints, name="endpoints"),

    path('<int:pk>/', include([
        path('', views.competenceUpdate, name='update'),
        path('delete/', views.deleteCompetence, name="delete"),
    ])),

    # COMPETENCE BUNDLES--
    path('bundles/',include([
        path('', views_bundles.bundle_list, name='bundles'),
        path('create/', views_bundles.bundle_create, name='bundle-create'), # create a new bundle
        path('<int:pk>/delete/', views_bundles.bundle_delete, name='bundle-delete'),
        path('<int:pk>/update/', views_bundles.bundle_update, name='bundle-update'),
        path('<int:pk>/retrieve/', views_bundles.bundle_retrieve, name='bundle-retrieve'),

        path('<int:pk>/add/', views_bundles.bundle_competences_add, name='bundle-competences-add'),
        path('competence/<int:competenceid>/delete/', views_bundles.bundle_competence_remove, name='bundle-competence-remove'),
        # path('<int:bundleid>/competence/<int:competeceid>/', views_bundles.bundle_competence_remove, name='bundle-competence-remove'),

        # path('<int:pk>/', views_bundles.bundle_competences, name='bundle-competences'),

    ])),

]

#HTMX
urlpatterns+=[
    path('list/', views.competenceList, name="list"),
]


from hklearn_genetic.genetic_algorithm import GeneticAlgorithm
from hklearn_genetic.problem import IntegerNQueen, RealNQueen, BinaryNQueen
from scipy import signal
from utils import average_list_of_lists
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import logging
import logging.handlers
import os

# labels = ['G1', 'G2', 'G3', 'G4', 'G5']
# men_means = [20, 34, 30, 35, 27]
# women_means = [25, 32, 34, 20, 25]
# child_means = [25, 32, 34, 20, 25]

# x = np.arange(len(labels))  # the label locations
# width = 0.2  # the width of the bars

# fig, ax = plt.subplots()
# rects1 = ax.bar(x - width, men_means, width, label='Men')
# rects2 = ax.bar(x, women_means, width, label='Women')
# rects3 = ax.bar(x + width, child_means, width, label='Children')

# # Add some text for labels, title and custom x-axis tick labels, etc.
# ax.set_ylabel('Scores')
# ax.set_title('Scores by group and gender')
# ax.set_xticks(x)
# ax.set_xticklabels(labels)
# ax.legend()

# ax.bar_label(rects1, padding=3)
# ax.bar_label(rects2, padding=3)
# ax.bar_label(rects3, padding=3)

# fig.tight_layout()

# plt.show()

handler = logging.handlers.WatchedFileHandler(os.environ.get("LOGFILE", "nqueen_tests.log"))
formatter = logging.Formatter(logging.BASIC_FORMAT)
handler.setFormatter(formatter)
root = logging.getLogger()
root.setLevel(os.environ.get("LOGLEVEL", "INFO"))
root.addHandler(handler)

colors = ['b', 'g', 'y', 'c', 'k', 'm']
params = {"Integer coding":500, "Real coding":500, "Binary coding":1000}
integer_means = []
integer_best = []
integer_global_count = []
real_means = []
real_best = []
real_global_count = []
binary_means = []
binary_best = []
binary_global_count = []
n_groups = list(range(12, 12 + 6*4 - 1, 4))
for dim in n_groups:
    gens_li_dict = {"Integer coding":[], "Real coding":[], "Binary coding":[]}
    ga_best_li_dict = {"Integer coding":[], "Real coding":[], "Binary coding":[]}
    ga_avg_li_dict = {"Integer coding":[], "Real coding":[], "Binary coding":[]}
    integer_best += [float('inf')]
    real_best += [float('inf')]
    binary_best += [float('inf')]
    integer_global_count += [0]
    real_global_count += [0]
    binary_global_count += [0]
    logging.info(f"Solutions for N = "f"{dim}")
    print(f"Solutions for N = "f"{dim}")
    for run in range(5):
        i_nqueen = IntegerNQueen(n_dim = dim)
        r_nqueen = RealNQueen(n_dim=dim)
        b_nqueen = BinaryNQueen(n_dim=dim)
        logging.info(f"Solutions for run = "f"{run}")
        print(f"Solutions for run = "f"{run}")

        ga = GeneticAlgorithm(pc = 0.9, pm = 1./dim, max_iter= params["Integer coding"], selection="tournament", elitism=0.1)
        sol, gens = ga.evolve(i_nqueen, 500)
        if gens < params["Integer coding"]:
            integer_best[-1] = 0
            integer_global_count[-1]+=1
            logging.info("Integer coding global solution: ")
            print("Integer coding global solution: ")
        else:
            integer_best[-1] = -ga.best[-1] if integer_best[-1] > -ga.best[-1] else integer_best[-1]
            logging.info("Integer coding local solution: ")
            print("Integer coding local solution: ")
        logging.info(sol)
        print(sol)
        logging.info(f"After "f"{gens}"f" generations")

        best = [-b for b in ga.best]
        avgs = [-avg for avg in ga.averages]
        gens_li_dict["Integer coding"]+=[gens]
        ga_best_li_dict["Integer coding"]+=[best]
        ga_avg_li_dict["Integer coding"]+=[avgs]
        # fig, axs = plt.subplots(2, 1, constrained_layout=True)
        # axs[0].plot(np.arange(gens), best)
        # axs[0].set_title(f"Integer coding, N = "f"{dim}")
        # axs[0].set_xlabel('Generations')
        # axs[0].set_ylabel('Best fitness')
        # fig.suptitle("N Queen Problem", fontsize=16)
        # axs[1].plot(np.arange(gens), avgs)
        # axs[1].set_title(f"Integer coding, N = "f"{dim}")
        # axs[1].set_xlabel('Generations')
        # axs[1].set_ylabel('Average fitness')
        # plt.show()

        ga = GeneticAlgorithm(pc = 0.9, pm = 1./dim, max_iter= params["Real coding"], selection="tournament", elitism=0.1)
        sol, gens = ga.evolve(r_nqueen, 500)
        if gens < params["Real coding"]:
            real_global_count[-1]+=1
            real_best[-1] = 0
            logging.info("Real coding global solution: ")
            print("Real coding global solution: ")
        else:
            real_best[-1] = -ga.best[-1] if real_best[-1] > -ga.best[-1] else real_best[-1]
            logging.info("Real coding local solution: ")
            print("Real coding local solution: ")
        logging.info(sol)
        print(sol)
        logging.info(f"After "f"{gens}"f" generations")
        best = [-b for b in ga.best]
        avgs = [-avg for avg in ga.averages]
        gens_li_dict["Real coding"]+=[gens]
        ga_best_li_dict["Real coding"]+=[best]
        ga_avg_li_dict["Real coding"]+=[avgs]
        # fig, axs = plt.subplots(2, 1, constrained_layout=True)
        # axs[0].plot(np.arange(gens), best)
        # axs[0].set_title(f"Real coding, N = "f"{dim}")
        # axs[0].set_xlabel('Generations')
        # axs[0].set_ylabel('Best fitness')
        # fig.suptitle("N Queen Problem", fontsize=16)
        # axs[1].plot(np.arange(gens), avgs)
        # axs[1].set_title(f"Real coding, N = "f"{dim}")
        # axs[1].set_xlabel('Generations')
        # axs[1].set_ylabel('Average fitness')
        # plt.show()

        ga = GeneticAlgorithm(pc = 0.9, pm = 1./(b_nqueen.gene_length*b_nqueen.n_dim), max_iter= params["Binary coding"], selection="tournament", elitism=0.1)
        sol, gens = ga.evolve(b_nqueen, 500)
        if gens < params["Binary coding"]:
            binary_global_count[-1]+=1
            binary_best[-1] = 0
            logging.info("Binary coding global solution: ")
            print("Binary coding global solution: ")
        else:
            binary_best[-1] = -ga.best[-1] if binary_best[-1] > -ga.best[-1] else binary_best[-1]
            logging.info("Binary coding local solution: ")
            print("Binary coding local solution: ")
        logging.info(sol)
        print(sol)
        logging.info(f"After "f"{gens}"f" generations")
        best = [-b for b in ga.best]
        avgs = [-avg for avg in ga.averages]
        gens_li_dict["Binary coding"]+=[gens]
        ga_best_li_dict["Binary coding"]+=[best]
        ga_avg_li_dict["Binary coding"]+=[avgs]
        # fig, axs = plt.subplots(2, 1, constrained_layout=True)
        # axs[0].plot(np.arange(gens), best)
        # axs[0].set_title(f"Binary coding, N = "f"{dim}")
        # axs[0].set_xlabel('Generations')
        # axs[0].set_ylabel('Best fitness')
        # fig.suptitle("N Queen Problem", fontsize=16)
        # axs[1].plot(np.arange(gens), avgs)
        # axs[1].set_title(f"Binary coding, N = "f"{dim}")
        # axs[1].set_xlabel('Generations')
        # axs[1].set_ylabel('Average fitness')
        # plt.show()

    for key in ["Integer coding", "Real coding", "Binary coding"]:
        gens_avg = np.average(gens_li_dict[key])
        if key == "Integer coding":
            integer_means += [gens_avg]
        elif key == "Real coding":
            real_means += [gens_avg]
        else:
            binary_means += [gens_avg]
        # for i in range(len(ga_best_li_dict[key])):
        #     if len(ga_best_li_dict[key][i]) < params[key]:
        #         ga_best_li_dict[key][i] += list(np.zeros(params[key] - len(ga_best_li_dict[key][i])))
        # for i in range(len(ga_avg_li_dict[key])):
        #     if len(ga_avg_li_dict[key][i]) < params[key]:
        #         ga_avg_li_dict[key][i] += list(np.zeros(params[key] - len(ga_avg_li_dict[key][i])))
        # ga_best_avg = np.average(np.array(ga_best_li_dict[key]), axis=0)
        # ga_avg_avg = np.average(np.array(ga_avg_li_dict[key]), axis=0)
        fig, axs = plt.subplots(2, 1, constrained_layout=True)
        for i, data in enumerate(ga_best_li_dict[key]):
            if len(data) <= int(gens_avg):
                axs[0].plot(np.arange(len(data)), data, color = colors[i] ,label = f'Run: {i}')
            else:
                axs[0].plot(np.arange(int(gens_avg)), data[0 : int(gens_avg)], color = colors[i], label = f'Run: {i}')
        for i, data in enumerate(ga_avg_li_dict[key]):
            if len(data) <= int(gens_avg):
                axs[1].plot(np.arange(len(data)), data, color = colors[i], label = f'Run: {i}')
            else:
                axs[1].plot(np.arange(int(gens_avg)), data[0 : int(gens_avg)], color = colors[i], label = f'Run: {i}')
        ga_best_avg = average_list_of_lists(ga_best_li_dict[key])
        ga_avg_avg = average_list_of_lists(ga_avg_li_dict[key])

        axs[0].plot(np.arange(int(gens_avg)), ga_best_avg[0 : int(gens_avg)], color = 'r', label = 'Average')
        axs[0].set_title(f"{key} "f", N = "f"{dim}")
        axs[0].set_xlabel('Generations')
        axs[0].set_ylabel('Best fitness')
        fig.suptitle("N Queen Problem for 5 runs", fontsize=16)
        axs[1].plot(np.arange(int(gens_avg)), ga_avg_avg[0 : int(gens_avg)], color = 'r', label = 'Average')
        axs[1].set_title(f"{key} "f", N = "f"{dim}")
        axs[1].set_xlabel('Generations')
        axs[1].set_ylabel('Average fitness')
        plt.legend()
        plt.savefig(f"{key}"f"_{dim}", bbox_inches='tight')
        #plt.show()

x = np.arange(len(n_groups))  # the label locations
width = 0.2  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width, integer_best, width, label='Integer')
rects2 = ax.bar(x, real_best, width, label='Real')
rects3 = ax.bar(x + width, binary_best, width, label='Binary')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Best fitness')
ax.set_title('Best fitness by Nqueens and coding')
ax.set_xticks(x)
ax.set_xticklabels(n_groups)
ax.legend()

ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)

fig.tight_layout()

plt.savefig("Best_Fitness", bbox_inches='tight')
#plt.show()

fig, ax = plt.subplots()
rects1 = ax.bar(x - width, integer_global_count, width, label='Integer')
rects2 = ax.bar(x, real_global_count, width, label='Real')
rects3 = ax.bar(x + width, binary_global_count, width, label='Binary')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Global solutions')
ax.set_title('Global solutions found by Nqueens and coding')
ax.set_xticks(x)
ax.set_xticklabels(n_groups)
ax.legend()

ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)

fig.tight_layout()

plt.savefig("Global_Solutions", bbox_inches='tight')
#plt.show()


import requests
from bs4 import BeautifulSoup

#          979-11-5839-179-9

#이건 크롤링 소스였고,
#일요일날 할일 . 소스를 몽땅 다 갈아 엎어서... .바코드용으로 재탄생 시키긱.
def isbnOutput(isbn):
    url = 'https://www.nl.go.kr/NL/contents/search.do?' \
          'srchTarget=total&pageNum=1&pageSize=10&kwd={}'.format(isbn)
    print("url is \n",url)
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/'
               '537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'}
    response = requests.get(url,headers=headers)

    if response.status_code == 200:
        #html = response.text
        html=response.content
        soup = BeautifulSoup(html, 'html.parser')
        #soup_one는 맨 위의 이미지 1개만.
        title = soup.select_one('#sub_content > div.content_wrap > div > '
                                'div.integSearch_wrap > div.search_cont_wrap >'
                                ' div > div > div.search_right_section > div.sect'
                                'ion_cont_wrap > div:nth-child(1) > div.cont_list.lis'
                                't_type > div.row > span.txt_left.row_txt_tit > a')
        textTitle = title.get_text()

        author = soup.select_one('#sub_content > div.content_wrap > div > '
                                 'div.integSearch_wrap > div.search_cont_wrap > div > '
                                 'div > div.search_right_section > div.section_cont_wrap > '
                                 'div:nth-child(1) > div.cont_list.list_type > div.row > span:nth-child(6)')
        textAuthor = author.get_text()

        publisher = soup.select_one('#sub_content > div.content_wrap > div > '
                                    'div.integSearch_wrap > div.search_cont_wrap > div > '
                                    'div > div.search_right_section > div.section_cont_wrap '
                                    '> div:nth-child(1) > div.cont_list.list_type > div.row'
                                    '> span:nth-child(7)')
        textPublisher = publisher.get_text()

        image = soup.select_one('#popDetailView > div.layer_popup.detail_layer_popup > div.popup_contents > div.detail_top_wrap.grid_wrap > div.grid.grid_l.img_wrap > img')
        print("image",image)#성공시 이미지 출력.
        #일단 이미지는 나중에 생각해보자.

        print("book name is \n",textTitle)
    else :
        print(response.status_code)

    return textTitle,textPublisher,textAuthor,image


from aiodocker.util import task
from urllib.parse import urlparse
import aiohttp
import json
import logging
import os.path
import ssl

__all__ = ['DockerHandler']

log = logging.getLogger(__name__)

class DockerHandler:

    def __init__(self, host, version, cert_path=None, tls_verify=None):
        cert, cert_ca = search_certs(cert_path)
        host, socket, connector = connect(host, tls_verify, cert, cert_ca)

        self.host = host
        self.socket = socket
        self.connector = connector

        self.version = version
        self.cert_path = cert_path
        self.tls_verify = tls_verify
        self.cert = cert
        self.cert_ca = cert_ca

    def get(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('GET', path, **kwargs)

    def post(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('POST', path, **kwargs)

    def put(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('PUT', path, **kwargs)

    def delete(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('DELETE', path, **kwargs)

    @task
    def request(self, method, path, **kwargs):
        version = kwargs.pop('version', self.version)
        url = '%s/v%s/%s' % (self.host, version, path.lstrip('/'))
        params = kwargs.get('params', {}).copy()
        kwargs['params'] = parameters(params)
        kwargs.setdefault('connector', self.connector)

        response = yield from aiohttp.request(method, url, **kwargs)
        return response

def parameters(data):

    def prepare(obj):
        if obj is True:
            return '1'
        if obj is False:
            return '0'
        if isinstance(obj, dict):
            return clean(obj)
        if isinstance(obj, (list, set, tuple)):
            return [prepare(elt) for elt in obj]
        return obj

    def clean(data):
        return {k: prepare(v) for k, v in data.items() if v is not None}

    response = clean(data)
    for k, v in response.items():
        if isinstance(v, (dict, list, set, tuple)):
            response[k] = json.dumps(v)
    return response

def connect(host, tls_verify, cert, cert_ca):
    parsed = urlparse(host)
    if parsed.scheme == 'unix':
        return connect_unix(parsed.path)
    else:
        return connect_tcp(host, tls_verify, cert, cert_ca)

def connect_unix(path):
    socket = path
    connector = aiohttp.TCPConnector(path=path)
    return 'http://127.0.0.1', socket, connector

def connect_tcp(host, tls_verify, cert, cert_ca):
    parsed = urlparse(host)
    scheme, hostname, port = parsed.scheme, parsed.hostname, parsed.port

    if scheme == 'tcp':
        scheme = 'https' if tls_verify else 'http'

    connector = None
    if scheme == 'https':
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.verify_mode = ssl.CERT_NONE
        if cert:
            context.load_cert_chain(*cert)
        connector = aiohttp.TCPConnector(verify_ssl=True,
                                         ssl_context=context)

    host = '%s://%s%s' % (scheme, hostname, (':%s' % port if port else ''))
    return host, None, connector

def search_certs(cert_path):
    cert, cert_ca = None, None

    if not cert_path:
        return cert, cert_ca

    cert_path = os.path.expanduser(cert_path)

    a = os.path.join(cert_path, 'cert.pem')
    b = os.path.join(cert_path, 'key.pem')
    if not os.path.isfile(a):
        log.warn('cert file is missing %s' % a)
        return cert, cert_ca

    if os.path.isfile(b):
        cert = a, b
    else:
        log.info('key file not found %s' % b)
        cert = a,

    c = os.path.join(cert_path, 'ca.pem')
    if os.path.isfile(c):
        cert_ca = c
    else:
        log.info('ca file is missing %s' % c)
    return cert, cert_ca


from pydantic import BaseModel
from typing import List

class User(BaseModel):
    name: str
    age: int
    email: str

    class Config:
        orm_mode = True

class Game(BaseModel):
    name: str

    class Config:
        orm_mode = True

class UserSchema(User):
    games: List[Game]

class GameSchema(Game):
    users: List[User]


###################################################################################
#
#       2019.7.10
#       建立血管三维图
#       ---------------------
#       作者：clovermini
#       来源：CSDN
#       原文：https://blog.csdn.net/baidu_33122327/article/details/86541585
#       版权声明：本文为博主原创文章，转载请附上博文链接！
#
###################################################################################

import os
import h5py
import numpy as np
import cv2

img_path = "D:/MINE_FILE/dataSet/CTA/CTA1/"
out_h5_path = 'D:/auxiliaryPlane/project/Python/medImgSegment/Documents/blood.h5'

dataset = np.zeros((178, 1208, 1261), np.float)

# 遍历指定地址下的所有图片
cnt_num = 0
img_list = sorted(os.listdir(img_path))
os.chdir(img_path)

for img in img_list:
    if img.endswith(".tif"):
        print(img)
        gray_img = cv2.imread(img, cv2.IMREAD_GRAYSCALE)
        print (gray_img.shape)
        dataset[cnt_num, :, :] = gray_img
        cnt_num += 1

with h5py.File(out_h5_path, 'w') as f:
    f['data'] = dataset  # 将数据写入文件的主键data下面


from prefect.infrastructure.docker import DockerContainer
from prefect.deployments import Deployment
from lab_three import alpha_flow

dock_block = DockerContainer.load("basic-docker-block")

#this example pulls a docker image i created in the ui (base python slim image for docker)
#and creates a deployment for alpha flow that will run inside the docker container
#also added some tags
docker_test = Deployment.build_from_flow(
    alpha_flow,
    "docker_two",
    apply= True,
    output= True,
    infrastructure=dock_block,
    tags=['test', 'shame', 'fear', 'docker'],
    work_queue_name = 'test_env'
)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import math
from typing import List, Optional, Tuple

import cv2
import numpy as np

from line_mapper import LineMapper
# from digit_recognizer_2 import create_recognizer
from solver import solve
from sudoku.solver import load_image, cut_out_field, find_corners, perspective_transform_contour, \
    extract_subcontour
from utils import show_image, wait_windows, scale_image_target_height, segment_length, get_line_coeffs

_GRID_LINES = 10

_VIZUALIZE = True

# image = load_image("../images/big-numbers.jpg")
# image = load_image("../images/slightly_blurry.jpg")
# image = load_image("../images/sudoku.jpg")
# image = load_image("../images/sudoku-rotated.jpg")
# image = load_image("../images/sudoku-1.jpg")
# image = load_image("../images/sudoku-2.jpg")
# image = load_image("../images/sudoku-2-rotated.jpg")
image = load_image("../images/warped.jpg")
# image = load_image("tmp/001.jpg")
# image = load_image("tmp/003.jpg")
# image = load_image("tmp/005.jpg")
# image = load_image("tmp/011.jpg")
# image = load_image("tmp/100.jpg")
# image = load_image("tmp/200.jpg")
# if _VIZUALIZE:
#     show_image("orig", image)

image = scale_image_target_height(image, 640)

t = time.time()

# Extract the field, its contour and corners.
field, field_contour, _, perspective_transform_matrix = cut_out_field(image)

field_gray = cv2.cvtColor(field.image, cv2.COLOR_BGR2GRAY)
if _VIZUALIZE:
    show_image("field_gray", field_gray)

# Adjust brightness.
field_gray_closed = cv2.morphologyEx(
    field_gray, cv2.MORPH_CLOSE,
    cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
field_gray_adj = np.divide(field_gray, field_gray_closed)
field_gray = cv2.normalize(field_gray_adj, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)
if _VIZUALIZE:
    show_image("field_gray adj", field_gray)

# Binarize the field.
bin_field = cv2.adaptiveThreshold(
    field_gray, maxValue=255,
    adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C,
    thresholdType=cv2.THRESH_BINARY_INV,
    blockSize=17,
    C=11)
if _VIZUALIZE:
    show_image("bin_field", bin_field)

# field_gray = cv2.GaussianBlur(field_gray, (7, 7), 0)

if _VIZUALIZE:
    show_image("field_gray no numbers", field_gray)

# Apply the Sobel operator of 2nd degree to both directions.
grad_x = cv2.Sobel(field_gray, ddepth=cv2.CV_64F, dx=2, dy=0, ksize=7, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
np.clip(grad_x, a_min=0, a_max=grad_x.max(), out=grad_x)
grad_x = cv2.normalize(grad_x, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)

grad_y = cv2.Sobel(field_gray, ddepth=cv2.CV_64F, dx=0, dy=2, ksize=7, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
np.clip(grad_y, a_min=0, a_max=grad_y.max(), out=grad_y)
grad_y = cv2.normalize(grad_y, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)

if _VIZUALIZE:
    show_image("grad_x", grad_x)
    show_image("grad_y", grad_y)

# Find the left and the top borders.

# Recalculate the contour and the corners on the perspective transformed image.
transformed_field_contour = perspective_transform_contour(field_contour, perspective_transform_matrix)
top_left_idx, top_right_idx, bottom_right_idx, bottom_left_idx = find_corners(transformed_field_contour)

# In the contour, points go counterclockwise.
# Top border: top right -> top left
# Right border: bottom right -> top right
# Bottom border: bottom left -> bottom right
# Left border: top left -> bottom left
top_border = extract_subcontour(transformed_field_contour, top_right_idx, top_left_idx)
# Change points order so they go from the top left corner.
top_border = np.flip(top_border, axis=0)
# # Swap x and y.
# top_border = np.flip(top_border, axis=1)
# right_border = extract_border(bottom_right_idx, top_right_idx)
bottom_border = extract_subcontour(transformed_field_contour, bottom_left_idx, bottom_right_idx)
left_border = extract_subcontour(transformed_field_contour, top_left_idx, bottom_left_idx)

cell_side = field.side // 9

def find_lines_1(work_image: np.ndarray, viz: np.ndarray, border: np.ndarray, border_mapper: LineMapper):
    gap = 5
    max_x_dist_between_points = gap * 3
    # y_center = 0
    y_center = border[0][1]
    y_center_max = border[-1][1]
    while y_center <= y_center_max:
        x_center = border_mapper.map_x(y_center)
        b = cell_side * 2

        lines = []
        for theta in range(0, 30 + 1):
            theta_tan = math.tan(math.radians(theta))

            line_top = []
            line_bottom = []
            top_wasted = False
            bottom_wasted = False
            for x_rel in range(0, b, gap):
                if top_wasted and bottom_wasted:
                    break

                x = x_rel + x_center

                if not top_wasted:
                    if (line_top and x - line_top[-1][0] < max_x_dist_between_points
                            or not line_top and x_rel < max_x_dist_between_points):
                        y_top = y_center - int(round(theta_tan * x_rel))
                        if y_top >= 0 and work_image[y_top, x] > 0:
                            line_top.append((x, y_top))
                    else:
                        top_wasted = True

                if not bottom_wasted:
                    if (line_bottom and x - line_bottom[-1][0] < max_x_dist_between_points
                            or not line_bottom and x_rel < max_x_dist_between_points):
                        y_bottom = y_center + int(round(theta_tan * x_rel))
                        if y_bottom < work_image.shape[0] and work_image[y_bottom, x] > 0:
                            line_bottom.append((x, y_bottom))
                    else:
                        bottom_wasted = True

            if not top_wasted and line_top:
                lines.append(line_top)
            # Prevent double adding.
            if not bottom_wasted and theta != 0 and line_bottom:
                lines.append(line_bottom)

        if not lines:
            y_center += 1
            continue

        max_line = max(lines, key=len)
        if len(max_line) > int(b // gap * 0.8):
            if _VIZUALIZE:
                for x, y in max_line:
                    cv2.circle(viz, (x, y), 1, (0, 0, 255), 1)
            y_center += cell_side // 2
        else:
            y_center += 1

def find_lines_2(work_image: np.ndarray, viz: np.ndarray, border: np.ndarray, border_mapper: LineMapper):
    border_start_x, border_start_y = border[0]
    border_end_x, border_end_y = border[-1]

    min_theta = 90 - 30
    max_theta = 90 + 30

    max_rho = work_image.shape[0] + work_image.shape[1]
    min_rho = -max_rho

    theta_step = 1
    rho_step = 1

    cells_in_sub = 3
    gap = 5

    num_theta = (max_theta - min_theta) // theta_step + 1
    num_rho = (max_rho - min_rho) // theta_step + 1
    hough_space = np.zeros((num_rho, num_theta), dtype=np.int32)
    hough_space2 = [
        [0 for _ in range(num_theta)] for _ in range(num_rho)
    ]
    points = [
        [[] for _ in range(num_theta)] for _ in range(num_rho)
    ]

    num_theta_sin = [None] * (max_theta - min_theta + 1)
    num_theta_cos = [None] * (max_theta - min_theta + 1)

    thetas = np.arange(min_theta, max_theta + 1, theta_step)
    theta_rads = np.radians(thetas)
    theta_sin = np.sin(theta_rads)
    theta_cos = np.cos(theta_rads)
    theta_off = (thetas - min_theta) // theta_step

    y_from = min(border_start_y, border_end_y)
    y_to = max(border_start_y, border_end_y)
    for y in range(y_from, y_to + 1):
        x_from = border_mapper.map_x(y)
        x_to = int(x_from + cell_side * cells_in_sub)

        y_sin = theta_sin * y

        for x in range(x_from, x_to + 1, gap):
            if work_image[y, x] == 0:
                continue

            rhos = theta_cos * x
            np.add(rhos, y_sin, out=rhos)
            rhos = np.int32(rhos)
            hough_space[rhos, theta_off] += 1

            # for theta in range(min_theta, max_theta, theta_step):
            #     theta_rad = math.radians(theta)
            #     rho = int(round(
            #         y * math.sin(theta_rad) + x * math.cos(theta_rad)
            #     ))
            #     rho = rho // rho_step
            #     theta_off = (theta - min_theta) // theta_step
            #     # hough_space[rho, theta_off] += 1
            #     hough_space2[rho][theta_off] += 1
            #     points[rho][theta_off].append((x, y))

    good = np.where(hough_space > (cell_side * cells_in_sub) / (gap * 1.1))  # todo no hardcoding
    for i in range(good[0].shape[0]):
        rho = good[0][i]
        theta = good[1][i]
        theta = theta * theta_step + min_theta
        theta_rad = math.radians(theta)
        a = np.cos(theta_rad)
        b = np.sin(theta_rad)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
        cv2.line(viz, (x1,y1), (x2,y2), (0,0,255), 1)
    pass

_, grad_y_thresh = cv2.threshold(grad_y, 5, 255, cv2.THRESH_BINARY)
top_border_mapper = LineMapper(top_border)

_, grad_x_thresh = cv2.threshold(grad_x, 5, 255, cv2.THRESH_BINARY)
grad_x_thresh = cv2.rotate(grad_x_thresh, cv2.ROTATE_90_COUNTERCLOCKWISE)
left_border_mapper = LineMapper(left_border)

work_image_orig = grad_y
work_image = grad_y_thresh
# work_image = grad_x_thresh
border = left_border
# border = top_border
border_mapper = left_border_mapper
# border_mapper = top_border_mapper

viz = cv2.cvtColor(work_image, cv2.COLOR_GRAY2BGR)

# find_lines_1(work_image, viz, border, border_mapper)
# for _ in range(1000):
#     find_lines_1(work_image, viz, border, border_mapper)
    # find_lines_2(work_image, viz, border, border_mapper)
# find_lines_2(work_image, viz, border, border_mapper)

def find_next_line(current_line: np.ndarray, horizonal_look_ahead: int):
    x1 = top_border[0, 0]
    x2 = x1 + horizonal_look_ahead
    a, b = np.polyfit(current_line[:, 0], current_line[:, 1], 1)
    y1 = int(round(a * x1 + b))
    y2 = int(round(a * x2 + b))

    # print(math.degrees(math.atan(a)))

    def _relative_coords(x1: int, y1: int, x2: int, y2: int) -> Tuple[int, int, int, int]:
        assert x1 < x2
        x2 -= x1
        x1 = 0
        y_min = min(y1, y2)
        y1 -= y_min
        y2 -= y_min
        return x1, y1, x2, y2

    x1_rel, y1_rel, x2_rel, y2_rel = _relative_coords(x1, y1, x2, y2)

    def create_mask(x1_rel: int, y1_rel: int, x2_rel: int, y2_rel: int) -> Tuple[np.ndarray, int, int]:
        assert x1_rel < x2_rel
        mask = np.zeros((abs(y1_rel - y2_rel) + 1, x2_rel - x1_rel + 1), dtype=np.uint8)
        cv2.line(mask, (x1_rel, y1_rel), (x2_rel, y2_rel), 255, 1)
        return mask

    mask = create_mask(x1_rel, y1_rel, x2_rel, y2_rel)
    max_intersect = np.count_nonzero(mask)
    intersect_threshold = max_intersect * 0.7

    seen_max = None
    seen_max_y_off = None
    seen_max_x_off = None
    for y_off in range(y1 + cell_side // 3, y1 + cell_side * 2):
        x_off = left_border_mapper.map_x(y_off)

        sub_img = work_image[y_off:mask.shape[0] + y_off, x_off:mask.shape[1] + x_off]
        assert sub_img.shape == mask.shape

        intersect = np.bitwise_and(sub_img, mask)
        s = np.sum(intersect) // 255

        if s >= intersect_threshold:
            if seen_max is None or s > seen_max:
                seen_max = s
                seen_max_y_off = y_off
                seen_max_x_off = x_off

            # print(y_off, s)
            # cv2.line(viz, (x1_rel + x_off, y1_rel + y_off), (x2_rel + x_off, y2_rel + y_off), (0, 255, 0), 1)
        else:
            if seen_max is not None:
                # print("Stopping at", y_off)
                break
    else:
        assert False

    # todo optimization: don't refine if more than another threshold

    # print(seen_max, seen_max_x_off, seen_max_y_off)
    # cv2.line(viz, (x1_rel + seen_max_x_off, y1_rel + seen_max_y_off), (x2_rel + seen_max_x_off, y2_rel + seen_max_y_off), (0, 255, 0), 1)

    win_h_half = 2

    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]

    x = x1_rel + seen_max_x_off
    y = y1_rel + seen_max_y_off

    dx = 5
    dy = a * dx
    points_to_collect = horizonal_look_ahead // dx
    line = []
    for i in range(points_to_collect):
        x_int = int(round(x))
        y_int = int(round(y))

        y_int = refine_point(x_int, y_int, 2,)
        if y_int is not None:
           line.append((x_int, y_int))

        # # cv2.rectangle(viz, (x_int, y_int - win_h_half), (x_int, y_int + win_h_half), (0, 255, 0), 1)
        # window = work_image_orig[y_int - win_h_half:y_int + win_h_half + 1, x_int:x_int + 1]
        # s = np.sum(window)
        # if s > 0:
        #     avg = np.sum(ys_centered * window) / s
        #     avg = int(round(avg))
        #     # print(avg)
        #     line.append((x_int, y_int + avg))

        x += dx
        y += dy
    return np.array(line)

def continue_line(line: List[np.ndarray]):
    win_h_half = 1

    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]

    line = list(line)
    last_len = len(line)

    for run in range(1000):  # effectively infinite
        tail = np.array(line[-5:])
        a, b = np.polyfit(tail[:, 0], tail[:, 1], 1)
        x, y = tail[-1]
        dx = 5
        dy = a * dx

        if x >= field.margin + field.side:
            break

        skipped_steps = 0
        for _ in range(40):
            x += dx

            if x >= field.margin + field.side:
                break

            y += dy
            x_int = int(round(x))
            y_int = int(round(y))
            # cv2.circle(viz, (x_int, y_int), 2, (0, 0, 255), -1)
            # print(work_image[y_int, x_int])

            if run % 2 == 0:
                color = (0, 0, 255)
            else:
                color = (255, 0, 0)

            # if _VIZUALIZE:
            #     cv2.rectangle(viz, (x_int, y_int - win_h_half), (x_int, y_int + win_h_half), color, 1)
            window = work_image_orig[y_int - win_h_half:y_int + win_h_half + 1, x_int:x_int + 1]
            s = np.sum(window)
            if s > 0:
                avg = np.sum(ys_centered * window) / s
                avg = int(round(avg))
                if _VIZUALIZE:
                    cv2.circle(viz, (x_int, y_int + avg), 2, color, -1)
                line.append((x_int, y_int + avg))
                if avg != 0:
                    break
            else:
                skipped_steps += 1
                if skipped_steps >= 2:
                    break
                else:
                    continue

        if len(line) == last_len:
            break
        last_len = len(line)

def refine_point(x: int, y: int, win_h_half: int) -> Optional[int]:
    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]
    window = work_image_orig[y - win_h_half:y + win_h_half + 1, x:x + 1]
    s = np.sum(window)
    if s > 0:
        avg = np.sum(ys_centered * window) / s
        avg = int(round(avg))
        return y + avg
    else:
        return None

horizonal_look_ahead = cell_side * 2

first_point_behind = np.argmax(top_border[:, 0] >= top_border[0, 0] + horizonal_look_ahead) + 1
current_line = top_border[:first_point_behind + 1]

if _VIZUALIZE:
    for x, y in top_border:
        y1 = refine_point(x, y, 2)
        if y1 is not None:
            y = y1
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)

for i in range(8):
    # Due to noise and the border thickness, the first point is likely to be an outlier,
    # skipping it.
    current_line = current_line[1:, :]
    current_line = find_next_line(current_line, horizonal_look_ahead)
    if _VIZUALIZE:
        for x, y in current_line[1:]:
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)
    continue_line(current_line)

if _VIZUALIZE:
    for x, y in bottom_border:
        y1 = refine_point(x, y, 2)
        if y1 is not None:
            y = y1
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)

print()
print((time.time() - t) * 1000)

if _VIZUALIZE:
    show_image("grad_x_viz", viz, 700)
if _VIZUALIZE:
    wait_windows()
exit()

cells_in_sub = 3

x_from = 0
x_to = field.margin + cell_side * cells_in_sub
assert x_to > x_from

gap = 5

min_theta = 90 - 30
max_theta = 90 + 30
theta_step = 1
rho_step = 1

max_rho = image.shape[0] + (x_to - x_from)
min_rho = -max_rho

num_theta = (max_theta - min_theta) // theta_step + 1
num_rho = max_rho - min_rho + 1
hough_space = np.zeros((num_rho, num_theta), dtype=np.int32)
points = [
    [[] for _ in range(num_theta)] for _ in range(num_rho)
]
for y_center in range(grad_y_thresh.shape[0]):
    # TODO x should start with mapping
    for x_center in range(x_from, x_to, gap):
        if grad_y_thresh[y_center, x_center] == 0:
            continue
        for theta in range(min_theta, max_theta, theta_step):
            theta_rad = math.radians(theta)
            rho = int(round(
                y_center * math.sin(theta_rad) + x_center * math.cos(theta_rad)
            ))
            rho = rho // rho_step
            theta = (theta - min_theta) // theta_step
            hough_space[rho, theta] += 1
            points[rho][theta].append((x_center, y_center))

good = np.where(hough_space > (x_to - x_from) / gap / 100)  # todo no hardcoding
grad_y = cv2.cvtColor(grad_y, cv2.COLOR_GRAY2BGR)

lines = []
for i in range(good[0].shape[0]):
    rho = good[0][i]
    theta = good[1][i]
    line_points = points[rho][theta]
    line_points = sorted(line_points, key=lambda item: (item[0], item[1]))

    broken_line = False
    for j in range(len(line_points) - 1):
        x1 = line_points[j][0]
        x2 = line_points[j + 1][0]
        if abs(x1 - x2) > gap * 2.5:
            broken_line = True
            break
    if broken_line:
        continue

    [x1, y_top] = line_points[0]
    [x2, y2] = line_points[-1]
    length = segment_length(x1, y_top, x2, y2)
    if length / cell_side > cells_in_sub * 1.2:
        continue
    if length / cell_side < cells_in_sub * 0.6:
        continue

    rho = rho * rho_step
    theta = theta * theta_step + min_theta

    # print(rho, theta)
    # print(length / cell_side)

    lines.append((rho, theta, line_points))
    for x_center, y_center in line_points:
        cv2.circle(grad_y, (x_center, y_center), 1, (0, 0, 255), 1)
    # break

    # theta_rad = math.radians(theta)
    # a = np.cos(theta_rad)
    # b = np.sin(theta_rad)
    # x0 = a*rho
    # y0 = b*rho
    # x1 = int(x0 + 1000*(-b))
    # y1 = int(y0 + 1000*(a))
    # x2 = int(x0 - 1000*(-b))
    # y2 = int(y0 - 1000*(a))
    # cv2.line(sub_image,(x1,y1),(x2,y2),(0,0,255),1)

# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(45)) * 100)), (0, 0, 255), 1)
# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(30)) * 100)), (0, 0, 255), 1)
# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(18)) * 100)), (0, 0, 255), 1)

lines = sorted(lines, key=lambda x: x[0])  # sort by rho

if _VIZUALIZE:
    show_image("xxx", grad_y, 700)

print((time.time() - t) * 1000)

if _VIZUALIZE:
    # show_image("unwrapped", unwrapped_viz)
    # show_image("wrapped back", wrapped_viz)
    # show_image("field_viz", field_viz, 700)
    pass

if _VIZUALIZE:
    wait_windows()


import numpy as np
import matplotlib.pyplot as plt

xmin = -5
xmax = 5
dx = 0.1

N = int((xmax - xmin)/dx)

x = np.linspace(xmin, xmax, N+1)
#x = np.arange(xmin, xmax+dx, dx) #Alternative implementation

y = x**2 + 2*x + 1;

plt.plot(x,y)
plt.xlim([xmin,xmax])


import input_data
import tensorflow as tf
import matplotlib.pyplot as plt

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 定义变量
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
# 建立回归模型
y = tf.nn.softmax(tf.matmul(x,W) + b)
# 样本实际值
y_ = tf.placeholder("float", [None,10])
# 用交叉熵表示损失
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
# 构建梯度下降优化器
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
# 初始化变量
init = tf.initialize_all_variables()

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

xx=range(1000)
yy=[]
loss=[]

sess = tf.Session()
sess.run(init)
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    # 记录准确率
    yy.append(sess.run(accuracy, feed_dict={x: batch_xs, y_: batch_ys}))
    # 记录损失
    loss.append(sess.run(cross_entropy, feed_dict={x: batch_xs, y_: batch_ys}))

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
print(sess.run(cross_entropy, feed_dict={x: batch_xs, y_: batch_ys}))

sess.close()

plt.figure()
plt.plot(xx,yy,color="blue")
plt.figure()
plt.plot(xx,loss,color="red")
plt.legend()
plt.show()


import ast
import multiprocessing
import os
from itertools import chain

from flask import Flask, Response, abort, jsonify, request
from gunicorn.config import Config
from gunicorn.app.base import Application

from mtrpc.common.errors import RPCMethodArgError, RPCAccessDenied
from mtrpc.server.core import MTRPCServerInterface
from mtrpc.server import schema

class ConfigurableApplication(Application):
    @staticmethod
    def default_cfg():
        return {
            'worker_class': 'sync',
            'workers': 2,
            'secure_scheme_headers': {
                'X-FORWARDED-PROTO': 'https'
            },
            'preload_app': True,
            'user': os.getuid(),
        }

    def __init__(self, app, **config):
        self.app = app
        self._config = config
        super(ConfigurableApplication, self).__init__()

    def load(self):
        return self.app

    def init(self, parser, opts, args):
        self.cfg.set('default_proc_name', 'mtrpc')

    def load_config(self):
        self.cfg = Config()
        for k, v in chain(self.default_cfg().items(), self._config.items()):
            self.cfg.set(k.lower(), v)

class HttpServer(MTRPCServerInterface):

    CONFIG_DEFAULTS = {
        'http': {
            'bind': '127.0.0.1:5000',
            'debug': False,
            'root_token': None,
        }
    }

    CONFIG_SCHEMAS = MTRPCServerInterface.CONFIG_SCHEMAS + [schema.by_example(CONFIG_DEFAULTS)]

    RPC_MODE = 'server'

    def __init__(self, config_dict):
        super(HttpServer, self).__init__(config_dict)
        self.rpc_tree = None
        self.writer_lock = multiprocessing.Lock()

    def find_rpc_object(self, url):
        full_path = url.strip('/').replace('/', '.')
        try:
            return self.rpc_tree[full_path]
        except KeyError:
            abort(404, 'RPC endpoint not found')

    @classmethod
    def detect_type(cls, arg):
        """DWIM cast guessing parameter type, not really for production use"""
        if not arg:
            return u''
        try:
            return ast.literal_eval(arg)
        except ValueError:
            return unicode(arg)

    @classmethod
    def access_args(cls):
        return {
            'token': cls.auth_token(),
        }

    @classmethod
    def build_rpc_args(cls, args):
        out = {}
        for k in args:
            v = args.getlist(k)
            if len(v) == 1:
                out[k] = cls.detect_type(v[0])
            else:
                out[k] = [cls.detect_type(item) for item in v]

        return out

    @classmethod
    def call_rpc_object(cls, rpc_object, args):
        try:
            rpc_object.authorize(cls.access_args())
            return jsonify(response=rpc_object(**args))
        except RPCMethodArgError as exc:
            abort(400, str(exc).replace('{name}', rpc_object.full_name))
        except RPCAccessDenied:
            abort(403, 'Access denied')

    @classmethod
    def auth_token(cls):
        return request.headers.get('X-Auth-Token')

    def matches_root_token(self, token):
        root_token = self.config['http'].get('root_token')
        if root_token is None:
            return bool(self.config['http'].get('debug'))
        else:
            return token == root_token

    def authenticate(self, rpc_object):
        if self.matches_root_token(self.auth_token()):
            return
        try:
            ret = rpc_object.authorize(self.access_args())
        except RPCAccessDenied:
            abort(403, 'Access denied')

        if ret is NotImplemented:
            abort(403, 'Access denied')

    def get_help(self, rpc_object_url):
        rpc_object = self.find_rpc_object(rpc_object_url)
        return Response(rpc_object.__doc__, content_type='text/plain')

    def call_view(self, rpc_object_url):
        rpc_object = self.find_rpc_object(rpc_object_url)
        if not callable(rpc_object):
            abort(403, 'RPC object is not callable')
        self.authenticate(rpc_object)
        if not getattr(rpc_object, 'readonly', False):
            abort(405, 'Method not allowed')
        args = self.build_rpc_args(request.args)
        return self.call_rpc_object(rpc_object, args)

    def call(self, rpc_object_url):
        rpc_object = self.find_rpc_object(rpc_object_url)
        if not callable(rpc_object):
            abort(403, 'RPC object is not callable')
        self.authenticate(rpc_object)
        args = request.get_json()
        if args is None:
            args = self.build_rpc_args(request.form)
        if getattr(rpc_object, 'readonly', False):
            return self.call_rpc_object(rpc_object, args)
        if self.writer_lock.acquire(False):
            try:
                return self.call_rpc_object(rpc_object, args)
            finally:
                self.writer_lock.release()
        else:
                abort(503, 'A writer method is already running')

    def build_wsgi_app(self):
        flask_app = Flask(__name__)
        flask_app.route('/help/<path:rpc_object_url>', methods=['GET'])(self.get_help)
        flask_app.route('/call/<path:rpc_object_url>', methods=['GET'])(self.call_view)
        flask_app.route('/call/<path:rpc_object_url>', methods=['POST'])(self.call)
        return flask_app

    def start(self, rpc_tree, final_callback=None):
        self.rpc_tree = rpc_tree
        http_debug = self.config['http']['debug']
        http_bind = self.config['http']['bind']
        flask_app = self.build_wsgi_app()
        if http_debug:
            host, port = http_bind.rsplit(':', 1)
            flask_app.run(host=host, port=int(port), debug=True)
        else:
            app = ConfigurableApplication(flask_app, bind=http_bind)
            app.run()


from flask import Flask, render_template
app = Flask(__name__)
import pickle

# open a file, where you ant to store the data
file = open('model.pkl', 'rb')
clf = pickle.load(file)
file.close()

@app.route('/')
def hello_world():
    inputFeatures = [100,1,22,1,1]
    infProb=clf.predict_proba([inputFeatures])[0][1]
    return render_template('index.html')

    # return 'Hello,World!' + str(infProb)

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


import subprocess
import time

import psutil
from threading import Thread
import DBManager
import re

class Player:
    def __init__(self, path=None):
        self.dbManager = DBManager.DBManager()
        self.playback_process = None
        self.audio_file = self.dbManager.currently_active_book_path
        if path:
            self.audio_file = path
        self.starttime = None
        self.initial_progress = 0
        self.current_progress = 0
        if self.audio_file:
            self.dbManager.load_book(self.audio_file)
            self.initial_progress = self.current_progress = self.dbManager.get_progress(self.audio_file)
        self.stopped = True
        self.file_duration = None
        self.updater = Thread(target=self.progress_updater).start()

    def play(self):
        if not self.stopped:
            return
        if self.current_progress:
            self.playback_process = subprocess.Popen('ffplay -nodisp -v quiet -ss {0} \"{1}\"'.format(self.current_progress,
                                                                                self.audio_file))
        else:
            self.playback_process = subprocess.Popen('ffplay -nodisp -v quiet \"' + self.audio_file + '\"')
        self.starttime = time.time()
        try:
            # WARNING: janky code to check if its actually playing
            time.sleep(0.06)
            psutil.Process(self.playback_process.pid)
        except psutil.NoSuchProcess:
            print('An error occured while trying to play the file: ' + self.audio_file + '\n' +
                  str(self.playback_process.stdout))
            return 1
        self.starttime = time.time()
        self.initial_progress = self.current_progress
        self.stopped = False
        return 0

    def stop(self):
        self.stopped = True
        self.playback_process.kill()
        self.dbManager.save_progress(self.audio_file, self.current_progress)

    # Updates the audiobook progress every <interval> seconds.
    def progress_updater(self, interval=0.25):
        while True:
            if not self.stopped:
                playtime = time.time() - self.starttime
                self.current_progress = playtime + float(self.initial_progress)
                self.dbManager.save_progress(self.audio_file, self.current_progress)
            time.sleep(interval)

    def update_file_duration(self):
        if self.audio_file:
            output = subprocess.run('ffprobe -i \"{0}\" -show_entries format=duration -v quiet -of csv="p=0"'
                                    .format(self.audio_file), capture_output=True).stdout
            m = re.search(r'(\d+)\.?', str(output))
            if m:
                return float(m.group(1))
            else:
                return 0

    def get_current_progress(self):
        if self.current_progress:
            return float(self.current_progress)
        else:
            return None

    def seek(self, seconds):
        if not self.stopped:
            self.stop()
        self.current_progress = seconds
        self.play()


from agents import ListenerOutput
from RegexPlus.synthesis import synthesize
from stopit import ThreadingTimeout as Timeout
from greenery.parse import NoMatch

class RegexPlusListener:
    def __init__(self):
        pass

    def synthesize(self, specs, return_scores=True):
        strings = [[s for s, l in spec if l == '+'] for spec in specs][0]
        if len(strings) == 0:
            return ListenerOutput(
                [[]],
                [[]],
                [[]],
                [[]]
                )
        with Timeout(6) as timeout_ctx:
            try:
                regexes = synthesize(strings)
            except NoMatch:
                regexes = []
        if timeout_ctx.state == timeout_ctx.EXECUTED:
            return ListenerOutput(
                [[str(r[1]) for r in regexes]],
                [[i for i, r in enumerate(regexes)]],
                [[str(r[1]) for r in regexes]],
                [[r[0] for r in regexes]]
                )
        else:
            return ListenerOutput(
                [[]],
                [[]],
                [[]],
                [[]]
                )

if __name__ == "__main__":
    listener = RegexPlusListener()
    print(listener.synthesize([("a", "+"), ("b", "+"), ("c", "+")]))