+
    xȇiw%                        ^ RI Ht ^ RIt^ RIt ^RIHt ^RI
Ht ]P                  ]P                  ]P                  R 4       4       4       t]P                  ]P                  ]P                  R	 4       4       4       tRR
 lt]P                  RR l4       tRR ltRR lt]P                  RR l4       tRR ltRR ltRR ltRR ltRR ltRR ltR#   ] d2    ]P                  ! 4       R8w  d   ]P                  ! R4       ^ RI	Ht  Li ; i)    )unicode_literalsN)StringMatcherPyPyzYUsing slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning)SequenceMatcher)utilsc                     \         P                  ! W4      w  r\        R W4      p\         P                  ! ^dVP	                  4       ,          4      # )N)r   make_type_consistentr   intrratio)s1s2ms   && _/Users/max/.openclaw/workspace/postharvest/venv/lib/python3.14/site-packages/fuzzywuzzy/fuzz.pyr   r      s;     ''/FBb%A::cAGGIo&&    c                   \         P                  ! W4      w  r\        V 4      \        V4      8:  d   T pTpMTpT p\        RW#4      pVP	                  4       p. pV F  pV^,          V^ ,          ,
          ^ 8  d   V^,          V^ ,          ,
          M^ pV\        V4      ,           p	W8V	 p
\        RW*4      pVP                  4       pVR8  d    ^d# VP                  V4       K  	  \         P                  ! ^d\        V4      ,          4      # )zN"Return the ratio of the most similar substring
as a number between 0 and 100.Ngףp=
?)	r   r	   lenr   get_matching_blocksr   appendr
   max)r   r   shorterlongerr   blocksscoresblock
long_startlong_endlong_substrm2rs   &&           r   partial_ratior       s     ''/FB
2w#b'g.A""$F F-21Xa-@A,EU1Xa(1
G,1T78HHJt8MM!  ::cCK'((r   c                    V'       d   \         P                  ! WR7      MT pVP                  4       pRP                  \	        V4      4      pVP                  4       # )z*Return a cleaned string with token sorted.force_ascii )r   full_processsplitjoinsortedstrip)sr#   r%   tstokenssorted_strings   &&&   r   _process_and_sortr.   K   sG     <H		A	7QBXXZF IIfVn-M  r   c                 r    \        WVR 7      p\        WVR 7      pV'       d   \        WV4      # \        WV4      # )r%   )r.   r    r   )r   r   partialr#   r%   sorted1sorted2s   &&&&&  r   _token_sortr4   Z   s3    lKGlKGW..W&&r   c                    \        WRW#R7      # )zhReturn a measure of the sequences' similarity between 0 and 100
but sorting the token before comparing.
Fr1   r#   r%   r4   r   r   r#   r%   s   &&&&r   token_sort_ratior9   e   s     ru+aar   c                    \        WRW#R7      # )zuReturn the ratio of the most similar substring as a number between
0 and 100 but sorting the token before comparing.
Tr6   r7   r8   s   &&&&r   partial_token_sort_ratior;   l   s     rt``r   c                   V'       g	   W8X  d   ^d# V'       d   \         P                  ! WR7      MT pV'       d   \         P                  ! WR7      MTp\         P                  ! V4      '       g   ^ # \         P                  ! V4      '       g   ^ # \        VP	                  4       4      p\        VP	                  4       4      pVP                  V4      p	VP                  V4      p
VP                  V4      pRP                  \        V	4      4      pRP                  \        V
4      4      pRP                  \        V4      4      pVR,           V,           pVR,           V,           pVP                  4       pVP                  4       pVP                  4       pV'       d   \        pM\        pV! W4      V! VV4      V! VV4      .p\        V4      # )zFind all alphanumeric tokens in each string...
- treat them as a set
- construct two strings of the form:
    <sorted_intersection><sorted_remainder>
