
    tnir&                     *   d Z ddlmZ ddlmZmZmZmZ ddlm	Z	  e
d          Z e
d          ZdZdZdZd	Zd
ededeeeee
f         f         deeeee
f         f         fdZ eedd          Z eedd          Z eedd          ZdZdZdZdZeeeeedZi e eee          gZ eeeef          ed ed edi                                         Zdedee
         fdZdedede	fdZdedede fd Z!dedede	fd!Z"dedede	fd"Z#d#S )$z2Module contains the score calculation algorithems.    )partial)DictListUnioncast)SCORE_INDICESz-infinfg{Gztg{Gzg      ?
char_start	char_stop
hash_tablereturnc           	          |                                 }|                    fdt          t          |           t          |          dz             D                        |S )a  Generate index mapping for `bonus` calculation.

    Args:
        char_start: Starting char of the range.
        char_stop: Ending char of the range.
        value: Value to give to the range of char.
        hash_table: Base dictionary to add the mapping.

    Returns:
        A dictionary containing the given range with provided index.

    Examples:
        >>> _char_range_with("a", "d", 1, {})
        {'a': 1, 'b': 1, 'c': 1, 'd': 1}
    c              3   :   K   | ]}t          |          fV  d S )N)chr).0uni_charvalues     G/var/www/html/gpu-tools/venv/lib/python3.11/site-packages/pfzy/score.py	<genexpr>z#_char_range_with.<locals>.<genexpr>"   sB         
