import cv2
import os
import glob
import time
import pandas as pd
import numpy as np
import subprocess
from shutil import copyfile
import shutil
import winshell

#Read column from training.csv to know which frames have fish in them
test_video_folder = "D:\\Users\\208018409\\Documents\\DrivenData\\fish\\test_videos\\"
test_image_folder = "D:\\Users\\208018409\\Documents\\DrivenData\\fish\\test_images\\"
darknet_folder = "D:/Users/208018409/Documents/darknet-master/build/darknet/x64/data/"
result_folder = "D:/Users/208018409/Documents/darknet-master/build/darknet/x64/results/"
test_images_temp_folder = "D:/Users/208018409/Documents/DrivenData/fish/test_images_temp/"
fish_folder = "D:/Users/208018409/Documents/DrivenData/fish/test_images/"
temp_test_file = "temp_test_file.txt"

#Read mp4 files in directory
os.chdir(test_video_folder)
file = glob.glob("*.mp4")

number_of_files = len(file)     #number of files in folder
frame_count = 0     #tracks the total number of frames being reviewed
#loop through files and generate image for each frame
for i in range (0,number_of_files):
    os.chdir(test_video_folder)
    filename = file[i]
    file2 = open(darknet_folder + temp_test_file, "w")
    file3 = open(result_folder + "all_files.csv", "a")
    print('File #: {0} out of {1}'.format(i + 1, number_of_files))
    vidcap = cv2.VideoCapture(file[i])
    success,image = vidcap.read()
    count = 0
    success = True
    while success:
        success, image = vidcap.read()
        image_filename = test_image_folder + filename[:-4] + "_" + str(count) + ".jpg"
        file2.write(image_filename + "\n")
        cv2.imwrite(image_filename, image)  # save frame as JPEG file
        file3.write(image_filename + "\n")

        # check if all files are valid (not equal to 0k)
        if (os.stat(image_filename).st_size == 0):
            copyfile(test_image_folder + filename[:-4] + "_" + str(count - 1) + ".jpg",image_filename)

        print(count)
        count += 1
    file2.flush()
    file3.flush()
    file2.close
    file3.close

    os.chdir("D:/Users/208018409/Documents/darknet-master/build/darknet/x64/")
    command = "start cmd /c darknet.exe detector valid data/fish_final.data yolo-voc.2.0_fish.cfg backup/yolo-voc_17700.weights"
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
    process.communicate()

    #filter comp4_det_test_fish.txt
    if (os.stat(result_folder + 'comp4_det_test_fish.txt').st_size != 0):
        df = pd.read_csv(result_folder + "comp4_det_test_fish.txt",sep=" ")

        df.columns = ['filename', 'score', 'x1', 'y1', 'x2', 'y2']  #give columns names
        a = df.groupby(['filename'])['score'].transform(max) == df['score']
        b = df[a]

        keepers = b.loc[b['score'] > 0.1]

        #append to keepers.csv
        with open(result_folder + 'keepers_17700.csv', 'a') as f:
            if (os.stat(result_folder + 'keepers.csv').st_size == 0):
                keepers.to_csv(f, header=True,index=False)
            else:
                keepers.to_csv(f, header=False, index=False)

        with open(result_folder + 'keepers_temp.csv', 'w') as f:
                keepers.to_csv(f, header=True, index=False)

        keepers_temp = pd.read_csv(result_folder + 'keepers_temp.csv')

        #copy over temp files only
        keeper_filenames = keepers_temp['filename']
        for p in range (0,len(keeper_filenames)):
            temp = keeper_filenames[p]
            copyfile(temp + ".jpg",test_images_temp_folder + temp[len(test_image_folder):] + ".jpg")

    #delete files in test_image folder
    os.chdir(test_image_folder)
    filelist = glob.glob("*.jpg")
    for f in filelist:
        os.remove(f)

    #empty recycling bin
    #time.sleep(10)
    #winshell.recycle_bin().empty(confirm=False, show_progress=True,sound=False)


from socket import *
import socket
print("Client-Side\n")
#Emri serverit
serverName=input('Server name:')
#porti serverit
serverPort=int(input('Server port:'))

while True:
        #krijimi soketit
        s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        #variabla
        var=input('Operacioni (IPADDR, PORTNR, ZANORE, PRINTO, HOST, TIME, LOJA, FIBONACCI, KONVERTO, TEKCIFT, KRAHASO)?')
        if var=="":
           s.sendto(str.encode("2"))
        #dergimi i variables
        s.sendto(str.encode(var),(serverName, serverPort))
        #marrja e te dhenave nga serveri
        data, serverAddress=s.recvfrom(128)
        #printimi i te dhenave
        print(data.decode())
s.close()


"""
Bar chart demo with pairs of bars grouped for easy comparison.
"""
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.patches as mpatches

def multibar():
    n_groups = 10
    data = [[ 152, 281, 127, 43,  120,210,74,13,1,0], ## big
            [ 712, 543, 587, 543, 493,481,478,406,573,952], ## equal
            ]
    small = (136, 176, 286, 414, 387,309,448,581,426,48)

    fig, ax = plt.subplots()

    opacity = 0.4
    error_config = {'ecolor': '0.3'}

    ## single bar

    columns = ('$Class_{1}$', '$Class_{2}$', '$Class_{3}$', '$Class_{4}$', '$Class_{5}$','$Class_{6}$','$Class_{7}$','$Class_{8}$','$Class_{9}$','$Class_{10}$')

    # Get some pastel shades for the colors

    index = np.arange(len(columns))
    bar_width = 0.4

    # Initialize the vertical-offset for the stacked bar chart.
    y_offset = np.zeros(len(columns))
    #for row in range(2):## single bar have 2 part.
    plt.bar(index, data[0], bar_width, bottom=y_offset, color='#99FFFF', label = '$max_i > CP_i$')
    y_offset = y_offset + data[0]
    plt.bar(index, data[1], bar_width, bottom=y_offset, color='#00CC00',label = '$max_i = CP_i$')

    rects2 = ax.bar(index + bar_width, small, bar_width,
                    alpha=opacity, color='r',
                    error_kw=error_config,
                    label='$max_i$ < $CP_{i}$')
    ## set label name
    ax.set_xlabel('Class')
    ax.set_ylabel('Number of comparisons')
    ax.set_title('Comparison of CP set and Max set ')

    ## set ticks size
    ax.set_xticks(index + bar_width / 2)
    ax.set_xticklabels(columns)

    ## set class_i size
    #ax.xaxis.set_tick_params(labelsize=28)

    ## set legend position
    ax.legend(loc = 'best')

    ## set font
    '''
    font = {'family' : 'normal',
                'weight' : 'bold',
                'size'   : 20}
    plt.rc('font',**font)
    '''

    fig.tight_layout()

    ## save svg file
    #plt.savefig("/home/newslab/Pictures/schedule/test.svg")
    plt.show()

if __name__=="__main__":
    fo = open('resultComparison.txt','r')

    multibar()


# Future
from __future__ import division, print_function, unicode_literals

# Standard Library
from builtins import str

# Third Party
import pytest

# DocumentCloud
from documentcloud.exceptions import APIError

class TestSection:
    def test_create_delete(self, document_factory):
        document = document_factory()
        assert len(document.sections.list().results) == 0
        section = document.sections.create("Test Section", 0)
        assert len(document.sections.list().results) == 1

        # may not have two sections on the same page
        with pytest.raises(APIError):
            document.sections.create("Test Section 2", 0)

        section.delete()
        assert len(document.sections.list().results) == 0

    def test_str(self, document):
        assert str(document.sections[0])

    def test_page(self, document):
        assert document.sections[0].page == 0


#DONE: add all 2136 kanji to KanjiKard class
#TODO: create a basic UI
#TODO: allow user to make sets of cards
#TODO: make a practice mode that allows users to practice sets ok cards
#TODO: make algorithms to help determine how often and which cards show up in practice
#DONE: let user browse all kanji
#DONE: allow user to save data locally
#DONE: make load function to read saved local data
#DONE: make a search function that allows user to search by multiple different elements
#TODO: impliment an optional timer for practice mode
#TODO: make links to jishoo.org for further imformation regarding specific kanji
#TODO: other stuff
#DONE: use html scrubbing to load all kanji
#DONE: implement function to take all loaded kanji[] and put them into the KanjiKard class
#DONE: implement functions to traverse and search the doubly linked list of the KanjiKard class
import re
import struct
import os
from struct import *
from bs4 import BeautifulSoup

import re
import struct
from struct import *

class KanjiKard:
    """The class for KanjiKards"""
    kanji = ""      # The kanji character
    reading = ""    # The hiragana reading of character
    romanji = ""    # The romanji (english alphabet) reading
    english = ""    # The english meaning of the character
    grade_level = 1 # The grade level for which the character is learned
    learned = False # False until user has gotten a right/wrong ratio of 2
    num_attempts = 0# The number of attempts the user has used for the character
    num_right = 0   # The number of correct attempts
    num_wrong = 0   # The number of incorrect attempts
    daily_correct = 0
    daily_wrong = 0
    daily_easy = 0

    def __init__(self):
        self.next = None# pointer to next
        self.prev = None# pointer to previous

class User:
    def __init__(self):
        self.current_learned = []
        self.not_learned = []
        self.to_study = []
        self.user_sets = [[]]
    def add_learned(self, kard):
        self.current_learned.append(kard)
    def remove_learned(self, kard):
        self.current_learned.remove(kard)
    def add_not_learned(self, kard):
        self.not_learned.append(kard)
    def remove_not_learned(self, kard):
        self.not_learned.remove(kard)
    def add_to_study(self, kard):
        self.to_study.append(kard)
    def remove_to_study(self, kard):
        self.to_study.remove(kard)
    def add_user_set(self, head):
        adding = 1
        i = 0
        #bool deleted = False
        for item in self.user_sets:

            if item == []:
                print("item:", item)
                break
            if i == 9:
                print("You have the maximum number of sets. Would you like to delete one and mae a new set(y/n)?:")
                delete_set = input()
                if delete_set == 'y':
                    j = 0
                    print("Enter the number that appears next to the set you wish to delete:\n")
                    while j <= 9:
                        print(j+1," " ,self.user_sets[j][0], "\n")
                        j += 1
                    delete_num = input()
                    i = delete_num - 1
                    break
            i += 1

        print("TEST set:", self.user_sets)
        print("TEST set:[i]", self.user_sets[i])
        self.user_sets.append([])
        self.user_sets[i].append("new set" + str(i))
        #print("TEST set:[0]", self.user_sets[0])
        print("TEST set:", self.user_sets)
        #self.user_sets[i][0] = "new set" + str(i)
        print("Name your new set (press enter for default name):\n")
        new_set_name = input()
        if new_set_name == "":
            self.user_sets[i][0] = "new set" + str(i)
        else:
             self.user_sets[i][0] = new_set_name
        print("TEST set:", self.user_sets)
        while adding == 1:
            print("Would you like to search for kards to add or browse all kards?\n")
            print("press 1.) to search, 2.) to browse, or q.) to quit:")
            choice = input()
            print("inpiut:", choice)
            if choice == '1':
                temp = []
                temp = search(head)
                print("Which kard would you like to add(enter the number, 0 for none)?\n" )
                for kard in temp:
                    print(kard.kanji,":", kard.reading, ":", kard.romanji, ":", kard.english )
                kard_num = input()
                if kard_num == '0':
                    continue
                else:
                    self.user_sets[i].append(temp[int(kard_num) - 1])

            elif choice == '2':
                curr = KanjiKard()
                curr = head

                while curr.kanji != None:
                    print("Enter q to quit browsing\n")
                    print("would you like to add the following kard (y/n)?\n" )
                    print(curr.kanji,":", curr.reading, ":", curr.romanji, ":", curr.english )
                    user_y_n = input()
                    if user_y_n == 'y':
                        self.user_sets[i].append(curr)
                    elif user_y_n == 'q':
                        break
                    curr = curr.next
            elif choice == 'q':
                adding = 2
            print("TEST set:", self.user_sets)