- take ratios of those two strings
- controls for unordered partial matchesr"   r$   )r   r%   validate_stringsetr&   intersection
differencer'   r(   r)   r    r   r   )r   r   r1   r#   r%   p1p2tokens1tokens2r?   diff1to2diff2to1sorted_sectsorted_1to2sorted_2to1combined_1to2combined_2to1
ratio_funcpairwises   &&&&&              r   
_token_setrN   s   so    BH<H		B	8bB<H		B	8bB  $$  $$ "((*oG"((*oG''0L!!'*H!!'*H((6,/0K((6(+,K((6(+,K#%3M#%3M ##%K!'')M!'')M"

 	;.;.=-0H
 x=r   c                     \        WR W#R7      # )Fr6   rN   r8   s   &&&&r   token_set_ratiorQ      s    be``r   c                     \        WR W#R7      # )Tr6   rP   r8   s   &&&&r   partial_token_set_ratiorS      s    bd__r   c                   V'       d0   \         P                  ! WR7      p\         P                  ! WR7      pMT pTp\         P                  ! V4      '       g   ^ # \         P                  ! V4      '       g   ^ # \        WE4      # )ax  
Quick ratio comparison between two strings.

Runs full_process from utils on both strings
Short circuits if either of the strings is empty after processing.

:param s1:
:param s2:
:param force_ascii: Allow only ASCII characters (Default: True)
:full_process: Process inputs, used here to avoid double processing in extract functions (Default: True)
:return: similarity ratio
r"   )r   r%   r=   r   )r   r   r#   r%   rA   rB   s   &&&&  r   QRatiorU      sc     <<  $$  $$=r   c                    \        WRVR7      # )zr
Unicode quick ratio

Calls QRatio with force_ascii set to False

:param s1:
:param s2:
:return: similarity ratio
Fr#   r%   )rU   r   r   r%   s   &&&r   UQRatiorY      s     "e,GGr   c                :   V'       d0   \         P                  ! WR7      p\         P                  ! WR7      pMT pTp\         P                  ! V4      '       g   ^ # \         P                  ! V4      '       g   ^ # RpRpRp\        WE4      p	\	        \        \        V4      \        V4      4      4      \        \        V4      \        V4      4      ,          p
V
R8  d   RpV
^8  d   RpV'       di   \        WE4      V,          p\        WERR7      V,          V,          p\        WERR7      V,          V,          p\         P                  ! \        WW4      4      # \        WERR7      V,          p\        WERR7      V,          p\         P                  ! \        WV4      4      # )	a  
Return a measure of the sequences' similarity between 0 and 100, using different algorithms.

**Steps in the order they occur**

#. Run full_process from utils on both strings
#. Short circuit if this makes either string empty
#. Take the ratio of the two processed strings (fuzz.ratio)
#. Run checks to compare the length of the strings
    * If one of the strings is more than 1.5 times as long as the other
      use partial_ratio comparisons - scale partial results by 0.9
      (this makes sure only full results can return 100)
    * If one of the strings is over 8 times as long as the other
      instead scale by 0.6

#. Run the other ratio functions
    * if using partial ratio functions call partial_ratio,
      partial_token_sort_ratio and partial_token_set_ratio
      scale all of these by the ratio based on length
    * otherwise call token_sort_ratio and token_set_ratio
    * all token based comparisons are scaled by 0.95
      (on top of any partial scalars)

#. Take the highest value from these results
   round it and return it as an integer.

:param s1:
:param s2:
:param force_ascii: Allow only ascii characters
:type force_ascii: bool
:full_process: Process inputs, used here to avoid double processing in extract functions (Default: True)
:return:
r"   Tgffffff?g?g      ?Fg333333?r0   )r   r%   r=   r   floatr   r   minr    r;   rS   r
   r9   rQ   )r   r   r#   r%   rA   rB   try_partialunbase_scalepartial_scalebase	len_ratior1   ptsorptsertsortsers   &&&&            r   WRatiorf      sW   F <<  $$  $$ KLM=Dc#b'3r7+,s3r7CG/DDI 3 1}'-7(eD*+'UC*+ zz#dU:;;U;lJrE:\Izz#d$/00r   c                    \        WRVR7      # )zReturn a measure of the sequences' similarity between 0 and 100,
using different algorithms. Same as WRatio but preserving unicode.
FrW   )rf   rX   s   &&&r   UWRatiorh   .  s     "e,GGr   )T)TTT)TT)
__future__r   platformwarningsr   r   ImportErrorpython_implementationwarndifflib r   check_for_nonecheck_for_equivalencecheck_empty_stringr   r    r.   r4   r9   r;   rN   rQ   rS   rU   rY   rf   rh    r   r   <module>ru      s'   (  (?  '   ' ")   ")R! ' 'ba 1 1ha`:
HK1\HK	  (%%'61qr'(s   C 5D
D