#Developed by Zachary Williams

from tkinter import *
from functools import partial
from PIL import Image
import sys
from sys import platform

class mainclass(object):
    colorfillvar = 0
    gridwidth = 8
    gridheight = 8
    griddim = gridwidth * gridheight
    colors = []
    basecolor = "red"
    picname = []
    if platform == "linux" or platform == "linux2":
        buttonw = 2
        buttonh = 2
        toolbarw = 370
        toolbarh= 10
    elif platform == "darwin":
        buttonw = 2
        buttonh = 2
    elif platform == "win32" or "win64":
        buttonw = 2
        buttonh = 1
        toolbarw = 260
        toolbarh = 10
    COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace', 'linen', 'antique white',
              'papaya whip', 'blanched almond', 'bisque', 'peach puff', 'navajo white', 'lemon chiffon', 'mint cream',
              'azure', 'alice blue', 'lavender', 'lavender blush', 'misty rose', 'dark slate gray', 'dim gray',
              'slate gray', 'light slate gray', 'gray', 'light grey', 'midnight blue', 'navy', 'cornflower blue',
              'dark slate blue', 'slate blue', 'medium slate blue', 'light slate blue', 'medium blue', 'royal blue',
              'blue', 'dodger blue', 'deep sky blue', 'sky blue', 'light sky blue', 'steel blue', 'light steel blue',
              'light blue', 'powder blue', 'pale turquoise', 'dark turquoise', 'medium turquoise', 'turquoise', 'cyan',
              'light cyan', 'cadet blue', 'medium aquamarine', 'aquamarine', 'dark green', 'dark olive green',
              'dark sea green', 'sea green', 'medium sea green', 'light sea green', 'pale green', 'spring green',
              'lawn green', 'medium spring green', 'green yellow', 'lime green', 'yellow green', 'forest green',
              'olive drab', 'dark khaki', 'khaki', 'pale goldenrod', 'light goldenrod yellow', 'light yellow', 'yellow',
              'gold', 'light goldenrod', 'goldenrod', 'dark goldenrod', 'rosy brown', 'indian red', 'saddle brown',
              'sandy brown', 'dark salmon', 'salmon', 'light salmon', 'orange', 'dark orange', 'coral', 'light coral',
              'tomato', 'orange red', 'red', 'hot pink', 'deep pink', 'pink', 'light pink', 'pale violet red', 'maroon',
              'medium violet red', 'violet red', 'medium orchid', 'dark orchid', 'dark violet', 'blue violet', 'purple',
              'medium purple', 'thistle', 'snow2', 'snow3', 'snow4', 'seashell2', 'seashell3', 'seashell4',
              'AntiqueWhite1', 'AntiqueWhite2', 'AntiqueWhite3', 'AntiqueWhite4', 'bisque2', 'bisque3', 'bisque4',
              'PeachPuff2', 'PeachPuff3', 'PeachPuff4', 'NavajoWhite2', 'NavajoWhite3', 'NavajoWhite4', 'LemonChiffon2',
              'LemonChiffon3', 'LemonChiffon4', 'cornsilk2', 'cornsilk3', 'cornsilk4', 'ivory2', 'ivory3', 'ivory4',
              'honeydew2', 'honeydew3', 'honeydew4', 'LavenderBlush2', 'LavenderBlush3', 'LavenderBlush4', 'MistyRose2',
              'MistyRose3', 'MistyRose4', 'azure2', 'azure3', 'azure4', 'SlateBlue1', 'SlateBlue2', 'SlateBlue3',
              'SlateBlue4', 'RoyalBlue1', 'RoyalBlue2', 'RoyalBlue3', 'RoyalBlue4', 'blue2', 'blue4', 'DodgerBlue2',
              'DodgerBlue3', 'DodgerBlue4', 'SteelBlue1', 'SteelBlue2', 'SteelBlue3', 'SteelBlue4', 'DeepSkyBlue2',
              'DeepSkyBlue3', 'DeepSkyBlue4', 'SkyBlue1', 'SkyBlue2', 'SkyBlue3', 'SkyBlue4', 'LightSkyBlue1',
              'LightSkyBlue2', 'LightSkyBlue3', 'LightSkyBlue4', 'SlateGray1', 'SlateGray2', 'SlateGray3', 'SlateGray4',
              'LightSteelBlue1', 'LightSteelBlue2', 'LightSteelBlue3', 'LightSteelBlue4', 'LightBlue1', 'LightBlue2',
              'LightBlue3', 'LightBlue4', 'LightCyan2', 'LightCyan3', 'LightCyan4', 'PaleTurquoise1', 'PaleTurquoise2',
              'PaleTurquoise3', 'PaleTurquoise4', 'CadetBlue1', 'CadetBlue2', 'CadetBlue3', 'CadetBlue4', 'turquoise1',
              'turquoise2', 'turquoise3', 'turquoise4', 'cyan2', 'cyan3', 'cyan4', 'DarkSlateGray1', 'DarkSlateGray2',
              'DarkSlateGray3', 'DarkSlateGray4', 'aquamarine2', 'aquamarine4', 'DarkSeaGreen1', 'DarkSeaGreen2',
              'DarkSeaGreen3', 'DarkSeaGreen4', 'SeaGreen1', 'SeaGreen2', 'SeaGreen3', 'PaleGreen1', 'PaleGreen2',
              'PaleGreen3', 'PaleGreen4', 'SpringGreen2', 'SpringGreen3', 'SpringGreen4', 'green2', 'green3', 'green4',
              'chartreuse2', 'chartreuse3', 'chartreuse4', 'OliveDrab1', 'OliveDrab2', 'OliveDrab4', 'DarkOliveGreen1',
              'DarkOliveGreen2', 'DarkOliveGreen3', 'DarkOliveGreen4', 'khaki1', 'khaki2', 'khaki3', 'khaki4',
              'LightGoldenrod1', 'LightGoldenrod2', 'LightGoldenrod3', 'LightGoldenrod4', 'LightYellow2',
              'LightYellow3', 'LightYellow4', 'yellow2', 'yellow3', 'yellow4', 'gold2', 'gold3', 'gold4', 'goldenrod1',
              'goldenrod2', 'goldenrod3', 'goldenrod4', 'DarkGoldenrod1', 'DarkGoldenrod2', 'DarkGoldenrod3',
              'DarkGoldenrod4', 'RosyBrown1', 'RosyBrown2', 'RosyBrown3', 'RosyBrown4', 'IndianRed1', 'IndianRed2',
              'IndianRed3', 'IndianRed4', 'sienna1', 'sienna2', 'sienna3', 'sienna4', 'burlywood1', 'burlywood2',
              'burlywood3', 'burlywood4', 'wheat1', 'wheat2', 'wheat3', 'wheat4', 'tan1', 'tan2', 'tan4', 'chocolate1',
              'chocolate2', 'chocolate3', 'firebrick1', 'firebrick2', 'firebrick3', 'firebrick4', 'brown1', 'brown2',
              'brown3', 'brown4', 'salmon1', 'salmon2', 'salmon3', 'salmon4', 'LightSalmon2', 'LightSalmon3',
              'LightSalmon4', 'orange2', 'orange3', 'orange4', 'DarkOrange1', 'DarkOrange2', 'DarkOrange3',
              'DarkOrange4', 'coral1', 'coral2', 'coral3', 'coral4', 'tomato2', 'tomato3', 'tomato4', 'OrangeRed2',
              'OrangeRed3', 'OrangeRed4', 'red2', 'red3', 'red4', 'DeepPink2', 'DeepPink3', 'DeepPink4', 'HotPink1',
              'HotPink2', 'HotPink3', 'HotPink4', 'pink1', 'pink2', 'pink3', 'pink4', 'LightPink1', 'LightPink2',
              'LightPink3', 'LightPink4', 'PaleVioletRed1', 'PaleVioletRed2', 'PaleVioletRed3', 'PaleVioletRed4',
              'maroon1', 'maroon2', 'maroon3', 'maroon4', 'VioletRed1', 'VioletRed2', 'VioletRed3', 'VioletRed4',
              'magenta2', 'magenta3', 'magenta4', 'orchid1', 'orchid2', 'orchid3', 'orchid4', 'plum1', 'plum2', 'plum3',
              'plum4', 'MediumOrchid1', 'MediumOrchid2', 'MediumOrchid3', 'MediumOrchid4', 'DarkOrchid1', 'DarkOrchid2',
              'DarkOrchid3', 'DarkOrchid4', 'purple1', 'purple2', 'purple3', 'purple4', 'MediumPurple1',
              'MediumPurple2', 'MediumPurple3', 'MediumPurple4', 'thistle1', 'thistle2', 'thistle3', 'thistle4',
              'gray1', 'gray2', 'gray3', 'gray4', 'gray5', 'gray6', 'gray7', 'gray8', 'gray9', 'gray10', 'gray11',
              'gray12', 'gray13', 'gray14', 'gray15', 'gray16', 'gray17', 'gray18', 'gray19', 'gray20', 'gray21',
              'gray22', 'gray23', 'gray24', 'gray25', 'gray26', 'gray27', 'gray28', 'gray29', 'gray30', 'gray31',
              'gray32', 'gray33', 'gray34', 'gray35', 'gray36', 'gray37', 'gray38', 'gray39', 'gray40', 'gray42',
              'gray43', 'gray44', 'gray45', 'gray46', 'gray47', 'gray48', 'gray49', 'gray50', 'gray51', 'gray52',
              'gray53', 'gray54', 'gray55', 'gray56', 'gray57', 'gray58', 'gray59', 'gray60', 'gray61', 'gray62',
              'gray63', 'gray64', 'gray65', 'gray66', 'gray67', 'gray68', 'gray69', 'gray70', 'gray71', 'gray72',
              'gray73', 'gray74', 'gray75', 'gray76', 'gray77', 'gray78', 'gray79', 'gray80', 'gray81', 'gray82',
              'gray83', 'gray84', 'gray85', 'gray86', 'gray87', 'gray88', 'gray89', 'gray90', 'gray91', 'gray92',
              'gray93', 'gray94', 'gray95', 'gray97', 'gray98', 'gray99']

    def __init__(self, master):

        self.fillbutton = "0"
        menu = Menu(master)
        master.config(menu=menu)
        bFrame = Frame(master)
        subMenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="File", menu=subMenu)
        topPadding = Frame(master, width=self.toolbarw, height=self.toolbarh)
        subMenu.add_command(label="New File", command=partial(self.importpic, bFrame, topPadding))
        subMenu.add_command(label="Placeholder", command=self.doNothing)
        subMenu.add_separator()
        subMenu.add_command(label="Placeholder", command=self.doNothing)

        editMenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="Edit", menu=editMenu)
        editMenu.add_command(label="Remove Row", command=partial(self.removeRow, bFrame, topPadding))
        editMenu.add_command(label="Remove Col", command=partial(self.removeCol, bFrame, topPadding))
        viewMenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="View", menu=viewMenu)
        viewMenu.add_command(label="Color Chart", command=self.viewColorChart)

        toolbar = Frame(master, width=self.toolbarw, height=20, bg="grey")
        frameSep = Frame(master, width=self.toolbarw, height=3, bg="black")
        bottomPadding = Frame(master, width=self.toolbarw, height=40)
        self.setfillbutton = Checkbutton(bottomPadding, text="Fill")
        self.setfillbutton.config(state=DISABLED)
        self.setfillbutton.pack(side=LEFT)
        colorselect = Button(toolbar, text="Set Color", command=partial(self.colorfillask, bFrame, topPadding))
        colorselect.pack(side=LEFT)
        gridSelect = Button(toolbar, text="Grid Select", command=partial(self.changeGrid, bFrame, topPadding))
        gridSelect.pack(side=LEFT)
        View = Button(toolbar, text="View", command=partial(self.viewImage, 40))
        View.pack(side=LEFT)
        baseCol = Button(toolbar, text="Color Fill", command=partial(self.fillColor, bFrame, topPadding))
        baseCol.pack(side=LEFT)
        exportbut = Button(toolbar, text="Export", command=self.expFunc)
        exportbut.pack(side=LEFT)
        self.buttons = []

        for i in range(self.griddim):
            self.buttons.append(Button(bFrame, width=self.buttonw, height=self.buttonh, bg=self.basecolor,
                                       command=partial(self.buttonColor, i, bFrame, topPadding)))
            self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
            self.colors.append(self.basecolor)
        toolbar.pack_propagate(0)
        toolbar.pack(side=TOP)
        frameSep.pack(side=TOP)
        topPadding.pack(side=TOP)
        bFrame.pack()
        bottomPadding.pack(side=BOTTOM)

    def doNothing(self):
        print("Nope")

    def buttonColor(self, position, frame, padding):

        if self.colorfillvar == 0:
            colorask = Frame(padding)
            label_1 = Label(colorask, text="What Color?")
            entry_1 = Entry(colorask)
            label_2 = Label(colorask, text="Input takes lower case standard color, \nor #xxxxxxxxx hexadecimal number ")
            buttonOK = Button(colorask, text="OK",
                              command=partial(self.getEntry, entry_1, position, frame, colorask, padding))
            label_1.grid(row=0, sticky=E)
            entry_1.grid(row=0, column=1)
            label_2.grid(row=1, columnspan=2)
            buttonOK.grid(row=2, columnspan=2)
            colorask.pack()
        else:
            self.buttons[position].grid_forget()
            try:
                temp = Button(frame, width=self.buttonw, height=self.buttonh, bg=self.fillbutton,
                              command=partial(self.buttonColor, position, frame, padding))
            except:
                self.buttons[position] = Button(frame, width=self.buttonw, height=self.buttonh, bg='red',
                                                command=partial(self.buttonColor, position, frame, padding))
                self.buttons[position].grid(row=int(position / self.gridwidth), column=int(position % self.gridwidth))
                self.colors[position] = "red"
                print("Color entered is not recognized by tkinter. Please format the color as either a recognized tkinter string or #RGB or #RRGGBB or #RRRGGGBBB or #RRRRGGGGBBBB")
                return
            self.buttons[position] = Button(frame, width=self.buttonw, height=self.buttonh, bg=self.fillbutton,
                                            command=partial(self.buttonColor, position, frame, padding))
            self.buttons[position].grid(row=int(position / self.gridwidth), column=int(position % self.gridwidth))
            self.colors[position] = self.fillbutton

    def getEntry(self, entry, position, frame, colorask, padding):
        self.colorentry = entry.get()
        padding.config(width=self.toolbarw, height=self.toolbarh)
        colorask.destroy()
        if self.colorfillvar == 0:
            self.buttons[position].grid_forget()
            try:
                temp = Button(frame, width=self.buttonw, height=self.buttonh, bg=self.colorentry,
                              command=partial(self.buttonColor, position, frame, padding))
            except:
                self.buttons[position] = Button(frame, width=self.buttonw, height=self.buttonh, bg='red',
                                                command=partial(self.buttonColor, position, frame, padding))
                self.buttons[position].grid(row=int(position / self.gridwidth), column=int(position % self.gridwidth))
                self.colors[position] = "red"
                print("Something went wrong")
                return
            self.buttons[position] = Button(frame, width=self.buttonw, height=self.buttonh, bg=self.colorentry,
                                            command=partial(self.buttonColor, position, frame, padding))
            self.buttons[position].grid(row=int(position / self.gridwidth), column=int(position % self.gridwidth))
            self.colors[position] = self.colorentry
        else:
            self.fillbutton = self.colorentry

    def getButtonColor(self, button):
        rgb = button.winfo_rgb(button.cget('bg'))
        r = (rgb[0] >> 11)
        g = (rgb[1] >> 10)
        g = g << 5
        b = rgb[2] >> 11
        b = b << 11
        rgb = b + g + r
        return '0x%04x' % (rgb)

    def colorfillask(self, frame, padding):

        colorask = Frame(padding)

        label_1 = Label(colorask, text="What Color?")
        entry_1 = Entry(colorask)
        label_2 = Label(colorask, text="Input takes lower case standard color, \nor #xxxxxxxxx hexadecimal number ")
        container = Frame(colorask)
        buttonOK = Button(container, text="OK", command=partial(self.getEntry, entry_1, 1, frame, colorask, padding))
        buttonSet = Button(container, text="Set", command=self.setfillvar)
        buttonClear = Button(container, text="Clear", command=self.clearfillvar)

        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        label_2.grid(row=1, columnspan=2)
        buttonOK.grid(row=1, column=1)
        buttonSet.grid(row=1, column=2)
        buttonClear.grid(row=1, column=3)
        container.grid(row=2, columnspan=2)
        colorask.pack()

    def setfillvar(self):
        self.setfillbutton.select()
        self.colorfillvar = 1

    def clearfillvar(self):
        self.setfillbutton.deselect()
        self.colorfillvar = 0

    def changeGrid(self, frame, padding):
        gridask = Frame(padding)
        label_1 = Label(gridask, text="Grid Width:")
        entry_1 = Entry(gridask)
        label_2 = Label(gridask, text="Grid Height")
        entry_2 = Entry(gridask)
        buttonOK = Button(gridask, text="OK",
                          command=partial(self.getgridEntries, entry_1, entry_2, gridask, frame, padding))
        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        label_2.grid(row=1, column=0)
        entry_2.grid(row=1, column=1)
        buttonOK.grid(row=2, columnspan=2)
        gridask.pack()

    def getgridEntries(self, entry1, entry2, kill, frame, padding):
        if entry1.get() == "":
            kill.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        if entry2 != 1:
            try:
                temp1 = int(entry1.get())
                temp2 = int(entry2.get())
            except:
                kill.destroy()
                padding.config(width=self.toolbarw, height=self.toolbarh)
                return
            if int(entry1.get()) >30 or int(entry2.get()) >30:
                kill.destroy()
                padding.config(width=self.toolbarw, height=self.toolbarh)
                return
            self.gridwidth = int(entry1.get())
            self.gridheight = int(entry2.get())
        else:
            if entry1.get() in self.COLORS:
                self.basecolor = entry1.get()
            else:
                kill.destroy()
                padding.config(width=self.toolbarw, height=self.toolbarh)
                return
        for i in range(self.griddim):
            self.buttons[i].grid_forget()
        self.griddim = self.gridwidth * self.gridheight
        self.colors = []
        self.buttons = []
        for i in range(self.griddim):
            self.buttons.append(Button(frame, width=self.buttonw, height=self.buttonh, bg=self.basecolor,
                                       command=partial(self.buttonColor, i, frame, padding)))
            self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
            self.colors.append(self.basecolor)
        frame.pack()
        kill.destroy()
        padding.config(width=self.toolbarw, height=self.toolbarh)

    def viewImage(self, size):
        pixelI = Tk()
        canvas = Canvas(pixelI, width=self.gridwidth * size, height=self.gridheight * size)
        canvas.pack()
        for i in range(self.gridheight):
            for j in range(self.gridwidth):
                canvas.create_rectangle(j * size, i * size, j * size + size, i * size + size,
                                        fill=self.colors[i * self.gridwidth + j], width=0)

    def fillColor(self, frame, padding):
        fillAsk = Frame(padding)
        label_1 = Label(fillAsk, text="What Color?")
        entry_1 = Entry(fillAsk)
        label_2 = Label(fillAsk, text="Input takes lower case standard color, \nor #xxxxxxxxx hexadecimal number ")
        buttonOK = Button(fillAsk, text="OK", command=partial(self.getgridEntries, entry_1, 1, fillAsk, frame, padding))
        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        label_2.grid(row=1, columnspan=2)
        buttonOK.grid(row=2, columnspan=2)
        fillAsk.pack()

    def expFunc(self):
        print('writing file')
        file = open("bitmap.txt", "w")
        file.write(
            "uint16_t bitmap[] = {" + ','.join([self.getButtonColor(button) for button in self.buttons]) + "};\n\n")
        file.write("int idx = 0;\nfor (int i=0; i< " + str(self.gridheight) + "; i++){\n" + "\tfor (int j=0; j< " + str(
            self.gridwidth) +
                   "; j++){\n\t\tST7735_DrawPixel(j,i,bitmap[idx]);\n\t\tidx++;\n\t}\n}")
        file.close()

    def importpic(self, frame, padding):
        resizeask = Frame(padding)
        label_1 = Label(resizeask, text="Picture Name:")
        entry_1 = Entry(resizeask)
        label_2 = Label(resizeask, text="Resize Width")
        entry_2 = Entry(resizeask)
        label_3 = Label(resizeask, text="Resize Height")
        entry_3 = Entry(resizeask)
        buttonOK = Button(resizeask, text="OK",
                          command=partial(self.resizeandplace, entry_1, entry_2, entry_3, resizeask, frame, padding))
        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        label_2.grid(row=1, column=0)
        entry_2.grid(row=1, column=1)
        label_3.grid(row=2, column=0)
        entry_3.grid(row=2, column=1)
        buttonOK.grid(row=3, columnspan=2)
        resizeask.pack()

    def resizeandplace(self, entry1, entry2, entry3, kill, frame, padding):
        if entry1.get() == "" or entry2.get() == "" or entry3.get() == "":
            kill.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        self.picname = entry1.get()
        print(self.picname)
        try:
            im = Image.open(self.picname)
        except:
            kill.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        for i in range(self.griddim):
            self.buttons[i].grid_forget()
        temp1 = self.griddim
        temp2 = self.gridwidth
        temp3 = self.griddim
        self.gridwidth = int(entry2.get())
        self.gridheight = int(entry3.get())
        self.griddim = self.gridheight * self.gridwidth
        im = Image.open(self.picname)
        im = im.resize((self.gridwidth, self.gridheight), Image.NEAREST)
        pix = im.convert('RGB')
        self.colors = []
        self.buttons = []
        for i in range(self.griddim):
            r, g, b = pix.getpixel((int(i % self.gridwidth), int(i / self.gridwidth)))
            # print(int(i%self.gridheight), int(i/self.gridheight))
            # print(r,g,b)
            rgb = (r << 16) + (g << 8) + b
            rgb = "#%0.6x" % rgb
            # print(rgb)
            self.buttons.append(Button(frame, width=self.buttonw, height=self.buttonh, bg=rgb,
                                       command=partial(self.buttonColor, i, frame, padding)))
            if self.gridwidth < 55 or self.gridheight < 30:
                self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
            self.colors.append(rgb)
        print("Check")
        if self.gridwidth > 55 or self.gridheight > 30:
            print("did it work?")
            self.expFunc()
            self.viewImage(4)
            self.griddim = temp1
            self.gridwidth = temp2
            self.gridheight = temp3
            buttons = []
            for i in range(self.griddim):
                self.buttons.append(Button(frame, width=self.buttonw, height=self.buttonh, bg=self.basecolor,
                                           command=partial(self.buttonColor, i, frame, padding)))
                self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
                self.colors.append(self.basecolor)
            frame.pack()
        else:
            frame.pack()
        kill.destroy()
        im.save('resized_image.png')
        padding.config(width=self.toolbarw, height=self.toolbarh)

    def viewColorChart(self):
        MAX_ROWS = 36
        FONT_SIZE = 10  # (pixels)
        ColorChart = Tk()
        ColorChart.title("Named colour chart")
        row = 0
        col = 0
        for color in self.COLORS:
            e = Label(ColorChart, text=color, background=color,
                      font=(None, -FONT_SIZE))
            e.grid(row=row, column=col, sticky=E + W)
            row += 1
            if (row > 36):
                row = 0
                col += 1

    def removeRow(self, frame, padding):
        gridask = Frame(padding)
        label_1 = Label(gridask, text="Row: ")
        entry_1 = Entry(gridask)
        buttonOK = Button(gridask, text="OK",
                          command=partial(self.manMatRow, entry_1, gridask, frame, padding))
        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        buttonOK.grid(row=1, columnspan=2)
        gridask.pack()

    def removeCol(self, frame, padding):
        gridask = Frame(padding)
        label_1 = Label(gridask, text="Column: ")
        entry_1 = Entry(gridask)
        buttonOK = Button(gridask, text="OK",
                          command=partial(self.manMatCol, entry_1, gridask, frame, padding))
        label_1.grid(row=0, sticky=E)
        entry_1.grid(row=0, column=1)
        buttonOK.grid(row=1, columnspan=2)
        gridask.pack()

    def manMatRow(self, entry_1, gridask, frame, padding):
        try:
            temp1 = int(entry_1.get())
        except:
            print("Value given failed integer conversion")
            gridask.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        if int(entry_1.get()) <=0 or int(entry_1.get()) >self.gridheight:
            print("Integer given is out of bounds")
            gridask.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        rowID = int(entry_1.get())-1
        for i in range(self.griddim):
            self.buttons[i].grid_forget()
        self.buttons = []
        for i in range(self.gridwidth):
            del self.colors[self.gridwidth*rowID]
            print(i)
        self.gridheight = self.gridheight - 1
        self.griddim = self.gridheight*self.gridwidth
        for i in range(self.griddim):
            self.buttons.append(Button(frame, width=self.buttonw, height=self.buttonh, bg=self.colors[i],
                                       command=partial(self.buttonColor, i, frame, padding)))
            self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
        gridask.destroy()
        padding.config(width=self.toolbarw, height=self.toolbarh)
        frame.pack()

    def manMatCol(self, entry_1, gridask, frame, padding):
        try:
            temp1 = int(entry_1.get())
        except:
            print("Value given failed integer conversion")
            gridask.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        if int(entry_1.get()) <=0 or int(entry_1.get()) >self.gridwidth:
            print("Integer given is out of bounds")
            gridask.destroy()
            padding.config(width=self.toolbarw, height=self.toolbarh)
            return
        colID = int(entry_1.get())-1
        for i in range(self.griddim):
            self.buttons[i].grid_forget()
        self.buttons = []
        temp = []
        j=0
        for i in range(self.griddim):
            if (i%self.gridwidth == colID):
                continue
            else:
                temp.append(self.colors[i])
                j=j+1
        self.colors = temp
        self.gridwidth = self.gridwidth - 1
        self.griddim = self.gridheight*self.gridwidth
        for i in range(self.griddim):
            self.buttons.append(Button(frame, width=self.buttonw, height=self.buttonh, bg=self.colors[i],
                                       command=partial(self.buttonColor, i, frame, padding)))
            self.buttons[i].grid(row=int((i / self.gridwidth)), column=int((i % self.gridwidth)))
        gridask.destroy()
        padding.config(width=self.toolbarw, height=self.toolbarh)
        frame.pack()