"""
 = KanjiKard()
.kanji = ""
.reading = ""
.romanji = ""
.english = ""
.grade_level = 1
.learned = False
.num_attempts = 0
.num_right = 0
.num_wrong = 0
.daily_correct = 0
.daily_wrong = 0
.daily_easy = 0
.next =
.prev =
"""
#num_attempts, num_right, and num_wrong should always be initialized to 0 unless user data is loaded

head = KanjiKard() # This is the head to the list of KanjiKards
head.kanji = '頭'
head.english = 'head'
head.grade_level = 2
head.reading = 'あたま'
head.romanji = 'atama'
head.next = KanjiKard()

def no_save_file(head):
    temp = KanjiKard()
    temp = head
    count = 0
    after = KanjiKard()

    kanji_file = open("KanjiKard_list_V1.txt", "r")
    it = 0
    for line in kanji_file:
        kanji_in = line
        kanji_in = kanji_in[0:len(kanji_in)-1]
        if line == '\n':
            print("New line")
        elif line == None:
            print("None")
        elif it == 0:
            after.kanji = kanji_in
        # print(after.kanji)
            it += 1
        elif it == 1:
            after.reading = kanji_in
            #print(after.reading)
            it += 1
        elif it == 2:
            after.romanji = kanji_in
            #print(after.romanji)
            it += 1
        elif it == 3:
            after.english = kanji_in
            #print(after.english)
            it += 1
        elif it == 4:
            if kanji_in == 9:
                after.grade_level = "taught in junior high"
                #print(after.grade_level)
                it += 1
            else:
                after.grade_level = kanji_in
                #print(after.grade_level)
                it += 1
        elif it == 5:
            it = 0
            after.prev = temp
            temp.next = after
            temp = after
            after.next = KanjiKard()
            after = after.next
    kanji_file.close()

def save(head):
    save_file = open("KanjiKard_save.txt", "w")
    temp = KanjiKard()
    temp = head
    while temp.kanji != None:
        if temp.next == None:
            save_file.close()
            break
        save_file.write(temp.kanji)
        save_file.write('\n')
        save_file.write(temp.reading)
        save_file.write('\n')
        save_file.write(temp.romanji)
        save_file.write('\n')
        save_file.write(temp.english)
        save_file.write('\n')
        save_file.write(temp.grade_level)
        save_file.write('\n')
        save_file.write(temp.learned)
        save_file.write('\n')
        save_file.write(temp.num_atempts)
        save_file.write('\n')
        save_file.write(temp.num_right)
        save_file.write('\n')
        save_file.write(temp.num_wrong)
        save_file.write('\n')
        save_file.write(temp.daily_correct)
        save_file.write('\n')
        save_file.write(temp.daily_wrong)
        save_file.write('\n')
        save_file.write(temp.daily_easy)
        save_file.write('\n')
        temp = temp.next

def load(head):
    if not os.path.isfile("KanjiKard_save.txt"):
        no_save_file(head)
        return

    load_file = open("KanjiKard_save.txt", "r")
    temp = KanjiKard()
    temp = head
    after = KanjiKard()
    count = 0
    it = 0
    for line in load_file:
        in_line = line
        in_line = in_line[0:len(in_line) - 1]
        if line == '\n':
            continue
        elif line == None:
            continue
        elif it == 0:
            after.kanji = in_line
            it += 1
        elif it == 1:
            after.reading = in_line
            it += 1
        elif it == 2:
            after.romanji = in_line
            it += 1
        elif it == 3:
            after.english = in_line
            it += 1
        elif it == 4:
            after.grade_level = in_line
            it += 1
        elif it == 5:
            after.learned = in_line
            it += 1
        elif it == 6:
            after.num_attempts = in_line
            it += 1
        elif it == 7:
            after.num_right = in_line
            it += 1
        elif it == 8:
            after.num_wrong = in_line
            it += 1
        elif it == 9:
            after.daily_correct = in_line
            it += 1
        elif it == 10:
            after.daily_wrong = in_line
            it += 1
        elif it == 11:
            after.daily_easy = in_line
            it += 1
        elif it == 12:
            it = 0
            after.prev = temp
            temp.next = after
            temp = after
            after.next = KanjiKard()
            after = after.next
    load_file.close()

def load_user(head):
    temp = KanjiKard()
    temp = head
    new_user = User()
    while temp.kanji != None:
        # Here we check where the kard belongs
        # that is to_study, learned, not_learned
        if temp.learned == False:
            new_user.add_not_learned(temp)
        elif temp.learned == True:
            new_user.add_learned(temp)
        if temp.num_right > 2*temp.num_wrong:
            new_user.add_learned(temp)
            temp.learned = True
        elif temp.num_wrong > 0:
            new_user.add_to_study(temp)
        if temp.next == None:
            return new_user
        temp = temp.next

def update_user(head, cur_user):
    temp = KanjiKard()
    temp = head
    while temp.kanji != None:
        if temp.num_right > 2*temp.num_wrong:
            cur_user.add_learned(temp)
            temp.learned = True
            if temp in cur_user.not_learned:
                cur_user.remove_not_learned(tmep)
        elif temp.num_wrong > 0:
            cur_user.add_to_study(temp)
        else:
            cur_user.add_not_learned(temp)
            temp.learned = False
            if temp in cur_user.current_learned:
                cur_user.remove_learned(temp)
        if temp.daily_easy > 2:
            temp.add_learned(temp)
            temp.learned = True
            if temp in cur_user.not_learned:
                cur_user.remove_not_learned(tmep)
        if temp.daily_wrong > 1:
            temp.add_to_study(temp)
        if temp.daily_correct > 2*tmep.daily_wrong:
            if temp.daily_correct - tmep.daily_wrong > 10:
                cur_user.add_learned(temp)
                if temp in cur_user.not_learned:
                    cur_user.remove_not_learned(tmep)
        if temp.next == None:
            return cur_user
        temp = tmep.next

# the below will be used every time an answer is submitted for a card
def update_on_kard(temp, cur_user):
    if temp.num_right > 2*temp.num_wrong:
        cur_user.add_learned(temp)
        temp.learned = True
        if temp in cur_user.not_learned:
            cur_user.remove_not_learned(tmep)
    elif temp.num_wrong > 0:
        cur_user.add_to_study(temp)
    else:
        cur_user.add_not_learned(temp)
        temp.learned = False
        if temp in cur_user.current_learned:
            cur_user.remove_learned(temp)
    if temp.daily_easy > 2:
        temp.add_learned(temp)
        temp.learned = True
        if temp in cur_user.not_learned:
            cur_user.remove_not_learned(tmep)
    if temp.daily_wrong > 1:
        temp.add_to_study(temp)
    if temp.daily_correct > 2*tmep.daily_wrong:
        if temp.daily_correct - tmep.daily_wrong > 10:
            cur_user.add_learned(temp)
            if temp in cur_user.not_learned:
                cur_user.remove_not_learned(tmep)

def print_all(head): #prints all members of each KanjiKard
    temp = KanjiKard()
    temp = head
    temp_kanji = temp.kanji
    while temp_kanji != None:
        if temp.next == None:
            break
        print(temp.kanji,":", temp.reading, ":", temp.english )
        temp = temp.next
        temp_kanji = temp.kanji

def print_all_kanji(head): #prints only the kanji for each KanjiKard
    temp = KanjiKard()
    temp = head
    temp_kanji = temp.kanji
    while temp_kanji != None:
        if temp.next == None:
            break
        print(temp.kanji)
        temp = temp.next
        temp_kanji = temp.kanji

def findWholeWord(w):
    return re.compile(r'\b({0})\b'.format(w), flags=re.IGNORECASE).search

def search(head): #searches list for target kanji and returns pointer to that KanjiKard
    return_list = []
    print("Enter the romanji spelling, English word, hiraganna/katakanna, or kanji character for the kanji you want to search for: ")
    target = input()
    temp = KanjiKard()
    temp = head
    temp_kanji = temp.kanji
    num_found = 0
    while temp_kanji != None:
        if temp.next == None:
            if num_found == 0:
                print(target, "could not be found")
            else:
                print(target, "found", num_found, "times")
            break
        if temp.romanji == target or temp.english == target or temp.kanji == target or temp.reading == target or findWholeWord(target)(temp.english):
            print("Found", target)
            print(temp.kanji,":", temp.reading, ":", temp.romanji, ":", temp.english )
            print('\n')
            num_found += 1
            return_list.append(temp)
            #return temp

        temp = temp.next
        temp_kanji = temp.kanji
    return return_list

def clear():
    os.remove("KanjiKard_save.txt")
    no_save_file(head)

def end():
    global running
    global head
    running = 0
    save(head)

actions = {
    '1': print_all_kanji,
    '2': print_all,
    '3': search,
    '4': update_user,
    '5': clear,
    'q': end
}
running = 1
load(head)
cur_user = User()

cur_user = load_user(head)

while(running):
    print("Welcome\n")
    print("Available actions:\n")
    print("1.) display all kanji\n")
    print("2.) display all kanji : readings : meaning\n")
    print("3.) search for kanji\n")
    print("4.) refresh user data\n")
    print("5.) clear user data\n")
    print("6.) create a new kard set\n")
    print("q.) quit\n")
    print("Enter the number of the action you wish to execute: ")
    action = input()
    if action == 4:
        update_user(head, cur_user)
    if action == 5:
        cur_user = User()
    if action == '6':
        cur_user.add_user_set(head)
    else:
        actions[action](head)

"""
Turn
ing in "final" code that produces debugging output is bad form, and points may be deducted if you
have extensive debugging output. We suggest you the following:
o
Near the top of your program write a debug function that can be turned on and off by changing
a
single variable. For example,
debugging = True
def
debug(*s):
if
debugging:
print
(*s)
o
Where you want to produce debugging output use
:
debug(”This is my debugging output”)
instead of
print
.
o
(
How it works
: Using * in front of the parameter of a
function means that a
variable number
of arguments can be passed to that parameter. Then using *s as print
’
s
argument passes
along those arguments to print.)

"""


'''
Description: https://blog.csdn.net/qq_45859188
Author: NEFU AB_IN
version: 1.0
Date: 2021-03-08 20:28:04
LastEditors: NEFU AB_IN
LastEditTime: 2021-05-05 12:27:06
'''
l = list()
for n in range(100):
    i = 1
    j = 1
    b = set()
    while n - 2 * i >= 0:
        b.add(2 * l[n - i] - l[n - 2 * i])
        i += 1
        while j in b:
            b.remove(j)
            j += 1
            l.append(j)
print(*l)


#!/usr/bin/env python3

# https://docs.python.org/3/howto/curses.html

import curses
from curses import wrapper

def main(stdscr):
    stdscr.clear()
    stdscr.border()
    stdscr.addstr('asdf')
    stdscr.addstr(10, 40, 'qwerty')
    stdscr.addstr(4, 4, 'something')
    stdscr.getkey()

wrapper(main)


# Task3

import time
from inspect import signature
import numpy as np
import inspect

