from aufg1 import *
import time
import random
import sys
import csv

sys.setrecursionlimit(20000) 

def phone_number_generate():
    number = "8"
    text = "0123456789"
    for i in range(10):
        char = random.choice(text)
        number += char
    return number

def create_data(n=100):

    """ создаем сразу обычный массив и остортированный """

    records_sorted = []
    for i in range(n):
        name = f"User_{i:05d}"
        phone = phone_number_generate()
        records_sorted.append((name, phone))

    records_shuffled = records_sorted[:]
    random.shuffle(records_shuffled)
    return records_sorted, records_shuffled


def run_expirement(epoch=1, elements=1000):

    """ распределяем данные по трем структурам данных
    тестируем время операций (вставки, удаления, перебора) и записываем полученные результаты в файл """
    header = ["Структура", "Режим", "Операция", "Время (сек)"]
    
    for j in range(epoch):
        print(f"эпоха - {j+1}")
        
        results = [header]
        # создаем данные 
        records_sorted, records_shuffled = create_data(elements)

        datasets = [
        ("shuffled", records_shuffled),
        ("sorted", records_sorted)]

        # сразу будем обрабатывать и случайны и отсортированный данные
        for label, arr in datasets:

            linklist = None
            hashtab = hash_table(elements)
            bintree = None
        # заполнение связного списка
            start = time.perf_counter()
            for p in arr:
                linklist = ll_insert(linklist, p[0], p[1])
            end = time.perf_counter()
            results.append(["linklist", label, "insert", end-start])

        # поиск 110 имен в связном списке
            # несуществующие данные
            nonedata = [(f"None_{i}", phone_number_generate()) for i in range(10)]
            # случайная комбинация 
            chaossample = random.sample(arr, 100) + nonedata
            start = time.perf_counter()
            for p in chaossample:
                ll_find(linklist, p[0])
            end = time.perf_counter()
            results.append(["linklist", label, "find", end-start])

        # удаление 50 имен в св писке
            deldata = random.sample(arr, 50)
            start = time.perf_counter()
            for p in deldata:
                ll_delete(linklist, p[0])
            end = time.perf_counter()
            results.append(["linklist", label, "delete", end-start])

        # заполнение хэш-тфблицы
            start = time.perf_counter()
            for p in arr:
                ht_insert(hashtab, p[0], p[1])
            end = time.perf_counter()
            results.append(["hashtable", label, "insert", end-start])

        # поиск 110 имен в хэш таблице
            # несуществующие данные
            nonedata = [(f"None_{i}", phone_number_generate()) for i in range(10)]
            # случайная комбинация 
            chaossample = random.sample(arr, 100) + nonedata
            start = time.perf_counter()
            for p in chaossample:
                ht_find(hashtab, p[0])
            end = time.perf_counter()
            results.append(["hashtable", label, "find", end-start])

        # удаление 50 имен в хэш таблице
            deldata = random.sample(arr, 50)
            start = time.perf_counter()
            for p in deldata:
                ht_delete(hashtab, p[0])
            end = time.perf_counter()
            results.append(["hashtable", label, "delete", end-start])

        # заполнение дерева
            start = time.perf_counter()
            for p in arr:
                bintree = bst_insert(bintree, p[0], p[1])
            end = time.perf_counter()
            results.append(["bintree", label, "insert", end-start])

        # поиск 110 имен в дереве
            # несуществующие данные
            nonedata = [(f"None_{i}", phone_number_generate()) for i in range(10)]
            # случайная комбинация 
            chaossample = random.sample(arr, 100) + nonedata
            start = time.perf_counter()
            for p in chaossample:
                bst_find(bintree, p[0])
            end = time.perf_counter()
            results.append(["bintree", label, "find", end-start])

        # удаление 50 имен в дереве
            deldata = random.sample(arr, 50)
            start = time.perf_counter()
            for p in deldata:
                bst_delete(bintree, p[0])
            end = time.perf_counter()
            results.append(["bintree", label, "delete", end-start])

        filename = f"results/timedata_{elements}_epochs_{j+1}.csv"
        with open(filename, mode='w', encoding='utf-8', newline='') as file:
            writer = csv.writer(file)
            writer.writerows(results)



run_expirement(epoch=5, elements=5000)