root = Tk()
z = mainclass(root)
root.mainloop()
sys.exit()


import cv2
import numpy as np

# Load the image
img = cv2.imread("22_Picnic_Picnic_22_688.jpg")

# Define the kernel size for Gaussian Blur
kernel_size = (15, 15)

# Apply Gaussian Blur to the image
img_blur = cv2.GaussianBlur(img, kernel_size, 0)

# Display the original and blurred images
cv2.imshow("Original", img)
cv2.imshow("Blurred", img_blur)
cv2.imwrite("result/22_Picnic_Picnic_22_688_gaussian_blur.jpg", img_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

#In this example, the GaussianBlur function takes three arguments:
#img: the input image.
#kernel_size: the size of the kernel used for blurring. A larger kernel size will result in a more intense blur effect.
#0: the standard deviation of the Gaussian distribution used for blurring. A value of 0 means that the standard deviation will be calculated automatically based on the kernel size.


from rest_framework.routers import DefaultRouter
from .views import MessageViewSet, NotificationViewSet

router = DefaultRouter()
router.register(r'messages', MessageViewSet , basename='message_viewset')
router.register(r'notification', NotificationViewSet , basename='notification_viewset')

urlpatterns = [

] + router.urls


from pyspark.sql.functions import expr
from pyspark.sql.functions import from_unixtime
from pyspark.shell import spark

inputPath = '/Users/jiang.li/Desktop/event.json'
# spark.read 读取 json数据，并将表头time装换为date格式
events = spark.read \
    .option("inferSchema", "true") \
    .json(inputPath) \
    .withColumn("date", expr("time")) \
    .drop("time") \
    .withColumn("date", from_unixtime('date', 'yyyy-mm-dd'))
# withColumn("新的列","旧的列")  如果新旧两列的名称相同，那么新的列的表达式或者值会替换旧的列

events.show()


import praw
import re
import textwrap
from PIL import Image, ImageEnhance
import requests
from io import BytesIO
from PIL import ImageDraw, ImageFont, Image, ImageFilter, ImageChops
import numpy as np
from util import human_format
from better_profanity import profanity
import time
import lorem
from dotenv import load_dotenv
import os

class TestSubmission:
    class author:
        def __init__(self):
            self.name = "TestAuthor"

    class Comment:
        def __init__(self):
            self.author = TestSubmission.author()
            self.body = self.selftext = " ".join([lorem.paragraph() for i in range(1)])
            self.stickied = False
            self.score = 60000

    def __init__(self):
        self.title = " ".join([lorem.paragraph() for i in range(1)])
        self.selftext = " ".join([lorem.paragraph() for i in range(1)])

        # self.title = 10 * "a"
        # self.selftext = 0 * "a"

        self.num_comments = 3600
        self.score = 25000
        self.author = TestSubmission.author()
        self.comments =[TestSubmission.Comment() for i in range(8)]
        self.icon_img = "./assets/reddit.png"
        self.url = "https://www.reddit.com/r/AskReddit/"

class PostSubmission:
    def __init__(self, title, author, img, icon_img, url, id, isPost=True):
        self.title = title
        self.author = author
        self.img = img
        self.icon_img = icon_img
        self.isPost = isPost
        self.url = url
        self.id = id

class redditScrapper:
    def __init__(self, sub, bgres=1000):
        print("Initialized")
        self.sub = sub
        self.gildMinAmount = 8000
        self.textWrapLen = 58
        self.pageLength = 1300
        self.imageSize = 1000
        self.textWidth = 1000
        self.textHeight = 38
        self.elementPadding = 10
        self.textLeftPadding = 90
        self.resetBG(bgres)
        self.urlPattern = re.compile('\[(.*?)\]\(.*?\)')

        self.font = ImageFont.truetype("LucidaSansDemiBold.ttf", 25)
        self.mediumFont = ImageFont.truetype("calibrib.ttf", 26)
        self.smallFont = ImageFont.truetype("calibrib.ttf", 21)

        self.reddit = praw.Reddit(
            client_id=os.getenv('client_id'),
            client_secret=os.getenv('client_secret'),
            user_agent=os.getenv('user_agent'),
            check_for_async=False)

    def getPostFromLink(self, link, commentCount=4, saveOnCreate=False):
        listOfPosts = []
        print("Gather Post Started")
        submission = praw.models.Submission(reddit=self.reddit, url=link)
        subredditHelper = submission.subreddit
        subIconPath = subredditHelper.icon_img

        self.fillArrayFromSubmission(listOfPosts, submission, commentCount, True, saveOnCreate, subIconPath)

        return listOfPosts

    def changeSub(self, sub):
        self.sub = sub

    def resetBG(self, res):
        # response = requests.get('https://picsum.photos/' + str(res))
        response = requests.get(f"https://picsum.photos/{res}/{res}")
        self.background = Image.open(BytesIO(response.content))
        # self.background = Image.open("./outputs/pic.jpg")
        enhancer = ImageEnhance.Brightness(self.background)
        self.background = enhancer.enhance(0.6)

    def setHeight(self, text, content=None):
        content = content if content else ""
        lineCount = len(textwrap.wrap(text + content, width=self.textWrapLen))
        return max(lineCount + 4, 2) * 29 + self.elementPadding

    def addTitleContent(self, text, image, textColor="#ffffff", content=None, isHeadEmpty=True):
        draw = ImageDraw.Draw(image)

        margin = self.textLeftPadding
        offset = self.imageSize / 2 - self.textHeight / 2 + self.elementPadding + (29 if isHeadEmpty else 0)
        for line in textwrap.wrap(text, width=self.textWrapLen):
            draw.text((margin, offset), line, textColor, font=self.font)
            offset += self.font.getbbox(line)[3]

        if (content):
            for line in textwrap.wrap(content, width=self.textWrapLen):
                draw.text((margin, offset + 29), line, "#CBCBCC", font=self.font)
                offset += self.font.getbbox(line)[3]

    def addCustomText(self, image, text, pos=(0, 0), textColor="#ffffff", textAnchor="ms", storoke_fill=None,
                      stroke_width=0):
        # text = profanity.censor(text)
        draw = ImageDraw.Draw(image)
        draw.text(pos, text, textColor, font=self.smallFont, anchor=textAnchor)

    def addMediumCustomText(self, image, text, pos=(0, 0), textColor="#ffffff", textAnchor="ms", storoke_fill=None,
                            stroke_width=0):
        # text = profanity.censor(text)
        draw = ImageDraw.Draw(image)
        draw.text(pos, text, textColor, font=self.mediumFont, anchor=textAnchor, stroke_fill=storoke_fill,
                  stroke_width=stroke_width)

    def blurBox(self, image, blurAmount=8):

        draw = ImageDraw.Draw(image, "RGBA")
        draw.rectangle((int(self.imageSize / 2 - self.textWidth / 2),
                        int(self.imageSize / 2 - self.textHeight / 2),
                        int(self.imageSize / 2 + self.textWidth / 2),
                        int(self.imageSize / 2 + self.textHeight / 2)),
                       fill=(0, 0, 0, 80))

        # draw.rectangle((int(self.imageSize/2-self.textWidth/2),
        #                 int(self.imageSize/2-self.textHeight/2),
        #                 int(self.imageSize/2+self.textWidth/2),
        #                 int(self.imageSize/2+self.textHeight/2)),
        #                 fill =(0, 0, 0, 0), outline ="red")

        box = (
            int(self.imageSize / 2 - self.textWidth / 2),
            int(self.imageSize / 2 - self.textHeight / 2),
            int(self.imageSize / 2 + self.textWidth / 2),
            int(self.imageSize / 2 + self.textHeight / 2)
        )

        ic = image.crop(box)
        for i in range(blurAmount):  # with the BLUR filter, you can blur a few times to get the effect you're seeking
            ic = ic.filter(ImageFilter.BLUR)
        image.paste(ic, box)

    def crop_to_circle(self, im):
        bigsize = (im.size[0] * 3, im.size[1] * 3)
        mask = Image.new('L', bigsize, 0)
        ImageDraw.Draw(mask).ellipse((0, 0) + bigsize, fill=255)
        mask = mask.resize(im.size, Image.ANTIALIAS)
        mask = ImageChops.darker(mask, im.split()[-1])
        im.putalpha(mask)

    def addIcon(self, iconPath, image, posY, isIconOnUrl):
        logo = None
        if isIconOnUrl:
            response = requests.get(iconPath)
            logo = Image.open(BytesIO(response.content))
        else:
            logo = Image.open(iconPath)

        logo = logo.resize((60, 60))

        logo = logo.convert('RGBA')
        self.crop_to_circle(logo)

        image.paste(logo, (self.elementPadding, posY), logo)

        return logo

    def createImageWithText(self, title, icon="", isIconOnUrl=True):
        bg = self.background.copy()
        self.textHeight = self.setHeight(title)
        self.blurBox(bg)
        self.addTitleContent(title, bg)

        if icon != "":
            self.addIcon(icon, bg, int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding),
                         isIconOnUrl=isIconOnUrl)

        bg.show()
        return bg

    def isCommentBadCheck(self, comment):
        isRemoved = (comment.body == "[removed]")
        isBot = False if not comment.author else re.search('moderator', comment.author.name, re.IGNORECASE)
        isSticky = comment.stickied

        return isRemoved or isBot or isSticky

    def getRedditPostAsImage(self, filter="day", postCount=1, commentCount=4, saveOnCreate=False, isTesting=False):
        listOfPosts = []
        print("Gather Post Started")
        subredditHelper = None if isTesting else self.reddit.subreddit(self.sub)
        submissionArray = [TestSubmission() for i in range(postCount)] if isTesting else subredditHelper.top(time_filter=filter, limit=postCount)
        subIconPath = TestSubmission().icon_img if (isTesting or (not subredditHelper.icon_img) or (len(subredditHelper.icon_img) == 0)) else subredditHelper.icon_img
        isIconOnUrl = (not (isTesting or (not subredditHelper.icon_img) or (len(subredditHelper.icon_img) == 0)))

        for submission in submissionArray:
            self.fillArrayFromSubmission(listOfPosts, submission, commentCount, isIconOnUrl, saveOnCreate, subIconPath)

        return listOfPosts

    def gildPhoto(self, im, gradient_magnitude=3.5):
        if im.mode != 'RGBA':
            im = im.convert('RGBA')
        width, height = im.size
        gradient = Image.new('L', (width, 1), color=0xFF)
        for x in range(width):
            # gradient.putpixel((width-x-1, 0), 150-x)
            gradient.putpixel((width-x-1, 0), int(150 * (1 - gradient_magnitude * float(x)/width)))
        alpha = gradient.resize(im.size)
        black_im = Image.new('RGBA', (width, height), color=0x03BAFC) # i.e. black
        black_im.putalpha(alpha)
        return Image.alpha_composite(im, black_im)

    def fillArrayFromSubmission(self, listOfPosts, submission, commentCount, isIconOnUrl, saveOnCreate, subIconPath):
        self.resetBG(self.imageSize)
        title = submission.title
        print(title)
        content = submission.selftext
        name = submission.author.name if submission.author is not None else "Unknown"
        pages = textwrap.wrap(content, width=self.pageLength - len(title))
        # title = profanity.censor(title)
        title = self.urlPattern.sub(r'\1', title)
        bg = self.background.copy()

        self.textHeight = self.setHeight(title, pages[0] if len(pages) > 0 else "")
        self.blurBox(bg)

        if submission.score > self.gildMinAmount:
            bg = self.gildPhoto(bg)

        self.addTitleContent(title, bg, content=pages[0] if len(pages) > 0 else "")
        self.addIconSubScore(bg, isIconOnUrl, name, subIconPath, submission)

        if saveOnCreate:
            bg.save("outputs/" + str(
                int(round(time.time() * 100))) + " - " + submission.author.name + " - MAIN " + ".png")
        else:
            listOfPosts.append(PostSubmission(title, name, bg, subIconPath, submission.url, submission.id))

        imageCount = 1

        # For content that doesn't fit
        if len(pages) > 0:
            for count, page in enumerate(pages[1:]):
                imageCount += 1
                # page = profanity.censor(page)
                page = self.urlPattern.sub(r'\1', page)

                bg = self.background.copy()

                self.textHeight = self.setHeight(" ", page)
                self.blurBox(bg)
                if submission.score > self.gildMinAmount:
                    bg = self.gildPhoto(bg)

                self.addTitleContent(f"...{count + 1}/{len(pages)}...", bg, content=page)

                self.addIconSubScore(bg, isIconOnUrl, name, subIconPath, submission)

                if saveOnCreate:
                    bg.save(
                        "outputs/" + str(int(round(time.time() * 1000))) + " - " + submission.author.name + ".jpg")
                else:
                    listOfPosts.append(PostSubmission(title, name, bg, subIconPath, submission.url, submission.id))

        submission.comments.replace_more()
        for count, comment in enumerate(submission.comments):
            if imageCount > 10:
                break

            if commentCount == count:
                break

            if self.isCommentBadCheck(comment):
                continue

            commentPages = textwrap.wrap(comment.body, width=self.pageLength)
            if imageCount + len(commentPages) > 10:
                continue

            for page in commentPages:
                imageCount += 1
                commentBody = page
                # commentBody = profanity.censor(commentBody)
                commentBody = self.urlPattern.sub(r'\1', commentBody)

                commentAuthorName = comment.author.name if comment.author else "[deleted]"
                commentImage = self.background.copy()

                self.textHeight = self.setHeight(commentBody)
                self.blurBox(commentImage)
                if comment.score > self.gildMinAmount:
                    commentImage = self.gildPhoto(commentImage)

                self.addTitleContent(commentBody, commentImage, "#e8e8e8", isHeadEmpty=False)
                self.addScoreAuthor(comment, commentAuthorName, commentImage)
                self.addIcon(subIconPath, commentImage,
                            int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding), isIconOnUrl)

                if saveOnCreate:
                    commentImage.save(
                        "outputs/" + str(int(round(time.time() * 1000))) + " - " + submission.author.name + ".jpg")
                else:
                    listOfPosts.append(PostSubmission(f"{title} - {str(count)}", commentAuthorName, commentImage, subIconPath, submission.id, False))

        print(submission.author.name + "post is finished!")

    def addIconSubScore(self, bg, isIconOnUrl, name, subIconPath, submission):
        self.addIcon(subIconPath, bg, int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding),isIconOnUrl)
        self.addMediumCustomText(bg, "r/" + self.sub, (self.elementPadding * 3 + 60, int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding)),"#FF4500", textAnchor="lt", storoke_fill="#000000", stroke_width=2)
        self.addScoreAuthor(submission, name, bg)
        self.addCustomText(bg, human_format(submission.num_comments), (self.elementPadding + 30, int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding + 110)),"#39ceff")

    def addScoreAuthor(self, comment, commentAuthorName, commentImage):
        self.addCustomText(commentImage, human_format(comment.score), (self.elementPadding + 30, int(self.imageSize / 2 - self.textHeight / 2 + self.elementPadding + 85)),"#fa6505")
        self.addCustomText(commentImage, "/u/" + commentAuthorName, (self.imageSize - self.elementPadding, int(self.imageSize / 2 + self.textHeight / 2 - self.elementPadding)),"#ffffff", textAnchor="rs")


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jun 11 17:36:13 2019