class decorator3:
  def __init__(self,fun):
     self.fun= fun
     decorator3.fun1 = fun
     decorator3.source = inspect.getsource(fun)
     self.arguments= []
     decorator3.count= 0
     self.exe_time = 0

  def __call__(self,*args):
    start_time = 0
    decorator3.count+= 1
    self.output = self.fun(*args)
    start_time = time.time()
    self.fun(*args)
    self.exe_time = time.time() - start_time
    res = ''
    res = ' ' + str(decorator3.fun1.__name__) + ' ' + 'call:' + ' ' + str(self.count) + ' ' + 'executed in' + ' ' + str(format(self.exe_time, '.8f')) + ' ' + 'sec' + '\n'
    self.docstring = decorator3.fun1.__doc__
    self.type1 = type(self.fun)
    self.name = self.fun.__name__
    self.output = self.fun(*args)
    self.key =[]
    self.value =[]
    self.signature = inspect.signature(self.fun)
    self.Keyworded = {
        k: v.default
        for k, v in self.signature.parameters.items()
        if v.default is not inspect.Parameter.empty
    }
    self.positional = [
        k
        for k, v in self.signature.parameters.items()
        if v.default is inspect.Parameter.empty
    ]

    res += 'Name:' + '\t' + str(self.name) + '\n'
    res += 'Type:' + '\t' + str(self.type1) + '\n'
    res += 'Sign:' + '\t' + str(self.signature) + '\n'
    res += 'Args:'  + '\t' + 'positional' + str(self.positional) + '\n'
    res += '    '  + '\t' + 'Key=worded' + str(self.Keyworded) + '\n'
    res += 'Docs:'  + '\t' + str(self.docstring) + '\n'
    res += 'Source:'+ '\t' + decorator3.source + '\n'
    res += 'Output:' + '\t' + str(self.output)

    with open('Dumped.txt', 'w') as dump:
      dump.write(res)
    with open('Dumped.txt', 'r') as dump1:
      read = dump1.read()
    print(read)
    return self.exe_time


# Copyright 2021 AI Singapore. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Union, List
import pandas as pd
import numpy as np
from sklearn import metrics

from rarity.app import app
from rarity.data_loader import CSVDataLoader, DataframeLoader
from rarity.utils.common_functions import is_regression, is_classification

ERR_DESC = ['Mean Absolute Error', 'Mean Squared Error', 'Root Mean Squared Error', 'R Squared']
ERR_NAMES = ['MAE', 'MSE', 'RMSE', 'R2']

MAE_PATH = app.get_asset_url('MAE.png')
MSE_PATH = app.get_asset_url('MSE.png')
RMSE_PATH = app.get_asset_url('RMSE.png')
R2_PATH = app.get_asset_url('R2.png')
METRICS_FORMULA = [f'![MAE]({MAE_PATH})', F'![MSE]({MSE_PATH})',
                    f'![RMSE]({RMSE_PATH})', f'![R2]({R2_PATH})']

ERR_METRICS_DICT = {}
ERR_METRICS_DICT['Metrics Description'] = ERR_DESC
ERR_METRICS_DICT['Formula'] = METRICS_FORMULA
ERR_METRICS_DICT['Metrics Name'] = ERR_NAMES

class IntGeneralMetrics:
    """
    Transform raw data into input format suitable for visualization. General metrics cover
    confusion matrix, classification report, roc curve and precisionRecall curve

    Arguments:
        data_loader (:class:`~rarity.data_loader.CSVDataLoader` or :class:`~rarity.data_loader.DataframeLoader`):
            Class object from data_loader module

        viz_plot (str):
            Supported visualization types : ``confMat``, ``classRpt``, ``rocAUC``, ``preRacall``, ``stdErr``, None

    Important Attributes:

        - analysis_type (str):
            Analysis type defined by user during initial inputs preparation via data_loader stage.

    Returns:
        :obj:`~pd.DataFrame`:
            Dataframe with essential info suitable for visualization on regression task

    .. note::

            if classification, returns:

            - yTrue data in :obj:`~pd.Series`
            - yPred data in :obj:`~pd.Series` for [``confMat``, ``classRpt``] or :obj:`~pd.Dataframe` for [``rocAuc``, ``precRecall``]

            If multiclass, returns:

            - yPred data in :obj:`List[List[Tuple]]` pairing class label and yPred in :obj:`~pd.Series`
            - model_names in :obj:`List[str]`
    """
    def __init__(self, data_loader: Union[CSVDataLoader, DataframeLoader], viz_plot: str = None):
        self.data_loader = data_loader
        self.viz_plot = viz_plot
        self.analysis_type = self.data_loader.get_analysis_type()

    def _std_err_metrics(self, yTrue: pd.Series, yPred: pd.Series) -> List:
        mae = metrics.mean_absolute_error(yTrue, yPred)
        mse = metrics.mean_squared_error(yTrue, yPred)
        rmse = np.sqrt(metrics.mean_squared_error(yTrue, yPred))
        r2_score = metrics.r2_score(yTrue, yPred)
        return [int(mae), int(mse), int(rmse), round(r2_score, 4)]

    def xform(self):
        '''
        Core transformation function to tap-out data into input format suitable for plotly graph
        '''
        if is_regression(self.analysis_type):
            if self.viz_plot == 'stdErr':
                yTrue = self.data_loader.get_yTrue()
                yPreds = self.data_loader.get_yPreds()
                models = self.data_loader.get_model_list()
                if len(models) == 1:
                    ERR_METRICS_DICT[f'Model_{models[0]}'] = self._std_err_metrics(yTrue, yPreds)
                elif len(models) > 1:
                    for i in range(len(models)):
                        ERR_METRICS_DICT[f'Model_{models[i]}'] = self._std_err_metrics(yTrue, yPreds[yPreds.columns[i]])
                df = pd.DataFrame(ERR_METRICS_DICT)
            else:
                df = self.data_loader.get_all()
            return df

        elif is_classification(self.analysis_type):
            model_names = self.data_loader.get_model_list()
            yTrue = self.data_loader.get_yTrue()
            yTrue = yTrue['yTrue'].astype('string')
            preds = self.data_loader.get_yPreds()

            if self.viz_plot in ['confMat', 'classRpt']:
                yPred = [pred['yPred-label'] for pred in preds]
            elif self.viz_plot in ['rocAuc', 'precRecall']:
                yPred = [pred[pred.columns[-3]] for pred in preds]
                is_multiclass = len(set(yTrue)) > 2
                if is_multiclass:
                    yPred = []
                    for pred in preds:
                        label_keys = pred['yPred-label']
                        pred_values = pred[pred.columns[:-2]].max(axis=1)
                        pred_tmp = [(label_keys[i], pred_values[i]) for i in range(len(label_keys))]
                        yPred.append(pred_tmp)
            return yTrue, yPred, model_names


from data.loader2 import *
from deep_learning.preprocess.preprocess import *
from deep_learning.preprocess.visualize import *
from deep_learning.train.train3 import *
from deep_learning.test import *
from deep_learning.postprocess import *
import logging
import json

with open('params/steel-3.json') as f:
    params = json.loads(f.read())
    f.close()

logfile = LOG_DIR + params['name'] + '-' + params['id'] + '.log'

logger = logging.getLogger(params['logger_name'])
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler(logfile,'w')
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)

logger.info("Starting Pipeline...")

pp = PreProcess(params)
pp.process_dataframe()
#pp.run_check_augument()

#viz = Visualize(params)
#viz.visualize_images()

loader = Loader2(pp,params)
loader.process_data()
#loader.run_check_loader()
#
train = Train3(loader,params)
train.process_train_segmentation()

#test = Test(loader,params)
#test.process_segmentation()

logger.info("End Pipeline")

logging.shutdown()


import random

no=random.randint(0,20)
chances=5
used=0

print("Number guessing game :-")

while chances>0:
    used+=1
    i=int(input("Guess a number between 0-20: "))

    if i==no:
        print("You won the game in ",str(used)," chances !")
        break
    elif i<no:
        print("Sorry, guessed number is lessar than winning number.")
    elif i>no:
        print("Sorry, guessed number is greater that winning number.")

    chances-=1

if chances==0:
    print()
    print()
    print("You lose !")
    print("The number was, ",no)


'''VGG11/13/16/19 in Pytorch.'''
import torch
import torch.nn as nn

class SM_BatchNorm2d(nn.BatchNorm2d):
    def __init__(self, num_features, eps=1e-5, momentum=0.1,
                 affine=True, track_running_stats=True):
        super(SM_BatchNorm2d, self).__init__(
            num_features, eps, momentum, affine, track_running_stats)

    def forward(self, input):
        self._check_input_dim(input)

        exponential_average_factor = 0.0

        if self.training and self.track_running_stats:
            if self.num_batches_tracked is not None:
                self.num_batches_tracked += 1
                if self.momentum is None:  # use cumulative moving average
                    exponential_average_factor = 1.0 / float(self.num_batches_tracked)
                else:  # use exponential moving average
                    exponential_average_factor = self.momentum

        # calculate running estimates
        if self.training:
            mean = input.mean([2, 3])
            # print('mean size:', mean.size())
            # use biased var in train
            var = input.var([0, 2, 3], unbiased=False)
            # print('variance size:', var.size())
            n = input.numel() / input.size(1)
            with torch.no_grad():
                for i in range(mean.size(0)):
                    self.running_mean = exponential_average_factor * mean[i]\
                        + (1-exponential_average_factor) * self.running_mean
                    # self.running_mean = exponential_average_factor * mean\
                        # + (1 - exponential_average_factor) * self.running_mean
                # update running_var with unbiased var
                self.running_var = exponential_average_factor * var * n / (n - 1)\
                    + (1 - exponential_average_factor) * self.running_var
            input = (input - mean[:, :, None, None]) / (torch.sqrt(var[None, :, None, None] + self.eps))
        else:
            mean = self.running_mean
            var = self.running_var
            input = (input - mean[None, :, None, None]) / (torch.sqrt(var[None, :, None, None] + self.eps))

        if self.affine:
            input = input * self.weight[None, :, None, None] + self.bias[None, :, None, None]

        return input

cfg = {
    'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}

class VGG_SM_Batch(nn.Module):
    def __init__(self, vgg_name):
        super(VGG_SM_Batch, self).__init__()
        self.features = self._make_layers(cfg[vgg_name])
        self.classifier = nn.Linear(512, 10)

    def forward(self, x):
        out = self.features(x)
        out = out.view(out.size(0), -1)
        out = self.classifier(out)
        return out

    def _make_layers(self, cfg):
        layers = []
        in_channels = 3
        for x in cfg:
            if x == 'M':
                layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
            else:
                layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1),
                           SM_BatchNorm2d(x),
                           nn.ReLU(inplace=True)]
                in_channels = x
        layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
        return nn.Sequential(*layers)

def test():
    net = VGG('VGG11')
    x = torch.randn(2,3,32,32)
    y = net(x)
    print(y.size())

# test()


import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms

import torch.nn.functional as F
from torch.utils.tensorboard import SummaryWriter

from nets.simple_feedforward import FeedFowardNet

# tensorboard --logdir=logs --host=127.0.0.1
writer = SummaryWriter("logs/mnist1")

# Device configuration
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Hyper-parameters
input_size = 784  # 28x28
hidden_size = 100
num_classes = 10
num_epochs = 1
batch_size = 4
learning_rate = 0.01

# MNIST dataset
train_dataset = torchvision.datasets.MNIST(
    root="./data", train=True, transform=transforms.ToTensor(), download=True
)

