"""Module de tests des TP de MPSI (tronc commun).

Reconstitution du module d'origine, qui n'a pas été conservé : seules les
fonctions utilisées dans les feuilles de TP sont fournies.

    from civ import *
    init()
    test(f, arg1, ..., resultat_attendu)
    test_erreur(f, arg1, ..., TypeErreur)
    valide()
"""

_resultats = []


def init():
    """Remet à zéro le compteur de tests."""
    _resultats.clear()


def _appel(f, args):
    return '%s(%s)' % (getattr(f, '__name__', 'f'), ', '.join(repr(a) for a in args))


def test(f, *args):
    """test(f, a1, ..., an, r) vérifie que f(a1, ..., an) == r."""
    *args, attendu = args
    try:
        obtenu = f(*args)
    except Exception as e:
        print('ÉCHEC : %s lève %s: %s' % (_appel(f, args), type(e).__name__, e))
        _resultats.append(False)
        return False
    ok = obtenu == attendu
    if not ok:
        print('ÉCHEC : %s renvoie %r au lieu de %r' % (_appel(f, args), obtenu, attendu))
    _resultats.append(ok)
    return ok


def test_erreur(f, *args):
    """test_erreur(f, a1, ..., an, E) vérifie que f(a1, ..., an) lève l'exception E."""
    *args, erreur = args
    try:
        f(*args)
    except erreur:
        _resultats.append(True)
        return True
    except Exception as e:
        print('ÉCHEC : %s lève %s au lieu de %s' % (_appel(f, args), type(e).__name__, erreur.__name__))
    else:
        print('ÉCHEC : %s ne lève pas %s' % (_appel(f, args), erreur.__name__))
    _resultats.append(False)
    return False


def valide():
    """Affiche le bilan des tests effectués depuis le dernier init() puis remet à zéro."""
    n, ok = len(_resultats), sum(_resultats)
    if n and ok == n:
        print('OK! (%d test%s)' % (n, 's' if n > 1 else ''))
    else:
        print('%d test(s) réussi(s) sur %d' % (ok, n))
    _resultats.clear()
    return n > 0 and ok == n


def affiche_graphe_l_no(g):
    """Dessine le graphe non orienté donné par listes d'adjacence g (g[i] : voisins de i)."""
    import math
    import matplotlib.pyplot as plt
    n = len(g)
    pos = [(math.cos(2 * math.pi * i / n), math.sin(2 * math.pi * i / n)) for i in range(n)]
    fig, ax = plt.subplots(figsize=(4, 4))
    for i in range(n):
        for j in g[i]:
            if i < j:
                ax.plot([pos[i][0], pos[j][0]], [pos[i][1], pos[j][1]], color='#4a5568', zorder=1)
    for i, (x, y) in enumerate(pos):
        ax.scatter([x], [y], s=500, color='#dbe8f7', edgecolors='#2f6db5', zorder=2)
        ax.annotate(str(i), (x, y), ha='center', va='center', zorder=3)
    ax.set_axis_off()
    ax.set_aspect('equal')
    plt.show()
