from MP_records import records
import random as rd
import time
import csv
import codecs

def insert(lisst,name,phone):
    if len(lisst)==0:
        entry={"name":name,"phone":phone,"next":None}
        lisst.append(entry)
        return lisst
    else:
        entry={"name":name,"phone":phone,"next":None}
        if lisst[0]["phone"]==phone:
            lisst[0]["name"]=name
            return lisst
        if lisst[0]["next"]==None:
            lisst[0]["next"]=entry
            return lisst
        else:
            nexxt=lisst[0]["next"]
            if nexxt["phone"]==phone:
                nexxt["name"]=name
                return lisst
            while nexxt["next"]!=None:
                nexxt=nexxt["next"]
                if nexxt["phone"]==phone:
                    nexxt["name"]=name
                    return lisst
            nexxt["next"]=entry
            return lisst
        
def find(lisst, name):
    if len(lisst)>0:
        if lisst[0]["name"]==name:
            return lisst[0]["phone"]
        elif lisst[0]["next"]!=None:
            nexxt=lisst[0]["next"]
            while nexxt["next"]!=None:
                if nexxt["name"]==name:
                    return nexxt["phone"]
                else:
                    nexxt=nexxt["next"]
            if nexxt["name"]==name:
                return nexxt["phone"]
    return None


def delete(lisst,name):
    if len(lisst)>0:
        if lisst[0]["name"]==name:
            if lisst[0]["next"]!=None:
                lisst[0]=lisst[0]["next"]
                return lisst
            else:
                lisst.pop()
                return lisst
        elif lisst[0]["next"]!=None:
            if lisst[0]["next"]["name"]==name:
                if lisst[0]["next"]["next"]!=None:
                    lisst[0]["next"]=lisst[0]["next"]["next"]
                    return lisst
                else:
                    lisst[0]["next"]=None
                    return lisst
            elif lisst[0]["next"]["next"]!=None:
                nexxt1=lisst[0]["next"]
                nexxt2=nexxt1["next"]
                if nexxt2["name"]==name:
                    if nexxt2["next"]!=None:
                        nexxt1["next"]=nexxt2["next"]
                        return lisst
                    else:
                        nexxt1["next"]=None
                        return lisst
                while nexxt2["next"]!=None:
                    nexxt1=nexxt2
                    nexxt2=nexxt1["next"]
                    if nexxt2["name"]==name:
                        if nexxt2["next"]!=None:
                            nexxt1["next"]=nexxt2["next"]
                            return lisst
                        else:
                            nexxt1["next"]=None
                            return lisst

def bad_sort(names,phones):
    names1=[]
    phones1=[]
    while len(names)>0:
        min_=names[0].encode()
        ph=phones[0]
        for i in range(len(names)):
            nm=names[i].encode()
            if nm<min_:
                min_=nm
                ph=phones[i]
        #print(min_.decode()," - ",ph)
        names1.append(min_.decode())
        phones1.append(ph)
        names.remove(min_.decode())
        phones.remove(ph)
    #print(names1,"\n",phones1)
    return names1, phones1

def Shell(names,phones):
    N = len(names)
    n = N // 2
    while n>0:
        for i in range (0,N-n):
            j=i
            while j+n<N:
                if (names[j].encode())>(names[j+n].encode()):
                    t=names[j]
                    t1=phones[j]
                    names[j]=names[j+n]
                    phones[j]=phones[j+n]
                    names[j+n]=t
                    phones[j+n]=t1
                    j=i
                else:
                    j+=n
        n=n//2
    return names,phones

def list_all(lisst):
    names=[]
    phones=[]
    if len(lisst)>0:
        names.append(lisst[0]["name"])
        phones.append(lisst[0]["phone"])
        nexxt=lisst[0]["next"]
        while nexxt!=None:
            names.append(nexxt["name"])
            phones.append(nexxt["phone"])
            nexxt=nexxt["next"]
    else:
        print("List is empty")
        return
    names1, phones1 = bad_sort(names,phones)
    #names1, phones1 = Shell(names,phones)
    for i in range(len(names1)):
        print(names1[i]," - ",phones1[i],end='')
        if i%4==0:
            print("\n")
        else:
            print(", ",end='')
    print("\n")