test_dataset = torchvision.datasets.MNIST(
    root="./data", train=False, transform=transforms.ToTensor()
)

# Data loader
train_loader = torch.utils.data.DataLoader(
    dataset=train_dataset, batch_size=batch_size, shuffle=True
)

test_loader = torch.utils.data.DataLoader(
    dataset=test_dataset, batch_size=batch_size, shuffle=False
)

examples = iter(test_loader)
example_data, example_targets = examples.next()

img_grid = torchvision.utils.make_grid(example_data)
writer.add_image("mnist_images", img_grid)

# Fully connected neural network with one hidden layer
model = FeedFowardNet(input_size, hidden_size, num_classes).to(device)

# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

writer.add_graph(model, example_data.reshape(-1, 28 * 28))

# Train the model
running_loss = 0.0
running_correct = 0
n_total_steps = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # origin shape: [100, 1, 28, 28]
        # resized: [100, 784]
        images = images.reshape(-1, 28 * 28).to(device)
        labels = labels.to(device)

        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)

        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

        _, predicted = torch.max(outputs.data, 1)
        running_correct += (predicted == labels).sum().item()
        if (i + 1) % 100 == 0:
            print(
                f"Epoch [{epoch+1}/{num_epochs}], "
                + f"Step [{i+1}/{n_total_steps}], "
                + f"Loss: {loss.item():.4f}"
            )
            writer.add_scalar(
                "training loss", running_loss / 100, epoch * n_total_steps + i
            )
            writer.add_scalar(
                "accuracy", running_correct / 100, epoch * n_total_steps + i
            )
            running_correct = 0
            running_loss = 0.0

# Test the model
# In test phase, we don't need to compute gradients (for memory efficiency)
class_labels = []
class_preds = []
with torch.no_grad():
    n_correct = 0
    n_samples = 0
    for images, labels in test_loader:
        images = images.reshape(-1, 28 * 28).to(device)
        labels = labels.to(device)
        outputs = model(images)
        # max returns (value ,index)
        values, predicted = torch.max(outputs.data, 1)
        n_samples += labels.size(0)
        n_correct += (predicted == labels).sum().item()

        class_probs_batch = [F.softmax(output, dim=0) for output in outputs]

        class_preds.append(class_probs_batch)
        class_labels.append(predicted)

    # 10000, 10, and 10000, 1
    # stack concatenates tensors along a new dimension
    # cat concatenates tensors in the given dimension
    class_preds = torch.cat([torch.stack(batch) for batch in class_preds])
    class_labels = torch.cat(class_labels)

    acc = 100.0 * n_correct / n_samples
    print(f"Accuracy of the network on the 10000 test images: {acc} %")

    classes = range(10)
    for i in classes:
        labels_i = class_labels == i
        preds_i = class_preds[:, i]
        writer.add_pr_curve(str(i), labels_i, preds_i, global_step=0)
        writer.close()


#!/usr/bin/python
# Track target(s) for a specified time.

# The *with* keyword is standard in Python 2.6, but has to be explicitly imported in Python 2.5
from __future__ import with_statement
import numpy as np
import time
from katcorelib import collect_targets, standard_script_options, verify_and_connect,  start_session, user_logger
import katpoint

# Set up standard script options
parser = standard_script_options(usage="%prog [options] <'target/catalogue'> [<'target/catalogue'> ...]",
                                 description='Track one or more sources for a specified time. At least one '
                                             'target must be specified. Note also some **required** options below.')
# Add experiment-specific options
parser.add_option('-t', '--track-duration', type='float', default=20.0,
                  help='Length of time to track each source, in seconds (default=%default)')
parser.add_option( '--scan-duration', type='float', default=20.0*7,
                  help='Length of time to take when scaning each source, in seconds (default=%default)')
parser.add_option( '--scan-spacing', type='float', default=2./60.,
                  help='The spacing between each scan  in degrees (default=%default)')

parser.add_option('-m', '--max-duration', type='float', default=None,
                  help='Maximum duration of the script in seconds, after which script will end '
                       'as soon as the current track finishes (no limit by default)')
parser.add_option( '--max-extent', type='float', default=15./60.,
                  help='Maximum extent in degrees, the script will scan ')
parser.add_option( '--number-of-steps', type='int', default=10,
                  help='Number of pointings to do while scaning , the script will scan ')
parser.add_option('-e', '--scan-in-elevation', action="store_true", default=False,
                  help="Scan in elevation rather than in azimuth (default=%default)")

# Set default value for any option (both standard and experiment-specific options)
parser.set_defaults(description='Target track',dump_rate=2.0)
# Parse the command line
opts, args = parser.parse_args()

if len(args) == 0:
    raise ValueError("Please specify at least one target argument via name ('Cygnus A'), "
                     "description ('azel, 20, 30') or catalogue file name ('sources.csv')")

# Check options and build KAT configuration, connecting to proxies and devices
with verify_and_connect(opts) as kat:
    args_target_list =[]
    observation_sources = katpoint.Catalogue(antenna=kat.sources.antenna)
    args_target_obj = collect_targets(kat,args)
    observation_sources.add(args_target_obj)
            #user_logger.info("Found %d targets from Command line and %d targets from %d Catalogue(s) " %
            #                         (len(args_target_obj),num_catalogue_targets,len(args)-len(args_target_list),))
    # Quit early if there are no sources to observe
    if len(observation_sources.filter(el_limit_deg=opts.horizon)) == 0:
        user_logger.warning("No targets are currently visible - please re-run the script later")
    else:
        # Start capture session, which creates HDF5 file
        with start_session(kat, **vars(opts)) as session:
            session.standard_setup(**vars(opts))
            session.capture_start()
            time_start = time.time()
            for target in observation_sources.iterfilter(el_limit_deg=opts.horizon):
                if time.time() - time_start  > opts.max_duration :
                    user_logger.info("Maximum duration of '%s' s reached "%(opts.max_duration))
                    break
                for offset_y in np.linspace(-opts.max_extent,opts.max_extent,opts.number_of_steps):
                    session.label('raster')
                    user_logger.info("Doing scan of '%s' with current azel (%s,%s) "%(target.description,target.azel()[0],target.azel()[1]))
                    session.raster_scan(target, num_scans=7, scan_duration=opts.track_duration/7., scan_extent=2.0*opts.max_extent,
                                                scan_spacing=opts.scan_spacing, scan_in_azimuth=not opts.scan_in_elevation,
                                                projection=opts.projection)
                    session.label('track')
                    session.set_target(target) # Set the target
                    session.track(target, duration=opts.track_duration, announce=False) # Set the target & mode = point
                    for offset_x in np.linspace(-opts.max_extent,opts.max_extent,opts.number_of_steps):
                        session.label('track')
                        user_logger.info("Initiating %g-second track on target '%s'" % (opts.track_duration, target.name,))
                        user_logger.info("Offset of %f,%f degrees " %(offset_x,offset_y))
                        session.set_target(target)
                        session.ants.req.offset_fixed(offset_x,offset_y,opts.projection)
                        nd_params = session.nd_params
                        session.fire_noise_diode(announce=True, **nd_params)
                        time.sleep(opts.track_duration) # Snooze


# -*- coding: utf-8 -*-
"""FAB - Edit Company's Directory Profile page"""
import logging

from requests import Response, Session

from tests import get_absolute_url
from tests.functional.utils.context_utils import Company, Message
from tests.functional.utils.generic import escape_html
from tests.functional.utils.request import Method, check_response, make_request

LANDING = get_absolute_url("ui-supplier:landing")
URL = "{}/{}".format(LANDING, 'suppliers/{company_number}/contact')
EXPECTED_STRINGS = [
    "Send a message to",
    ("Fill in your details and a brief message summarising your needs that will"
     " be sent to the UK company."), "Your full name:", "Your company name:",
    "Country:", "Your email address:", "Industry:",
    "Enter a subject line for your message:", "Maximum 200 characters.",
    "Enter your message to the UK company:", "Maximum 1000 characters.",
    "Captcha:", "I agree to the great.gov.uk terms and conditions", "Send",
    "cancel"
]

EXPECTED_STRINGS_MESSAGE_SENT = [
    "Message sent", "Your message has been sent to", "Browse more companies"
]

def go_to(session: Session, company_number: str, company_name: str) -> Response:
    """Go to Company's FAS profile page using company's number.

    :param session: Supplier session object
    :param company_number: company number
    :param company_name: name of the company
    :return: response object
    """
    full_url = URL.format(company_number=company_number)
    response = make_request(Method.GET, full_url, session=session)
    should_be_here(response, name=company_name)
    return response

def should_be_here(response, *, name=None):
    expected = EXPECTED_STRINGS + [escape_html(name)] if name else EXPECTED_STRINGS
    check_response(response, 200, body_contains=expected)
    logging.debug("Supplier is on FAS Contact Company page")

def submit(session: Session, message: Message, company_number: str):
    full_url = URL.format(company_number=company_number)
    headers = {"Referer": URL.format(company_number=company_number)}
    data = {
        "body": message.body,
        "company_name": message.company_name,
        "country": message.country,
        "email_address": message.email_address,
        "full_name": message.full_name,
        "g-recaptcha-response": message.g_recaptcha_response,
        "sector": message.sector,
        "subject": message.subject,
        "terms": message.terms
    }
    response = make_request(
        Method.POST, full_url, session=session, headers=headers, data=data)
    return response

def should_see_that_message_has_been_sent(company: Company, response: Response):
    expected = EXPECTED_STRINGS_MESSAGE_SENT + [escape_html(company.title)]
    check_response(response, 200, body_contains=expected)
    logging.debug("Buyer was told that the message has been sent")


import cv2 as cv
import numpy as np
import random

roi = cv.imread('picture5.jpg')

saltpepper_img = roi.copy()

noise_amount = (roi.shape[0]*roi.shape[1])*0.1

for i in range(int(noise_amount)):
    row = random.randint(0,roi.shape[0]-1)
    col = random.randint(0,roi.shape[1]-1)
    value = random.choice([255,0])
    for j in range(3):
        saltpepper_img.itemset(row,col,j,value)

cv.imwrite('./saltpepper.jpg',saltpepper_img)
cv.imshow('saltpepper',saltpepper_img)
cv.imshow('origin',roi)
cv.waitKey(0)
cv.destroyAllWindows()


from Tkinter import *
from SimpleTable import *
from TaskDownloader import Task
import json
import tkFileDialog
import urllib2

window = Tk()
window.title("ToDo list app")

json_file_uri = "https://raw.githubusercontent.com/TechnikumLacznosci/intro/master/files/tasks.json"

def instantiate_table(data_list):
    # Define number of columns
    column_count = len(data_list[0])
    # Define number of rows
    row_count = len(data_list)
    # Empty table object with size row_count x column_count
    table = SimpleTable(window, row_count, column_count)
    table.grid(row='0', column='0')

    def get_from_table(i, j, tab):
        return data_list[i][data_list[i].keys()[j]]

    # Fill table with values
    for i in range(0, row_count):
        for j in range(0, column_count):
            table.set(i, j, get_from_table(i, j, table))

# Add file dialog button
def call_file_dialog():
    file_extensions = [("JSON File", '*.json'), ("All files", '*')]
    window.filename = tkFileDialog.askopenfilename(initialdir = 'C:\\',
        title="Select file: ", filetypes = file_extensions)
    with open(window.filename, 'r') as json_file:
        data_list = json.load(json_file)
        # remove previous table
        window.nametowidget('tableWithTasks').grid_forget()
        instantiate_table(data_list)

