#Imporieren aller module
from turtle import*
import random
import time
import math

title("Main Hub")

#Wichtige Vorbereitungen

def hi():
    pu()
    setpos(-100,0)
    pd()
    lt(90)
    fd(200)
    bk(100)
    rt(90)
    fd(100)
    lt(90)
    fd(100)
    bk(200)
    pu()
    setpos(50,0)
    pd()
    fd(200)

speed(10000)
ht()

#Lässt den Benutzer auswählen, ob die Formen zufällig oder in einem Kreis angeordnet, nach Wünschen des Benutzers gezeichnet werden sollen.
print("ready")
hi()
program_choice = int(numinput("Welches Program sollte ausgeführt werden?", "                       1=Custom, 2=Random, 3=Drunken Man                    ",1,minval=1))


#Definition des Befehls Vieleck(). Der Grundbaustein des Programms
def vieleck(anzahl_seiten,radius, anzahl_kreis_printed, figuren, kreise, figur_nummer, save_first):
    parts_circle = 1
    time_durchgang_start = time.time()
    for i in range(anzahl_seiten):
        fd(radius/anzahl_seiten)
        rt(360/anzahl_seiten)
        parts_circle += 1
        if parts_circle / anzahl_seiten * 100 >= 50 and parts_circle / anzahl_seiten * 100 < 50.1:
            print("            Circle:",parts_circle / anzahl_seiten * 100, "%")
    time_durchgang_end = time.time()
    exact_timecalculation(time_durchgang_start, time_durchgang_end, anzahl_seiten, radius, anzahl_kreis_printed, figuren, kreise, figur_nummer, save_first)


#Definition des Befehls, der mit beendigung des Auswahlverfahrens aufgerufen wird. Verwaltet die wichtigsten feautures
def figur(seite,radiusin,anzahlkr,anzahl_figuren,erh_input):   
    figur_number = 1
    first_time = 1
    print("Globally: 0 % done")
    for i in range(anzahl_figuren):
        change_color(figur_number)
        print("drawing figure number",figur_number)
        anzahl_kr_printed = 0
        for i in range(anzahlkr):
            vieleck(seite,radiusin, anzahl_kr_printed, anzahl_figuren, anzahlkr, figur_number, first_time)
            rt(360/anzahlkr)
            anzahl_kr_printed += 1
            print(anzahl_kr_printed / anzahlkr * 100, "%")
        radiusin += erh_input
        figur_number += 1
        print("done")
        print("Globally:", (figur_number - 1) / anzahl_figuren * 100, "% done")

#Berechnet, sobald das Programm begonnen hatte zu zeichnen, wie lange der Vorgang noch dauern wird. 
def exact_timecalculation(time_durchgang_end_1, time_durchgang_start_1, seitenzahl, radiusinput, anzahl_kreise_printed, figuren, kreise, figur_number, save_1):
    print("Time per shape", time_durchgang_start_1 - time_durchgang_end_1)
    remaining_circles = (figuren * kreise) - ((anzahl_kreise_printed + ((figur_number - 1) * kreise)))
    remaining_time = remaining_circles * ((time_durchgang_end_1 - time_durchgang_start_1) * -1)
    print(((anzahl_kreise_printed + ((figur_number - 1) * kreise))), "/", (kreise * figuren), "shapes got already printed.", remaining_circles, "remaining")
    print("ETA:", remaining_time, "seconds or", remaining_time / 60, "minutes")
    if save_1 > 1:
        remaining_time = save_time_end
        save_1 = 0
    else:
        save_1 = 0

#Wechselt die Farbe
def change_color(anz_figuren):
    if anz_figuren >= 1 and anz_figuren < 2:
        color("red")
    else:
        if anz_figuren >= 2 and anz_figuren < 3:
            color("green")
        else:
            if anz_figuren >= 3 and anz_figuren < 4:
                color("blue")
            else:
                if anz_figuren >= 4 and anz_figuren < 5:
                    color("brown")
                else:
                    color("black")


