#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
sys.path.append('/usr/local/lib/python3.5/site-packages')
import gi
import shutil
import cv2
import os
import copy as cp
import decimal
import openpyxl
from openpyxl import Workbook
from pathlib import Path
import numpy as np
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf
from natsort import natsorted
from PIL import Image
from time import sleep
import smbus
import time

builder = Gtk.Builder()
builder.add_from_file("Interface.glade")

window = builder.get_object("mainMenu")
image = builder.get_object("image1")
lblHasil = builder.get_object("lblHasil")
lblPersamaan = builder.get_object("lblPersamaan")
window.set_position(Gtk.WindowPosition.CENTER)
window.show_all()

class mainWindowHandler:

    global filename
    global foldername
    global tmpfolder
    global inputaction
    global lastRow
    global lastNo

    # Define some device parameters
    I2C_ADDR  = 0x3f # I2C device address
    LCD_WIDTH = 16   # Maximum characters per line

    # Define some device constants
    LCD_CHR = 1 # Mode - Sending data
    LCD_CMD = 0 # Mode - Sending command

    LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
    LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
    LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
    LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

    LCD_BACKLIGHT  = 0x08  # On
    #LCD_BACKLIGHT = 0x00  # Off

    ENABLE = 0b00000100 # Enable bit

    # Timing constants
    E_PULSE = 0.0005
    E_DELAY = 0.0005

    #Open I2C interface
    #bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
    bus = smbus.SMBus(1) # Rev 2 Pi uses 1

    def __init__(self):
        # Initialise display
        self.lcd_init()

    def lcd_init(self):
      # Initialise display
      self.lcd_byte(0x33,self.LCD_CMD) # 110011 Initialise
      self.lcd_byte(0x32,self.LCD_CMD) # 110010 Initialise
      self.lcd_byte(0x06,self.LCD_CMD) # 000110 Cursor move direction
      self.lcd_byte(0x0C,self.LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
      self.lcd_byte(0x28,self.LCD_CMD) # 101000 Data length, number of lines, font size
      self.lcd_byte(0x01,self.LCD_CMD) # 000001 Clear display
      time.sleep(self.E_DELAY)

    def lcd_byte(self, bits, mode):
      # Send byte to data pins
      # bits = the data
      # mode = 1 for data
      #        0 for command

      bits_high = mode | (bits & 0xF0) | self.LCD_BACKLIGHT
      bits_low = mode | ((bits<<4) & 0xF0) | self.LCD_BACKLIGHT

      # High bits
      self.bus.write_byte(self.I2C_ADDR, bits_high)
      self.lcd_toggle_enable(bits_high)

      # Low bits
      self.bus.write_byte(self.I2C_ADDR, bits_low)
      self.lcd_toggle_enable(bits_low)

    def lcd_toggle_enable(self, bits):
      # Toggle enable
      time.sleep(self.E_DELAY)
      self.bus.write_byte(self.I2C_ADDR, (bits | self.ENABLE))
      time.sleep(self.E_PULSE)
      self.bus.write_byte(self.I2C_ADDR,(bits & ~self.ENABLE))
      time.sleep(self.E_DELAY)

    def lcd_string(self, message,line):
      # Send string to display

      message = message.ljust(self.LCD_WIDTH," ")

      self.lcd_byte(line, self.LCD_CMD)

      for i in range(self.LCD_WIDTH):
        self.lcd_byte(ord(message[i]),self.LCD_CHR)

    def printkelcd(self, message1, message2):
        self.lcd_string(message1,self.LCD_LINE_1)
        self.lcd_string(message2,self.LCD_LINE_2)

    def onDeleteWindow(self, * args):
        Gtk.main_quit(*args)

    def add_filters(self, dialog):
        filter_any = Gtk.FileFilter()
        filter_any.set_name("Any files")
        filter_any.add_pattern("*")
        dialog.add_filter(filter_any)

    def btnInputFile_clicked_cb(self, button):
        self.inputaction = 2
        dialog = Gtk.FileChooserDialog("Please choose your file", window,
                                       Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                                                                   Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        self.add_filters(dialog)
        response = dialog.run()
        if (response == Gtk. ResponseType.OK):
            self.filename = dialog.get_filename()
            image.set_from_file(self.filename)
        dialog.destroy()

    def btnInputFolder_clicked_cb(self, button):
        self.inputaction=1
        dialog = Gtk.FileChooserDialog("Please choose your folder", window,
                                       Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                                                                   Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        response = dialog.run()
        if (response == Gtk. ResponseType.OK):
            self.foldername = dialog.get_filename()
        dialog.destroy()

    def btnInputCamera_clicked_cb(self, button):
        self.inputaction=3
        print("Gambar telah diambil")

    def savetoXLSX(self):
        wb = Workbook()

        excel_data = Path("data/data.xlsx")
        if excel_data.is_file():
            book = openpyxl.load_workbook('data/data.xlsx')

            sheet = book.active
            self.lastRow = sheet['C2'].value
            self.lastNo = sheet['C3'].value
            path=os.getcwd()
            path = path.replace(" ", "%20")
            dirFiles = natsorted(os.listdir(self.foldername))

            if self.inputaction==1:
                for file in dirFiles:
                    if (file.endswith(".png") or file.endswith(".jpg") or file.endswith(".jpeg")):

                        filename = os.path.join(self.foldername+"/"+file)
                        print ("Processing file: " + filename)
                        shutil.copyfile(filename, "data/sumber/"+str(self.lastNo)+".png")
                        luasDaun = self.countAreaObject(filename, True)
                        rgbDaun = self.RGBCount(filename, True)
                        kelilingDaun = self.countKeliling(filename, True)
                        persamaanluas = self.persamaan_luas(luasDaun)
                        persamaankeliling = self.persamaan_keliling(kelilingDaun)
                        persamaanrgb = self.persamaan_rgb(rgbDaun)
                        umurluas = self.cekumur_luas(persamaanluas)
                        umurkeliling = self.cekumur_keliling(persamaankeliling)
                        umurrgb = self.cekumur_rgb(persamaanrgb)

                        sheet['A'+str(self.lastRow)]=self.lastNo
                        sheet['B'+str(self.lastRow)]=filename
                        #Luas
                        sheet['C'+str(self.lastRow)]=luasDaun[0]
                        sheet['D'+str(self.lastRow)]=luasDaun[1]
                        sheet['E'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/luasdaun/"+str(self.lastNo)+"_atas.png\",\"LINK\")"
                        sheet['F'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/luasdaun/"+str(self.lastNo)+"_bawah.png\",\"LINK\")"
                        sheet['AP'+str(self.lastRow)] = persamaanluas
                        sheet['AS'+str(self.lastRow)] = umurluas

                        #RGB
                        colRgb = 7
                        for i in rgbDaun:
                            item = i.tolist()
                            for x in item:
                                sheet.cell(row=self.lastRow, column=colRgb).value = x
                                colRgb +=1

                        sheet['AK'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/rgbdaun/"+str(self.lastNo)+".png\",\"LINK\")"
                        sheet['AR'+str(self.lastRow)] = persamaanrgb
                        sheet['AU'+str(self.lastRow)] = umurrgb

                        #Keliling
                        sheet['AL'+str(self.lastRow)]=kelilingDaun[0]
                        sheet['AM'+str(self.lastRow)]=kelilingDaun[1]
                        sheet['AN'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/kelilingdaun/"+str(self.lastNo)+"_atas.png\",\"LINK\")"
                        sheet['AO'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/kelilingdaun/"+str(self.lastNo)+"_bawah.png\",\"LINK\")"
                        sheet['AQ'+str(self.lastRow)] = persamaankeliling
                        sheet['AT'+str(self.lastRow)] = umurkeliling
                        self.lastRow +=1
                        self.lastNo +=1
                        print ("\n")
                sheet['C2'] = self.lastRow
                sheet['C3'] = self.lastNo
                book.save("data/data.xlsx")
            else:
                shutil.copyfile(self.filename, "data/sumber/"+str(self.lastNo)+".png")
                luasDaun = self.countAreaObject(self.filename, True)
                rgbDaun = self.RGBCount(self.filename, True)
                kelilingDaun = self.countKeliling(self.filename, True)
                sheet['A'+str(self.lastRow)]=self.lastNo
                sheet['B'+str(self.lastRow)]=self.filename
                #Luas
                sheet['C'+str(self.lastRow)]=luasDaun[0]
                sheet['D'+str(self.lastRow)]=luasDaun[1]
                sheet['E'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/luasdaun/"+str(self.lastNo)+"_atas.png\",\"LINK\")"
                sheet['F'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/luasdaun/"+str(self.lastNo)+"_bawah.png\",\"LINK\")"

                #RGB
                colRgb = 7
                for i in rgbDaun:
                    item = i.tolist()
                    for x in item:
                        sheet.cell(row=self.lastRow, column=colRgb).value = x
                        colRgb +=1

                sheet['AK'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/rgbdaun/"+str(self.lastNo)+".png\",\"LINK\")"
                #Keliling
                sheet['AL'+str(self.lastRow)]=kelilingDaun[0]
                sheet['AM'+str(self.lastRow)]=kelilingDaun[1]
                sheet['AN'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/kelilingdaun/"+str(self.lastNo)+"_atas.png\",\"LINK\")"
                sheet['AO'+str(self.lastRow)]="=HYPERLINK(\"file://"+path+"/data/kelilingdaun/"+str(self.lastNo)+"_bawah.png\",\"LINK\")"
                self.lastRow +=1
                self.lastNo +=1
                sheet['C2'] = self.lastRow
                sheet['C3'] = self.lastNo
                book.save("data/data.xlsx")

    def btnSave_clicked_cb(self, button):
        self.savetoXLSX()
        print ("selesai menyimpan")

    def on_btnLuasDaun_clicked(self, button):
        if (self.inputaction==1):
            #inputfromfolder
            print("test")
        else:
            jumlahluas = self.countAreaObject(self.filename, False)
            persamaanluas = self.persamaan_luas(jumlahluas)
            umurluas = self.cekumur_luas(persamaanluas)
            lblPersamaan.set_text("(" + str(umurluas) + ")")

    def on_btnRgbDaun_clicked(self, button):
        if (self.inputaction==1):
            #inputfromfolder
            print("test")
        else:
            jumlahrgb = self.RGBCount(self.filename, False)
            persamaanrgb = self.persamaan_rgb(jumlahrgb)
            umurrgb = self.cekumur_rgb(persamaanrgb)
            lblPersamaan.set_text("(" + str(umurrgb) + ")")

    def on_btnKelilingDaun_clicked(self, button):
        if (self.inputaction==1):
            #inputfromfolder
            print("test")
        else:
            jumlahkeliling = self.countKeliling(self.filename, False)
            persamaankeliling = self.persamaan_keliling(jumlahkeliling)
            umurkeliling = self.cekumur_keliling(persamaankeliling)
            lblPersamaan.set_text("(" + str(umurkeliling) + ")")

    def cekumur_keliling(self, inputvar):
        hasil = 0
        #umur 1 bulan
        if (inputvar>=0.7 and inputvar<=0.71):
            hasil = 1
        if (inputvar>=0.749000001 and inputvar<=0.77):
            hasil = 1
        if (inputvar>=0.7460000010 and inputvar<=0.8100000000):
            hasil = 1
        if (inputvar>=0.9250000100 and inputvar<=0.9370000000):
            hasil = 1

        #umur 2 bulan
        if (inputvar>=0.7100000100 and inputvar<=0.7140000000):
            hasil = 2
        if (inputvar>=0.7270000010 and inputvar<=0.7490000000):
            hasil = 2
        if (inputvar>=0.9000000100 and inputvar<=0.9250000000):
            hasil = 2
        if (inputvar>=0.9383500010 and inputvar<=0.9390000000):
            hasil = 2

        #umur 3 bulan
        if (inputvar>=0.7140000001 and inputvar<=0.7150000000):
            hasil = 3
        if (inputvar>=0.7190000010 and inputvar<=0.7270000000):
            hasil = 3
        if (inputvar>=0.8500000100 and inputvar<=0.9000000000):
            hasil = 3
        if (inputvar>=0.9370000010 and inputvar<=0.9383500000):
            hasil = 3
        if (inputvar>=0.9390000010 and inputvar<=0.9392000000):
            hasil = 3

        #umur 4 bulan
        if (inputvar>=0.7150000010 and inputvar<=0.7155000000):
            hasil = 4
        if (inputvar>=0.7170000010 and inputvar<=0.7190000000):
            hasil = 4
        if (inputvar>=0.8100000100 and inputvar<=0.8500000000):
            hasil = 4
        if (inputvar>=0.9392500010 and inputvar<=0.9400000000):
            hasil = 4

        #umur 5 bulan
        if (inputvar>=0.7155000001 and inputvar<=0.7170000000):
            hasil = 5
        if (inputvar>=0.7700000010 and inputvar<=0.7460000000):
            hasil = 5
        if (inputvar>=0.9392000001 and inputvar<=0.9392500000):
            hasil = 5

        print ("Umur daun adalah: " + str(hasil))
        self.printkelcd("Umur daun adalah", str(hasil) + " Bulan")
        return hasil

    def cekumur_luas(self, inputvar):
        hasil = 0

        #umur 1 bulan
        if (inputvar>=0.998500000001000 and inputvar<=0.998800000000000):
            hasil = 1
        if (inputvar>=0.999000000000000 and inputvar<=1.000000000000000):
            hasil = 1

        #umur 2 bulan
        if (inputvar>=0.990355240000000 and inputvar<=0.990355248900000):
            hasil = 2
        if (inputvar>=0.990355255000001 and inputvar<=0.990355256500000):
            hasil = 2
        if (inputvar>=0.990355500000000 and inputvar<=0.990355862000000):
            hasil = 2
        if (inputvar>=0.990356000001000 and inputvar<=0.990356500000000):
            hasil = 2
        if (inputvar>=0.990358000001000 and inputvar<=0.990450000000000):
            hasil = 2
        if (inputvar>=0.990500000001000 and inputvar<=0.996000000000000):
            hasil = 2
        if (inputvar>=0.996500000010000 and inputvar<=0.998500000000000):
            hasil = 2
        if (inputvar>=0.998800000001000 and inputvar<=0.999000000000000):
            hasil = 2

        #umur 3 bulan
        if (inputvar>=0.990355249000000 and inputvar<=0.990355249250000):
            hasil = 3
        if (inputvar>=0.990355249303001 and inputvar<=0.990355249305000):
            hasil = 3
        if (inputvar>=0.990355249430001 and inputvar<=0.990355249450000):
            hasil = 3
        if (inputvar>=0.990355250000000 and inputvar<=0.990355253000000):
            hasil = 3
        if (inputvar>=0.990355256500010 and inputvar<=0.990355259000000):
            hasil = 3
        if (inputvar>=0.990355260000100 and inputvar<=0.990355499999000):
            hasil = 3
        if (inputvar>=0.990355862000001 and inputvar<=0.990356000000000):
            hasil = 3
        if (inputvar>=0.990356500000010 and inputvar<=0.990358000000000):
            hasil = 3
        if (inputvar>=0.990451000000000 and inputvar<=0.990500000000000):
            hasil = 3

        #umur 4 bulan
        if (inputvar>=0.990355249260000 and inputvar<=0.990355249266999):
            hasil = 4
        if (inputvar>=0.990355249267111 and inputvar<=0.990355249267600):
            hasil = 4
        if (inputvar>=0.990355249269000 and inputvar<=0.990355249271000):
            hasil = 4
        if (inputvar>=0.990355249281001 and inputvar<=0.990355249283000):
            hasil = 4
        if (inputvar>=0.990355249285001 and inputvar<=0.990355249303000):
            hasil = 4
        if (inputvar>=0.990355249305001 and inputvar<=0.990355249340000):
            hasil = 4
        if (inputvar>=0.990355249400010 and inputvar<=0.990355249430000):
            hasil = 4
        if (inputvar>=0.990355249480001 and inputvar<=0.990355250000000):
            hasil = 4
        if (inputvar>=0.990355253000010 and inputvar<=0.990355255000000):
            hasil = 4
        if (inputvar>=0.996000000010000 and inputvar<=0.996500000000000):
            hasil = 4

        #umur 5 bulan
        if (inputvar>=0.990355249267000 and inputvar<=0.990355249267110):
            hasil = 5
        if (inputvar>=0.990355249267601 and inputvar<=0.990355249268999):
            hasil = 5
        if (inputvar>=0.990355249271001 and inputvar<=0.990355249281000):
            hasil = 5
        if (inputvar>=0.990355249283001 and inputvar<=0.990355249285000):
            hasil = 5
        if (inputvar>=0.990355249340010 and inputvar<=0.990355249400000):
            hasil = 5
        if (inputvar>=0.990355249450010 and inputvar<=0.990355249480000):
            hasil = 5
        if (inputvar>=0.990355259000010 and inputvar<=0.990355260000000):
            hasil = 5

        print ("Umur daun adalah: " + str(hasil))
        return hasil

    def cekumur_rgb(self, inputvar):
        inputvar = inputvar*100000
        hasil = 0

        #umur 1 bulan
        if (inputvar>=0.029369724484205 and inputvar<=0.029719015774401):
            hasil = 1
        if (inputvar>=0.030505103311023 and inputvar<=0.0325):
            hasil = 1
        if (inputvar>=0.039230750612453 and inputvar<=0.042599):
            hasil = 1
        if (inputvar>=0.145315385263545 and inputvar<=0.211297905573164):
            hasil = 1
        if (inputvar>=0.214007566327266 and inputvar<=0.217214368282262):
            hasil = 1
        if (inputvar>=0.21775070875511 and inputvar<=0.219367890609806):
            hasil = 1

        #umur 2 bulan
        if (inputvar>=0.0326 and inputvar<=0.034066493664224):
            hasil = 2
        if (inputvar>=0.055999 and inputvar<=0.063999):
            hasil = 2
        if (inputvar>=0.079999 and inputvar<=0.139999):
            hasil = 2
        if (inputvar>=0.211586807805377 and inputvar<=0.213999):
            hasil = 2
        if (inputvar>=0.217493983284268 and inputvar<=0.217699):
            hasil = 2
        if (inputvar>=0.219406643722113 and inputvar<=0.219799):
            hasil = 2
        if (inputvar>=801 and inputvar<=1090):
            hasil = 2
        if (inputvar>=1250 and inputvar<=2000):
            hasil = 2
        if (inputvar>=3562.99 and inputvar<=3566):
            hasil = 2
        if (inputvar>=3610 and inputvar<=3610.469):
            hasil = 2
        if (inputvar>=3611 and inputvar<=3627):
            hasil = 2
        if (inputvar>=3656 and inputvar<=3668):
            hasil = 2
        if (inputvar>=3669 and inputvar<=12000):
            hasil = 2

        #umur 3 bulan
        if (inputvar>=0.02 and inputvar<=0.021):
            hasil = 3
        if (inputvar>=0.0273 and inputvar<=0.0285):
            hasil = 3
        if (inputvar>=2 and inputvar<=80):
            hasil = 3
        if (inputvar>=2101 and inputvar<=3220):
            hasil = 3
        if (inputvar>=3261 and inputvar<=3295):
            hasil = 3
        if (inputvar>=3321 and inputvar<=3370):
            hasil = 3
        if (inputvar>=3421 and inputvar<=3563):
            hasil = 3
        if (inputvar>=3583 and inputvar<=3609):
            hasil = 3
        if (inputvar>=3609.5 and inputvar<=3609.9):
            hasil = 3
        if (inputvar>=3610.47 and inputvar<=3611):
            hasil = 3
        if (inputvar>=3627.1 and inputvar<=3639.999):
            hasil = 3
        if (inputvar>=3663 and inputvar<=3668.999):
            hasil = 3

        #umur 4 bulan
        if (inputvar>=0.0001 and inputvar<=0.0104):
            hasil = 4
        if (inputvar>=0.0108 and inputvar<=0.012):
            hasil = 4
        if (inputvar>=0.0137 and inputvar<=0.0138):
            hasil = 4
        if (inputvar>=0.021 and inputvar<=0.0215):
            hasil = 4
        if (inputvar>=0.022 and inputvar<=0.0225):
            hasil = 4
        if (inputvar>=0.026 and inputvar<=0.0269):
            hasil = 4
        if (inputvar>=0.0285 and inputvar<=0.02935):
            hasil = 4
        if (inputvar>=0.03 and inputvar<=0.0305):
            hasil = 4
        if (inputvar>=81 and inputvar<=800):
            hasil = 4
        if (inputvar>=1091 and inputvar<=1249):
            hasil = 4
        if (inputvar>=3221 and inputvar<=3260):
            hasil = 4
        if (inputvar>=3371 and inputvar<=3420):
            hasil = 4
        if (inputvar>=3566.1 and inputvar<=3582.99):
            hasil = 4
        if (inputvar>=3609.1 and inputvar<=3609.499):
            hasil = 4
        if (inputvar>=3609.91 and inputvar<=3609.9):
            hasil = 4

        #umur 5 bulan
        if (inputvar>=0.01199 and inputvar<=0.013699):
            hasil = 5
        if (inputvar>=0.01381 and inputvar<=0.019999):
            hasil = 5
        if (inputvar>=0.02151 and inputvar<=0.021999):
            hasil = 5
        if (inputvar>=0.02551 and inputvar<=0.02559):
            hasil = 5
        if (inputvar>=0.027 and inputvar<=0.027299):
            hasil = 5
        if (inputvar>=0.034067 and inputvar<=0.039):
            hasil = 5
        if (inputvar>=0.0426 and inputvar<=0.055998):
            hasil = 5
        if (inputvar>=0.064 and inputvar<=0.07998):
            hasil = 5
        if (inputvar>=0.2198 and inputvar<=1.99):
            hasil = 5
        if (inputvar>=3628 and inputvar<=3655.99):
            hasil = 5
        print ("Umur daun adalah: " + str(hasil))
        return hasil

    def persamaan_rgb(self, inputvar):
        #tahap penjumlahan
        inputvar2 = cp.deepcopy(inputvar)
        indexItem = 0
        for i in inputvar:
            item = i.tolist()
            sumofItem = 0
            for x in item:
                x1= x*0.01
                sumofItem = sumofItem + x1
            inputvar2[indexItem]=sumofItem
            indexItem +=1

        v11=1.4004
        v21=-0.2972
        v31=1.5537
        v41=-1.2604
        v51=0.6302
        v12=-3.5916
        v22=0.7617
        v32=-2.7840
        v42=2.2625
        v52=2.0473
        v13=1.2331
        v23=1.5439
        v33=-1.9324
        v43=7.1158
        v53=1.9876
        v14=0.8985
        v24=-0.0452
        v34=-0.9155
        v44=-2.7155
        v54=-1.8111
        v15=1.8386
        v25=-1.0646
        v35=-1.0175
        v45=-0.2514
        v55=0.3470
        v16=-1.1064
        v26=4.5201
        v36=-1.1779
        v46=3.0497
        v56=-0.4884
        v17=-3.3348
        v27=-0.2015
        v37=2.0500
        v47=-0.0438
        v57=-0.3871
        v18=0.7826
        v28=0.6025
        v38=-3.0437
        v48=1.9025
        v58=1.7143
        v19=1.1794
        v29=-2.5524
        v39=-5.2434
        v49=-0.2866
        v59=2.0611
        v110=-2.9668
        v210=-3.6863
        v310=0.5320
        v410=-1.7164
        v510=0.4906
        bz1=0.8734
        bz2=-1.7877
        bz3=1.0375
        bz4=-5.1055
        bz5=-5.6914
        w1=-3.3221
        w2=-0.5377
        w3=0.7797
        w4=-1.7300
        w5=6.3210
        b0=4.2648
        e=10

        #tahap pembobotan
        z_in1=w1+((inputvar2[0]*v11)+(inputvar2[1]*v12)+(inputvar2[2]*v13)+(inputvar2[3]*v14)+(inputvar2[4]*v15)+(inputvar2[5]*v16)+(inputvar2[6]*v17)+(inputvar2[7]*v18)+(inputvar2[8]*v19)+(inputvar2[9]*v110))
        z_in2=w2+((inputvar2[0]*v21)+(inputvar2[1]*v22)+(inputvar2[2]*v23)+(inputvar2[3]*v24)+(inputvar2[4]*v25)+(inputvar2[5]*v26)+(inputvar2[6]*v27)+(inputvar2[7]*v28)+(inputvar2[8]*v29)+(inputvar2[9]*v210))
        z_in3=w3+((inputvar2[0]*v31)+(inputvar2[1]*v32)+(inputvar2[2]*v33)+(inputvar2[3]*v34)+(inputvar2[4]*v35)+(inputvar2[5]*v36)+(inputvar2[6]*v37)+(inputvar2[7]*v38)+(inputvar2[8]*v39)+(inputvar2[9]*v310))
        z_in4=w4+((inputvar2[0]*v41)+(inputvar2[1]*v42)+(inputvar2[2]*v43)+(inputvar2[3]*v44)+(inputvar2[4]*v45)+(inputvar2[5]*v46)+(inputvar2[6]*v47)+(inputvar2[7]*v48)+(inputvar2[8]*v49)+(inputvar2[9]*v410))
        z_in5=w5+((inputvar2[0]*v51)+(inputvar2[1]*v52)+(inputvar2[2]*v53)+(inputvar2[3]*v54)+(inputvar2[4]*v55)+(inputvar2[5]*v56)+(inputvar2[6]*v57)+(inputvar2[7]*v58)+(inputvar2[8]*v59)+(inputvar2[9]*v510))

        #fungsi aktivasi
        z1=1/(1+pow(e,-(z_in1)))
        z2=1/(1+pow(e,-(z_in2)))
        z3=1/(1+pow(e,-(z_in3)))
        z4=1/(1+pow(e,-(z_in4)))
        z5=1/(1+pow(e,-(z_in5)))

        #output
        y_in=b0+((z1*bz1)+(z2*bz2)+(z3*bz3)+(z4*bz4)+(z5*bz5))
        result=1/(1+pow(e,-(y_in)))
        print("Hasilt persamaan: " + str(result))
        return result

    def persamaan_keliling(self, inputvar):
        var11=2.0157
        var21=-2.5408
        var31=2.9785
        var41=0.0689
        var51=-4.3687
        var12=-1.8502
        var22=0.5244
        var32=0.3451
        var42=0.1044
        var52=2.0059

        bz1=-0.7890
        bz2=0.4114
        bz3=-1.6262
        bz4=3.3549
        bz5=-0.3437

        w1=-2.4535
        w2=-2.9795
        w3=3.2752
        w4=0.8474
        w5=4.2016

        b0=-0.5387
        e=10

        #tahap pembobotan
        z_in1=w1+((inputvar[0]*var11)+(inputvar[1]*var12))
        z_in2=w2+((inputvar[0]*var21)+(inputvar[1]*var22))
        z_in3=w3+((inputvar[0]*var31)+(inputvar[1]*var32))
        z_in4=w4+((inputvar[0]*var41)+(inputvar[1]*var42))
        z_in5=w5+((inputvar[0]*var51)+(inputvar[1]*var52))

        #fungsi aktivasi
        z1=1/(1+pow(e,-(z_in1)))
        z2=1/(1+pow(e,-(z_in2)))
        z3=1/(1+pow(e,-(z_in3)))
        z4=1/(1+pow(e,-(z_in4)))
        z5=1/(1+pow(e,-(z_in5)))

        #output
        y_in=b0+((z1*bz1)+(z2*bz2)+(z3*bz3)+(z4*bz4)+(z5*bz5))
        result=1/(1+pow(e,-(y_in)))
        print("Hasilt persamaan: " + str(result))
        return result

    def persamaan_luas(self, inputvar):
        inputvar[0] = inputvar[0]*0.1
        inputvar[1] = inputvar[1]*0.1
        v11=0.5430
        v21=1.6464
        v31=-5.5055
        v41=0.6884
        v51=-0.5672
        v12=6.3309
        v22=-4.7068
        v32=-7.0952
        v42=-5.5650
        v52=-1.6284
        bz1=-0.7986
        bz2=1.6986
        bz3=-3.3620
        bz4=1.4270
        bz5=-9.4362
        w1=-6.6344
        w2=-1.6962
        w3=4.1913
        w4=6.2366
        w5=-2.4389
        b0=2.8101
        e=10

        #tahap pembobotan
        z_in1=w1+((inputvar[0]*v11)+(inputvar[1]*v12))
        z_in2=w2+((inputvar[0]*v21)+(inputvar[1]*v22))
        z_in3=w3+((inputvar[0]*v31)+(inputvar[1]*v32))
        z_in4=w4+((inputvar[0]*v41)+(inputvar[1]*v42))
        z_in5=w5+((inputvar[0]*v51)+(inputvar[1]*v52))

        #fungsi aktivasi
        z1=1/(1+pow(e,-(z_in1)))
        z2=1/(1+pow(e,-(z_in2)))
        z3=1/(1+pow(e,-(z_in3)))
        z4=1/(1+pow(e,-(z_in4)))
        z5=1/(1+pow(e,-(z_in5)))

        #output
        y_in=b0+((z1*bz1)+(z2*bz2)+(z3*bz3)+(z4*bz4)+(z5*bz5))
        result=1/(1+pow(e,-(y_in)))
        print("Hasilt persamaan: " + str(result))
        return result

    def RGBCount(self, filename, saveImage):
        global rgb1, rgb2, rgb3, rgb4, rgb5, rgb6, rgb7, rgb8, rgb9, rgb10
        img = cv2.imread(filename)
        rgb_read=cv2.imread(filename)
        height, width = img.shape[:2]
        #get rgb
        #point 1
        rgb1 = rgb_read[int(height * .5)-20,0+100]
        #point 2
        rgb2 = rgb_read[int(height * .5)-20,50+int((width-150) * .30)]
        #point 3
        rgb3 = rgb_read[int(height * .5)-20,50+int((width-150) * .55)]
        #point 4
        rgb4 = rgb_read[int(height * .5)-20,50+int((width-150) * .70)]
        #point 5
        rgb5 = rgb_read[int(height * .5)-20,50+int((width-150) * .80)]

        #point 6
        rgb6 = rgb_read[int(height * .5)+20,0+100]
        #point 7
        rgb7 = rgb_read[int(height * .5)+20,50+int((width-150) * .30)]
        #point 8
        rgb8 = rgb_read[int(height * .5)+20,50+int((width-150) * .55)]
        #point 9
        rgb9 = rgb_read[int(height * .5)+20,50+int((width-150) * .70)]
        #point 10
        rgb10 = rgb_read[int(height * .5)+20,50+int((width-150) * .80)]

        #point 1
        cv2.line(img, (0+100,int(height * .5)-20),(0+100,int(height * .5)-20),(0,0,255),5)
        #point 2
        cv2.line(img, (100+int((width-150) * .30),int(height * .5)-20),(100+int((width-150) * .30),int(height * .5)-20),(0,0,255),5)
        #point 3
        cv2.line(img, (100+int((width-150) * .55),int(height * .5)-20),(100+int((width-150) * .55),int(height * .5)-20),(0,0,255),5)
        #point 4
        cv2.line(img, (100+int((width-150) * .70),int(height * .5)-20),(100+int((width-150) * .70),int(height * .5)-20),(0,0,255),5)
        #point 5
        cv2.line(img, (100+int((width-150) * .80),int(height * .5)-20),(100+int((width-150) * .80),int(height * .5)-20),(0,0,255),5)

        #point 6
        cv2.line(img, (0+100,int(height * .5)+20),(0+100,int(height * .5)+20),(0,0,255),5)
        #point 7
        cv2.line(img, (100+int((width-150) * .30),int(height * .5)+20),(100+int((width-150) * .30),int(height * .5)+20),(0,0,255),5)
        #point 8
        cv2.line(img, (100+int((width-150) * .55),int(height * .5)+20),(100+int((width-150) * .55),int(height * .5)+20),(0,0,255),5)
        #point 9
        cv2.line(img, (100+int((width-150) * .70),int(height * .5)+20),(100+int((width-150) * .70),int(height * .5)+20),(0,0,255),5)
        #point 10
        cv2.line(img, (100+int((width-150) * .80),int(height * .5)+20),(100+int((width-150) * .80),int(height * .5)+20),(0,0,255),5)

        if saveImage==True:
            cv2.imwrite("data/rgbdaun/"+ str(self.lastNo)+".png", img)
        else:
            cv2.imwrite("rgbdaun.png", img)

        #image.set_from_file("rgbdaun.png")

        print("RGB Titik ke 1:" ,rgb1)
        print("RGB Titik ke 2:" ,rgb2)
        print("RGB Titik ke 3:" ,rgb3)
        print("RGB Titik ke 4:" ,rgb4)
        print("RGB Titik ke 5:" ,rgb5)
        print("RGB Titik ke 6:" ,rgb6)
        print("RGB Titik ke 7:" ,rgb7)
        print("RGB Titik ke 8:" ,rgb8)
        print("RGB Titik ke 9:" ,rgb9)
        print("RGB Titik ke 10:" ,rgb10)

        lblHasil.set_text("Titik ke 1: " + str(rgb1) + "\n" +
                          "Titik ke 2: " + str(rgb2) + "\n" +
                          "Titik ke 3: " + str(rgb3) + "\n" +
                          "Titik ke 4: " + str(rgb4) + "\n" +
                          "Titik ke 5: " + str(rgb5) + "\n" +
                          "Titik ke 6: " + str(rgb6) + "\n" +
                          "Titik ke 7: " + str(rgb7) + "\n" +
                          "Titik ke 8: " + str(rgb8) + "\n" +
                          "Titik ke 9: " + str(rgb9) + "\n" +
                          "Titik ke 10: " + str(rgb10))
        result = [rgb1, rgb2,rgb3,rgb4,rgb5, rgb6, rgb7, rgb8, rgb9, rgb10]
        return result

    def countKeliling(self, filename, saveImage):
        global kelilingAtas, kelilingBawah
        #reading the image
        image = cv2.imread(filename)

        edged = cv2.Canny(image, 70, 150)

        count_keliling = cv2.countNonZero(edged)

        height, width = edged.shape[:2]
        # Let's get the starting pixel coordiantes (top left of cropped top)
        start_row, start_col = int(0), int(0)
        # Let's get the ending pixel coordinates (bottom right of cropped top)
        end_row, end_col = int(height * .5), int(width)
        cropped_top = edged[start_row:end_row , start_col:end_col]
        if saveImage==True:
            cv2.imwrite("data/kelilingdaun/"+str(self.lastNo)+"_atas.png",cropped_top)
        else:
            cv2.imwrite("countourTop.png",cropped_top)
        h_top, w_top = edged.shape[:2]
        cons_keliling = 33 #19cmx+(2*7cm) 7cm = 14cm/2 satu sisi tidak dihitung karna dibagi 2
        #dapatkan ukuan pixel per cm
        cons_divided = ((2*h_top) + w_top)/cons_keliling
        cropped_top = np.array(cropped_top)

        count_keliling = cv2.countNonZero(cropped_top)
        kelilingAtas=round(count_keliling/cons_divided)

        # Let's get the starting pixel coordiantes (top left of cropped bottom)
        start_row, start_col = int(height * .5), int(0)
        # Let's get the ending pixel coordinates (bottom right of cropped bottom)
        end_row, end_col = int(height), int(width)
        cropped_bot = edged[start_row:end_row , start_col:end_col]
        if saveImage==True:
            cv2.imwrite("data/kelilingdaun/"+str(self.lastNo)+"_bawah.png",cropped_bot)
        else:
            cv2.imwrite("countourBot.png",cropped_bot)
        h_bot, w_bot = cropped_bot.shape[:2]
        cropped_bot = np.array(cropped_bot)

        count_keliling = cv2.countNonZero(cropped_bot)
        kelilingBawah=round(count_keliling/cons_divided)

        print("Keliling daun bagian atas: ", kelilingAtas)
        print("Keliling daun bagian bawah: ", kelilingBawah)
        lblHasil.set_text("(" + str(kelilingAtas) + "," + str(kelilingBawah)+ ")")
        result = [kelilingAtas, kelilingBawah]
        return result

    def countAreaObject(self, filename, saveImage):
        global luasdauntop, luasdaunbot

        img = cv2.imread(filename)

        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        gray = cv2.medianBlur(gray, 5)
        #cv2.imwrite("gray.jpg",gray)
        ret, thresh = cv2.threshold(gray, 70, 255,cv2.THRESH_BINARY)

        height, width = thresh.shape[:2]
        # Let's get the starting pixel coordiantes (top left of cropped top)
        start_row, start_col = int(0), int(0)
        # Let's get the ending pixel coordinates (bottom right of cropped top)
        end_row, end_col = int(height * .5), int(width)
        cropped_top = thresh[start_row:end_row , start_col:end_col]

        h_top, w_top = cropped_top.shape[:2]

        cons_luas = 133 #19cmx7cm 7cm = 14cm/2
        #dapatkan ukuan pixel per cm
        cons_divided = (h_top * w_top)/cons_luas

        cropped_top = np.array(cropped_top)
        if saveImage==True:
            cv2.imwrite("data/luasdaun/"+str(self.lastNo)+"_atas.png", cropped_top)
        else:
            cv2.imwrite("cropped_top.png", cropped_top)

        count_white_top = cv2.countNonZero(cropped_top)
        luasdauntop = (h_top * w_top)- count_white_top
        luasdauntop = round(luasdauntop/cons_divided)
        print("Luas daun bagian atas: ", luasdauntop)

        # Let's get the starting pixel coordiantes (top left of cropped bottom)
        start_row, start_col = int(height * .5), int(0)
        # Let's get the ending pixel coordinates (bottom right of cropped bottom)
        end_row, end_col = int(height), int(width)
        cropped_bot = thresh[start_row:end_row , start_col:end_col]
        h_bot, w_bot = cropped_bot.shape[:2]
        cropped_bot = np.array(cropped_bot)

        if saveImage==True:
            cv2.imwrite("data/luasdaun/"+str(self.lastNo)+"_bawah.png", cropped_bot)
        else:
            cv2.imwrite("cropped_bot.png", cropped_bot)
        count_white_bot = cv2.countNonZero(cropped_bot)
        luasdaunbot = (h_bot * w_bot)- count_white_bot
        luasdaunbot = round(luasdaunbot/cons_divided)

        print("Luas daun bagian bawah: ", luasdaunbot)
        lblHasil.set_text("(" + str(luasdauntop) + "," + str(luasdaunbot)+ ")")
        result = [luasdauntop,luasdaunbot]
        return result

    def thresholdingTest(self, filename):
        #reading the image
        image = cv2.imread(filename)
        gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        gray = cv2.medianBlur(gray, 5)
        cv2.imwrite("gray.jpg",gray)
        for i in range(127):
            ret, thresh = cv2.threshold(gray, i, 255,cv2.THRESH_BINARY)
            cv2.imwrite("thresh"+str(i)+".jpg",thresh)
            th2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
            cv2.imwrite("adaptivethresh"+str(i)+".jpg",thresh)

        print ("selesai")
    def background_remover4(self, filename):
        # Read image
        im_in = cv2.imread(filename, cv2.IMREAD_GRAYSCALE);

        # Threshold.
        # Set values equal to or above 220 to 0.
        # Set values below 220 to 255.

        th, im_th = cv2.threshold(im_in, 70, 255, cv2.THRESH_BINARY_INV);

        # Copy the thresholded image.
        im_floodfill = im_th.copy()

        # Mask used to flood filling.
        # Notice the size needs to be 2 pixels than the image.
        h, w = im_th.shape[:2]
        mask = np.zeros((h+2, w+2), np.uint8)

        # Floodfill from point (0, 0)
        cv2.floodFill(im_floodfill, mask, (0,0), 255);

        # Invert floodfilled image
        im_floodfill_inv = cv2.bitwise_not(im_floodfill)
        test = cv2.bitwise_and(im_floodfill)
        test2 = cv2.bitwise_and(im_floodfill_inv)
        # Combine the two images to get the foreground.
        im_out = im_th | im_floodfill_inv

        # Display images.
        cv2.imwrite("Thresholded Image.jpg", im_th)
        cv2.imwrite("Floodfilled Image.jpg", im_floodfill)
        cv2.imwrite("Inverted Floodfilled Image.jpg", im_floodfill_inv)
        cv2.imwrite("Foreground.jpg", im_out)
        cv2.imwrite("Foreground1.jpg", test)
        cv2.imwrite("Foreground2.jpg", test2)

    def background_remover3(self, img):
        stencil = np.zeros(img.shape).astype(img.dtype)
        #(_, cnts, _) = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        contours = [np.array([[100, 180], [200, 280], [200, 180]]), np.array([[280, 70], [12, 20], [80, 150]])]
        color = [255, 255, 255]
        cv2.fillPoly(stencil, contours, color)
        result = cv2.bitwise_and(img, stencil)
        cv2.imwrite("result.jpg", result)

    def background_remover2(self, filename):
        original_image = cv2.imread(filename)
        # 1 Convert to gray & Normalize
        gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
        gray_img = sharp(cv2.get_contrasted(gray_img))
        gray_img = normalize(gray_img, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)
        cv2.imwrite("Gray.jpg", gray_img)

        # 2 Find Threshold
        gray_blur = cv2.GaussianBlur(gray_img, (7, 7), 0)
        adapt_thresh_im = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 1)
        max_thresh, thresh_im = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
        thresh = cv2.bitwise_or(adapt_thresh_im, thresh_im)

        # 3 Dilate
        gray = cv2.Canny(thresh, 88, 400, apertureSize=3)
        gray = cv2.dilate(gray, None, iterations=8)
        gray = cv2.erode(gray, None, iterations=8)
        cv2.imwrite("Trheshold.jpg", gray)

        # 4 Flood
        contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contour_info = []
        for c in contours:
            contour_info.append((
                c,
                cv2.isContourConvex(c),
                cv2.contourArea(c),
            ))
        contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)
        max_contour = contour_info[0]
        holes = np.zeros(gray_img.shape, np.uint8)
        drawContours(holes, max_contour, 0, 255, -1)
        cv2.imwrite("Holes.jpg", holes)

        mask = cv2.GaussianBlur(holes, (15, 15), 0)
        mask = np.dstack([mask] * 3)  # Create 3-channel alpha mask

        mask = mask.astype('float32') / 255.0  # Use float matrices,
        img = original_image.astype('float32') / 255.0  # for easy blending
        masked = (mask * img) + ((1 - mask) * (0,0,1))  # Blend
        masked = (masked * 255).astype('uint8')

        cv2.imwrite("Maked.jpg", masked)

    def get_holes(self, image, thresh):
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        im_bw = cv2.threshold(gray, thresh, 255, cv2.THRESH_BINARY)[1]
        im_bw_inv = cv2.bitwise_not(im_bw)

        (_, cnts, _) = cv2.findContours(im_bw_inv.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        for cnt in cnts:
            cv2.drawContours(im_bw_inv, [cnt], 0, 255, -1)
        cv2.imwrite("testss.jpg", im_bw_inv)
        nt = cv2.bitwise_not(im_bw)
        im_bw_inv = cv2.bitwise_or(im_bw_inv, nt)
        return im_bw_inv

    def remove_background(self, image, thresh, scale_factor=.25, kernel_range=range(1, 15), border=None):
        border = border or kernel_range[-1]

        holes = self.get_holes(image, thresh)
        small = cv2.resize(holes, None, fx=scale_factor, fy=scale_factor)
        bordered = cv2.copyMakeBorder(small, border, border, border, border, cv2.BORDER_CONSTANT)

        for i in kernel_range:
            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2*i+1, 2*i+1))
            bordered = cv2.morphologyEx(bordered, cv2.MORPH_CLOSE, kernel)

        unbordered = bordered[border: -border, border: -border]
        mask = cv2.resize(unbordered, (image.shape[1], image.shape[0]))
        fg = cv2.bitwise_and(image, image, mask=mask)
        return fg

    def background_remover(self, imgo):
        height, width = imgo.shape[:2]

        #Create a mask holder
        mask = np.zeros(imgo.shape[:2],np.uint8)

        #Grab Cut the object
        bgdModel = np.zeros((1,65),np.float64)
        fgdModel = np.zeros((1,65),np.float64)

        #Hard Coding the Rect… The object must lie within this rect.
        rect = (10,10,width-30,height-30)
        cv2.grabCut(imgo,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
        mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
        img1 = imgo*mask[:,:,np.newaxis]

        #Get the background
        background = imgo - img1

        #Change all pixels in the background that are not black to white
        background[np.where((background > [0,0,0]).all(axis = 2))] = [255,255,255]

        #Add the background and the image
        final = background + img1
        return final

    def getMultiImage(self):
        camera = cv2.VideoCapture(0)

        for i in range(10):
            print ("Taking image")
            retval, camera_capture = camera.read()
            file = "tmp.png"
            file = self.checkfile(file)
            cv2.imwrite(file, camera_capture)
        del(camera)

    def checkfile(self, path):
         path      = os.path.expanduser(path)

         if not os.path.exists(path):
            return path

         root, ext = os.path.splitext(os.path.expanduser(path))
         dir       = os.path.dirname(root)
         fname     = os.path.basename(root)
         candidate = fname+ext
         index     = 0
         ls        = set(os.listdir(dir))
         while candidate in ls:
                 candidate = "{}_{}{}".format(fname,index,ext)
                 index    += 1
         return os.path.join(dir,candidate)

builder.connect_signals(mainWindowHandler())

Gtk.main()


import datetime
import icu
from collections import defaultdict
from copy import deepcopy

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.forms import ModelForm, CheckboxSelectMultiple, TextInput, DateInput, BooleanField, ModelMultipleChoiceField
from django.template import defaultfilters

from urnik.templatetags.tags import dan_tozilnik_mnozina
from urnik.utils import teden_dneva
from .layout import nastavi_sirine_srecanj, nastavi_barve

MIN_URA, MAX_URA = 7, 20
ENOTA_VISINE = 1 / (MAX_URA - MIN_URA)
DNEVI = ('ponedeljek', 'torek', 'sreda', 'četrtek', 'petek')
ENOTA_SIRINE = 1 / len(DNEVI)
DAYS_IN_WEEK = 7

collator = icu.Collator.createInstance(icu.Locale(settings.LANGUAGE_CODE))

class OsebaQuerySet(models.QuerySet):

    def aktivni(self):
        slusatelji = self.filter(predmeti__isnull=False)
        ucitelji = self.filter(srecanja__isnull=False)
        return (slusatelji | ucitelji).distinct()

class Oseba(models.Model):
    ime = models.CharField(max_length=192)
    priimek = models.CharField(max_length=192)
    email = models.EmailField(blank=True)
    domaca_stran = models.CharField(max_length=192, blank=True)
    user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name='oseba')

    objects = OsebaQuerySet.as_manager()

    class Meta:
        verbose_name_plural = 'osebe'
        default_related_name = 'osebe'
        ordering = ('priimek', 'ime')

    @property
    def priimek_ime(self):
        if self.ime:
            return '{} {}'.format(self.priimek, self.ime)
        else:
            return self.priimek

    def __str__(self):
        if self.ime:
            return '{} {}'.format(self.ime, self.priimek)
        else:
            return self.priimek

    def __lt__(self, other):
        return self.vrstni_red() < other.vrstni_red()

    def vrstni_red(self):
        if self.ime:
            return (collator.getSortKey(self.priimek), collator.getSortKey(self.ime))
        else:
            return (collator.getSortKey(self.priimek), )

    def vsa_srecanja(self, semester):
        return (self.srecanja.filter(semester=semester) | semester.srecanja.filter(predmet__slusatelji=self)).distinct()

class Letnik(models.Model):
    MATEMATIKA, FIZIKA = 'M', 'F'
    ODDELEK = (
        (MATEMATIKA, 'matematika'), (FIZIKA, 'fizika'),
    )
    oddelek = models.CharField(max_length=1, choices=ODDELEK, blank=True)
    smer = models.CharField(max_length=192)
    leto = models.CharField(max_length=192, null=True)
    kratica = models.CharField(max_length=64)

    class Meta:
        verbose_name_plural = 'letniki'
        default_related_name = 'letniki'
        ordering = ('oddelek', 'smer', 'leto')

    def __str__(self):
        if self.leto:
            return '{}, {}'.format(self.smer, self.leto)
        else:
            return self.smer

    def srecanja(self, semester):
        return semester.srecanja.filter(predmet__letniki=self).distinct()

class UcilnicaQuerySet(models.QuerySet):
    VELIKOST = [
        ('majhna', 'majhna'),
        ('obicajna', 'običajna'),
        ('velika', 'velika'),
    ]

    # TODO: fix this mess
    def ustrezne(self, tip, oddelek):
        if oddelek == 'MAT':
            obicajna = Ucilnica.MATEMATICNA
        else:
            obicajna = Ucilnica.FIZIKALNA
        if tip == 'velika':
            ustrezne = self.filter(tip=obicajna, velikost__gte=60)
            alternative = self.filter(velikost__gte=45)
        elif tip == 'obicajna':
            ustrezne = self.filter(tip=obicajna, velikost__gte=30, velikost__lt=60)
            alternative = self.filter(velikost__gte=24, velikost__lt=80)
        elif tip == 'majhna':
            ustrezne = self.filter(tip=obicajna, velikost__lt=30)
            alternative = self.filter(velikost__lt=40)
        elif tip == 'racunalniska':
            ustrezne = self.filter(tip=Ucilnica.RACUNALNISKA)
            alternative = self.none()
        elif tip == 'praktikum':
            ustrezne = self.filter(tip=Ucilnica.PRAKTIKUM)
            alternative = self.none()
        else:
            ustrezne = self.none()
            alternative = self.filter(velikost__isnull=True)

        return list(ustrezne), list(alternative.exclude(pk__in=ustrezne))

    def ustrezne_velikosti(self, velikosti):
        if not velikosti:
            return self.all()
        ustrezne = self.none()
        if 'majhna' in velikosti:
            ustrezne |= self.filter(velikost__lt=30)
        if 'obicajna' in velikosti:
            ustrezne |= self.filter(velikost__gte=30, velikost__lt=60)
        if 'velika' in velikosti:
            ustrezne |= self.filter(velikost__gte=60)
        return ustrezne

    def objavljene(self):
        return self.filter(tip__in=Ucilnica.OBJAVLJENI_TIPI)

class Ucilnica(models.Model):
    MATEMATICNA, FIZIKALNA, RACUNALNISKA = 'M', 'F', 'R'
    PRAKTIKUM, PISARNA, ZUNANJA = 'P', 'K', 'X'
    TIP = (
        (MATEMATICNA, 'matematična'), (FIZIKALNA, 'fizikalna'),
        (RACUNALNISKA, 'računalniška'), (PRAKTIKUM, 'praktikum'),
        (PISARNA, 'pisarna'), (ZUNANJA, 'zunanja'),
    )
    OBJAVLJENI_TIPI = (
        MATEMATICNA,
        FIZIKALNA,
        RACUNALNISKA,
        PRAKTIKUM,
    )

    tip = models.CharField(max_length=1, choices=TIP, default=ZUNANJA, blank=True)
    oznaka = models.CharField(max_length=192, unique=True)
    kratka_oznaka = models.CharField(max_length=10, blank=True)
    velikost = models.PositiveSmallIntegerField(blank=True, null=True)
    objects = UcilnicaQuerySet.as_manager()

    class Meta:
        verbose_name_plural = 'ucilnice'
        default_related_name = 'ucilnice'
        ordering = ('oznaka',)

    def __str__(self):
        return self.oznaka

    def __lt__(self, other):
        return self.vrstni_red() < other.vrstni_red()

    def kratko_ime(self):
        if self.kratka_oznaka:
            return self.kratka_oznaka
        return self.oznaka

    def vrstni_red(self):
        return collator.getSortKey(self.oznaka)

class Predmet(models.Model):
    ime = models.CharField(max_length=192)
    kratica = models.CharField(max_length=64)
    stevilo_studentov = models.PositiveSmallIntegerField(blank=True, null=True)
    slusatelji = models.ManyToManyField('urnik.Oseba', blank=True)
    letniki = models.ManyToManyField('urnik.Letnik', blank=True)

    class Meta:
        verbose_name_plural = 'predmeti'
        default_related_name = 'predmeti'
        ordering = ('ime',)

    def __str__(self):
        return self.ime

    def __lt__(self, other):
        return self.vrstni_red() < other.vrstni_red()

    def vrstni_red(self):
        return collator.getSortKey(self.ime)

    def kratice_letnikov(self):
        return ', '.join(letnik.kratica for letnik in self.letniki.all())

class SemesterQuerySet(models.QuerySet):
    def v_obdobju(self, od, do):
        return self.filter(do__gte=od, od__lte=do)

class Semester(models.Model):
    ime = models.CharField(max_length=192)
    od = models.DateField()
    do = models.DateField()
    objavljen = models.BooleanField(default=False)

    objects = SemesterQuerySet.as_manager()

    class Meta:
        verbose_name_plural = 'semestri'
        ordering = ('od',)

    def __str__(self):
        return self.ime

    def pripravi_kopijo(self):
        novi_semester = Semester.objects.create(
            ime=self.ime + ' (kopija)',
            od=self.od + datetime.timedelta(days=365),
            do=self.do + datetime.timedelta(days=365),
            objavljen=False
        )
        for srecanje in self.srecanja.all():
            srecanje.podvoji(novi_semester=novi_semester)
        return novi_semester

    def prihodnji_tedni(self):
        razlika = datetime.timedelta(weeks=1)
        tedni = set()
        danes = datetime.date.today()
        dan = danes
        while dan < self.do:
            tedni.add(teden_dneva(dan))
            dan += razlika
        if self.do >= danes:
            tedni.add(teden_dneva(self.do))
        return tedni

class SrecanjeQuerySet(models.QuerySet):

    def odlozena(self):
        return self.filter(dan__isnull=True, ura__isnull=True).select_related('ucilnica', 'predmet').prefetch_related('ucitelji')

    def neodlozena(self):
        return self.filter(dan__isnull=False, ura__isnull=False)

    def prekrivanja(self):
        prekrivanja_ucilnic = defaultdict(set)
        prekrivanja_oseb = defaultdict(set)
        srecanja = self.neodlozena().select_related(
            'ucilnica',
        ).prefetch_related(
            'ucitelji',
            'predmet__slusatelji'
        )
        for srecanje in srecanja:
            for ura in range(srecanje.ura, srecanje.ura + srecanje.trajanje):
                for ucitelj in srecanje.ucitelji.all():
                    prekrivanja_oseb[(ucitelj, srecanje.dan, ura)].add(srecanje)
                if srecanje.predmet:
                    for slusatelj in srecanje.predmet.slusatelji.all():
                        prekrivanja_oseb[(slusatelj, srecanje.dan, ura)].add(srecanje)
                prekrivanja_ucilnic[(srecanje.ucilnica, srecanje.dan, ura)].add(srecanje)
        prekrivanja_po_tipih = {
            'Prekrivanja učilnic': prekrivanja_ucilnic,
            'Prekrivanja oseb': prekrivanja_oseb,
        }
        return {
            opis_tipa: {
                prekrivanje: srecanja
                for prekrivanje, srecanja in prekrivanja_tipa.items()
                if len(srecanja) > 1 and str(prekrivanje[0]).strip() != 'X'
            }
            for opis_tipa, prekrivanja_tipa in prekrivanja_po_tipih.items()
        }

    def urnik(self, barve=[]):
        self = self.neodlozena(
        ).order_by(
            'dan', 'ura', 'trajanje'
        ).distinct(
        ).select_related(
            'ucilnica', 'predmet'
        ).prefetch_related(
            'predmet__letniki', 'ucitelji', 'predmet__slusatelji'
        )
        nastavi_sirine_srecanj(self)
        nastavi_barve(self, barve)
        return self

class Termin(object):
    def __init__(self, dan, ura):
        self.dan = dan
        self.ura = ura

    def style(self):
        left = (self.dan - 1) * ENOTA_SIRINE
        top = (self.ura - MIN_URA) * ENOTA_VISINE
        height = ENOTA_VISINE
        width = ENOTA_SIRINE
        return 'position: absolute; left: {:.2%}; width: {:.2%}; top: {:.2%}; height: {:.2%};'.format(left, width, top, height)

class TerminUrejanje(Termin):
    ZASEDEN = 'zaseden'

    def __init__(self, dan, ura, ustrezne, alternative, zasedenost_ucilnic, srecanje):
        super().__init__(dan, ura)
        self.ucilnice = []
        self.zasedenost = self.ZASEDEN
        ure = range(self.ura, self.ura + srecanje.trajanje)
        proste_ustrezne = False
        deloma_proste_ustrezne = False
        proste_alternative = False
        deloma_alternative = False

        for ucilnica in alternative:
            ucilnica = deepcopy(ucilnica)
            ucilnica.ustreznost = 'alternativa'
            self.ucilnice.append(ucilnica)
        for ucilnica in ustrezne:
            ucilnica = deepcopy(ucilnica)
            ucilnica.ustreznost = 'ustrezna'
            self.ucilnice.append(ucilnica)
        self.ucilnice.sort()

        def prosta(zasedenost_ucilnic, ucilnica, dan, ura):
            return ucilnica not in zasedenost_ucilnic.get((dan, ura), [])

        for ucilnica in self.ucilnice:
            if all(prosta(zasedenost_ucilnic, ucilnica, dan, ura) for ura in ure):
                ucilnica.zasedenost = 'prosta'
                if ucilnica.ustreznost == 'ustrezna':
                    proste_ustrezne = True
                else:
                    proste_alternative = True
            elif any(prosta(zasedenost_ucilnic, ucilnica, dan, ura) for ura in ure):
                ucilnica.zasedenost = 'deloma_prosta'
                if ucilnica.ustreznost == 'ustrezna':
                    deloma_proste_ustrezne = True
                else:
                    deloma_alternative = True
            else:
                ucilnica.zasedenost = 'zasedena'

        if proste_ustrezne:
            self.zasedenost = 'prosto'
        elif deloma_proste_ustrezne and proste_alternative:
            self.zasedenost = 'proste_le_alternative'
        elif deloma_proste_ustrezne:
            self.zasedenost = 'deloma'
        elif proste_alternative:
            self.zasedenost = 'proste_alternative'
        elif deloma_alternative:
            self.zasedenost = 'deloma_proste_alternative'

class Srecanje(models.Model):
    PREDAVANJA, SEMINAR, VAJE, LABORATORIJSKE_VAJE = 'P', 'S', 'V', 'L'
    TIP = (
        (PREDAVANJA, 'predavanja'), (SEMINAR, 'seminar'),
        (VAJE, 'vaje'), (LABORATORIJSKE_VAJE, 'laboratorijske vaje'),
    )
    semester = models.ForeignKey('urnik.Semester', on_delete=models.PROTECT)
    predmet = models.ForeignKey('urnik.Predmet', null=True, blank=True, on_delete=models.SET_NULL)
    tip = models.CharField(max_length=1, choices=TIP, blank=True)
    oznaka = models.CharField(max_length=64, blank=True)
    ucitelji = models.ManyToManyField('urnik.Oseba', blank=True)
    dan = models.PositiveSmallIntegerField(choices=enumerate(DNEVI, 1), blank=True, null=True)
    ura = models.PositiveSmallIntegerField(blank=True, null=True)
    trajanje = models.PositiveSmallIntegerField(null=True)
    ucilnica = models.ForeignKey('urnik.Ucilnica', null=True, blank=True, on_delete=models.SET_NULL)
    objects = SrecanjeQuerySet.as_manager()

    class Meta:
        verbose_name_plural = 'srečanja'
        default_related_name = 'srecanja'
        ordering = ('predmet', 'tip', 'oznaka', 'dan', 'ura', 'trajanje')

    def __str__(self):
        if self.dan and self.ura:
            return '{}, {}{}, {}, {}, {}–{}, {}'.format(
                self.predmet, self.tip, self.oznaka, ', '.join(str(ucitelj) for ucitelj in self.ucitelji.all()),
                self.get_dan_display(), self.ura, self.ura + self.trajanje,
                self.ucilnica
            )
        else:
            return '{}, {}{}, {}, odloženo, {}'.format(
                self.predmet, self.tip, self.oznaka, ', '.join(str(ucitelj) for ucitelj in self.ucitelji.all()),
                self.ucilnica
            )

    @property
    def od(self):
        return self.ura

    @property
    def do(self):
        if self.ura:
            return self.ura + self.trajanje

    def se_po_urah_prekriva(self, od, do):
        return self.od < do and od < self.do

    def podvoji(self, novi_semester=None):
        stari_ucitelji = list(self.ucitelji.all())
        self.id = None
        if novi_semester is not None:
            self.semester = novi_semester
        self.save()
        for ucitelj in stari_ucitelji:
            self.ucitelji.add(ucitelj)

    def odlozi(self):
        self.dan = None
        self.ura = None
        self.save()

    def nastavi_trajanje(self, trajanje):
        self.trajanje = trajanje
        self.save()

    def premakni(self, dan, ura, ucilnica):
        self.dan = dan
        self.ura = ura
        self.ucilnica = ucilnica
        self.save()

    def lahko_skrajsam(self):
        return self.trajanje > 1

    def lahko_podaljsam(self):
        return not self.ura or self.do < MAX_URA

    def lahko_odlozim(self):
        return self.dan and self.ura

    def po_potrebi_okrajsano_ime_predmeta(self):
        if hasattr(self, 'sirina') and ((self.sirina >= 0.5 and len(self.predmet.ime) < 45 and self.trajanje > 1) or self.sirina == 1):
            return self.predmet.ime
        else:
            return self.predmet.kratica

    def povezana_srecanja(self):
        srecanja = self.semester.srecanja
        letniki_poslusajo = srecanja.filter(predmet__letniki__in=self.predmet.letniki.all())
        ucitelj_uci = srecanja.filter(ucitelji__in=self.ucitelji.all())
        ucitelj_poslusa = srecanja.filter(predmet__slusatelji__in=self.ucitelji.all())
        return (letniki_poslusajo | ucitelj_uci | ucitelj_poslusa).exclude(
            pk=self.pk
        ).distinct()

    def style(self):
        if self.dan and self.ura and hasattr(self, 'sirina'):
            left = (self.dan - 1 + self.zamik) * ENOTA_SIRINE
            top = (self.ura - MIN_URA) * ENOTA_VISINE
            height = self.trajanje * ENOTA_VISINE
            width = self.sirina * ENOTA_SIRINE
            return 'left: {:.2%}; width: {:.2%}; top: {:.2%}; height: {:.2%};'.format(
                left, width, top, height)
        else:
            return ''

    def css_classes(self):
        classes = []
        if hasattr(self, 'leftmost') and self.leftmost: classes.append('leftmost')
        if hasattr(self, 'rightmost') and self.rightmost: classes.append('rightmost')
        return ' '.join(classes)

    def prosti_termini(self, tip, oddelek):
        ustrezne, alternative = Ucilnica.objects.ustrezne(tip=tip, oddelek=oddelek)
        if self.ucilnica not in ustrezne and self.ucilnica not in alternative:
            ustrezne.insert(0, self.ucilnica)

        zasedenost_ucilnic = defaultdict(set)
        for srecanje in self.semester.srecanja.neodlozena().filter(ucilnica__in=ustrezne + alternative).exclude(pk=self.pk).select_related('ucilnica'):
            for ura in range(srecanje.ura, srecanje.ura + srecanje.trajanje):
                zasedenost_ucilnic[(srecanje.dan, ura)].add(srecanje.ucilnica)

        termini = {}
        for dan in range(1, 6):
            for ura in range(MIN_URA, MAX_URA - self.trajanje + 1):
                termini[(dan, ura)] = TerminUrejanje(
                    dan=dan,
                    ura=ura,
                    ustrezne=ustrezne,
                    alternative=alternative,
                    zasedenost_ucilnic=zasedenost_ucilnic,
                    srecanje=self,
                )
        return termini

    def dnevi_med(self, od, do):
        od = max(od, self.semester.od)
        dan = od + datetime.timedelta((self.dan - (od.weekday()+1)) % DAYS_IN_WEEK)
        assert dan.weekday() + 1 == self.dan, "Ups."
        dan_konca = min(self.semester.do, do)
        razlika = datetime.timedelta(weeks=1)
        while dan <= dan_konca:
            yield dan
            dan += razlika

class RezervacijaQuerySet(models.QuerySet):

    def v_tednu(self, ponedeljek):
        nedelja = ponedeljek + datetime.timedelta(days=6)
        return self.filter(
            dan_konca__isnull=True,
            dan__gte=ponedeljek,
            dan__lte=nedelja,
        ) | self.filter(
            dan_konca__isnull=False,
            dan__lte=nedelja,
        ).exclude(
            dan_konca__lt=ponedeljek,
        )

    def prihajajoce(self):
        return self.filter(dan__gte=datetime.date.today()) | self.filter(dan_konca__gte=datetime.date.today())

class Rezervacija(models.Model):
    ucilnice = models.ManyToManyField('urnik.Ucilnica', blank=False,
                                      limit_choices_to={'tip__in': Ucilnica.OBJAVLJENI_TIPI}, verbose_name='Učilnice')
    osebe = models.ManyToManyField('urnik.Oseba', verbose_name='Osebe')
    dan = models.DateField(verbose_name='Dan začetka', blank=False, null=False, help_text='Za kateri dan želite rezervirati')
    dan_konca = models.DateField(blank=True, null=True, verbose_name='Dan konca', help_text='Dan konca rezervacije; izpolnite le, če je drugačen od začetka')
    MOZNE_URE = tuple((u, str(u)+":00") for u in range(MIN_URA, MAX_URA+1))
    od = models.PositiveSmallIntegerField(blank=False, null=False, choices=MOZNE_URE, help_text='Od katere ure želite rezervirati')
    do = models.PositiveSmallIntegerField(blank=False, null=False, choices=MOZNE_URE, help_text='Do katere ure želite rezervirati')
    opomba = models.CharField(max_length=192, blank=False, null=False, help_text='Razlog za rezervacijo')
    potrjena = models.BooleanField(default=False, null=False, help_text='Ali so to rezervacijo potrdili posvečeni ljudje')
    avtor_rezervacije = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, help_text='Kdo je dejansko naredil rezervacijo', on_delete=models.CASCADE)
    cas_rezervacije = models.DateTimeField(auto_now_add=True, help_text="Datum in čas, ko je bila rezervacija narejena", verbose_name='Datum in čas rezervacije')

    objects = RezervacijaQuerySet.as_manager()

    @property
    def zacetek(self):
        return self.dan

    @property
    def konec(self):
        return self.dan_konca or self.dan

    def __str__(self):
        if self.dan_konca:
            return "Rezervacija od {} do {}, {}–{} za {}".format(self.zacetek, self.konec, self.od, self.do, self.opomba)
        else:
            return "Rezervacija dne {}, {}–{} za {}".format(self.zacetek, self.od, self.do, self.opomba)

    class Meta:
        verbose_name_plural = 'rezervacije'
        default_related_name = 'rezervacije'
        ordering = ('dan', 'od', 'do')

    def dnevi(self):
        return self.dnevi_med(self.zacetek, self.konec)

    def prihajajoci_dnevi(self):
        return self.dnevi_med(datetime.date.today(), self.konec)

    def dnevi_med(self, od, do):
        dan = max(self.zacetek, od)
        dan_konca = min(self.konec, do)
        razlika = datetime.timedelta(days=1)
        while dan <= dan_konca:
            yield dan
            dan += razlika

    def se_po_urah_prekriva(self, od, do):
        return self.od < do and od < self.do

class RezervacijeModelMultipleChoiceField(ModelMultipleChoiceField):
    def __init__(self, *args, **kwargs):
        ModelMultipleChoiceField.__init__(self, *args, **kwargs)
        it = self.iterator(self)
        self.choices = [it.choice(obj) for obj in sorted(self.queryset)]

class OsebeModelMultipleChoiceField(RezervacijeModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return obj.priimek_ime

class UcilniceModelMultipleChoiceField(RezervacijeModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return obj.oznaka

class RezevacijeForm(ModelForm):

    PREKRIVANJA = 'prekrivanja'

    osebe = OsebeModelMultipleChoiceField(queryset=Oseba.objects.all(),
                                          help_text='Osebe, ki si lastijo to rezervacijo')
    ucilnice = UcilniceModelMultipleChoiceField(queryset=Ucilnica.objects.objavljene(),
                                                help_text='Izberite učilnice, ki jih želite rezervirati',
                                                widget=CheckboxSelectMultiple())
    use_required_attribute = False

    class Meta:
        model = Rezervacija
        fields = ['ucilnice', 'osebe', 'dan', 'dan_konca', 'od', 'do', 'opomba']
        widgets = {
            'dan': DateInput(attrs={'placeholder': 'npr. 15. 1. 2019', 'class': 'datepicker'}),
            'dan_konca': DateInput(attrs={'placeholder': 'ponavadi prazno, lahko tudi npr. 17. 1. 2019', 'class': 'datepicker'}),
            'opomba': TextInput(attrs={'placeholder': 'npr. izpit Analiza 1 FIN'}),
        }

    def __init__(self, *args, **kwargs):
        dovoli_prekrivanja = kwargs.pop('dovoli_prekrivanja', None)
        super(RezevacijeForm, self).__init__(*args, **kwargs)
        if dovoli_prekrivanja:
            self.fields['ignoriraj_prekrivanja'] = BooleanField(
                required=False, initial=False,
                help_text='Zavedam se prekrivanj in vseeno želim rezervirati izbrane učilnice '
                          'v izbranih dnevih in urah.')

    def clean_dan(self):
        dan = self.cleaned_data['dan']
        if dan < datetime.date.today():
            raise ValidationError("Datum rezervacije mora biti v prihodnosti.")
        return dan

    def clean(self):
        cleaned = super().clean()
        if self.errors:
            return cleaned

        od = cleaned.get('od')
        do = cleaned.get('do')
        if od >= do:
            self.add_error(None, ValidationError("Ura začetka rezervacije mora biti pred uro konca rezervacije."))

        dan = cleaned.get('dan')
        konec = cleaned.get('dan_konca')
        if konec:
            if dan == konec:
                self.cleaned_data['dan_konca'] = None
            elif dan > konec:
                self.add_error(None, ValidationError("Dan začetka rezervacije moda biti "
                                                     "pred dnevom konca rezervacije."))
        ignoriraj = cleaned.get('ignoriraj_prekrivanja')
        if not ignoriraj:
            self._preveri_konflikte(cleaned)

        return self.cleaned_data

    def _preveri_konflikte(self, cleaned):
        from urnik.iskanik_konfliktov import IskalnikKonfliktov
        ucilnice = cleaned.get('ucilnice')
        dan = cleaned.get('dan')
        konec = cleaned.get('dan_konca') or dan
        od = cleaned.get('od')
        do = cleaned.get('do')
        iskalnik = IskalnikKonfliktov(ucilnice, dan, konec)
        iskalnik.dodaj_srecanja()
        iskalnik.dodaj_rezervacije(Rezervacija.objects.prihajajoce())

        date_format = lambda d: defaultfilters.date(d, "D, j. b")
        for u in ucilnice:
            d = dan
            while d <= konec:
                konflikti = iskalnik.konflikti(u, d, od, do)
                for r in konflikti.rezervacije:
                    oseba = r.osebe.all()[:1]
                    self.add_error(None, ValidationError(
                        'Vaša rezervacija bi se prekrivala z rezervacijo osebe %(oseba)s %(dan)s '
                        'od %(od)i do %(do)i z razlogom %(razlog)s.',
                        params={
                            'oseba': oseba[0] if oseba else 'neznan',
                            'dan': "od {} do {}".format(date_format(r.dan), date_format(r.dan_konca))
                            if r.dan_konca else "dne {}".format(date_format(r.dan)),
                            'razlog': r.opomba,
                            'od': r.od,
                            'do': r.do,
                        },
                        code=RezevacijeForm.PREKRIVANJA,
                    ))

                for s in konflikti.srecanja:
                    self.add_error(None, ValidationError(
                        'Vaša rezervacija bi se prekrivala s predmetom %(predmet)s (%(semester)s), ki se izvaja '
                        'ob %(dan_v_tednu)s od %(od)i do %(do)i.',
                        params={
                            'predmet': s.predmet,
                            'semester': s.semester,
                            'dan_v_tednu': dan_tozilnik_mnozina(s.dan),
                            'od': s.od,
                            'do': s.do,
                        },
                        code=RezevacijeForm.PREKRIVANJA,
                    ))

                d += datetime.timedelta(days=1)


import tflearn as tf
from tflearn.layers.core import input_data,dropout,fully_connected
from tflearn.layers.estimator import regression
from tflearn.data_utils import load_csv
import tensorflow as tfs

data,target=load_csv('dataset.csv',target_column=-1,columns_to_ignore=[1],has_header=True,categorical_labels=True,n_classes=2)
sess=tfs.Session()
outp = tfs.gather(data,2)
print(sess.run(outp))
outp1 = tfs.gather(target,2)
print(sess.run(outp1))

network = input_data(shape=[None,23],name='input')
network = fully_connected(network,10,activation='relu',name='nn_layer_1')
network = fully_connected(network,5,activation='relu',name='nn_layer_2')
network = fully_connected(network,2,activation='softmax',name='output_layer')
network = regression(network,optimizer='adam',loss='categorical_crossentropy',learning_rate=0.001)
model = tf.DNN(network, tensorboard_verbose=3)
#model.fit(data,target,n_epoch=50,validation_set=0.3,show_metric=True,run_id='model1')


# CMPT 120 Intro to Programming
# Lab 8
# Author: Vincent Manna
# Created: 2020-04-19

class item:
    item = 'flashlight'
    description = 'a device that shines light into a directed spot.'

    def render(self):
        print(item.description)

it = item()
it.render()

def containsitem():
    lablist = ['flashlight', 'lamp', 'table', 'desk']
    search = 'flashlight'
    result = [i for i in lablist if search in i]
    print('The string searched for is: ' + str(result))

containsitem()


import sys
import pygame
import random
from snake_utility import Snake, Cherry, SnakeGameStatusFlags
import json

def set_new_cherry_pos(snake_lst):
    """
    Sets new cherry position.

    :param snake_lst: List, containing all snake instances present in the game. This is needed
                      to check that cherry will not be placed onto a snake.
    :type snake_lst: list of Snake
    """

    new_cherry_pos = random.randrange(0, width, Snake.block_size), random.randrange(0, height, Snake.block_size)

    # check if new cherry position is within any of the snakes and set new one
    for snk in snake_lst:
        while new_cherry_pos in snk.block_pos_lst:
            new_cherry_pos = random.randrange(0, width, Snake.block_size), random.randrange(0, height, Snake.block_size)

    return new_cherry_pos

def init_game(config_data):
    """
    Initializes the game with configuration, defined in config_data.

    :param config_data: Dictionary, which contains configuration for the game, such as
                        game window dimensions, number of snakes, keyboard keys, etc.
    :type config_data: dict

    :return: Lists of initialized snakes and cherries.
    :rtype: tuple of list
    """
    # colors for snakes
    snake_colors = [(0, 255, 0),  # player 1 is green
                    (0, 0, 255),  # player 2 is blue
                    (255, 255, 50),  # player 3 is yellow
                    (205, 0, 205)]  # player 4 is purple

    # create snake instances
    init_snake_lst = []
    for i in range(config_data["num_snakes"]):
        keys = config_data["keys"][i]
        snake = Snake(start_pos=config_data["start_pos"][i],
                      move_keys={'up': pygame.__getattribute__(keys[0]),
                                 'right': pygame.__getattribute__(keys[1]),
                                 'down': pygame.__getattribute__(keys[2]),
                                 'left': pygame.__getattribute__(keys[3])},
                      color=snake_colors[i],
                      block_size=config_data["block_size"],
                      num_of_start_blocks=config_data["initial_snake_length"])

        init_snake_lst.append(snake)

    # create cherry instances
    init_cherry_lst = []
    for i in range(config_data["num_cherries"]):
        cherry = Cherry(block_size)
        cherry.set_new_random_position(init_snake_lst, config_data["main_window_size"])
        init_cherry_lst.append(cherry)

    return init_snake_lst, init_cherry_lst

def redraw_screen(snake_lst, cherry_lst, block_size):
    """
    Redraws screen with updated snake and cherry positions.

    :param snake_lst: List of all snakes in the game.
    :type snake_lst: list of Snake

    :param cherry_lst: List of all cherries in the game.
    :type cherry_lst: list of Cherry

    :param block_size: Size of one block of snake or cherry in pixels.
    :type block_size: int
    """
    # clear screen
    screen.fill(BLACK)

    # draw snakes
    for snake in snake_lst:
        for block_pos in snake.block_pos_lst:
            pygame.draw.rect(screen,
                             snake.color,
                             (block_pos[0], block_pos[1], block_size, block_size))

    # draw cherries
    for cherry in cherry_lst:
        pygame.draw.rect(screen,
                         (255, 0, 0),
                         (cherry.position[0], cherry.position[1], block_size, block_size))

    # update display
    pygame.display.update()

def main_loop(snake_list, cherry_list):
    """
    Main loop of the game. This function returns only if snake collision occured.

    """
    while True:
        # capture events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                # happens when user tries to close window
                sys.exit()  # exit from game
            elif event.type == pygame.KEYDOWN:
                # happens on key pressed
                # check which snake's key was pressed and add it to key stack
                for snake in snake_list:
                    if event.key in [val for _, val in snake.move_keys.items()]:
                        snake.key_stack.append(event.key)
            elif event.type == pygame.USEREVENT:  # happens on each timer tick

                for snake in snake_list:
                    snake.get_dir_from_keystack()
                    snake.set_new_state(size, snake_list)

                    # check if there is collision
                    if snake.collision:
                        return SnakeGameStatusFlags.COLLISION_OCCURENCE

                    # check if any of the cherries was eaten by the current snake
                    for cherry in cherry_list:
                        if snake.block_pos_lst[0] == cherry.position:
                            # append new block to snake that ate the cherry
                            snake.block_pos_lst.append(snake.block_pos_lst[-1])

                            # set new random position for the eaten cherry
                            cherry.set_new_random_position(snake_lst, size)

                # redraw screen with updated snake and cherry positions
                redraw_screen(snake_list, cherry_list, block_size)

if __name__ == '__main__':
    pygame.init()

    # load configuration data
    with open('config.json', 'r') as config_file:
        configuration_data = json.load(config_file)

    size = width, height = configuration_data["main_window_size"]
    BLACK = 0, 0, 0
    refresh_rate = configuration_data["refresh_rate"]
    start_pos = configuration_data["start_pos"]
    block_size = configuration_data["block_size"]

    # set display
    screen = pygame.display.set_mode(size)

    # set timer
    pygame.time.set_timer(pygame.USEREVENT, refresh_rate)

    timer = pygame.time.get_ticks()

    while True:
        # initialize new game
        snake_lst, cherry_pos = init_game(configuration_data)

        # main loop will exit only if collision occurs
        main_loop(snake_lst, cherry_pos)


"Conversor de bases númericas"
n = input("Você deseja converter números S/N: ")
while n=='S'or n =='s':
    num = int(input("Número a ser convertido: "))
    print('''
        1 para Binário
        2 para Hexadecimal''')
    x = int(input("Sua escolha: "))
    if x ==1:
     print("número digitado foi {} e sua converção para binário é {}".format(num,bin(num)[2:]))
    else:
        print("o número digitado foi {} e sua converção {}".format(num,hex(num)[2:]))
    n = input("Você deseja converter números S/N: ")


from bs4 import BeautifulSoup
from urllib.request import urlopen
import pandas as pd

################### 코스피:1 , 코스닥:2 #########################
def get_code(num):
    response = urlopen('https://www.sedaily.com/Stock/Quote?type='+str(num))
    soup = BeautifulSoup(response, 'html.parser')

    all_table = soup.find_all('div', {'class': 'table'})

    code_dict = {}
    for thead in all_table:
        dl = thead.find('dl', {'class': 'thead'})

        dt = dl.find('dt')
        fieldName = dt.text

        tbody = thead.find_all('dl', {'class': 'tbody'})

        for dl in tbody:
            name = dl.find('dt').get_text()
            dd = dl.find('dd')
            code = dd.get('id').replace('dd_Item_', '')

            code_dict[code] = [name, fieldName]
    return code_dict

df_kospi_present = pd.DataFrame(get_code(1)).T

df_kospi_present.columns = ['종목명', '업종']

df_kospi_present.to_csv("kospi_code.csv")

df_kosdaq_present = pd.DataFrame(get_code(2)).T

df_kosdaq_present.columns = ['종목명', '업종']

df_kosdaq_present.to_csv("kosdaq_code.csv")


import requests
import signal
import socket
import subprocess
import time
from collections import defaultdict
from datetime import datetime

import pytest

from utils import providers
from utils.cfmedb import db_session_maker
from utils.conf import cfme_data
from utils.datafile import template_env
from utils.events import setup_for_event_testing
from utils.log import create_logger
from utils.path import scripts_path
from utils.ssh import SSHClient
from utils.wait import wait_for, TimedOutError

logger = create_logger('events')

def get_current_time_GMT():
    """ Because SQLite loves GMT.

    Returns:
        datetime() with current GMT time
    """
    return datetime.strptime(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), "%Y-%m-%d %H:%M:%S")

class HTMLReport(object):
    def __init__(self, events):
        self.events = events

    def generate(self, filename):
        template = template_env.get_template('event_testing.html')
        with open(filename, "w") as outfile:
            outfile.write(template.render(events=self.events))

class EventExpectation(object):
    """ Expectation for an event.

    This object embeds an expectation in order to be able to easily compare
    whether the two expectations are the same but just with different time.

    This is the actual object returned by the :py:func:`register_event` fixture.
    """

    TIME_FORMAT = "%Y-%m-%d %H:%M:%S"

    def __init__(self, sys_type, obj_type, obj, event, time=None):
        self.sys_type = sys_type
        self.obj_type = obj_type
        self.obj = obj
        self.event = event
        self.arrived = None
        if time:
            self.time = time
        else:
            self.time = get_current_time_GMT()

    def __eq__(self, other):
        try:
            assert self.sys_type == other.sys_type
            assert self.obj_type == other.obj_type
            assert self.obj == other.obj
            assert self.event == other.event
            return True
        except (AssertionError, AttributeError):
            return False

    @property
    def colour(self):
        return "green" if self.arrived else "red"

    @property
    def time_friendly(self):
        return datetime.strftime(self.time, self.TIME_FORMAT)

    @property
    def success_friendly(self):
        return "success" if self.arrived else "failed"

    @property
    def time_difference(self):
        if self.arrived:
            td = self.arrived - self.time
            return int(round(td.total_seconds()))
        else:
            return "Did not come"

class EventListener(object):

    TIME_FORMAT = "%Y-%m-%d-%H-%M-%S"

    def __init__(self, listener_port, settle_time, verbose=False):
        self.listener_port = int(listener_port)
        listener_filename = scripts_path.join('listener.py').strpath
        self.listener_script = "%s 0.0.0.0 %d" % (listener_filename, self.listener_port)
        if not verbose:
            self.listener_script += ' --quiet'
        self.settle_time = int(settle_time)
        self.expectations = []
        self.processed_expectations = defaultdict(list)
        self.listener = None

    def get_listener_host(self):
        return "http://%s" % self.get_ip_address()

    def get_ip_address(self):
        """ This returns this machine's active IP address.

        It uses Sean's service to query the address.
        """
        data = cfme_data.get("event_testing")
        assert data, "No event_testing section in cfme_data yaml"
        ipecho = data.get("ip_echo")
        assert ipecho, "No event_testing/ip_echo in cfme_data yaml"
        try:
            host = ipecho["host"]
            port = int(ipecho["port"])
        except (TypeError, KeyError):
            raise Exception("Could not read data from event_testing/ip_echo/{host, port}")
        connection = socket.create_connection((host, port))
        try:
            return str(connection.recv(39)).strip()
        finally:
            connection.close()

    def _get(self, route):
        """ Query event listener
        """
        assert not self.finished, "Listener dead!"
        listener_url = "%s:%d" % (self.get_listener_host(), self.listener_port)
        logger.info("checking api: %s%s" % (listener_url, route))
        r = requests.get(listener_url + route)
        r.raise_for_status()
        response = r.json()
        logger.debug("Response: %s" % response)
        return response

    def _delete_database(self):
        """ Sends a DELETE /events request for listener.

        Listener reacts to this kind of request by truncating contents of the events table.

        Returns:
            Boolean signalizing success.
        """
        assert not self.finished, "Listener dead!"
        listener_url = "%s:%d" % (self.get_listener_host(), self.listener_port)
        r = requests.delete(listener_url + "/events")
        r.raise_for_status()
        return r.json().get("result") == "success"

    def mgmt_sys_type(self, sys_type, obj_type):
        """ Map management system type from cfme_data.yaml to match event string
            and also add possibility of host based test.
        """
        # TODO: obj_type ('ems' or 'vm') is the same for all tests in class
        #       there must be a better way than to pass this around
        ems_map = {"rhevm": "EmsRedhat",
                   "virtualcenter": "EmsVmware"}
        vm_map = {"rhevm": "VmRedhat",
                  "virtualcenter": "VmVmware"}
        if obj_type in {"ems"}:
            return ems_map.get(sys_type)
        elif obj_type in {"vm"}:
            return vm_map.get(sys_type)
        elif obj_type in {"host"}:
            return obj_type

    def check_db(self, sys_type, obj_type, obj, event, after=None, before=None):
        """ Utility to check listener database for event

        Args:
            after: Return only events that happened AFTER this time
            before: Return only events that happened BEFORE this time

        Note:
            Both can be combined. If None, then the filter won't be applied.
        """
        max_attempts = 10
        sleep_interval = 2
        req = "/events/%s/%s?event=%s" % (self.mgmt_sys_type(sys_type, obj_type), obj, event)
        # Timespan limits
        if after:
            req += "&from_time=%s" % datetime.strftime(after, self.TIME_FORMAT)
        if before:
            req += "&to_time=%s" % datetime.strftime(before, self.TIME_FORMAT)

        for attempt in range(1, max_attempts + 1):
            data = self._get(req)
            try:
                assert len(data) > 0
            except AssertionError as e:
                if attempt < max_attempts:
                    logger.debug("Waiting for DB (%s/%s): %s" % (attempt, max_attempts, e))
                    time.sleep(sleep_interval)
                    pass
                # Enough sleeping, something went wrong
                else:
                    logger.exception("Check DB failed. Max attempts: '%s'." % (max_attempts))
                    return False
            else:
                # No exceptions raised
                logger.info("DB row found for '%s'" % req)
                return datetime.strptime(data[0]["event_time"], "%Y-%m-%d %H:%M:%S")
        return False

    def check_all_expectations(self):
        """ Check whether all triggered events have been captured.

        Sets a flag for each event.

        Simplified to check just against the time of registration
        and the begin of this check.

        Returns:
            Boolean whether all events have already been captured.

        """
        check_started = get_current_time_GMT()
        for expectation in self.expectations:
            # Get the events with the same parameters, just with different time
            the_same = [item
                        for item
                        in self.expectations
                        if item == expectation and item is not expectation
                        ]
            # Split them into preceeding and following events
            preceeding_events = [event
                                 for event
                                 in the_same
                                 if event.time <= expectation.time and event is not expectation
                                 ]
            # Get immediate predecessor's of follower's time of this event
            preceeding_event = preceeding_events[-1].time if preceeding_events else expectation.time
            #following_event = following_events[0].time if following_events else check_started
            # Shorten the params
            params = [expectation.sys_type,
                      expectation.obj_type,
                      expectation.obj,
                      expectation.event]
            came = self.check_db(*params, after=preceeding_event, before=check_started)
            if came:
                expectation.arrived = came
        return all([exp.arrived is not None for exp in self.expectations])

    @property
    def expectations_count(self):
        return len(self.expectations)

    def add_expectation(self, sys_type, obj_type, obj, event):
        expectation = EventExpectation(sys_type, obj_type, obj, event)  # Time added automatically
        self.expectations.append(expectation)

    def __call__(self, sys_type, obj_type, obj, events):
        if not isinstance(events, list):
            events = [events]
        for event in events:
            logger.info("Event registration: %s" % str(locals()))
            self.add_expectation(sys_type, obj_type, obj, event)

    @pytest.fixture(scope="session")
    def listener_info(self):
        """ Listener fixture

        This fixture provides listener's address and port.
        It is used in setup test cases located at:
        ``/tests/test_setup_event_testing.py``
        """
        return type(
            "Listener",
            (object,),
            {
                "host": self.get_listener_host(),
                "port": self.listener_port
            }
        )

    @property
    def finished(self):
        if not self.listener:
            return True
        return self.listener.poll() is not None

    def start(self):
        assert not self.listener, "Listener can't be running in order to start it!"
        logger.info("Starting listener %s" % self.listener_script)
        logger.info("In order to run the event testing, port %d must be enabled." %
            self.listener_port)
        logger.info("sudo firewall-cmd --add-port %d/tcp --permanent" % self.listener_port)
        self.listener = subprocess.Popen(self.listener_script,
                                         shell=True)
        logger.info("Listener pid %d" % self.listener.pid)
        time.sleep(3)
        assert not self.finished, "Listener has died. Something must be blocking selected port"
        logger.info("Listener alive")

    def stop(self):
        assert self.listener, "Listener must be running in order to stop it!"
        logger.info("Killing listener %d" % (self.listener.pid))
        self.listener.send_signal(signal.SIGINT)
        self.listener.wait()
        self.listener = None

    def pytest_unconfigure(self, config):
        """ Collect and clean up the testing.

        If the event testing is active, collects results, stops the listener
        and generates the report.
        """
        if config.getoption("event_testing_enabled"):
            # Collect results
            try:
                # Generate result report
                report = HTMLReport(self.processed_expectations)
                report.generate(config.getoption("event_testing_result"))
                # Report to the terminal
                termreporter = config.pluginmanager.getplugin('terminalreporter')
                termreporter.write_sep('-', 'Stopping event listener')
            finally:
                self.stop()

def pytest_addoption(parser):
    parser.addoption('--event-testing',
                     action='store_true',
                     dest='event_testing_enabled',
                     default=False,
                     help='Enable testing of the events. (default: %default)')
    parser.addoption('--event-testing-result',
                     action='store',
                     dest='event_testing_result',
                     default="log/events.html",
                     help='Filename of result report. (default: %default)')
    parser.addoption('--event-testing-port',
                     action='store',
                     dest='event_testing_port',
                     default="65432",
                     help='Port of the testing listener. (default: %default)')
    parser.addoption('--event-testing-settletime',
                     action='store',
                     dest='event_testing_settletime',
                     default=60,
                     help='Time to wait after all testing has been finished' +
                     'for remaining events to come. (default: %default)')
    parser.addoption('--event-testing-verbose-listener',
                     action='store_true',
                     dest='event_testing_verbose_listener',
                     default=False,
                     help='Enabled access logging from the event listener')

def pytest_configure(config):
    """ Event testing setup.

    Sets up and registers the EventListener plugin for py.test.
    If the testing is enabled, listener is started.
    """
    plugin = EventListener(config.getoption("event_testing_port"),
                           config.getoption("event_testing_settletime"),
                           config.getoption("event_testing_verbose_listener"))
    registration = config.pluginmanager.register(plugin, "event_testing")
    assert registration
    if config.getoption("event_testing_enabled"):
        plugin.start()

@pytest.fixture(scope="module")
def configure_appliance_for_event_testing(listener_info):
    """ This fixture ensures that the appliance is configured for event testing.
    """
    return setup_for_event_testing(
        SSHClient(), db_session_maker(), listener_info, providers.list_infra_providers()
    )

@pytest.yield_fixture(scope="function")
def register_event(uses_event_listener, configure_appliance_for_event_testing, request):
    """register_event(sys_type, obj_type, obj, event)
    Event registration fixture (ALWAYS PLACE BEFORE PAGE NAVIGATION FIXTURE!)

    This fixture is used to notify the testing system that some event
    should have occured during execution of the test case using it.
    It does not register anything by itself.

    Args:
        sys_type: Management system type to expect
        obj_type: Management system related object type to expect
        obj: Expected identifier for related object
        event: Event name or list of event names to expect

    Returns: :py:class:`EventExpectation`

    Usage:

        def test_something(foo, bar, register_event):
            register_event("systype", "objtype", "obj", "event")
            # or
            register_event("systype", "objtype", "obj", ["event1", "event2"])
            # do_some_stuff_that_triggers()

    For host_events, use `None` for sys_type.

    It also registers the time when the registration was done so we can filter
    out the same events, but coming in other times (like vm on/off/on/off will
    generate 3 unique events, but twice, distinguishable only by time).
    It can also partially prevent scumbag 'Jimmy' ruining the test if he does
    something in the hypervisor that the listener registers.

    After the test function finishes, it checks the listener whether it has caught the events.
    If any of the events has not been caught, it raises a pytest.fail.
    Before and after each test run using this fixture, database is cleared.

    """
    # We pull out the plugin directly.
    self = request.config.pluginmanager.getplugin("event_testing")  # Workaround for bind
    node_id = request.node.nodeid

    if self.listener is not None:
        logger.info("Clearing the database before testing ...")
        self._delete_database()
        self.expectations = []

    yield self  # Run the test and provide the plugin as a fixture

    if self.listener is not None:
        logger.info("Checking the events ...")
        try:
            wait_for(self.check_all_expectations,
                     delay=5,
                     num_sec=75,
                     handle_exception=True)
        except TimedOutError:
            pass

        self.processed_expectations[node_id].extend(self.expectations)
        logger.info("Clearing the database after testing ...")
        self._delete_database()
        self.expectations = []


from app.models.common import Game, Team, Member
from app.models.composite import GameTeam

__author__ = 'changsuyouk'
import unittest

import os
import requests

os.environ["unittest_mode"] = "enable"

from app import db

class SimpleTest(unittest.TestCase):

    def setUp(self):
        print("===== setting os enviroment =====")
        print(os.environ.get("unittest_mode"))
        self.uri = "http://localhost:5000"
        # session = self.r.session()
        # session.config['keep_alive'] = False

    def test_app(self):
        print("================")
        print("start testing test_game_model.py")
        db.drop_all()
        db.create_all()
        # self.setUp()
        self.test_get_current_date()
        self.test_get_current_session()
        self.test_session()
        self.test_create_game()
        self.test_create_members()
        self.test_add_members_to_team_instance()
        self.test_test_api()
        self.test_create_game_api()
        self.test_member_api()
        self.test_team_api()

    def test_get_current_date(self):
        import datetime
        now = datetime.datetime.now()
        date = now.strftime("%y%m%d")
        date = int(date)
        assert Game.get_current_date() == date

    def test_get_current_session(self):
        assert Game.get_current_session() == 1

    def test_session(self):
        Game.increase_current_session()
        Game.increase_current_session()
        assert Game.get_current_session() == 3

    def test_create_game(self):
        print("make curator 30 team")
        GameTeam.create_one("curator", 30)
        teams = Team.query.count()
        assert teams == 30

    def test_create_members(self):
        Member.create_many_from_string(1, "FRED,DAVID,MICHAEL")
        member = Member.query.count()
        assert member == 3
        print("test_create_members done")

    def test_add_members_to_team_instance(self):
        team = Team.query.filter(Team.id==1).one()
        members = Member.get_members_as_string(team.id)
        assert members == "FRED,DAVID,MICHAEL"
        print("test_add_members_to_team_instance done")

    def test_test_api(self):
        r = requests.get(self.uri + "/test")
        assert r.status_code == 200
        r.close()
        print("test_test_api done")

    def test_create_game_api(self):
        from json import dumps
        json = [{"job":"curator", "count":30},{"job":"archivist", "count":30},{"job":"educator", "count":30}]
        data = dumps(json)
        r = requests.post(self.uri + "/teams", data = data)

        print(r.text)
        r.close()
        print("test_create_game_api done")

    def test_member_api(self):
        members = "FRED,DAVID,MICHAEL"
        r = requests.post(self.uri + "/teams/1/members/"+members)
        r.close()
        print("text : ", r.text)
        print("test_member_api done")

    def test_team_api(self):
        r = requests.get(self.uri + "/teams/1")
        r.close()
        print(r.text)
        print("test_team_api done")