def get_data_from_internet():
    try:
        task = Task(json_file_uri)
        task_list = task.get_all()
        instantiate_table(task_list)
    except urllib2.URLError:
        print("Failed to load the given URL")

def frame_with_buttons():
    button_frame = Frame(window)
    button_frame.grid(row='1', column='0')

    button_call_file_dialog = Button(button_frame, text="Choose file", command=call_file_dialog)
    button_call_file_dialog.grid(row='0', column='0')

# Fill table with the data from the internet
get_data_from_internet()
# Add buttons below the table
frame_with_buttons()

# Add form
add_form = Tk()
e0 = Entry(add_form)
e1 = Entry(add_form)
e2 = Entry(add_form)
e3 = Entry(add_form)
e4 = Entry(add_form)
Label(add_form, text="Data rozpoczecia").grid(row=0)
Label(add_form, text="Data zakończenia").grid(row=1)
Label(add_form, text="Tytuł").grid(row=2)
Label(add_form, text="Opis").grid(row=3)
Label(add_form, text="Flagi").grid(row=4)
e0.grid(row=0, column=2)
e1.grid(row=1, column=2)
e2.grid(row=2, column=2)
e3.grid(row=3, column=2)
e4.grid(row=4, column=2)
button_formularz1 = Button(add_form, text="Ok")
button_formularz1.grid(column=0, row=5)
button_formularz2 = Button(add_form, text="Anuluj")
button_formularz2.grid(column=1, row=5)

# Add 'Load tasks' button
button_call_table = Button(window, text="Załaduj zadania", command=get_data_from_internet)
button_call_table.grid(column='0', row='0')

button_call_file_dialog = Button(window, text="Wybierz plik", command=call_file_dialog)
button_call_file_dialog.grid(column='1', row='0')

# Run app
window.mainloop()


import sys

v = sys.version

if "3.%s" % v[2] not in v:
    print("This program is not presently designed to run in Python 2.X")
    sys.exit()
else:
    import tkinter as tk
    from random import randint
    from random import choice
    from tkinter import filedialog as fd
    from tkinter import messagebox as mb

# Todo: Add support for all bit depths!
# Todo: Add a "resolution" option!
# Todo: Add a "save to .txt" option and function!

def printer_kwargs(**kwargs):
    pass

