Commits

Marcin Kasperski committed 3be2d5c

Support for partial (truncated) names

  • Participants
  • Parent commits 3d1b520

Comments (0)

Files changed (3)

src/mekk/fics/datatypes/game_type.py

 
     def __hash__(self):
         return hash(self._game_type)
+
+# TODO: is wild vs wild/fr any problem here?

src/mekk/fics/datatypes/player.py

 """
 from collections import namedtuple
 
+# How much of name remains in truncated form
+TRUNCATED_LEN = 8 # TODO: check, it is probably a bit more
+
 class PlayerName(object):
     """
     Representation of a player handle. The class mostly behaves
     as a string, but all comparison operations are case agnostic
     (i.e. MekK == mekk) to mimic FICS behaviour.
+
+    Also makes comparison equal for possibly truncated names
     """
-    __slots__ = 'name',
+    __slots__ = 'name', 'trunc'
 
-    def __init__(self, name):
+    def __init__(self, name, can_be_truncated=False):
         self.name = name
+        self.trunc = can_be_truncated
 
     def __str__(self):
         return self.name
     def __eq__(self, other):
         if type(other) in [str, unicode]:
             other_name = other.lower()
+            other_trunc = False
         else:
+            assert isinstance(other, PlayerName)
             other_name = other.name.lower()
-        return self.name.lower() == other_name
+            other_trunc = other.trunc
+        my_name = self.name.lower()
+        if my_name == other_name:
+            return True
+        if self.trunc and not other_trunc and other_name.startswith(my_name) and len(my_name) >= TRUNCATED_LEN:
+            return True
+        if not self.trunc and other_trunc and my_name.startswith(other_name) and len(other_name) >= TRUNCATED_LEN:
+            return True
+        return False
 
     def __cmp__(self, other):
         if type(other) in [str, unicode]:
-            other_name = other
+            other_name = other.lower()
+            other_trunc = False
         else:
-            other_name = other.name
-        return cmp(self.name.lower(), other_name.lower())
+            other_name = other.name.lower()
+            other_trunc = other.trunc
+        my_name = self.name.lower()
+        if my_name == other_name:
+            return 0
+        if self.trunc and not other_trunc and other_name.startswith(my_name) and len(my_name) >= TRUNCATED_LEN:
+            return 0
+        if not self.trunc and other_trunc and my_name.startswith(other_name) and len(other_name) >= TRUNCATED_LEN:
+            return 0
+        return cmp(my_name, other_name)
 
     def __hash__(self):
-        return hash(self.name.lower())
+        # To stay equal to other possible shortened items
+        return hash(self.name.lower()[:TRUNCATED_LEN])
 
 # TODO: glue for calculating full handle using "handles prefix" command
 

tests/test_playerName.py

         p2 = PlayerName("Mek")
         self.failIfEqual(p1, p2)
     def test_substring_is_equal(self):
-        raise SkipTest
+        p1 = PlayerName("Malabelajestluba")
+        p2 = PlayerName("Malabelaj", can_be_truncated=True)
+        self.failUnlessEqual(p1, p2)
+    def test_full_substring_is_not_equal(self):
+        p1 = PlayerName("Malabelajestluba")
+        p2 = PlayerName("Malabelaj", can_be_truncated=False)
+        self.failIfEqual(p1, p2)
+    def test_short_substring_is_not_equal(self):
+        p1 = PlayerName("Malabelajestluba")
+        p2 = PlayerName("Mala", can_be_truncated=True)
+        self.failIfEqual(p1, p2)
     def test_hashable(self):
         d = { PlayerName("ala"): 1, PlayerName("bela"): 2 }
         self.failUnlessEqual( d[PlayerName("bela")], 2 )
         d[ PlayerName("ala") ] = 3
         self.failUnlessEqual( d[PlayerName("ala")], 3 )
+    def test_hashable_short(self):
+        d = { PlayerName("alamalaka"): 1, PlayerName("belamalaka"): 2 }
+        self.failUnlessEqual( d[PlayerName("belamalaka")], 2 )
+        d[ PlayerName("alamalaka", True) ] = 3
+        self.failUnlessEqual( d[PlayerName("alamalaka")], 3 )
+        d[ PlayerName("belamalak", True) ] = 5
+        self.failUnlessEqual( d[PlayerName("belamalaka")], 5 )
+        self.failIf( PlayerName("belamalak") in d )
+        self.failUnlessEqual( d[PlayerName("belamalak", True)], 5 )
+        d[ PlayerName("bela", True) ] = 6
+        d[ PlayerName("belaj", True) ] = 7
+        self.failUnlessEqual( d[PlayerName("belamalaka")], 5 )
+        self.failUnlessEqual( d[PlayerName("bela")], 6 )
+        self.failUnlessEqual( d[PlayerName("belaj")], 7 )
     def test_comparable_with_string(self):
         self.failUnlessEqual(PlayerName("Mekk"), "mekk")
         self.failIfEqual(PlayerName("Mekk"), "mek")