def test():
    lisst=[]      
    insert(lisst,"Abba",1)
    insert(lisst,"Cafr",43)
    insert(lisst,"Babba",2)
    insert(lisst,"V",2)
    insert(lisst,"Babadsaba",3)
    insert(lisst,"Cabr",34)
    insert(lisst,"Aaaaa",4)
    insert(lisst,"Ba",5)
    a=find(lisst,"Aaaaa")
    print(a)
    
    print(lisst,'\n')
    delete(lisst,"Abba")
    # print(lisst,'\n')
    # delete("Aaaaa")
    # print(lisst,'\n')
    # delete("Ba")
    # print(lisst,'\n')
    # delete("Babadsaba")
    # print(lisst,'\n')
    delete(lisst,"Aaaaa")
    # print(lisst,'\n')
    list_all(lisst)
    print(lisst,'\n')
    
def run_shuffled(records_shuffled):
    insertion_times=[]
    finding_times=[]
    deletion_times1=[]
    print("Shuffled list: ")
    for k in range(5):
        lisst=[]
        rd.shuffle(records_shuffled)
        
        #А. Вставка всех записей
        start=time.perf_counter()
        for i in range(len(records_shuffled)):
            insert(lisst, records_shuffled[i][0], records_shuffled[i][1])
        end=time.perf_counter()
        insertion_times.append(end-start)
        
        #Б. Поиск 100 случайных записей
        names=[]
        for i in range(100):
            index=rd.randint(0,9999)
            name=lisst[0]
            while index>0:
                name=name["next"]
                index-=1
            names.append(name["name"])
        for i in range(10):
            names.append("A")
        rd.shuffle(names)
        
        start=time.perf_counter()
        for i in range(len(names)):
            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()
            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"Время (сек)"],
    ["LinkedList", u"случайный", u"вставка", insertion_times[0]],
    ["LinkedList", u"случайный", u"вставка", insertion_times[1]],
    ["LinkedList", u"случайный", u"вставка", insertion_times[2]],
    ["LinkedList", u"случайный", u"вставка", insertion_times[3]],
    ["LinkedList", u"случайный", u"вставка", insertion_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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"Время (сек)"],
    ["LinkedList", u"случайный", u"поиск", finding_times[0]],
    ["LinkedList", u"случайный", u"поиск", finding_times[1]],
    ["LinkedList", u"случайный", u"поиск", finding_times[2]],
    ["LinkedList", u"случайный", u"поиск", finding_times[3]],
    ["LinkedList", u"случайный", u"поиск", finding_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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"Время (сек)"],
    ["LinkedList", u"случайный", u"удаление", del_times[0]],
    ["LinkedList", u"случайный", u"удаление", del_times[1]],
    ["LinkedList", u"случайный", u"удаление", del_times[2]],
    ["LinkedList", u"случайный", u"удаление", del_times[3]],
    ["LinkedList", u"случайный", u"удаление", del_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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=[]
        
        #А. Вставка всех записей
        start=time.perf_counter()
        for i in range(len(records_shuffled)):
            insert(lisst, records_shuffled[i][0], records_shuffled[i][1])
        end=time.perf_counter()
        insertion_times.append(end-start)
        
        #Б. Поиск 100 случайных записей
        names=[]
        for i in range(100):
            index=rd.randint(0,9999)
            name=lisst[0]
            while index>0:
                name=name["next"]
                index-=1
            names.append(name["name"])
        for i in range(10):
            names.append("A")
        rd.shuffle(names)
        
        start=time.perf_counter()
        for i in range(len(names)):
            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()
            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"Время (сек)"],
    ["LinkedList", u"отсортированный", u"вставка", insertion_times[0]],
    ["LinkedList", u"отсортированный", u"вставка", insertion_times[1]],
    ["LinkedList", u"отсортированный", u"вставка", insertion_times[2]],
    ["LinkedList", u"отсортированный", u"вставка", insertion_times[3]],
    ["LinkedList", u"сотсортированный", u"вставка", insertion_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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"Время (сек)"],
    ["LinkedList", u"отсортированный", u"поиск", finding_times[0]],
    ["LinkedList", u"отсортированный", u"поиск", finding_times[1]],
    ["LinkedList", u"отсортированный", u"поиск", finding_times[2]],
    ["LinkedList", u"отсортированный", u"поиск", finding_times[3]],
    ["LinkedList", u"отсортированный", u"поиск", finding_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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"Время (сек)"],
    ["LinkedList", u"отсортированный", u"удаление", del_times[0]],
    ["LinkedList", u"отсортированный", u"удаление", del_times[1]],
    ["LinkedList", u"отсортированный", u"удаление", del_times[2]],
    ["LinkedList", u"отсортированный", u"удаление", del_times[3]],
    ["LinkedList", u"отсортированный", u"удаление", del_times[4]],
    [u"Структура", u"Режим", u"Операция", u"Среднее время (сек)"],
    ["LinkedList", 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)