def printer(hires=True, trueascii=False, simple=False, invert=False,
            brightness=0, glitch=False, dstyle=1):
    selectedfile = fd.askopenfile(mode='rb')
    with selectedfile as f:
        file_header = [i for i in f.read(14)]
        file_type = file_header[:2]
        if file_type != [66, 77]:
            # If the first two bytes aren't the ASCII values for "BM"...
            print("This is not a .bmp file.")
            raise AttributeError

        f.seek(18, 0)
        # Bytes 18 to 25 are for the image dimensions in pixels.
        img_dimen = [i for i in f.read(8)]
        img_w = sum([i*(16**(e*2)) for e, i in enumerate(img_dimen[:4])])
        img_h = sum([i*(16**(e*2)) for e, i in enumerate(img_dimen[4:])])
        img_numofbytes = img_w*img_h*3
        # ^^ This is how many bytes are the image's pixel data.
        # For the moment, this only supports 24-bit images. So w*h*3.

        pixel_data_offset = [str(i) for i in file_header[10:][::-1] if i != 0]
        # ^^ This is reversed to convert it from little to big endian.
        pdo_int = int("".join(pixel_data_offset))

        f.seek(pdo_int, 0)

        if (img_w*3) % 4:
            # If the image's width isn't divisible by four, null bytes have to
            # be taken into account or else the resulting image will be skewed.
            offset = (img_w*3) % 4
            img_numofbytes += offset * img_h
        else:
            offset = 0

        print("Image dimensions are %i by %i" % (img_w, img_h))
        print("Image pixel data begins at byte %i" % pdo_int)
        print("Null byte offset is %i" % offset)

        pixels = f.read(img_numofbytes)  # !!!ONLY SUPPORTS 24-BIT IMAGES!!!
        r = img_w*3 + offset  # Width of a row in bytes.
        # ONLY SUPPORTS 24-BIT IMAGES!!!
        pic_rows = [pixels[i:i+r] for i in range(0, len(pixels), r)][::-1]
        # ^^ This is reversed because the bytes in a
        # .bmp file start bottom to top.

        uniramp = ["  ", "-,", ",░", "░░", "░▒", "▒▒", "▒▓", "▓▓", "▓█", "██"]
        # This is the standard unicode ramp that is used for all of the
        # default parameters with no other modifications...
        asciiramp = " .:-=+*#%@"
        if hires:
            asciiramp = [i*2 for i in asciiramp]
        uni_simpleramp = "  ░░▒▒▓▓██"
        if hires:
            uni_simpleramp = [i*2 for i in uni_simpleramp]
        if simple or not hires:
            uniramp = uni_simpleramp
        if trueascii:
            uniramp = asciiramp
            brightness += 1
        if invert:
            uniramp.reverse()

        pixel_rows = []

        for row in pic_rows:  # This creates the rows exitof pixels.
            pixels_on_row = []
            for i in range(0, len(row)-offset, 3):
                # Subtracting the offset keeps the null bytes from being read
                # as pixel data.
                pixel = [i for i in row[i:i+3]]
                x = int(255/len(uniramp))
                # ^^ This calculates what to divide the lightness value by
                # to get its correct place in the ramp.
                pixval = int((pixel[2]*.21
                             + pixel[1]*.72
                              + pixel[0]*.07)//x) + brightness
                # ^^ This calculates the lightness of the given pixel, and
                # applies the brightness arg to increase or decrease
                # the resulting value.

                if pixval < 0:
                    pixval = 0
                if pixval > len(uniramp)-1:
                    pixval = len(uniramp)-1
                # ^^ Precaution to prevent invalid index values.
                if dstyle == 2:
                    pixval = uniramp[pixval][::choice([-1, 1])]
                else:
                    pixval = uniramp[pixval]

                pixels_on_row.append(pixval)

            if glitch:
                pixels_on_row = glitcher(pixels_on_row, offset, uniramp)

            pixel_rows.append("".join(pixels_on_row))

        if hires:
            for row in pixel_rows:
                print(row)
        else:
            for row in pixel_rows[::2]:
                print(row)
        f.seek(0, 0)

def glitcher(row, offset, ramp):
    will_shuffle = choice([True, False])
    will_invert = randint(0, 3)
    rrs = randint(0, (len(row) - offset // 4))  # Random row shuffle.
    if will_shuffle:
        row = row[rrs:] + row[:rrs]
    if will_invert == 0:
        row = [ramp[ramp[::-1].index(i)] for i in row]
    return row

try:
    printer(hires=False)
except AttributeError:
        print("Either no file was selected, the file failed to load, "
              + "or some other error was encountered.")
finally:
    sys.exit()


from requests.utils import requote_uri
import requests
import time
import hashlib
import macDb
import binascii

unknown="unknown"

def init(dbPath):
    macDb.init(dbPath)

def getMacManufacturerId(mac):
    if(mac != None and len(mac) >8):
        return mac[:8]
    else:
        return None

def hashedMac(mac):
    if(mac != None and mac != ""):
        m = hashlib.sha256()
        m.update(str.encode(mac, encoding="UTF-8"))
        digest = m.digest()
        hashStr = binascii.b2a_base64(digest, newline=False)
        return hashStr.decode("UTF-8")
    else:
        return None

def lookupMacRequest(mac):
    url = requote_uri("https://api.macvendors.com/{}".format(mac))
    r = requests.get(url)
    # just to avoid blacklisting
    time.sleep(1)
    if (r.status_code < 300):
        return r.text
    else:
        return unknown

def lookupMac(mac):
    macId = getMacManufacturerId(mac)
    dbResult = macDb.getManufacturer(macId)
    if(dbResult == None):
        name = lookupMacRequest(mac)
        if(name != unknown):
            macDb.store(macId, name)
        return name
    else:
        print("cache hit")
        return dbResult


import torch.utils.data as data
from torch.utils.data.dataset import Subset
from torchvision.datasets.folder import default_loader
from torchvision.transforms import functional as F
from PIL import Image
import os
import h5py
import numpy as np
import cv2
from scipy.io import loadmat
import torch

from PIL import Image

def get_dataset(config, data_transforms=None, test=False, limit=None):

    nyu_hdf5_loader = NYU_HDF5_Loader(config.data_dir, limit=limit, no_val=config.no_val)

    if test:
        datasets = {'test': NYU_Depth_V2(nyu_hdf5_loader,
                                         'test',
                                         transform = data_transforms['eval'],
                                         get_image_transform = data_transforms['eval'])
        }

    else:
        datasets = {'train': NYU_Depth_V2(nyu_hdf5_loader,
                                          'train',
                                          transform = data_transforms['train']['data'],
                                          target_transform = data_transforms['train']['target'],
                                          get_image_transform = data_transforms['eval']),
                    'val': NYU_Depth_V2(nyu_hdf5_loader,
                                        'val',
                                        transform = data_transforms['eval'],
                                        get_image_transform = data_transforms['eval'])
        }

    return datasets

detection_label_names_subset = ['BACKGROUND', 'bathtub', 'bed', 'bookshelf', 'box', 'chair', 'counter',
                      'desk', 'door', 'dresser', 'garbage bin', 'lamp', 'monitor',
                      'night stand', 'pillow', 'sink', 'sofa', 'table',
                      'television', 'toilet']

rock_val_scenes = ['bathroom_0039','bathroom_0041','bathroom_0049','bathroom_0051', 'bedroom_0098', 'bedroom_0104','bedroom_0106',
                   'bedroom_0107','bedroom_0113','bedroom_0116','bedroom_0118','bedroom_0120','bedroom_0124','bedroom_0125','bedroom_0126',
                   'bedroom_0129','bedroom_0130','classroom_0016','classroom_0018','conference_room_0002','dining_room_0028',
                   'dining_room_0031','dining_room_0034','home_office_0006','kitchen_0049','kitchen_0050','kitchen_0051','kitchen_0052',
                   'living_room_0062','living_room_0063','living_room_0068','living_room_0069','living_room_0070','living_room_0071',
                   'living_room_0078','office_0024','office_0026','playroom_0002','reception_room_0004','study_0006','study_room_0004']

all_scene_types = ['foyer', 'study', 'printer_room', 'home_storage', 'indoor_balcony', 'living_room', 'kitchen', 'computer_lab',
                   'bookstore', 'conference_room', 'laundry_room', 'reception_room', 'classroom', 'office', 'dining_room',
                   'basement', 'bedroom', 'bathroom', 'furniture_store', 'dinette', 'student_lounge', 'excercise_room',
                   'office_kitchen', 'study_room', 'playroom', 'cafe', 'home_office']

def get_bboxes_from_masks(instance_masks):
    bboxes = np.zeros((instance_masks.shape[2], 4), dtype=np.float32)
    #print(instance_masks.shape[0]) 480
    for ii in range(instance_masks.shape[2]):
        for i in range(instance_masks.shape[1]):
            if np.sum(instance_masks[:,i,ii]):
                bboxes[ii,0] = i # xmin
                break
        for i in reversed(range(instance_masks.shape[1])):
            if np.sum(instance_masks[:,i,ii]):
                bboxes[ii,2] = i # xmax
                assert bboxes[ii,2] > bboxes[ii,0], 'invalid width bbox'
                break
        for i in range(instance_masks.shape[0]):
            if np.sum(instance_masks[i,:,ii]):
                bboxes[ii,1] = i # ymin
                break
        for i in reversed(range(instance_masks.shape[0])):
            if np.sum(instance_masks[i,:,ii]):
                bboxes[ii,3] = i # ymax
                assert bboxes[ii,3] > bboxes[ii,1], 'invalid height bbox'
                break
    return bboxes

def get_instance_masks(img_object_labels, img_instances):

    H, W = img_object_labels.shape

    A = np.asarray([img_object_labels.reshape(-1,1), img_instances.reshape(-1,1)], dtype=np.uint16)
    pairs = np.unique(A, axis=1)
    pairs = pairs[:,np.sum(pairs, axis=0)!=0].transpose()

    N = pairs.shape[0]

    instance_masks = np.zeros((H,W,N))
    instance_labels = np.zeros((N,), dtype=np.int64)

    for ii in range(N):
        instance_masks[:,:,ii] = (img_object_labels == pairs[ii,0]) * (img_instances == pairs[ii,1])
        instance_labels[ii] = pairs[ii,0]
    return instance_masks, instance_labels

def sn_normalize(depthImg):
    mean = np.mean(depthImg)
    std = np.std(depthImg)
    out = depthImg.astype(np.float32) - mean
    out /= std
    out = np.clip(out, -1.5, 1.5)
    out = (out + 1.5) / 3.0
    return out

def compute_normals(depths, verbose=False):

    shape = list(depths.shape)
    shape.append(3)
    normals = np.zeros(tuple(shape))

    for i in range(depths.shape[0]):
        if verbose:
            print('Computing %d' % i)
        d_im = depths[i,:,:]
        surf = np.zeros((d_im.shape[0], d_im.shape[1], 3), dtype=np.float32)
        n = np.zeros(3, dtype=np.float32)

        img = np.array(d_im, dtype=np.float32)
        img = cv2.bilateralFilter(img, 25, 10, 10)
        img = cv2.copyMakeBorder(img, 1, 1, 1, 1, cv2.BORDER_REPLICATE)

        for x in range(0, d_im.shape[0]-1):
            for y in range(0, d_im.shape[1]-1):
                dzdx = (img[x+1,y] - img[x-1,y])/2.0
                dzdy = (img[x,y+1] - img[x,y-1])/2.0
                n[0]=-dzdx
                n[1]=-dzdy
                n[2]=1.0
                n /= np.linalg.norm(n)
                surf[x,y,0]=n.item(0)
                surf[x,y,1]=n.item(1)
                surf[x,y,2]=n.item(2)

        gauss = cv2.GaussianBlur(surf,(0,0),3)
        unsharp = cv2.addWeighted(surf,1.5,gauss,-0.5,0,surf)

        surf = sn_normalize(surf)

        normals[i,:,:,:] = surf

    return normals

class NYU_HDF5_Loader():
    """This is the HDF5 file reader for the NYU V2 Dataset

    It reads the hdf5 files and computes the indexes for the train, validation and test samples.
    It also implements the load_split function to load data in memory (used to pass it to the
    NYU_Depth_V2 class).
    """

    def __init__(self, root, limit=None, use_rock_val_scenes=True, no_val=0):
        # Begin by opening hdf5 file
        self.root = root
        self.limit = limit
        self.use_rock_val_scenes = use_rock_val_scenes
        self.no_val = no_val
        self.hdf5_dataset = h5py.File(os.path.join(self.root, 'nyu_depth_v2_labeled.mat'))
        # Open splits file and compute train - val - test splits indexes
        self.splits = loadmat(os.path.join(self.root, 'splits.mat'))
        self.split_idxs = {
            'train': self.splits['trainNdxs'].reshape(-1) - 1, # Matlab indexes start from 1
            'test': self.splits['testNdxs'].reshape(-1) - 1    # Matlab indexes start from 1 :)
        }
        self.objs = [obj for obj in self.hdf5_dataset['scenes'][0][self.split_idxs['train']]]
        self.scenes = [''.join(chr(c) for c in self.hdf5_dataset[obj]) for obj in self.hdf5_dataset['scenes'][0]]
        self.train_scenes = [''.join(chr(c) for c in self.hdf5_dataset[obj]) for obj in self.hdf5_dataset['scenes'][0][self.split_idxs['train']]]
        self.trainval_idxs = self._compute_trainval_idxs()
        self.idxs_dict = {
            'train': self.trainval_idxs[0],
            'val': self.trainval_idxs[1],
            'test': self.split_idxs['test'].tolist()
        }

    def _compute_trainval_idxs(self):
        scenes = list(set(self.train_scenes))

        train_scenes, val_scenes = set(), set()

        if self.no_val:
            print('Using the entire trainval set for training')
            train_idxs = self.split_idxs['train'].tolist()
            val_idxs = self.split_idxs['test'].tolist()
            return train_idxs, val_idxs

        elif self.use_rock_val_scenes:
            print('computing rock train-val splits using val scenes used in ROCK')
            for scene in scenes:
                if scene in rock_val_scenes:
                    val_scenes.add(scene)
                else:
                    train_scenes.add(scene)
        else:
            print('Computing random trainval set')
            for i in range(len(scenes)):
                if i % 6 == 0:
                    val_scenes.add(scenes[i])
                else:
                    train_scenes.add(scenes[i])

        train_idxs, val_idxs = [], []
        for i in self.split_idxs['train']:
            if self.scenes[i] in train_scenes:
                train_idxs.append(i)
            else:
                val_idxs.append(i)
        return train_idxs, val_idxs

    def load_split(self, phase='train', use_precomputed=True):

        assert phase in ['train', 'val', 'test']
        idxs = self.idxs_dict[phase][:self.limit]

        print('Loading NYU_Depth_V2 %s data in memory' % phase)
        images = self.hdf5_dataset['images'][idxs][()].transpose((0,3,2,1))
        labels = self.hdf5_dataset['labels'][idxs][()].transpose((0,2,1))
        instances = self.hdf5_dataset['instances'][idxs][()].transpose((0,2,1))
        depths = self.hdf5_dataset['depths'][idxs][()].transpose((0,2,1))

        if use_precomputed:
            normals = np.load('./data/normals.npy')[idxs]
        else:
            print('Calculating Surface Normals from Depth Maps')
            normals = compute_normals(depths * 25.5)

        names = [''.join(chr(c) for c in self.hdf5_dataset[obj]) for obj in self.hdf5_dataset['names'][0]]
        scene_types = [''.join(chr(c) for c in self.hdf5_dataset[obj]) for obj in self.hdf5_dataset['sceneTypes'][0][idxs]]
        scene_idxs = [all_scene_types.index(scene_type) for scene_type in scene_types]

        return idxs, images, labels, instances, depths, names, scene_idxs, normals

class NYU_Depth_V2(data.Dataset):

    def __init__(self, hdf5_loader, phase, transform=None, depth_transform=None, target_transform=None, get_image_transform=None,
                 detection=True, use_label_subset=True, remove_negatives_for_detection=True, compute_gaussian_masks=False):
        # init path and transforms
        self.transform = transform
        self.depth_transform = depth_transform
        self.target_transform = target_transform
        self.get_image_transform = get_image_transform
        self.compute_gaussian_masks = compute_gaussian_masks
        # Load data from loader
        data = hdf5_loader.load_split(phase)
        # Pointers to data
        self.ids = data[0]
        self.images = data[1]
        self.labels = data[2]
        self.instances = data[3]
        self.depths = data[4]
        self.names = data[5]
        self.scene_types = data[6]
        self.normals = data[7]
        # Logic to use only the provided subset labels
        self.use_label_subset = use_label_subset
        if use_label_subset:
            self.class_names = detection_label_names_subset
            self.labels_subset = [136, 157, 88, 26, 5, 7, 36, 28, 169, 12, 144, 49, 158, 119, 24, 83, 19, 172, 124]
            self.labels_to_subset_labels = {label: i+1 for i, label in enumerate(self.labels_subset)}
            self._use_label_subset()

        self.detection = detection
        if detection:
            self.bboxes, self.bboxes_labels = self._compute_bboxes()
            if remove_negatives_for_detection:
                to_remove_idxs = []
                for i in range(len(self.bboxes)):
                    if len(self.bboxes[i]) == 0:
                        to_remove_idxs.append(i)
                if len(to_remove_idxs):
                    self._remove_negatives(to_remove_idxs)

    def _remove_negatives(self, idxs):
        print('Removing %d samples without bboxes' % len(idxs))
        to_keep = [i for i in range(self.images.shape[0]) if i not in idxs]
        self.ids = [self.ids[i] for i in range(self.images.shape[0]) if i not in idxs]
        self.images = self.images[to_keep]
        self.labels = self.labels[to_keep]
        self.instances = self.instances[to_keep]
        self.depths = self.depths[to_keep]
        self.normals = self.normals[to_keep]
        self.scene_types = [self.scene_types[i] for i in range(len(self.scene_types)) if i not in idxs]
        self.bboxes = [self.bboxes[i] for i in range(len(self.bboxes)) if i not in idxs]
        self.bboxes_labels = [self.bboxes_labels[i] for i in range(len(self.bboxes_labels)) if i not in idxs]

    def _use_label_subset(self):
        print('Converting labels to only use the 19 classes subset')
        # create a mask for valid labels
        mask = np.isin(self.labels, self.labels_subset).astype(np.uint32)
        # use the mask to update instances and labels to use the 19 classes (everything else is set to zero)
        self.labels = self.labels * mask
        self.instances = self.instances * mask
        del mask

    def _compute_gaussian_masks(self):
        masks = np.zeros(self.depths.shape)

    def _compute_bboxes(self):
        bboxes = []
        bboxes_labels = []
        for i in range(self.images.shape[0]):
            instance_masks, instance_labels = get_instance_masks(self.labels[i], self.instances[i])
            img_bboxes = get_bboxes_from_masks(instance_masks)
            if self.use_label_subset:
                for ii in range(instance_labels.shape[0]):
                    instance_labels[ii] = self.labels_to_subset_labels[instance_labels[ii]]
            bboxes.append(img_bboxes)
            bboxes_labels.append(instance_labels)
        return bboxes, bboxes_labels

    def __getitem__(self, index):

        # access to indexed elements
        img, label, instances, depth, normals = self.images[index], self.labels[index], self.instances[index], self.depths[index], self.normals[index]
        scene_type = self.scene_types[index]

        bboxes = self.bboxes[index]
        bboxes_labels = self.bboxes_labels[index]

        # Load image
        img = Image.fromarray(img, mode='RGB')

        # Load labels, depth and instances as 1-channel images
        label = Image.fromarray(label.astype(np.uint32), mode='I')
        instances = Image.fromarray(instances, mode='P')
        depth = Image.fromarray(depth, mode='F')

        # Load normals
        normals_0 = Image.fromarray(normals[:,:,0].astype(np.float32), mode='F')
        normals_1 = Image.fromarray(normals[:,:,1].astype(np.float32), mode='F')
        normals_2 = Image.fromarray(normals[:,:,2].astype(np.float32), mode='F')

        normals = (normals_0, normals_1, normals_2)

        # Apply transforms
        try:
            if self.transform is not None:
                img, bboxes, bboxes_labels, depth, normals = self.transform(img, bboxes, bboxes_labels, depth, normals)
                normals = torch.stack(list(normals), 1).squeeze()
        except ValueError:
            print('Error at index %d' % index)
            print(bboxes)
            raise Exception
        if self.target_transform is not None:
            bboxes, bboxes_labels = self.target_transform(bboxes, bboxes_labels)

        # return transformed data and labels
        return index, img, depth, scene_type, bboxes, bboxes_labels, normals

    def __len__(self):
        return self.images.shape[0]

    def get_image(self, index):
        image = self.images[index]
        image = Image.fromarray(image, mode='RGB')
        if self.get_image_transform is not None:
            image, _, _, _, _ = self.get_image_transform(image)
        return image

    def get_annotation(self, index):
        '''This method is to conform with the ssd implementation of qfgaohao'''
        bboxes, bboxes_labels = self.bboxes[index], self.bboxes_labels[index]
        is_difficult = np.zeros(bboxes.shape[0], dtype=np.uint8)
        annotation = (bboxes, bboxes_labels, is_difficult)
        return self.ids[index], annotation


"""A modified clustering module that clusters and groups pre-cropped faces into
different folder for easy labeling.
"""
# MIT License
#
# Copyright (c) 2017 Ming Zhao@ NYTimes
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
import numpy as np
import argparse
import os
import shutil
import sys
sys.path.append('/Users/207229/Google Drive/Work/facial/facenet/src/')

import time
import math
#import pickle
#from sklearn.svm import SVC
from sklearn.cluster import DBSCAN, AffinityPropagation
from sklearn.metrics.pairwise import euclidean_distances
import facenet
from glob import glob
from matplotlib import pyplot as plt

#%%
def group_faces_to_dir(all_img_paths, labels, cluster_path):
    '''copy all face images to their corresponding dirs determined by clustering algo.
    '''
    if not os.path.exists(cluster_path):
        os.makedirs(cluster_path)
    for l in labels:
        label_dir = cluster_path + '/{}'.format(l)
        if not os.path.exists(label_dir):
            os.makedirs(label_dir)
        # copy face images to their corresponding label dir
        pic_ind = np.where(labels == l)[0]
        [shutil.copy(all_img_paths[i], os.path.join(label_dir, all_img_paths[i].split('/')[-1])) for i in pic_ind]
    return

#%% ########
def split_dataset(dataset, min_nrof_images_per_class, nrof_train_images_per_class):
    train_set = []
    test_set = []
    for cls in dataset:
        paths = cls.image_paths
        # Remove classes with less than min_nrof_images_per_class
        if len(paths)>=min_nrof_images_per_class:
            np.random.shuffle(paths)
            train_set.append(facenet.ImageClass(cls.name, paths[:nrof_train_images_per_class]))
            test_set.append(facenet.ImageClass(cls.name, paths[nrof_train_images_per_class:]))
    return train_set, test_set

#%%
def main(args):

    clustering_method = args.clustering_method
    tag = args.tag

    with tf.Graph().as_default():

        with tf.Session() as sess:

            np.random.seed(seed=args.seed)

            all_img_paths = glob(args.data_dir + '*/*.png', recursive=True)
            assert len(all_img_paths) > 0, 'Number of images must be >0!'
            print('\nFound {} images in total'.format(len(all_img_paths)))

            # Load the model
            print('Loading feature extraction model')
            facenet.load_model(args.model)

            # Get input and output tensors
            images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
            embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
            phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
            embedding_size = embeddings.get_shape()[1]

            # Run forward pass to calculate embeddings
            print('Calculating features for images')
            nrof_images = len(all_img_paths)
            nrof_batches_per_epoch = int(math.ceil(1.0*nrof_images / args.batch_size))
            print('Number of batches = {}'.format(nrof_batches_per_epoch))
            #nrof_batches_per_epoch = 1
            emb_array = np.zeros((nrof_images, embedding_size))
            for i in range(nrof_batches_per_epoch):
                print('Working on batch #{}'.format(i))
                start_index = i*args.batch_size
                end_index = min((i+1)*args.batch_size, nrof_images)
                paths_batch = all_img_paths[start_index:end_index]
                images = facenet.load_data(paths_batch, False, False, args.image_size)
                feed_dict = { images_placeholder:images, phase_train_placeholder:False }
                emb_array[start_index:end_index,:] = sess.run(embeddings, feed_dict=feed_dict)
            print('Completed generating embeddings\n')
    # End of TF graph

    #%%

    if clustering_method == 'AffinityPropagation':

        # Use AffinityPropagation
        affinity_matrix = -euclidean_distances(emb_array, squared=True)
        af = AffinityPropagation(preference = np.min(affinity_matrix)).fit(emb_array)
        cluster_centers_indices = af.cluster_centers_indices_
        labels = af.labels_
        n_clusters_ = len(cluster_centers_indices)
        print('Estimated number of clusters: %d' % n_clusters_)

        cluster_dir_name = 'AP_pref_{0:3.3f}_{}'.format(np.min(affinity_matrix,tag))

    elif clustering_method == 'dbscan':
        # Pre-calculate affinity matrix, using squared_L2 distance (required for FaceNet representation)
        affinity_matrix = euclidean_distances(emb_array, squared=True)
        eps_arr = np.linspace(0.4, 1.0, 25)

        n_clusters_arr = []
        n_outliers_arr = []
        for eps in eps_arr:
            #db = DBSCAN(eps=eps, min_samples=3,metric='euclidean').fit(emb_array)

            db = DBSCAN(eps=eps, min_samples=3,metric='precomputed').fit(affinity_matrix)

            labels = db.labels_

            # Number of clusters in labels, ignoring noise if present.
            n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
            n_outliers = np.sum(labels == -1)
            n_clusters_arr.append(n_clusters)
            n_outliers_arr.append(n_outliers)

        print('---> Please check the plots and find the best eps value !!!')
        plt.ion()
        plt.figure()
        plt.plot(eps_arr, n_clusters_arr, 'o-')
        plt.show()

        plt.figure()
        plt.plot(eps_arr, n_outliers_arr, 'o-')
        plt.show()

    #%% After exploring the parameters we need to hand pick a best esp value for the final, actual clustering
        best_eps_input = input('Enter your pick for the best EPS value (default=0.625): ')
        if best_eps_input =='':
            best_eps = 0.625
        else:
            best_eps = float(best_eps_input)
        print(' best_eps value for final iteration = {}'.format(best_eps))

        db = DBSCAN(eps=best_eps, min_samples=3,metric='precomputed').fit(affinity_matrix)

        labels = db.labels_

        # Number of clusters in labels, ignoring noise if present.
        n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
        n_outliers = np.sum(labels == -1)
        print('N_clusters, N_outliers = {}, {}'.format(n_clusters, n_outliers))

        cluster_dir_name = 'DBSCAN_eps_{0:2.3f}_{1}'.format(best_eps, tag)
        # Write model to pkl file
    #%%
    if args.create_clustered_dir is True:
        if args.output_data_dir == '':
            data_path = os.path.dirname(os.path.abspath(args.data_dir))
        else:
            data_path = args.output_data_dir
        print('Clutered data are saved at: {}'.format(os.path.join(data_path, cluster_dir_name)) )
        group_faces_to_dir(all_img_paths, labels, os.path.join(data_path, cluster_dir_name) )
    print('Clustering completed! Congrats!\n')
    return

if __name__ == '__main__':

    parser = argparse.ArgumentParser()

    parser.add_argument('data_dir', type=str,
        help='Path to the data directory containing aligned face patches.')
    parser.add_argument('model', type=str,
        help='Could be either a directory containing the meta_file and ckpt_file or a model protobuf (.pb) file')
    parser.add_argument('--batch_size', type=int,
        help='Number of images to process in a batch.', default=100)
    parser.add_argument('--image_size', type=int,
        help='Image size (height, width) in pixels.', default=160)
    parser.add_argument('--seed', type=int,
        help='Random seed.', default=42)
    parser.add_argument('--clustering_method', type=str,
        help='Algorithm used for clustering', default='dbscan')
    parser.add_argument('--tag', type=str,
        help='Unique tag name for the instance', default=time.strftime("%Y%b%d_%H%M"))
    parser.add_argument('--create_clustered_dir', default=False, action="store_true",
        help='Set to True to actually create the clustered directory (safeguard)')
    parser.add_argument('--output_data_dir', default='',
        help='Dir path to store clustered images.')

    args = parser.parse_args()

    #%%
    """ # uncomment this block for interactive ipython debugging and testing
    arg_str = '../../data/nyt/test_aligned_60/raw2/ ../../models/facenet_models/20170512-110547/20170512-110547.pb --batch_size 100'
    args = parser.parse_args(arg_str.split())
    clustering_method = 'dbscan'
    """

    main(args)


# -*- coding: utf-8 -*-
"""
Created on Sat Jan 27 12:20:40 2018

@author: 潇湘
"""

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

#import os
#import sys

from PIL import Image,ImageFilter#这是一个图象处理模块，需要安装,进入p35环境里pip install pillow即可

from tensorflow.examples.tutorials.mnist import input_data#导入训练模块的数据处理模块

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)#用数据处理模块下载并解压成四个文件

import tensorflow as tf

class ModelV():#定义一个类，用类的思想来编程要好理解一些（个人观点）
    def __init__(self):#初始化，相当于vc中的构造函数

        self.x=tf.placeholder(tf.float32,[None,784])#类的成员变量x是一个占位符，用于接受外部输入的图片数据
        self.W=tf.Variable(tf.zeros([784,10]))#类的成员变量W是一个tensorflow变量，用于存储每次训练的权重

#这是一个2维列表，784表示28*28个象素点，10表示0~9共10个结果，W总共有784*10个值

        self.b=tf.Variable(tf.zeros([10]))#类的成员变量b，是偏置值共10个
        self.y=tf.nn.softmax(tf.matmul(self.x,self.W)+self.b)#类的成员变量y，存储矩阵乘法后的值
        self.y_=tf.placeholder(tf.float32,[None,10])#类的成员变量y_是个占位符，存放标签即每个训练图片对应的正确的结果，用于对比识别是否正确。

        self.save_path = "model_v/model.ckpt"#训练好的模型的存放路径，注意：要在开始训练时在本程序的当前目录下建一个目录model_v
        self.init = tf.global_variables_initializer()
        self.saver = tf.train.Saver()
        self.sess = tf.InteractiveSession()

    def train(self):#训练模型的函数
        self.sess.run(self.init)
        cross_entropy=tf.reduce_mean(-tf.reduce_sum(self.y_*tf.log(self.y),reduction_indices=[1]))
        train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
        for i in range(20000):
            batch = mnist.train.next_batch(50)
            train_step.run(feed_dict={self.x: batch[0], self.y_: batch[1]})

        self.saver.save(self.sess, self.save_path)
        print ("ModelV saved.")

    def predict(self):#预测用的函数，它只是用于测试模型的识别率，实际不用这个函数

        #all_vars = tf.trainable_variables()#查看训练过程中的所有参数
        #for v in all_vars:
            #print(v.name,v.eval_r(self.sess))
        self.saver.restore(self.sess, self.save_path)
        print ("ModelV restored.")

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

        print (accuracy.eval_r(feed_dict={self.x: mnist.test.images, self.y_: mnist.test.labels}))

        #print ('v2', self.v2.eval_r(self.sess))
        print(self.y)
        print ('------------------------------------------------------------------')
    def predict1(self,imvalue):#预测你的图片的数字是什么用的函数，它就是主要要用的函数
        self.saver.restore(self.sess, self.save_path)
        print ("start predict")

        prediction = tf.argmax(self.y,1)
        print(prediction.eval_r(feed_dict={self.x:[imvalue]}))

        print ('------------------------------------------------------------------')
    def imageprepare(self,path):#图象处理函数，它用于处理你的手写图片，把图片处理成标准格式便于识别
    #你的图片可以在画图中生成，在生成时剪切一下，拖动虚线，使它象素为28*28左右即可，当然也可用相机照一张，再处理也可
        im = Image.open(path).convert('L')#打开你书写的图片，转化成黑白的（L表示黑白模式）
        width = float(im.size[0])
        height = float(im.size[1])
        newImage = Image.new('L', (28, 28), (255)) #creates white canvas of 28x28 pixels

        if width > height: #check which dimension is bigger
            #Width is bigger. Width becomes 20 pixels.
            nheight = int(round((20.0/width*height),0)) #resize height according to ratio width
            if (nheight == 0): #rare case but minimum is 1 pixel
                nheight = 1
            # resize and sharpen
            img = im.resize((20,nheight), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
            wtop = int(round(((28 - nheight)/2),0)) #caculate horizontal pozition
            newImage.paste(img, (4, wtop)) #paste resized image on white canvas
        else:
            #Height is bigger. Heigth becomes 20 pixels.
            nwidth = int(round((20.0/height*width),0)) #resize width according to ratio height
            if (nwidth == 0): #rare case but minimum is 1 pixel
                nwidth = 1
            # resize and sharpen
            img = im.resize((nwidth,20), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
            wleft = int(round(((28 - nwidth)/2),0)) #caculate vertical pozition
            newImage.paste(img, (wleft, 4)) #paste resized image on white canvas

        #newImage.save("sample.png")

        tv = list(newImage.getdata()) #get pixel values

        #normalize pixels to 0 and 1. 0 is pure white, 1 is pure black.
        tva = [ (255-x)*1.0/255.0 for x in tv]
        #print(tva)
        return tva

if __name__ == '__main__':
    v = ModelV()#实例化一个类

    v.train()#用实例调用类的训练函数，先训练出一个模型，再识别

    imvalue = v.imageprepare("8.png")#用类的实例调用类的图片处理函数处理图片名8.png，这个图片要放在当前目录下

    v.predict1(imvalue)#用类的实例调用类的预测函数预测处理后的图片究竟是哪个数字


# Copyright 2017 Rice University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function
import tensorflow as tf
import numpy as np

import os
import json
import collections

from bayou.models.core.model import Model
from bayou.models.core.utils import CHILD_EDGE, SIBLING_EDGE
from bayou.models.core.utils import read_config

MAX_GEN_UNTIL_STOP = 20
MAX_AST_DEPTH = 5

class BayesianPredictor(object):

    def __init__(self, save, sess):
        self.sess = sess

        # load the saved config
        with open(os.path.join(save, 'config.json')) as f:
            config = read_config(json.load(f), save_dir=save, infer=True)
        self.model = Model(config, True)

        # restore the saved model
        tf.global_variables_initializer().run()
        saver = tf.train.Saver(tf.global_variables())
        ckpt = tf.train.get_checkpoint_state(save)
        saver.restore(self.sess, ckpt.model_checkpoint_path)

    def infer(self, evidences):
        psi = self.psi_from_evidence(evidences)
        self.calls_in_last_ast = []
        return self.generate_ast(psi)

    def psi_random(self):
        return np.random.normal(size=[1, self.model.config.latent_size])

    def psi_from_evidence(self, js_evidences):
        return self.model.infer_psi(self.sess, js_evidences)

    def gen_until_STOP(self, psi, depth, in_nodes, in_edges, check_call=False):
        ast = []
        nodes, edges = in_nodes[:], in_edges[:]
        num = 0
        while True:
            assert num < MAX_GEN_UNTIL_STOP # exception caught in main
            dist = self.model.infer_ast(self.sess, psi, nodes, edges)
            idx = np.random.choice(range(len(dist)), p=dist)
            prediction = self.model.config.decoder.chars[idx]
            nodes += [prediction]
            if check_call:  # exception caught in main
                assert prediction not in ['DBranch', 'DExcept', 'DLoop', 'DSubTree']
            if prediction == 'STOP':
                edges += [SIBLING_EDGE]
                break
            js = self.generate_ast(psi, depth + 1, nodes, edges + [CHILD_EDGE])
            ast.append(js)
            edges += [SIBLING_EDGE]
            num += 1
        return ast, nodes, edges

    def generate_ast(self, psi, depth=0, in_nodes=['DSubTree'], in_edges=[CHILD_EDGE]):
        assert depth < MAX_AST_DEPTH
        ast = collections.OrderedDict()
        node = in_nodes[-1]

        # Return the "AST" if the node is an API call
        if node not in ['DBranch', 'DExcept', 'DLoop', 'DSubTree']:
            ast['node'] = 'DAPICall'
            ast['_call'] = node
            self.calls_in_last_ast.append(node)
            return ast

        ast['node'] = node
        nodes, edges = in_nodes[:], in_edges[:]

        if node == 'DBranch':
            ast_cond, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges, check_call=True)
            ast_then, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges)
            ast_else, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges)
            ast['_cond'] = ast_cond
            ast['_then'] = ast_then
            ast['_else'] = ast_else
            return ast

        if node == 'DExcept':
            ast_try, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges)
            ast_catch, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges)
            ast['_try'] = ast_try
            ast['_catch'] = ast_catch
            return ast

        if node == 'DLoop':
            ast_cond, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges, check_call=True)
            ast_body, nodes, edges = self.gen_until_STOP(psi, depth, nodes, edges)
            ast['_cond'] = ast_cond
            ast['_body'] = ast_body
            return ast

        if node == 'DSubTree':
            ast_nodes, _, _ = self.gen_until_STOP(psi, depth, nodes, edges)
            ast['_nodes'] = ast_nodes
            return ast


