a
    kÄ#dû  ã                   @   sx   d dl mZ d dlmZmZmZmZmZmZm	Z	 d dl
mZ d dlmZ eeef Ze	rdd dlmZ G dd„ deƒZdS )	é    )Údefaultdict)ÚUnionÚListÚOptionalÚDictÚTupleÚSetÚTYPE_CHECKING)Úlog_automotive)ÚEcuState)Ú_TransitionTuplec                   @   s`   e Zd ZdZdd„ Zddd„Zdd„ Zd	d
„ Zedd„ ƒZ	edd„ ƒZ
ddd„Zedd„ ƒZdS )ÚGraphaº  
    Helper object to store a directional Graph of EcuState objects. An edge in
    this Graph is defined as Tuple of two EcuStates. A node is defined as
    EcuState.

    self.edges is a dict of all possible next nodes
    e.g. {'X': ['A', 'B', 'C', 'E'], ...}

    self.__transition_functions has all the transition_functions between
    two nodes, with the two nodes as a tuple as the key
    e.g. {('X', 'A'): 7, ('X', 'B'): 2, ...}
    c                 C   s   t tƒ| _i | _i | _d S )N)r   ÚlistÚedgesÚ_Graph__transition_functionsÚweights©Úself© r   ú]/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/automotive/scanner/graph.pyÚ__init__"   s    
zGraph.__init__Nc                 C   s0   | j |d   |d ¡ d| j|< || j|< dS )z­
        Inserts new edge in directional graph
        :param edge: edge from node to node
        :param transition_function: tuple with enter and cleanup function
        r   é   N)r   Úappendr   r   )r   ÚedgeZtransition_functionr   r   r   Úadd_edge(   s    
zGraph.add_edgec                 C   s   | j  |d¡S )z¡
        Returns a TransitionTuple for an Edge, if available.
        :param edge: Tuple of EcuStates
        :return: According TransitionTuple or None
        N)r   Úget©r   r   r   r   r   Úget_transition_tuple_for_edge3   s    z#Graph.get_transition_tuple_for_edgec                 C   s.   z| j |  d7  < W n ty(   Y n0 dS )zs
        Increases the weight of an Edge
        :param edge: Edge on which the weight has t obe increased
        r   N)r   ÚKeyErrorr   r   r   r   Údownrate_edge<   s    zGraph.downrate_edgec                 C   s   | j S )zH
        Get the dict of all TransistionTuples
        :return:
        )r   r   r   r   r   Útransition_functionsG   s    zGraph.transition_functionsc                 C   s   t dd„ | j ¡ D ƒƒS )zG
        Get a set of all nodes in this Graph
        :return:
        c                 S   s$   g | ]\}}||g D ]}|‘qqS r   r   )Ú.0ÚkÚpÚnr   r   r   Ú
<listcomp>W   ó    zGraph.nodes.<locals>.<listcomp>)Úsetr   Úitemsr   r   r   r   ÚnodesP   s    zGraph.nodesúSystemStateGraph.gvTc           	   
   C   sâ   zddl m} W n ty.   t d¡ Y dS 0 |ddddd	œd
did�}| jD ]}| t|ƒ¡ qP| j 	¡ D ]`\}}z|du r„dn
|d d }W n t
tfy¬   d}Y n0 |jt|d ƒt|d ƒ|d� qn|j||d� dS )z¿
        Renders this Graph as PDF, if `graphviz` is installed.

        :param filename: A filename for the rendered PDF.
        :param view: If True, rendered file will be opened.
        r   )ÚDigraphzPlease install graphviz.NZSystemStateGraphZ	lightgreyZfilledÚbox)Z	fillcolorÚstyleÚshapeZconcentrateÚtrue)ÚnameZ	node_attrZ
graph_attrÚ r   Údesc)Úlabel)Úview)Úgraphvizr+   ÚImportErrorr
   Úinfor)   ÚnodeÚstrr   r(   ÚAttributeErrorr   r   Úrender)	r   Úfilenamer4   r+   Zpsr$   ÚeÚfr2   r   r   r   r;   Y   s*    
þü

"zGraph.renderc                    sü   |di‰|}t ƒ ‰||kr¾ˆ |¡ | j| }ˆ| d }|D ]L}| j||f | }|ˆvrj||fˆ|< q>ˆ| d }||kr>||fˆ|< q>‡‡fdd„ˆD ƒ‰ ˆ s¨g S tˆ ‡ fdd„d�}qˆ| d }	|g}
|	d	urð|
 |	¡ ˆ|	 d }	qÐ|
 ¡  |
S )
aW  
        Compute shortest paths from initial to end in graph
        Partly from https://benalexkeen.com/implementing-djikstras-shortest-path-algorithm-with-python/  # noqa: E501
        :param graph: Graph where path is computed
        :param initial: Start node
        :param end: End node
        :return: A path as list of nodes
        )Nr   r   c                    s   i | ]}|ˆvr|ˆ | “qS r   r   )r!   r8   )Úshortest_pathsÚvisitedr   r   Ú
<dictcomp>–   s   ÿz"Graph.dijkstra.<locals>.<dictcomp>c                    s   ˆ |  d S )Nr   r   )r"   )Únext_destinationsr   r   Ú<lambda>œ   r&   z Graph.dijkstra.<locals>.<lambda>)Úkeyr   N)r'   Úaddr   r   Úminr   Úreverse)ÚgraphÚinitialÚendZcurrent_nodeÚdestinationsZweight_to_current_nodeZ	next_nodeÚweightZcurrent_shortest_weightZ	last_nodeÚpathr   )rB   r?   r@   r   Údijkstrax   s>    

ÿÿ
ÿ
zGraph.dijkstra)N)r*   T)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   Úpropertyr    r)   r;   ÚstaticmethodrN   r   r   r   r   r      s   
	


r   N)Úcollectionsr   Zscapy.compatr   r   r   r   r   r   r	   Zscapy.contrib.automotiver
   Zscapy.contrib.automotive.ecur   Z_EdgeZ*scapy.contrib.automotive.scanner.test_caser   Úobjectr   r   r   r   r   Ú<module>	   s   $