
    ,jr&                        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#y#)$z2Module contains the score calculation algorithems.    )partial)DictListUnioncast)SCORE_INDICESz-infinfg{Gztg{Gzg      ?
char_start	char_stop
hash_tablereturnc           	          |j                         }|j                  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   8   K   | ]  }t        |      f  y w)N)chr).0uni_charvalues     L/home/ubuntu/waydroid_script/venv/lib/python3.12/site-packages/pfzy/score.py	<genexpr>z#_char_range_with.<locals>.<genexpr>"   s"       
Xs      )copyupdaterangeord)r
   r   r   r   s     ` r   _char_range_withr      sH    $ "J c*os9~/AB      azAZ09g?g?gffffff?g333333?)/-_ .r      haystackc                     d}g }| D ]@  }|j                  t        t        j                  |d         j                  |d             |}B |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   <   sR    : IE \+//$":;??	1MN	 Lr   needlec                    t        |       t        |      }}t        |      }| j                         r|j                         }|dk(  s||k(  rt        t        t        |            fS t        |      D cg c]  }t        |      D cg c]  }d c} }}t        |      D cg c]  }t        |      D cg c]  }d c} }}t        |      D ]  }t        }	||dz
  k(  rt        nt        }
t        |      D ]  }| |   ||   k(  rqt        }|dk(  r|t        z  ||   z   }n6|dk7  r1t        ||dz
     |dz
     ||   z   ||dz
     |dz
     t        z         }|||   |<   t        ||	|
z         x||   |<   }	t        ||   |<   |	|
z   x||   |<   }	  |dz
  |dz
  }}d}t        |      D cg c]  }d }}|dk\  rt|dk\  rd|s||   |   ||   |   k(  rF||   |   t        k7  r7|dkD  xr% |dkD  xr ||   |   ||dz
     |dz
     t        z   k(  }|||<   |dz  }n|dz  }|dk\  rd|dz  }|dk\  rt||dz
     |dz
     |fS c c}w c c}w c c}w c c}w c c}w )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   r   F)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haystack_lenbonus_scorer%   running_scoreresult_scorei
prev_score	gap_scorejscorematch_requiredindicess                  r   _scorerL   a   s   *  #6{CMJ"K ~~>># Q*4$uZ0111 38
2C(-.E,'(q((M ( 38
2C'-.E,'(q('L ' : I
 +,zA~*=&?	|$ 	IAayHQK'!6 11KNBE!V$QU+AE2[^C%a!e,QU36MME
 ',a #25eZ)=S2TTQ"Z&/a #2<y2HHQ"Z!	II6 ><!+qAN
+,Qq,G,
q&1f -"21"5a9K"K"1%2E MAM$Q*$QU+AE25LLM  
QQ' 1f( 	
Q+ q&. 
Q'q(897BB 	)( 	)'D -s6   3I	I 
I"I4	I

=I,	I I
Ic                     | j                         |j                         }} | syd}| D ]  }|j                  ||      dz   }|dk  s y y)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)r7   find)r3   r)   offsetr1   s       r   _subsequencerP      sX    $ ||~x~~'7HFF tV,q0Q; r   c                 B    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)rP   rL   r:   )r3   r)   s     r   
fzy_scorerrR      s%    4 FH%fh''$r   c                 x   g }d}| j                         |j                         }} | j                  d      D ]T  } | s|j                  | |      }|dk  r
t        dfc S t	        |       }|j                  t        |||z                ||z  }V |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(   )r7   splitrN   r:   r5   extendr   )r3   r)   rK   rO   r@   s        r   substr_scorerrW     s    : GF||~x~~'7HF,,s# vv.A:d?"[
uVVj%89:* 'z "+/GAJ
&'!wqzA~*>>gbkTUoAVV r   N)$__doc__	functoolsr   typingr   r   r   r   
pfzy.typesr   floatr:   r8   r=   r;   r<   r?   strintr   
lower_with
upper_with
digit_withSCORE_MATCH_SLASHSCORE_MATCH_WORDSCORE_MATCH_CAPITALSCORE_MATCH_DOT	BONUS_MAPr,   r-   r2   rL   boolrP   rR   rW    r   r   <module>ri      s   8  * * $&M	%L	    #8<S%U
BS=S8T	#uS%Z 
 !4 %sC0
%sC0
%sC0
   						 Iz*=yIJ4S>:aAz!R?P1Q#RS"S "T%[ "JaC3 aC# aC- aCH   :s c m @1# 1 1 1r   