#skladowe: wytrzymalosc, wydajnosc, atak, enchanty, materiał
#metody: naprawianie go, zyskanie enchanta, niszczenie bloków

def wytrzymalosc_dla_materialu(material):
    if material == 'drewno':
        return 59
    elif material == 'kamien':
        return 150
    elif material == 'stal':
        return 250

def atak_dla_materialu(material):
    if material == 'drewno':
        return 50
    elif material == 'kamien':
        return 100
    elif material == 'stal':
        return 150

def wydajnosc_dla_materialu(material):
    if material == 'drewno':
        return 10
    elif material == 'kamien':
        return 20
    elif material == 'stal':
        return 30

class Kilof:
    def __init__(self, material, enchanty=[]):
        self.wytrzymalosc_max = wytrzymalosc_dla_materialu(material)
        self.aktualna_wytrzymalosc = self.wytrzymalosc_max
        self.wydajnosc = wydajnosc_dla_materialu(material)
        self.atak = atak_dla_materialu(material)
        self.material = material
        self.enchanty = enchanty
    def napraw(self):
        self.aktualna_wytrzymalosc = wytrzymalosc_max
        print('naprawiono')
    def enchantuj(self, enchant):
        self.enchanty.append(enchant)
    def niszcz_blok(self, blok):
        pass

