import random
from random import shuffle
from time import time
from sys import argv, exit


formules = {
        "∫ x^α" : "1/(α+1) x^(α+1), ∀α ∈ ℝ",
        "∫ 1/x" : "ln|x|",
        "∫ ln": "x ln x - x",
        "∫ e^αx": "1/(α+1) e^αx, ∀α ∈ ℝ",
        "∫ cos(ωx+φ)": "1/ω sin(ωx+φ)",
        "∫ sin(ωx+φ)": "-1/ω cos(ωx+φ)",
        "∫ tan x": "-ln|cos x|",
        "∫ ch": "sh",
        "∫ sh": "ch",
        "∫ 1/(x² + 1)": "arctan x",
        "∫ 1 / √1-x²": "arcsin x",
        "∫ 1 / (1-x²)": "1/2 ln |1+x / 1-x|",
        "∫ f'/f": "ln|f|",
        "∫ f' f": "f^2/2",
        "∫ f' e^f": "e^f",
        "∫ f' g ° f": "g°f",
        "∫_a^b f' g": "[fg]_a^b - ∫_a^b g' f,  ∀f,g ∈ 𝒞¹",
        "∫_φ(a)^φ(b) f":"∫_a^b f(φ(t)) φ'(t) dt,  ∀φ bijective [a, b] -> φ([a, b])",
        "DL_n e^x": "∑ x^k/k! + o(x^n)",
        "DL_n sin x": "∑ (-1)^k x^2k+1 / (2k+1)! + o(x^2n+1)",
        "DL_n cos x": "∑ (-1)^k x^2k / (2k)! + o(x^2n)",
        "DL_n sh x": "∑ x^2k+1 / (2k+1)! + o(x^2n+1)",
        "DL_n ch x": "∑ x^2k / (2k)! + o(x^2n)",
        "DL_n 1 / 1-x": "∑ x^k + o(x^n)",
        "DL_n 1 / 1+x": "∑ (-1)^k x^k + o(x^n)",
        "DL_n ln(1+x)": "∑ (-1)^k+1 x^k/k + o(x^n)",
        "DL_n ln(1-x)": "- ∑ x^k/k + o(x^n)",
        "DL_n (1+x)^α": "∑ α(α-1)⋯(α-k+1)/k! x^k + o(x^n),  ∀α ∈ ℝ",
#        "DL 1 terme e^x": "1",
#        "DL 1 terme sin x": "x",
#        "DL 1 terme cos x": "1",
#        "DL 1 terme sh x": "x",
#        "DL 1 terme ch x": "1",
#        "DL 1 terme 1 / 1-x": "1",
#        "DL 1 terme 1 / 1+x": "1",
#        "DL 1 terme ln(1+x)": "x",
#        "DL 1 terme ln(1-x)": "-x",
#        "DL 1 terme (1+x)^α": "1",
#        "DL 1 terme √1+x": "1",
#        "DL 1 terme tan x": "x",
#        "DL 1 terme arctan x": "x",
#        "DL 1 terme arcsin x": "x",
#        "DL 2 termes e^x": "1 + x",
#        "DL 2 termes sin x": "x - x^3/6",
#        "DL 2 termes cos x": "1 - x^2/2",
#        "DL 2 termes sh x": "x + x^3/6",
#        "DL 2 termes ch x": "1 - x^2/2",
#        "DL 2 termes 1 / 1-x": "1 + x",
#        "DL 2 termes 1 / 1+x": "1 - x",
#        "DL 2 termes ln(1+x)": "x - x²/2",
#        "DL 2 termes ln(1-x)": "-x - x²/2",
#        "DL 2 termes (1+x)^α": "1 + αx",
#        "DL 2 termes √1+x": "1 + x/2",
#        "DL 2 termes tan x": "x + x^3/3",
#        "DL 2 termes arctan x": "x - x^3/3",
#        "DL 2 termes arcsin x": "x + x^3/6",
#        "DL_3 termes e^x": "1 + x + x^2/2",
        "DL_3 termes sin x": "x - x^3/6 + x^5/120",
        "DL_3 termes cos x": "1 - x^2/2 + x^4/24",
        "DL_3 termes sh x": "x + x^3/6 + x^5/120",
        "DL_3 termes ch x": "1 + x^2/2 + x^4/24",
        "DL_3 termes 1 / 1-x": "1 + x + x^2",
        "DL_3 termes 1 / 1+x": "1 - x + x^2",
        "DL_3 termes ln(1+x)": "x - x^2/2 + x^3/3",
        "DL_3 termes ln(1-x)": "- x - x^2/2 - x^3/3",
        "DL_3 termes (1+x)^α": "1 + αx + (α(α-1))/2 x^2",
        "DL_3 termes √1+x": "1 + x/2 - x/4",
        "DL_4 termes (1+x)^α": "1 + αx + (α(α-1))/2 x^2 + (α(α-1)(α-2))/6 x^3",
}

if __name__ == "__main__":
    command = argv[1] if len(argv) > 1 else "lauront"
    if command == "lauront":
        times = []
        timeout = float(argv[2]) if len(argv) > 2 else 8
        while True:
            remaining = list(formules.keys())
            chosen = random.choice(remaining)
            done = 0
            while remaining:
                # don't pick previous one.
                chosen = random.choice([ r for r in remaining if r != chosen])
                print(chosen)
                start = time()
                input()
                end = time()
                times.append(end-start)
                if end-start > timeout:
                    print(f"""
        <Lauron> {round(end-start, 1)} secondes ‽‽‽ C'est trop long! 
        Tu connais pas ton cours ! Apprends-moi ça:
        {formules.get(chosen, '<INTERNAL ERROR>')}
                    """)
                    input()
                else:
                    print(f"""
        Tu m'as dis
        {formules.get(chosen, '<INTERNAL ERROR>')}
        n'est-ce pas?
                    """)
                    if input() == "y":
                        remaining.remove(chosen)
                        print(f"{len(remaining)} to go")
            print(f"sessions finished. meantime is {sum(times)/len(times)}s")
    elif command == "list":
        while True:
            énoncés = list(formules.keys())
            shuffle(énoncés)
            print("\n".join(énoncés))
            input("anoda one?")
    else:
        print("unknown command.")
        exit(1)