#Führt den zufälligen Teil des Programms aus
def vieleck_random_randomize():
    amount_circles_drawn = 0
    pu()
    amount_circles = random.randint(25, 75)
    print(amount_circles, "shapes need to be printed. Esitmated time:", amount_circles * 0.35, "seconds")
    print("0 / 0 or 0 % done")
    for i in range(amount_circles):
        color(random.random(),random.random(),random.random())
        size = random.randint(50, 250)
        width(random.randint(2, 10))
        ecken = random.randint(3, 20)
        setpos(random.randint(-300,300), random.randint(-300,300))
        fuellen = random.randint(0,1)
        pd()
        if fuellen >= 1:
            begin_fill()
            for i in range(ecken):
                fd(size / ecken)
                rt(360 / ecken)
            end_fill()
        else:
            for i in range(ecken):
                fd(size / ecken)
                rt(360 / ecken)
        amount_circles_drawn += 1
        pu()
        print(amount_circles_drawn, "/", amount_circles, "or", amount_circles_drawn / amount_circles * 100, "% drawn.")
    print("100 % done. Process ended with a 0")
 
#Definition des Betrunkenen Mannes??
def drunken_man_walk_show(schritte,distanz):
    for i in range(schritte):
        fd(distanz)
        setheading(random.randint(0, 360))
        
def drunken_man_walk_calculate(anzahl_tests,anzahl_figuren_test,add,anzahl_tests_pro,ausgabe):
    print("started. Going to make the test", anzahl_tests, "times to get a result which is as acurate as possible")
    schritte = 100
    schritte_begin = schritte
    distanz = 20
    summe = 0
    summe_second = 0
    l = [1]
    for i in range(anzahl_figuren_test):
        amount_atemps_per = 0
        for i in range(anzahl_tests):
            print("Collecting data for", schritte,"steps, collecting data for try number", amount_atemps_per + 1, "/", anzahl_tests)
            for i in range(anzahl_tests_pro):
                drunken_man_walk_show(schritte,distanz)
                x = xcor()
                y = ycor()
                d = math.sqrt(x**2 + y**2)
                summe += d
                pu()
                home()
                pd()
            summe_calc = summe / anzahl_tests_pro
            print("Average dislocation of 0.0 is:", summe_calc,"pixels, with a amount of steps of", schritte,".")
            summe_second += summe_calc
            reset()
            summe = 0
            amount_atemps_per += 1
        print("TOTAL Average dislocation of 0.0 is:", summe_second / anzahl_tests, "pixels with", schritte, "steps")
        print("Next size getting executed")
        result = summe_second / anzahl_tests
        l.append(result)
        schritte += add
        summe_second = 0
    l.remove(1)
    l.reverse()
    print("\n\n\n")
    print("entire list:",l)
    print("\n_________________________ \n\n\n")
    if ausgabe == 1:
        for i in range(anzahl_figuren_test):
            show = l.pop()
            print(schritte_begin, "has an average dislocation of", show)
            schritte_begin += add
    else:
        print("Schritte    |     Durchschnittliche Entfernung")
        print("----------------------------------------------")
        for i in range(anzahl_figuren_test):
            show = l.pop()
            print(schritte_begin, "        |    ", show)
            schritte_begin += add
        
        
        
 