kilof1 = Kilof('drewno')
kilof2 = Kilof('stal', ['sharpness', 'efficiency'])

kilof1.enchantuj('sharpness')

print(kilof1.material)
print(kilof1.enchanty)

print(kilof2.material)
print(kilof2.enchanty)


#!/usr/bin/python2
# -*- coding: utf-8 -*-
#__author__ = Özgür Erdoğdu
#__e-mail__ = ozgurerdogdu@yandex.com.tr

from PyQt4.QtGui import *
from PyQt4 import uic
import os
import sifre.ana_program
import sifre.kullanici_olustur
import sifre.pr_db, sifre.kripto

class Giris(QDialog):
    def __init__(self, ebeveyn = None):
        self.dizin = os.getcwd()
        if not os.path.exists(self.dizin + '/db'):
            os.mkdir(self.dizin + '/db')
        QWidget.__init__(self, ebeveyn)
        self.ui = uic.loadUi(self.dizin + '/ui/giris.ui', self)
        self.veritabani = sifre.pr_db.Veri()
        self.veritabani.db_baglan()
        try:
            db_k = self.veritabani.isaretci.execute('''SELECT kullanici_id FROM tbl_kullanici''')
            for d in db_k:
                if d:
                    self.ui.pushButton.setEnabled(False)
                    self.ui.pushButton.setText(u'Kayıtlı kullanıcı var!')
                else:
                    self.ui.pushButton_4.setEnabled(False)
                    self.ui.lineEdit.setDisabled(True)
                    self.ui.lineEdit_2.setDisabled(True)
        except:
            QMessageBox.warning(self, u'VERİTABANI',
                u'''Veritabanı Oluşturuluyor.''')
            self.veritabani.tbl_kullanici_olustur()
        self.veritabani.db_kapat()

        self.veritabani.kr_baglan()
        try:
            kr_k = self.veritabani.isaretci.execute('''SELECT kripto_id FROM tbl_kripto''')
        except:
            QMessageBox.warning(self, u'KRİPTO',
                u'''Kriptolar Oluşturuluyor.\nLütfen Bekleyin.''')
            self.veritabani.kriptolar()
        self.veritabani.kr_kapat()

    def yeni_kullanici_olustur(self):
        self.veritabani.db_baglan()
        kul = sifre.kullanici_olustur.Kullanici()
        kul.show()
        self.ui.pushButton.setEnabled(False)
        self.ui.lineEdit.setDisabled(False)
        self.ui.lineEdit_2.setDisabled(False)
        self.ui.pushButton_4.setEnabled(True)
        self.veritabani.db_kapat()

    def giris(self):
        self.kullanici_adi = self.ui.lineEdit.text()
        self.kullanici_sifre = self.ui.lineEdit_2.text()
        self.veritabani.db_baglan()
        db = self.veritabani.isaretci.execute('''SELECT * FROM tbl_kullanici''')
        for d in db.fetchall():
            self.veritabani.kr_baglan()
            kr_db = self.veritabani.isaretci.execute('''SELECT * FROM tbl_kripto WHERE kripto_id={0}'''.format(d[3]))
            for k_d in kr_db.fetchall():
                if self.kullanici_adi == sifre.kripto.degistir_kod_coz(str(d[1]), k_d[1]) and \
                   self.kullanici_sifre == sifre.kripto.degistir_kod_coz(str(d[2]), k_d[1]):
                    mp = sifre.ana_program.AnaPencere()
                    mp.show()
                    pen.close()
                    break
            else:
                QMessageBox.warning(self, u'HATA.',
                    u'''Kullanıcı Adı veya Şifre hatalı.''')
                return
        self.veritabani.db_kapat()

    def programi_sifirla(self):
        eminmisin = QMessageBox.question(
            self,
            u'EMİN MİSİN?',
            u'Tüm veriler silinsin mi?',
            QMessageBox.Yes,
            QMessageBox.No
        )
        if eminmisin == QMessageBox.Yes:
            os.remove(self.dizin + '/db/ozel.oe')
            self.ui.pushButton.setEnabled(True)
            self.ui.pushButton.setText(u'YENİ KULLANICI OLUŞTUR')
            self.ui.lineEdit.setDisabled(True)
            self.ui.lineEdit_2.setDisabled(True)
            self.ui.pushButton_4.setEnabled(False)
        else:
            self.ui.lineEdit.setDisabled(False)
            self.ui.lineEdit_2.setDisabled(False)
        self.veritabani.tbl_kullanici_olustur()

uyg = QApplication([])
pen = Giris()
pen.show()
uyg.exec_()