@author: vikram
"""

"""
Research the below wesbite and post some data on it
https://requestbin.com
"""
# Code Challenge

"""
Create a client REST API that sends and receives some information from the Server by calling server's REST API.
You are expected to create two functions each for Sending and Receiving data.

    You need to make two api calls, one with POST method for sending data and the other with GET method to receive data

    All the communication i.e. sending and receiving of data with the server has to be in JSON format

    First send the data to cloud using the "http://13.127.155.43/api_v0.1/sending" api with the following fields (Field names should be same as shown ):
            Phone_Number (pass phone number as string and not as integer)
            Name
            College_Name
            Branch

    Now receive the data from cloud using the "http://13.127.155.43/api_v0.1/receiving" api with
    “Phone_Number” along with the number you are looking for as query parameter
    Print the server responses from both the cases.

    The first one will give response-code : 200 and response-message : "Data added Successfully", if all goes well.
    The second one will give all the details stored with the phone number you provided as query parameter.
    Both the responses will be in JSON format.

"""
import json
import requests
Host = "https://en0i28004x2ex.x.pipedream.net/post"
data = {"firstname":"dev","language":"English"}
headers = {"Content-Type":"application/json","Content-Length":len(data),"data":json.dumps(data)}

def post_method():
    response = requests.post(Host,data,headers)
    return response

print ( post_method().text )


from openfermion.ops import FermionOperator, QubitOperator
from openfermion.transforms import jordan_wigner
from openfermion.utils.commutators import commutator
import itertools

iEj = lambda i, j: str(i)+'^ '+str(j)+' '
ijE = lambda i, j: str(i)+'^ '+str(j)+'^ '
Eij = lambda i, j: str(i)+' '+str(j)+' '
ijEkl = lambda i, j, k, l: ijE(i, j) + Eij(k, l)

n = lambda i: FermionOperator(iEj(i, i))
nn = lambda i, j: n(i)*n(j)
number_op = lambda k: sum([n(i) for i in range(k)])

iEjxkEl = lambda i, j, k, l: FermionOperator(iEj(i, j) + iEj(k, l))
sym_iEj = lambda i, j: FermionOperator(iEj(i, j)) + FermionOperator(iEj(j, i))
anti_iEj = lambda i, j: FermionOperator(iEj(i, j)) - FermionOperator(iEj(j, i))

gA_r = lambda i, j, k, l: iEjxkEl(j, i, l, k) + iEjxkEl(l, k, j, i) + iEjxkEl(i, j, k, l) + iEjxkEl(k, l, i, j)
gA_i = lambda i, j, k, l: iEjxkEl(j, i, l, k) + iEjxkEl(l, k, j, i) - iEjxkEl(i, j, k, l) - iEjxkEl(k, l, i, j)
gB_r = lambda i, j, k, l: iEjxkEl(j, i, k, l) + iEjxkEl(k, l, j, i) + iEjxkEl(i, j, l, k) + iEjxkEl(l, k, i, j)
gB_i = lambda i, j, k, l: iEjxkEl(j, i, k, l) + iEjxkEl(k, l, j, i) - iEjxkEl(i, j, l, k) - iEjxkEl(l, k, i, j)
gAB = lambda i, j, k, l: gA_r(i, j, k, l) + gB_r(i, j, k, l)
gA_B = lambda i, j, k, l: gA_r(i, j, k, l) - gB_r(i, j, k, l)
gAB_s = lambda i, j, k, l: t_s(gA_r, i, j, k, l) + t_s(gB_r, i, j, k, l)
gA_B_s = lambda i, j, k, l: t_s(gA_r, i, j, k, l) - t_s(gB_r, i, j, k, l)
gAB_3 = lambda p, q, r: n(p)*(sym_iEj(q, r)) + (sym_iEj(r, q))*n(p)
gA_B_3 = lambda p, p2, q: n(p)*(anti_iEj(p2, q)) + (anti_iEj(p2, q))*n(p)
gAB_3_s = lambda p, q, r: gAB_3(2*p, 2*q, 2*r) + gAB_3(2*p + 1, 2*q, 2*r) + gAB_3(2*p, 2*q + 1, 2*r + 1) + gAB_3(2*p + 1, 2*q + 1, 2*r + 1)
gAB_3_s_list = lambda p, q, r: [gAB_3(2*p, 2*q, 2*r), gAB_3(2*p + 1, 2*q, 2*r), gAB_3(2*p, 2*q + 1, 2*r + 1), gAB_3(2*p + 1, 2*q + 1, 2*r + 1)]

#spin
o_s = lambda f, i, j: f(2*i, 2*j) + f(2*i + 1, 2*j + 1)
t_s = lambda f, i, j, k, l: f(2*i, 2*j, 2*k, 2*l) + f(2*i + 1, 2*j + 1, 2*k, 2*l) + f(2*i, 2*j, 2*k + 1, 2*l + 1) + f(2*i + 1, 2*j + 1, 2*k + 1, 2*l + 1)
t_s_list = lambda f, i, j, k, l: list([f(2*i, 2*j, 2*k, 2*l), f(2*i + 1, 2*j + 1, 2*k, 2*l), f(2*i, 2*j, 2*k + 1, 2*l + 1) , f(2*i + 1, 2*j + 1, 2*k + 1, 2*l + 1)])

get_f = lambda a, f: f(a[0], a[1], a[2], a[3])
gA_s = lambda i, j, k, l: t_s(gA_r, i, j, k, l)
gB_s = lambda i, j, k, l: t_s(gB_r, i, j, k, l)
gA_s_list = lambda i, j, k, l: t_s_list(gA_r, i, j, k, l)
gB_s_list = lambda i, j, k, l: t_s_list(gB_r, i, j, k, l)
gAB_s_list = lambda i, j, k, l: t_s_list(gAB, i, j, k, l)
gA_B_s_list = lambda i, j, k, l: t_s_list(gA_B, i, j, k, l)

symsym = lambda i, j, k, l: sym_iEj(i, j)*sym_iEj(k, l)
antianti = lambda i, j, k, l: anti_iEj(i, j)*anti_iEj(k, l)
dd_s = lambda f, i, j: f(2*i, 2*j, 2*i, 2*j) + f(2*i + 1, 2*j + 1, 2*i, 2*j) + f(2*i, 2*j, 2*i + 1, 2*j + 1) + f(2*i + 1, 2*j + 1, 2*i + 1, 2*j + 1)

#checking if the terms of the hamiltonian two body tensor commute:
def check_pauli_commutation(op_list, verbose = True):

    combs = list(itertools.combinations(op_list, 2))
    for a, b in combs:
        if commutator(a, b).induced_norm() != 0.0:
            if verbose:
                print('{} and {} don\'t commute!'.format(a, b))
            return False
    return True

def check_self_commuting(op, verbose = True):
    """
    checks if all the Pauli words on jordan-wigner transforming the fermionic operator commute (fully-commuting set)
    """
    op_list = get_pauli_list(op)
    if verbose:
        print('Number of terms: {}'.format(len(op_list)))
    a = check_pauli_commutation(op_list, verbose)
    if verbose:
        print('Commuting: {}'.format(a))
    return a

def get_pauli_list(op):
    """
    returns list of Pauli operators
    """
    if type(op) == FermionOperator:
        op_jw = jordan_wigner(op)
    else:
        op_jw = op

    op_list = [a for a in op_jw.get_operators()]
    op_list_unit = [QubitOperator(list(a.terms.keys())[0]) for a in op_list]
    return op_list_unit

def get_n_pauli(op):
    """
    returns number of Paulis
    """
    return len(get_pauli_list(op))

def check_pair_commuting(op1, op2, verbose = False, all = True):
    if type(op1) == FermionOperator:
        op1, op2 = jordan_wigner(op1), jordan_wigner(op2)
    if commutator(op1, op2).induced_norm() != 0.0:
        if verbose:
            print('Operators dont commute!')
        return False

    if all == False:
        return True
    #else they commute
    #check if each Pauli commutes
    if verbose:
        print('Operators commute. Checking if completely commuting...')
    op_list = get_pauli_list(op1) + get_pauli_list(op2)
    a = check_pauli_commutation(op_list, False)
    if verbose:
        print('Commuting: {}'.format(a))
    return a

def check_all_Z(op):
    '''
    Checks if all Z

    Input:
    op : QubitOperator
    '''
    op_list = list(op.terms.keys())
    for i in range(len(op_list)):
        for j in range(len(op_list[i])):
            if op_list[i][j][1] != 'Z':
                return False
    return True


import psycopg2
from config import config

class DataAccess():

    @classmethod
    def connexion(cls):

     #""" Connect to the PostgreSQL database server """
        conn = None

        try:
            # read connection parameters
            params = config()

            # connect to the PostgreSQL server
            print('Connecting to the PostgreSQL database...')
            conn = psycopg2.connect(**params)

        except (Exception, psycopg2.DatabaseError) as error:
            print(error)

        return conn

    @classmethod
    def close_connexion(cls):

        cls.conn = cls.connexion()
        if cls.conn is not None:
            cls.conn.close()
            print('Database connection closed.')

    @classmethod
    def get_facilities(cls):
        cls.cur = cls.connexion().cursor()
        cls.cur.execute('SELECT * FROM cd.facilities')
        data = cls.cur.fetchall()
        #data = cls.cur.fetchone()
        print(data)
        cls.close_connexion()
        return (data)

DataAccess.get_facilities()


# -*- coding: utf-8 -*-
"""
Document classifier using Linear Support Vector Machine Classifier
preprocessed with TD-IDF vectorizer
Created on Mon Mar 22 20:26:18 2021