#Wird ausgeführt, wenn der vom Benutzer einstellbare Modus ausgewählt wird.
if program_choice >= 1 and program_choice < 2:
    title("Custom Design")
    reset()
    ht()
    speed(10000)
    print("Custom Design")
    seiteninput = int(numinput("Wie viele Seiten?", "   Gerade Zahl von 3-unendlich      ",10,minval=3))
    radiusinput = int(numinput("Wie gross soll der Radius sein?", "         Gerade Zahl von 50-unendlich        ",50,minval=50))
    anzahlkrinput = int(numinput("Wie viele Kreise sollen gezeichnet werden??", "            Gerade Zahl von 1-unendlich            ",5,minval=1))
    figureninput = int(numinput("Wie viele Figuren sollen gezeichnet werden?", "                 Gerade Zahl von 1-unendlich               ",5,minval=1))
    erhinput = int(numinput("Um wieviel soll sich sich der Radius der Kreise erhöhen?", "                         Gerade Zahl von 20-unendlich                     ",50,minval=20))
    verzoegerung = int(numinput("Wie schnell soll die Animation laufen?", "                       Gerade Zahl von 1-unendlich, umso höher, desto schneller                  ",50,minval=0))
    print("starting process...")
    tracer(verzoegerung)
    print(anzahlkrinput * figureninput, "circles need to be printed. Estimated time until completion:", (anzahlkrinput * figureninput * (seiteninput * 0.0330383)), "seconds or", (anzahlkrinput * figureninput * (seiteninput * 0.0330383)) / 60, "minutes")
    time.sleep(2)
    draw_time_start = time.time()
    figur(seiteninput,radiusinput,anzahlkrinput,figureninput,erhinput)
    draw_time_end = time.time()
    draw_time = (draw_time_end - draw_time_start) - (anzahlkrinput * figureninput * (seiteninput * 0.0330383))
    print("Drawing of", anzahlkrinput * figureninput, "shapes has taken", draw_time_end - draw_time_start , "seconds or", (draw_time_end - draw_time_start) / 60, "minutes, estimated:", (anzahlkrinput * figureninput * (seiteninput * 0.0330383)), "seconds, which means a diffrence of", draw_time, "seconds or missed by", draw_time * 100, "%")
    print("Click to exit")
    

else:
    if program_choice >= 2 and program_choice < 3:
        title("Random Design")
        reset()
        ht()
        speed(10000)
        print("Random Design")
        draw_time_start = time.time()
        vieleck_random_randomize()
        draw_time_end = time.time()
        print("Drawing has taken", draw_time_end - draw_time_start , "seconds")
        print("Click to exit")
    else:
        if program_choice >= 3 and program_choice < 4:
            title("Drunken Man's Walk")
            reset()
            ht()
            speed(0)
            print("Drunken Man's Walk")
            easy_difficult = int(numinput("Soll es gezeigt oder eine Tabelle erstellt werden?", "        1=Normal, 2=Tabelle         ",1,minval=1))
            if easy_difficult == 1:
                title("Drunken Man's Walk: standard")
                drunken_man_walk_show(100,20)
            else:
                title("Drunken Man's Walk: List")
                tests_total = int(numinput("Wie viele unterschiedliche Längen sollten getestet werden?", "            Dauer erhöht sich extrem, Genauigkeit genauso                            ",10,minval=1))
                tests_per = int(numinput("Wieviele Tests sollten pro Länge durchgeführt werden?", "        Dauer erhöht sich extrem, Genauigkeit genauso                               ",10,minval=1))
                addition = int(numinput("Um wieviel soll die Schrittzahl vergrössert werden?", "              Dauer erhöht sich unbedeutend, abhängig von Tests                   ", 100, minval=1))
                executes_per = int(numinput("Wie viele Spuren sollen gezeichnet werden?", "        Dauer erhöht sich ziemlich, Genauigkeit genauso                                ",1000,minval=1))
                tracerdelay = int(numinput("Alle wie viele Striche soll aktualisiert werden?", "        umso höher, desto schneller             ",10000,minval=1))
                output = int(numinput("Wie soll die Liste ausgegeben werden?", "        1 = Liste, 2 = Tabelle             ",1,minval=1, maxval=2))
                tracer(tracerdelay)
                drunken_man_walk_calculate(tests_per,tests_total,addition,executes_per,output)
                
        else:
            print("wrong")
update()
exitonclick()