from MP_records import records
import random as rd
import time
import csv
import codecs
import sys
sys.setrecursionlimit(15000)

def bst_insert(root,name,phone):
    if root==None:
        entry={"name":name,"phone":phone,"left":None,"right":None}
        root=entry
        return root
    else:
        entry={"name":name,"phone":phone,"left":None,"right":None}
        if root["phone"]==phone:
            root["name"]=name
            return root
        else:
            if (name.encode())<(root["name"].encode()):
                if root["left"]==None:
                    root["left"]=entry
                else:
                    bst_insert(root["left"], name, phone)
            else:
                if root["right"]==None:
                    root["right"]=entry
                else:
                    bst_insert(root["right"], name, phone)
        
def bst_find(root, name):
    a=None
    if root!=None:
        if root["name"]==name:
            return root["phone"]
        else:
            if (name.encode())>(root["name"].encode()) and root["right"]:
                a=bst_find(root["right"], name)
            elif root["left"] and a==None:
                a=bst_find(root["left"], name)
    return a


def bst_delete(root,name):
    while root["name"]!=name:
        if (name.encode())>(root["name"].encode()):
            if root["right"]==None:
                #print("None")
                return
            else:
                if root["right"]["name"]==name and root["right"]["right"]==None and root["right"]["left"]==None:
                    root["right"]=None
                    return
                root=root["right"]
        else:
            if root["left"]==None:
                #print("None")
                return
            else:
                if root["left"]["name"]==name and root["left"]["right"]==None and root["left"]["left"]==None:
                    root["left"]=None
                    return
                root=root["left"]
    if root["right"]:
        root1=root["right"]
        if root1["left"]:
            if root1["left"]["left"]:
                while root1["left"]["left"]:
                    root1=root1["left"]
                root2=root1["left"]
            else:
                root2=root1["left"]
        else:
            root["name"]=root1["name"]
            root["phone"]=root1["phone"]
            root["right"]=root1["right"]
            return
        if root2["right"]:
            root["name"]=root2["name"]
            root["phone"]=root2["phone"]
            root1["left"]=root2["right"]
            return
            #del root2
        else:
            root["name"]=root2["name"]
            root["phone"]=root2["phone"]
            root1["left"]=None
            #print(root1.right.data)
            return
    elif root["left"]:
        temp=root["left"]["left"]
        root["name"]=root["left"]["name"]
        root["phone"]=root["left"]["phone"]
        root["right"]=root["left"]["right"]
        root["left"]=temp
        return

def bst_list_all(root):
    if root["left"]:
        bst_list_all(root["left"])
    print(root["name"]," - ",root["phone"])
    if root["right"]:
        bst_list_all(root["right"])
    
def test():
    root=None
    root=bst_insert(root,"Abba",1)
    bst_insert(root,"Babba",2)
    bst_insert(root,"Cabba",3)
    bst_insert(root,"Aaaaa",4)
    bst_insert(root,"Abfga",5)
    bst_insert(root,"Arte",6)
    bst_insert(root,"Aaxa",7)
    bst_insert(root,"Aaax",8)
    bst_insert(root,"Aaxx",9)
    print(root)
    print(bst_find(root, "Aaaaa"))
    print(bst_find(root, "Aaxx"))
    print(bst_find(root, "Aaax"))
    print(bst_find(root, "Babba"))
    print(bst_find(root, "Cabba"))
    print(bst_find(root, "Arte"))
    print(bst_find(root, "Aaxa"))
    print(bst_find(root, "Abba"))
    print(bst_find(root, "Abfga"))
    print(bst_find(root, "Abb"))
    #bst_delete(root, "Cabba")
    print(root)
    bst_list_all(root)
    