X            )copyupdaterangeord)r
   r   r   r   s     ` r   _char_range_withr      su    $ ""J    c*oos9~~/ABB      r   azAZ09g?g?gffffff?g333333?)/-_ .r      haystackc                     d}g }| D ]Q}|                     t          t                              |d                                       |d                     |}R|S )a  Calculate bonus score for the given haystack.

    The bonus are applied to each char based on the previous char.

    When previous char is within the `BONUS_MAP` then additional bonus
    are applied to the current char due to it might be the start of a new
    word.

    When encountered a mix case character, if the current char is capitalised then
    if the previous char is normal case or within `BONUS_MAP`, additional bounus are applied.

    Args:
        haystack: String to calculate bonus.

    Returns:
        A list of float matching the length of the given haystack
        with each index representing the bonus score to apply.

    Examples:
        >>> _bonus("asdf")
        [0.9, 0, 0, 0]
        >>> _bonus("asdf asdf")
        [0.9, 0, 0, 0, 0, 0.8, 0, 0, 0]
        >>> _bonus("asdf aSdf")
        [0.9, 0, 0, 0, 0, 0.8, 0.7, 0, 0]
        >>> _bonus("asdf/aSdf")
        [0.9, 0, 0, 0, 0, 0.9, 0.7, 0, 0]
    r#   r   )appendBONUS_STATESBONUS_INDEXget)r)   	prev_charbonuschars       r   _bonusr2   <   s^    : IE  \+//$":":;??	1MMNNN		Lr   needlec                 <   t          |           t          |          c}t          |          }|                                 r|                                }|dk    s|k    r#t          t          t          |                    fS fdt          |          D             }fdt          |          D             }t          |          D ]}t          }||dz
  k    rt          nt          }t                    D ]}	| |         ||	         k    rt          }
|dk    r|	t          z  ||	         z   }
nK|	dk    rEt          ||dz
           |	dz
           ||	         z   ||dz
           |	dz
           t          z             }
|
||         |	<   t          |
||z             x||         |	<   }t          ||         |	<   ||z   x||         |	<   }ˌ|dz
  dz
  }	}d}d t          |          D             }|dk    r|	dk    r|s||         |	         ||         |	         k    rZ||         |	         t          k    rC|dk    o1|	dk    o+||         |	         ||dz
           |	dz
           t          z   k    }|	||<   |	dz  }	n|	dz  }	|	dk    |dz  }|dk    ||dz
           dz
           |fS )af  Use fzy logic to calculate score for `needle` within the given `haystack`.

    2 2D array to track the score.
    1. The running score (`running_score`) which represents the best score for the current position.
    2. The result score (`result_score`) which tracks to overall best score that could be for the current positon.

    With every consequtive match, additional bonuse score are given and for every non matching char, a negative
    gap score is applied.

    After the score is calculated, the final matching score will be stored at the last position of the `result_score`.

    Backtrack the result by comparing the 2 2D array to find the corresponding indices.

    Args:
        needle: Substring to find in haystack.
        haystack: String to be searched and scored.

    Returns:
        A tuple of matching score with a list of matching indices.
    r   c                 B    g | ]}d  t                    D             S )c                     g | ]}d S r    r   r%   s     r   
<listcomp>z%_score.<locals>.<listcomp>.<listcomp>       (((q(((r   r   r   r%   haystack_lens     r   r:   z_score.<locals>.<listcomp>   s=     ( ( (-.((E,''(((( ( (r   c                 B    g | ]}d  t                    D             S )c                     g | ]}d S r7   r8   r9   s     r   r:   z%_score.<locals>.<listcomp>.<listcomp>   r;   r   r<   r=   s     r   r:   z_score.<locals>.<listcomp>   s=     ' ' '-.((E,''(((' ' 'r   r   Fc                     g | ]}d S r7   r8   r9   s     r   r:   z_score.<locals>.<listcomp>   s    ,,,Qq,,,r   )lenr2   islowerlower	SCORE_MAXlistr   	SCORE_MINSCORE_GAP_TRAILINGSCORE_GAP_INNERSCORE_GAP_LEADINGmaxSCORE_MATCH_CONSECUTIVE)r3   r)   
needle_lenbonus_scorerunning_scoreresult_scorei
prev_score	gap_scorejscorematch_requiredindicesr>   s                @r   _scorerX   a   sM   *  #6{{CMMJ""K ~~ $>>## Q*44$uZ001111( ( ( (27
2C2C( ( (M
' ' ' '27
2C2C' ' 'L : I I
 +,zA~*=*=&&?	|$$ 	I 	IAayHQK''!66 11KNBEE!VV$QU+AE2[^C%a!e,QU36MM E
 ',a #25eZ)=S2T2TTQ"ZZ&/a #2<y2HHQ"ZZ!	I( ><!+qAN,,%
++,,,G
q&&1ff "/"21"5a9K"K"K"1%22E MAM$Q*$QU+AE25LLM  
QQ' 1ff( 	
Q+ q&&. 
Q'q(897BBr   c                     |                                  |                                 }} | sdS d}| D ]$}|                    ||          dz   }|dk    r dS %dS )a  Check if needle is subsequence of haystack.

    Args:
        needle: Substring to find in haystack.
        haystack: String to be searched and scored.

    Returns:
        Boolean indicating if `needle` is subsequence of `haystack`.

    Examples:
        >>> _subsequence("as", "bbwi")
        False
        >>> _subsequence("as", "bbaiws")
        True
        >>> _subsequence("sa", "bbaiws")
        False
    Tr   r   F)rD   find)r3   r)   offsetr1   s       r   _subsequencer\      sr    $ ||~~x~~'7'7HF tF  tV,,q0Q;;55 4r   c                 T    t          | |          rt          | |          S t          dfS )a  Use fzy matching algorithem to match needle against haystack.

    Note:
        The `fzf` unordered search is not supported for performance concern.
        When the provided `needle` is not a subsequence of `haystack` at all,
        then `(-inf, None)` is returned.

    See Also:
        https://github.com/jhawthorn/fzy/blob/master/src/match.c

    Args:
        needle: Substring to find in haystack.
        haystack: String to be searched and scored against.

    Returns:
        A tuple of matching score with a list of matching indices.

    Examples:
        >>> fzy_scorer("ab", "acb")
        (0.89, [0, 2])
        >>> fzy_scorer("ab", "acbabc")
        (0.98, [3, 4])
        >>> fzy_scorer("ab", "wc")
        (-inf, None)
    N)r\   rX   rG   )r3   r)   s     r   
fzy_scorerr^      s0    4 FH%% fh'''$r   c                    g }d}|                                  |                                 }} |                     d          D ]f} | s|                    | |          }|dk     rt          dfc S t	          |           }|                    t          |||z                        ||z  }g|sd|fS |d         dz   |d         z
   d|d         dz   z  z   d|d         dz   z  z   |fS )aU  Match needle against haystack using :meth:`str.find`.

    Note:
        Scores may be negative but the higher the score, the higher
        the match rank. `-inf` score means no match found.

    See Also:
        https://github.com/aslpavel/sweep.py/blob/3f4a179b708059c12b9e5d76d1eb3c70bf2caadc/sweep.py#L837

    Args:
        needle: Substring to find in haystack.
        haystack: String to be searched and scored against.

    Returns:
        A tuple of matching score with a list of matching indices.

    Example:
        >>> substr_scorer("ab", "awsab")
        (-1.3, [3, 4])
        >>> substr_scorer("ab", "abc")
        (0.5, [0, 1])
        >>> substr_scorer("ab", "iop")
        (-inf, None)
        >>> substr_scorer("ab", "asdafswabc")
        (-1.6388888888888888, [7, 8])
        >>> substr_scorer(" ", "asdf")
        (0, [])
    r   r&   Nr   r(   )rD   splitrZ   rG   rB   extendr   )r3   r)   rW   r[   rM   s        r   substr_scorerrc     s   : GF||~~x~~'7'7HF,,s##   	vv..A::d?"""[[
uVVj%899:::* 'z "+/GAJ
&'!wqzA~*>>gbkTUoAVV r   N)$__doc__	functoolsr   typingr   r   r   r   
pfzy.typesr   floatrG   rE   rJ   rH   rI   rL   strintr   
lower_with
upper_with
digit_withSCORE_MATCH_SLASHSCORE_MATCH_WORDSCORE_MATCH_CAPITALSCORE_MATCH_DOT	BONUS_MAPr,   r-   r2   rX   boolr\   r^   rc   r8   r   r   <module>rt      s   8 8       * * * * * * * * * * * * $ $ $ $ $ $E&MM	E%LL	    #8<S%U
BS=S8T	#uS%Z 
 !   4 W%sC00
W%sC00
W%sC00
   					 	 Izz*=yIIJd4S>::aAzz!R?P?P1Q1Q#R#RSS"S "T%[ " " " "JaC3 aC# aC- aC aC aC aCH      :s c m    @1# 1 1 1 1 1 1 1 1r   