@author: jgharris
"""
# Preprocessing parameters
minLength=5             #Mininmun number of words for running classifer
MAXFEATURES=2000
mindf=1
maxdf=1.0
mindf=1
alphasmooth=1
ngramrange=(1,3)
MAXSTRINGLENGH=7060
FIRSTSTRINGLENGTH=80
CREG=1.

# SVC options
PENALTY='l2'
LOSS='squared_hinge'
DUAL=False
DEBUG=1

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import cross_val_score
#from sklearn.model_selection import train_test_split

from sklearn.svm import LinearSVC
#from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
import unittest
import pickle
import time

#import matplotlib
#import matplotlib.pyplot as plt
#import numpy as np

# path is './' for final build, but may be '../' for testing in IDE

unit_temp_file_path='./'
unit_model_name='linSVCv0'
start_time=time.time()
class DocClfTLinSVC():
    def __init__(self,maxStringLength=MAXSTRINGLENGH, \
                 firstStringLength=FIRSTSTRINGLENGTH,
                 penalty=PENALTY,loss=LOSS,dual=DUAL,
                 creg=CREG,
                 maxFeatures=MAXFEATURES
                 ):
        self.maxStringLength=maxStringLength
        self.firstStringLength=firstStringLength
        self.loss=loss
        self.penalty=penalty
        self.creg=creg
        self.dual=dual
        self.maxFeatures=maxFeatures
        self.message="LinearSVC using TF-IDF with "+"%5d" % maxFeatures + " features " + \
        " ngram-range "+"%2d" % ngramrange[0]+" to "+"%2d" % ngramrange[1] + \
        " maxString Length "+ "%6d" % self.maxStringLength +"Creg="+"%4.2f" % self.creg

        return

# Truncate string. Not implemented--possibility of combining counts from
#  begining of document with counts from most of document
# Documents must be truncated due to apparent length limit to GET URL

    def preprocess(self,x):
        xprocessed=[]
        xbegin=[]
        for item in x:
            xprocessed.append(item[0:self.maxStringLength])
            xbegin.append(item[0:self.firstStringLength])
        return xprocessed,xbegin
    def fit(self,x,y):
            # generate dictionary of words and numb of word occurences
            # in each document
        xprocessed,xbegin=self.preprocess(x)
        self.vectorizer=\
        TfidfVectorizer(max_df=maxdf,min_df=mindf,max_features=self.maxFeatures,
                               ngram_range=ngramrange)
        xv=self.vectorizer.fit_transform(xprocessed)
        self.nbclf=LinearSVC(penalty=self.penalty,loss=self.loss,dual=self.dual,
                C=self.creg)
        self.nbclf.fit(xv,y)
        ytrain=self.nbclf.predict(xv)
        return ytrain

    #predict for a group of x value

    def predict(self,x):
        if (len(x[0])<minLength):
            y=["No input"]
            return y
        try:
            xprocessed,xbegin=self.preprocess(x)
            xv=self.vectorizer.transform(xprocessed)
            y=self.nbclf.predict(xv)
        except:
            raise
        return y
    def crossVal(self,cvec,xtrain,ytrain):
        scorelist=[]
        global start_time
        for item in cvec:
           modelt=make_pipeline(
            TfidfVectorizer(max_df=maxdf,min_df=mindf,max_features=self.maxFeatures,
                               ngram_range=ngramrange),
            LinearSVC(penalty=self.penalty,loss=self.loss,dual=self.dual,
                C=item)
            )
           if(DEBUG>=1):
               print(modelt.named_steps)
           scores=cross_val_score(modelt,xtrain,ytrain)
           print("time=%7.1f " % (time.time()-start_time),end="")
           print("%5.2f " % item, end=' ')
           [print("%10.5f " % xval,end='') for xval in scores]
           print("")
           scorelist.append(scores)
        return scorelist

    # Compute confidence given predicted values & return confusion matrix

    def confidence(self,ytest,ytestpred):
        conf_mat = confusion_matrix(ytest, ytestpred)
    # compute accuracy given predicted value
        labels = sorted(set(ytest))
        self.confidence=dict(zip(labels, conf_mat.diagonal()/
                                 (.1+conf_mat.sum(axis=0))))
        return conf_mat
    #
    # get the Confidence score for a single item:
    # "x" is stuck in here, but not used because it may be possible
    # to improve the Confidence estimate by metrics like
    # distance from separating boundary or a relative score
    #
    def getConfidence(self,x,y):
        try:
            return self.confidence[y]
        except:
            return -1.0;

# Note that directory at top may need to be changed depending on
# whether this is run from the ./app or home directory
#  This tries to catch that error

class TestDocLinSVC(unittest.TestCase):
    def setUp(self):
       modelFile=unit_temp_file_path+unit_model_name+".pckmdl"
       try:
          with open(modelFile,"rb") as myFile:
             self.myModel=pickle.load(myFile)
          testF=open(unit_temp_file_path+unit_model_name+"testdata.txt","rt")
       except:
           with open('../'+modelFile,"rb") as myFile:
             self.myModel=pickle.load(myFile)
           testF=open('../'+unit_temp_file_path+unit_model_name+"testdata.txt","rt")

       self.cases=[]

       for line in testF:
           y,x=line.strip().split(',')
           self.cases.append((x,y))
       testF.close()
    def testpredict(self):
        print("")
        for case in self.cases:
            result=self.myModel.predict([case[0]])
            print((result,case[1]))
            self.assertEqual(result,case[1])

if __name__=='__main__':
    unittest.main()


"""Wire URL to view to access the API"""
from django.urls import path   # define different parts in app

from user import views

app_name = 'user'

urlpatterns = [   # routing for user functionality
    path('create/', views.CreateUserView.as_view(), name='create'),
    path('token/', views.CreateTokenView.as_view(), name='token'),
    path('me/', views.ManageUserView.as_view(), name='me'),
]