class_docstr: strcmp95 similarity
  
  http://cpansearch.perl.org/src/SCW/Text-JaroWinkler-0.1/strcmp95.c
class_docstr_tok: ["strcmp95","similarity","http",":","\/\/cpansearch.perl.org\/src\/SCW\/Text-JaroWinkler-0.1\/strcmp95.c"]
code: def __call__(self, s1: str, s2: str) -> float:
      s1 = s1.strip().upper()
      s2 = s2.strip().upper()
  
      result = self.quick_answer(s1, s2)
      if result is not None:
          return result
  
      len_s1 = len(s1)
      len_s2 = len(s2)
  
      adjwt = defaultdict(int)
  
      # Initialize the adjwt array on the first call to the function only.
      # The adjwt array is used to give partial credit for characters that
      # may be errors due to known phonetic or character recognition errors.
      # A typical example is to match the letter "O" with the number "0"
      for c1, c2 in self.sp_mx:
          adjwt[c1, c2] = 3
          adjwt[c2, c1] = 3
  
      if len_s1 > len_s2:
          search_range = len_s1
          minv = len_s2
      else:
          search_range = len_s2
          minv = len_s1
  
      # Blank out the flags
      s1_flag = [0] * search_range
      s2_flag = [0] * search_range
      search_range = max(0, search_range // 2 - 1)
  
      # Looking only within the search range, count and flag the matched pairs.
      num_com = 0
      yl1 = len_s2 - 1
      for i, sc1 in enumerate(s1):
          lowlim = max(i - search_range, 0)
          hilim = min(i + search_range, yl1)
          for j in range(lowlim, hilim + 1):
              if s2_flag[j] == 0 and s2[j] == sc1:
                  s2_flag[j] = 1
                  s1_flag[i] = 1
                  num_com += 1
                  break
  
      # If no characters in common - return
      if num_com == 0:
          return 0.0
  
      # Count the number of transpositions
      k = n_trans = 0
      for i, sc1 in enumerate(s1):
          if not s1_flag[i]:
              continue
          for j in range(k, len_s2):
              if s2_flag[j] != 0:
                  k = j + 1
                  break
          if sc1 != s2[j]:
              n_trans += 1
      n_trans = n_trans // 2
  
      # Adjust for similarities in unmatched characters
      n_simi = 0
      if minv > num_com:
          for i in range(len_s1):
              if s1_flag[i] != 0:
                  continue
              if not self._in_range(s1[i]):
                  continue
              for j in range(len_s2):
                  if s2_flag[j] != 0:
                      continue
                  if not self._in_range(s2[j]):
                      continue
                  if (s1[i], s2[j]) not in adjwt:
                      continue
                  n_simi += adjwt[s1[i], s2[j]]
                  s2_flag[j] = 2
                  break
      num_sim = n_simi / 10.0 + num_com
  
      # Main weight computation
      weight = num_sim / len_s1 + num_sim / len_s2
      weight += (num_com - n_trans) / num_com
      weight = weight / 3.0
  
      # Continue to boost the weight if the strings are similar
      if weight <= 0.7:
          return weight
  
      # Adjust for having up to the first 4 characters in common
      j = min(minv, 4)
      i = 0
      for sc1, sc2 in zip(s1, s2):
          if i >= j:
              break
          if sc1 != sc2:
              break
          if sc1.isdigit():
              break
          i += 1
      if i:
          weight += i * 0.1 * (1.0 - weight)
  
      # Optionally adjust for long strings.
  
      # After agreeing beginning chars, at least two more must agree and
      # the agreeing characters must be > .5 of remaining characters.
      if not self.long_strings:
          return weight
      if minv <= 4:
          return weight
      if num_com <= i + 1 or 2 * num_com < minv + i:
          return weight
      if s1[0].isdigit():
          return weight
      res = (num_com - i - 1) / (len_s1 + len_s2 - i * 2 + 2)
      weight += (1.0 - weight) * res
      return weight
  
imports: from __future__ import annotations
  from collections import defaultdict
  from itertools import zip_longest
  from typing import Any, Sequence, TypeVar
  from .base import Base, BaseSimilarity
  from .types import SimFunc, TestFunc
label_desc: Use image node_id 4 for calling the StrCmp95 obj's underlying member method code with example usage: obj.__call__(s1, s2) and returns: weight, result, int, weight, weight, weight, weight, weight