def recup_piece(ligne):
    position_courante=0 # Position du caractère étudié
    carac=ligne[position_courante] # Caractère courant
    while carac !="-": # Tant que l'on a pas atteint le "-"
        position_courante+=1 # Position du caractère étudié 
        carac=ligne[position_courante] # Caractère courant
    piece_une=int(ligne[0:position_courante]) # Recupération de la première pièce
    position_courante+=1 # Evolution de la position courante
    depart_piece_deux=position_courante # Position de départ pour récupérer la 2eme pièce
    while carac !=":": # Tant que l'on a pas atteint :
        position_courante+=1
        carac=ligne[position_courante]
    piece_deux=int(ligne[depart_piece_deux:position_courante-1]) # Pour récupérer la 2eme pièce, bien penser à écrire position_courante-1 car avant les :, il y a un espace.
    return[piece_une,piece_deux]

def recup_piece2(ligne):
    position1=ligne.index("-")
    position2=ligne.index (":")
    piece_une=int(ligne[0:position1]) # Recupération de la première pièce
    piece_deux=int(ligne[position1+1:position2-1]) # Pour récupérer la 2eme pièce, bien penser à écrire position_courante-1 car avant les :, il y a un espace.
    return[piece_une,piece_deux]

liaisons={"pivot":0,"glissière":0,"hélicoïdale":0,"pivot glissant":0,"sphérique":0,"appui plan":0,"sphère-cylindre":0,"sphère-plan":0,"sphérique à doigt":0,"cylindre-plan":0}
mobilites={"pivot":1,"glissière":1,"hélicoïdale":1,"pivot glissant":2,"sphérique":3,"appui plan":3,"sphère-cylindre":4,"sphère-plan":5,"sphérique à doigt":2,"cylindre-plan":4}


def recup_liaison(ligne):
    limite=len("Liaison ")
    position_courante=len(ligne)-limite
    while ligne[position_courante:position_courante+limite]!="Liaison ":
        position_courante-=1
    return ligne[position_courante+limite:-1]
    
def recup_mobilite(ligne):
    longueur=len("mobilité = ")
    return int(ligne[longueur:])



def lecture_fichier(fichier,liaisons):
    fichier=open(fichier,"r",encoding='latin') # Ouverture du fichier en mode lecture dans un format adapté
    ligne=fichier.readline() # Lecture de la première ligne inutile dans le traitement de nos données
    listes_relations_pieces=[] # Initialisation de la liste de stockage des différentes pièces en relation
    for ligne in fichier: # Pour toutes les lignes ...
        if ligne[0:len("mobilite")]!="mobilite": # ... jusqu'à atteindre la dernière ligne 
            listes_relations_pieces.append(recup_piece(ligne)) # On récupère les différentes pièces en liaison grâce à la fonction précédemment mise en place
            liaisons[recup_liaison(ligne)]+=1 # mise à jour du dictionnaire liaisons.
        else:
            mobilite=recup_mobilite(ligne)
    return listes_relations_pieces,mobilite
    
listes_relations_pieces,mobilite=lecture_fichier(r"\\serveur01\HOSPITF\Travail\Téléchargements\Programmes Pyhton\graphe_cinematique_exo.txt",liaisons)


def nombre_pieces(listes_relations_pieces):
    pieces_trouvees=[]
    for i in range(len(listes_relations_pieces)):
        if listes_relations_pieces[i][0] not in pieces_trouvees:
            pieces_trouvees.append(listes_relations_pieces[i][0])
        if listes_relations_pieces[i][1] not in pieces_trouvees:
            pieces_trouvees.append(listes_relations_pieces[i][1])
    return len(pieces_trouvees)
        
nombre_pieces=nombre_pieces(listes_relations_pieces)

mat_adjacence=[[0]*nombre_pieces for j in range(nombre_pieces)]

for i in range(len(listes_relations_pieces)):
    mat_adjacence[listes_relations_pieces[i][0]][listes_relations_pieces[i][1]]=1
    mat_adjacence[listes_relations_pieces[i][1]][listes_relations_pieces[i][0]]=1

from collections import deque

def recherche_voisins(mat_adj,noeud):
    return [i for i in range(len(mat_adj)) if mat_adj[noeud][i]!=0]
    
def parcours_largeur_graphe(mat_adj,depart):
    file=deque([depart]) # Initialisation de la file avec le premier noeud à visiter
    noeuds_visites=[depart] # Initialisation de la variable qui contiendra les numeros de noeuds visités, on commence par le noeud départ
    cycle=0
    pere_liste=[-1]*len(mat_adj)
    while len(file) != 0:
        noeud_courant=file.pop(0) # Recupération du numéro du noeud courant
        voisins=recherche_voisins(mat_adj,noeud_courant) # Recherhce des voisins 
        pere=noeud_courant
        for v in voisins: # Pour tous les noeuds voisin du noeud courant non visités...
            if v not in noeuds_visites:
                noeuds_visites.append(v) # ... on l'ajoute aux noeuds visités ...
                file.append(v) # ... et à la file d'étude.
                pere_liste[v]=pere
            else:
                if pere_liste[pere]!=v:
                    cycle+=1
    return noeuds_visites,cycle//2 # PENSEZ A DIVISER PAR 2, CAR EN EFFET LORS D'UN PARCOURS, ON DECOUVRE 2 FOIS UNE MEME ARETE


noeuds_visites,nombre_cyclo=parcours_largeur_graphe(mat_adjacence,0)
inconnues_cinematiques=0
for i in mobilites:
    inconnues_cinematiques+=mobilites[i]*liaisons[i]
hyperstatisme=6*nombre_cyclo-inconnues_cinematiques+mobilite


## Rappel : parcours en profondeur
def parcours_profondeur_graphe_iteratif(mat_adj,depart):
    n=len(mat_adj) # Taille de la matrice d'adjacence
    noeuds_visites=[0]*n # Initialisation de la liste noeuds_visites
    pile=deque([depart]) # Initialisation de la pile
    while len(pile)!=0:
        noeud_courant=pile.pop() # Recuperation du noeud courant
        if noeuds_visites[noeud_courant]==0: # S'il n'a pas déjà été découvert ...
            noeuds_visites[noeud_courant]=1 
            voisins_non_visites=[i for i in range(n) if mat_adj[noeud_courant][i]!=0 and noeuds_visites[i]==0]  # Recherche de ses voisins non découverts
            pile.extend(voisins_non_visites) # Ajout à la pile des voisins non découverts
    return noeuds_visites

# methode récursive
def parcours_profondeur_graphe(mat_adj,depart):
    n=len(mat_adj)
    noeuds_visites=[0]*n
    noeuds_visites[depart]=1
    visiter(depart,noeuds_visites)
    return noeuds_visites
    
def visiter(noeud,noeuds_visites):
    if noeuds_visites[noeud]==0: 
        noeuds_visites[noeud]=1
    voisins_non_visites=[i for i in range(len(mat_adj)) if mat_adj[noeud][i]!=0 and noeuds_visites[i]==0] 
    for v in voisins_non_visites:
        visiter(v,noeuds_visites)






    