def run_shuffled(records_shuffled):
    insertion_times=[]
    finding_times=[]
    deletion_times1=[]
    print("Shuffled list: ")
    for k in range(5):
        lisst=None
        
        #А. Вставка всех записей
        start=time.perf_counter()
        lisst=bst_insert(lisst, records_shuffled[0][0], records_shuffled[0][1])
        for i in range(1,len(records_shuffled)):
            bst_insert(lisst, records_shuffled[i][0], records_shuffled[i][1])
        end=time.perf_counter()
        insertion_times.append(end-start)
        
        #Б. Поиск 100 случайных записей
        names=[]
        index=rd.randint(0,9899)
        for i in range(100):
            names.append(records_shuffled[index][0])
            index+=1
        for i in range(10):
            names.append("A")
        rd.shuffle(names)
        
        start=time.perf_counter()
        for i in range(len(names)):
            bst_find(lisst,names[i])   
        end=time.perf_counter()
        finding_times.append(end-start)
        
        #В. Удаление 50 случайных записей
        for i in range(10):
            names.remove("A")
        rd.shuffle(names)
        deletion_times=[]
        
        for i in range(50):
            start=time.perf_counter()
            bst_delete(lisst,names[i])
            end=time.perf_counter()
            ttt=end-start
            deletion_times.append(ttt)
        deletion_times1.append(deletion_times)
        
        print("Run number ",k+1)
        print("Insertion time: ",insertion_times[k])
        print("Finding time: ",finding_times[k])
        print("Deletion times: ","\n",deletion_times)
        print("\n")
    
    temp=0
    for i in range(5):
        temp+=insertion_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"случайный", u"вставка", insertion_times[0]],
    ["BinarySearchTree", u"случайный", u"вставка", insertion_times[1]],
    ["BinarySearchTree", u"случайный", u"вставка", insertion_times[2]],
    ["BinarySearchTree", u"случайный", u"вставка", insertion_times[3]],
    ["BinarySearchTree", u"случайный", u"вставка", insertion_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"случайный", u"вставка", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
    
    temp=0
    for i in range(5):
        temp+=finding_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"случайный", u"поиск", finding_times[0]],
    ["BinarySearchTree", u"случайный", u"поиск", finding_times[1]],
    ["BinarySearchTree", u"случайный", u"поиск", finding_times[2]],
    ["BinarySearchTree", u"случайный", u"поиск", finding_times[3]],
    ["BinarySearchTree", u"случайный", u"поиск", finding_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"случайный", u"поиск", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
        
    temp=0
    del_times=[]
    for i in range(5):
        for j in range(50):
            temp+=deletion_times1[i][j]
        temp=temp/50
        del_times.append(temp)
        temp=0
    
    temp=0
    for i in range(5):
        temp+=del_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"случайный", u"удаление", del_times[0]],
    ["BinarySearchTree", u"случайный", u"удаление", del_times[1]],
    ["BinarySearchTree", u"случайный", u"удаление", del_times[2]],
    ["BinarySearchTree", u"случайный", u"удаление", del_times[3]],
    ["BinarySearchTree", u"случайный", u"удаление", del_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"случайный", u"удаление", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
        writer.writerows("\n")

def run_sorted(records_shuffled):
    insertion_times=[]
    finding_times=[]
    deletion_times1=[]
    print("Sorted list: ")
    for k in range(5):
        lisst=None
        
        #А. Вставка всех записей
        start=time.perf_counter()
        lisst=bst_insert(lisst, records_shuffled[0][0], records_shuffled[0][1])
        for i in range(1,len(records_shuffled)):
            bst_insert(lisst, records_shuffled[i][0], records_shuffled[i][1])
        end=time.perf_counter()
        insertion_times.append(end-start)
        
        #Б. Поиск 100 случайных записей
        names=[]
        index=rd.randint(0,9899)
        for i in range(100):
            names.append(records_shuffled[index][0])
            index+=1
        for i in range(10):
            names.append("A")
        rd.shuffle(names)
        
        start=time.perf_counter()
        for i in range(len(names)):
            bst_find(lisst,names[i])   
        end=time.perf_counter()
        finding_times.append(end-start)
        
        #В. Удаление 50 случайных записей
        for i in range(10):
            names.remove("A")
        rd.shuffle(names)
        deletion_times=[]
        
        for i in range(50):
            start=time.perf_counter()
            bst_delete(lisst,names[i])
            end=time.perf_counter()
            ttt=end-start
            deletion_times.append(ttt)
        deletion_times1.append(deletion_times)
        
        print("Run number ",k+1)
        print("Insertion time: ",insertion_times[k])
        print("Finding time: ",finding_times[k])
        print("Deletion times: ","\n",deletion_times)
        print("\n")
    
    temp=0
    for i in range(5):
        temp+=insertion_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"вставка", insertion_times[0]],
    ["BinarySearchTree", u"отсортированный", u"вставка", insertion_times[1]],
    ["BinarySearchTree", u"отсортированный", u"вставка", insertion_times[2]],
    ["BinarySearchTree", u"отсортированный", u"вставка", insertion_times[3]],
    ["BinarySearchTree", u"сотсортированный", u"вставка", insertion_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"вставка", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
    
    temp=0
    for i in range(5):
        temp+=finding_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"поиск", finding_times[0]],
    ["BinarySearchTree", u"отсортированный", u"поиск", finding_times[1]],
    ["BinarySearchTree", u"отсортированный", u"поиск", finding_times[2]],
    ["BinarySearchTree", u"отсортированный", u"поиск", finding_times[3]],
    ["BinarySearchTree", u"отсортированный", u"поиск", finding_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"поиск", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
        
    temp=0
    del_times=[]
    for i in range(5):
        for j in range(50):
            temp+=deletion_times1[i][j]
        temp=temp/50
        del_times.append(temp)
        temp=0
    
    temp=0
    for i in range(5):
        temp+=del_times[i]
    temp=temp/5
    
    results = [
    [u"Структура", u"Режим", u"Операция", u"Время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"удаление", del_times[0]],
    ["BinarySearchTree", u"отсортированный", u"удаление", del_times[1]],
    ["BinarySearchTree", u"отсортированный", u"удаление", del_times[2]],
    ["BinarySearchTree", u"отсортированный", u"удаление", del_times[3]],
    ["BinarySearchTree", u"отсортированный", u"удаление", del_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["BinarySearchTree", u"отсортированный", u"удаление", temp,]
    ]
    
    with codecs.open("docs/data/[1]results.csv", "a+", "utf-16") as f:
        writer = csv.writer(f)
        writer.writerows(results)
        writer.writerows("\n")
        writer.writerows("\n")

records_shuffled, records_sorted = records()
run_shuffled(records_shuffled)
run_sorted(records_sorted)
