def checkPeriods(name): words = wordList(name) for word in words: if word[-1] == ',': word = word[:-1] numPeriods = word.count('.') if not numPeriods: continue letters = justLetters(word) numLetters = len(letters) if word[-1] != '.': notify.info('word "%s" does not end in a period' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods > 2: notify.info('word "%s" has too many periods' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods == 2: if not word[1] == '.' and word[3] == '.': notify.info('word "%s" does not fit the J.T. pattern' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage word[3] == '.'
def checkJapanese(name): asciiSpace = range(32, 33) asciiDigits = range(48, 64) hiragana = range(12353, 12448) katakana = range(12449, 12544) halfwidthKatakana = range(65381, 65440) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 for char in (ord(char) for char in te.decodeText(name)): if char not in allowedUtf8: if char in asciiDigits: notify.info('name contains not allowed ascii digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains not allowed utf8 char: 0x%04x' % char) return OTPLocalizer.NCBadCharacter % te.encodeWtext( unichr(char)) elif char in halfwidthCharacter: dc += 0.5 else: dc += 1 if dc < 2: notify.info('name is too short: %0.1f' % dc) return OTPLocalizer.NCTooShort elif dc > 8: notify.info( 'name has been occupied more than eight display cells: %0.1f' % dc) return OTPLocalizer.NCGeneric
def checkJapanese(name): asciiSpace = range(32, 33) asciiDigits = range(48, 64) hiragana = range(12353, 12448) katakana = range(12449, 12544) halfwidthKatakana = range(65381, 65440) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 for char in (ord(char) for char in te.decodeText(name)): if char not in allowedUtf8: if char in asciiDigits: notify.info('name contains not allowed ascii digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains not allowed utf8 char: 0x%04x' % char) return OTPLocalizer.NCBadCharacter % te.encodeWtext(unichr(char)) elif char in halfwidthCharacter: dc += 0.5 else: dc += 1 if dc < 2: notify.info('name is too short: %0.1f' % dc) return OTPLocalizer.NCTooShort elif dc > 8: notify.info('name has been occupied more than eight display cells: %0.1f' % dc) return OTPLocalizer.NCGeneric
def fontHasCharacters(name, font=font): if font: tn = TextNode('NameCheck') tn.setFont(font) for c in name: if not tn.hasCharacter(ord(c)): notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c)) return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
def badCharacters(name, _validCharacter = _validCharacter): for char in name: if not _validCharacter(char): if char in string.digits: notify.info('name contains digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(char)
def perWord(word): word = word letters = justLetters(word) if len(letters) > 2: letters = TextEncoder().decodeText(TextEncoder.lower(TextEncoder().encodeWtext(letters))) filtered = filterString(letters, letters[0]) if filtered == letters: notify.info('word "%s" uses only one letter' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCGeneric
def allCaps(name): letters = justLetters(name) if len(letters) > 2: upperLetters = TextEncoder().decodeText(TextEncoder.upper(TextEncoder().encodeWtext(letters))) for i in xrange(len(upperLetters)): if not upperLetters[0].isupper(): return if upperLetters == letters: notify.info('name is all caps') return OTPLocalizer.NCAllCaps
def __typedAName(self, *args): self.notify.debug('__typedAName') self.nameEntry['focus'] = 0 name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) problem = self.nameIsValid(self.nameEntry.get()) if problem: self.rejectName(problem) return self.checkNameTyped(justCheck=True)
def repeatedChars(name): count = 1 lastChar = None i = 0 while i < len(name): char = name[i] i += 1 if char == lastChar: count += 1 else: count = 1 lastChar = char if count > 2: notify.info('character %s is repeated too many times' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCRepeatedChar % TextEncoder().encodeWtext(char)
def _typedAName(self, *args): self.nameEntry['focus'] = 0 name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) self.notify.debug('Chosen name: %s' % self.nameEntry.get()) problem = NameCheck.checkName(name, [self._checkNpcNames], font=self.nameEntry.getFont()) if problem: print problem self.nameEntry.enterText('') else: self.fsm.request('Approved')
def _typedAName(self, *args): self.nameEntry['focus'] = 0 name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) self.notify.debug('Chosen name: %s' % self.nameEntry.get()) problem = NameCheck.checkName(name, [ self._checkNpcNames], font = self.nameEntry.getFont()) if problem: print problem self.nameEntry.enterText('') else: self.fsm.request('Approved')
def makeSign(topStr, signStr, textId): top = self.geom.find('**/' + topStr) sign = top.find('**/' + signStr) locator = top.find('**/sign_origin') signText = DirectGui.OnscreenText(text=TextEncoder.upper(TTLocalizer.GlobalStreetNames[textId][-1]), font=ToontownGlobals.getSuitFont(), scale=TTLocalizer.BCHQLsignText, fg=(0, 0, 0, 1), parent=sign) signText.setPosHpr(locator, 0, -0.1, -0.25, 0, 0, 0) signText.setDepthWrite(0)
def hasLetters(name): words = wordList(name) for word in words: letters = justLetters(word) if len(letters) == 0: notify.info('word "%s" has no letters' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedLetters
def checkJapanese(name): # Japan allows ASCII space, hiragana, katakana, and half-width katakana, # but, allows not ASCII and kanji(CJK) characters for a name # All Japanese characters are three-byte-encoded utf-8 characters from unicode # Reference: http://unicode.org/charts/ asciiSpace = range(0x20, 0x21) asciiDigits = range(0x30, 0x40) hiragana = range(0x3041, 0x30A0) katakana = range(0x30A1, 0x3100) halfwidthKatakana = range(0xFF65, 0xFFA0) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 # Return None if name is OK, error string if name is not OK for char in (ord(char) for char in te.decodeText(name)): if char not in allowedUtf8: # Notify error string, if not allowed utf-8 character if char in asciiDigits: notify.info('name contains not allowed ascii digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains not allowed utf8 char: 0x%04x' % char) return OTPLocalizer.NCBadCharacter % te.encodeWtext( unichr(char)) else: # Restrict the number of characters, if three-byte-encoded utf-8 character # The full-width characters would fit into a single display cell, # and the half-width characters would fit two to a display cell if char in halfwidthCharacter: dc += 0.5 else: dc += 1 # Japan restricts the number of the characters, if occupied less then two display cell # and more then eight display cell. if (dc < 2): notify.info('name is too short: %0.1f' % dc) return OTPLocalizer.NCTooShort elif (dc > 8): notify.info( 'name has been occupied more than eight display cells: %0.1f' % dc) return OTPLocalizer.NCGeneric
def allCaps(name): # MICKEY MOUSE letters = justLetters(name) # J.T. -> OK if len(letters) > 2: upperLetters = TextEncoder().decodeText( TextEncoder.upper(TextEncoder().encodeWtext(letters))) # some unicode characters can't be capitalized for i in xrange(len(upperLetters)): if not upperLetters[0].isupper(): # at least one letter is not upper-case # name is not all-caps # excessive capitalization will be caught by mixedCase() return if upperLetters == letters: notify.info('name is all caps') return OTPLocalizer.NCAllCaps
def complete(self): self.nameEntry['focus'] = 0 name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) self.notify.debug('Chosen name: %s' % name) if self.customName: problem = NameCheck.checkName(name, [ self._checkNpcNames], font = self.nameEntry.getFont()) if problem: print problem self.nameEntry.enterText('') else: self.fsm.request('Done') else: self.fsm.request('Done')
def complete(self): self.nameEntry['focus'] = 0 name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) self.notify.debug('Chosen name: %s' % name) if self.customName: problem = NameCheck.checkName(name, [self._checkNpcNames], font=self.nameEntry.getFont()) if problem: print problem self.nameEntry.enterText('') else: self.fsm.request('Done') else: self.fsm.request('Done')
def getTypeANameProblem(self, callback): if not self.customName: callback(None) else: problem = None name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) problem = NameCheck.checkName(self.nameEntry.get(), [ self._checkNpcNames], font = self.nameEntry.getFont()) if problem: callback(problem) elif self.cr: self.ignore(self.cr.getWishNameResultMsg()) self.acceptOnce(self.cr.getWishNameResultMsg(), self._handleSetWishnameResult) self._nameCheckCallback = callback self._sendSetWishname(justCheck = True) return None
def checkJapanese(name): asciiSpace = range(32, 33) asciiDigits = range(48, 64) hiragana = range(12353, 12448) katakana = range(12449, 12544) halfwidthKatakana = range(65381, 65440) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 for char in lambda [outmost-iterable]: for char in [outmost-iterable]:
def checkApostrophes(name): words = wordList(name) for word in words: numApos = word.count("'") if numApos > 2: notify.info('word "%s" has too many apostrophes.' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCApostrophes numApos = name.count("'") if numApos > 3: notify.info('name has too many apostrophes.') return OTPLocalizer.NCApostrophes
def getTypeANameProblem(self, callback): if not self.customName: callback(None) else: problem = None name = self.nameEntry.get() name = TextEncoder().decodeText(name) name = name.strip() name = TextEncoder().encodeWtext(name) self.nameEntry.enterText(name) problem = NameCheck.checkName(self.nameEntry.get(), [self._checkNpcNames], font=self.nameEntry.getFont()) if problem: callback(problem) elif self.cr: self.ignore(self.cr.getWishNameResultMsg()) self.acceptOnce(self.cr.getWishNameResultMsg(), self._handleSetWishnameResult) self._nameCheckCallback = callback self._sendSetWishname(justCheck=True) return None
def _getName(self): newName = '' if self.mode == self._NameGUI__MODE_TYPEANAME: newName = self.nameEntry.get() newName = TextEncoder().decodeText(newName) newName = newName.strip() newName = TextEncoder().encodeWtext(newName) else: newName += self.names[0] if len(newName) > 0 and len(self.names[1]) > 0: newName += ' ' newName += self.names[1] if len(newName) > 0 and len(self.names[2]) > 0: newName += ' ' newName += self.names[2] if self.names[2] in PL.PirateNames_LastNamePrefixesCapped: newName += self.names[3].capitalize() else: newName += self.names[3] return newName
def perWord(word): if '.' in word: return None for char in word: if ord(char) >= 128: return None letters = filterString(word, string.letters) if len(letters) > 2: vowels = filterString(letters, 'aeiouyAEIOUY') if len(vowels) == 0: notify.info('word "%s" has no vowels' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedVowels
def checkPeriods(name): """ periods are allowed at the end of words, or in two-letter words, like 'J.T.' """ words = wordList(name) for word in words: # strip off any trailing commas if word[-1] == ',': word = word[:-1] numPeriods = word.count('.') if not numPeriods: continue letters = justLetters(word) numLetters = len(letters) # word must end in '.' if word[-1] != '.': notify.info('word "%s" does not end in a period' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage # max periods is 2 if numPeriods > 2: notify.info('word "%s" has too many periods' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods == 2: # 2nd and 4th characters should be periods if not ((word[1] == '.') and (word[3] == '.')): notify.info('word "%s" does not fit the J.T. pattern' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage return None
def perWord(word): # if there's a period, assume it's an abbrevation if '.' in word: return None # Check if there's an extended character; if # so, it might be a vowel. for char in word: if ord(char) >= 0x80: return None letters = filterString(word, string.letters) # things like 'MD' are ok without periods if len(letters) > 2: vowels = filterString(letters, 'aeiouyAEIOUY') if len(vowels) == 0: notify.info('word "%s" has no vowels' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedVowels
def match(npcName, name = name): name = TextEncoder().encodeWtext(name) name = name.strip() return TextEncoder.upper(npcName) == TextEncoder.upper(name)
def checkName(name, otherCheckFuncs=[], font=None): # misc check functions; # name should not be a wide-character string (for example it should be utf-8) # return None if name is OK, error string if name is not OK # check functions are given unicode strings # if font is passed in, checkName() will make sure all characters in the name # are valid characters in the font def longEnough(name): if len(name) < 2: notify.info('name is too short') return OTPLocalizer.NCTooShort def emptyName(name): if name.strip() == '': notify.info('name is empty') return OTPLocalizer.NCTooShort def printableChars(name): for char in name: # If it is an extended character, we cannot test it for printability here (but # presumably it is some printable character.) if ord(char) < 0x80 and char not in string.printable: notify.info('name contains non-printable char #%s' % ord(char)) return OTPLocalizer.NCGeneric validAsciiChars = set(".,'-" + string.letters + string.whitespace) def _validCharacter(c, validAsciiChars=validAsciiChars, font=font): if c in validAsciiChars: return True # check for Unicode alphabetic characters and whitespace if c.isalpha() or c.isspace(): return True return False def badCharacters(name, _validCharacter=_validCharacter): for char in name: if not _validCharacter(char): if char in string.digits: notify.info('name contains digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCBadCharacter % TextEncoder( ).encodeWtext(char) def fontHasCharacters(name, font=font): if font: tn = TextNode('NameCheck') tn.setFont(font) for c in name: if not tn.hasCharacter(ord(c)): notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c)) return OTPLocalizer.NCBadCharacter % TextEncoder( ).encodeWtext(c) def hasLetters(name): #,..., words = wordList(name) for word in words: letters = justLetters(word) if len(letters) == 0: notify.info('word "%s" has no letters' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedLetters def hasVowels(name): # ndssmvwls def perWord(word): # if there's a period, assume it's an abbrevation if '.' in word: return None # Check if there's an extended character; if # so, it might be a vowel. for char in word: if ord(char) >= 0x80: return None letters = filterString(word, string.letters) # things like 'MD' are ok without periods if len(letters) > 2: vowels = filterString(letters, 'aeiouyAEIOUY') if len(vowels) == 0: notify.info('word "%s" has no vowels' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedVowels for word in wordList(name): problem = perWord(word) if problem: return problem def monoLetter(name): # eeeeeeeee def perWord(word): word = word letters = justLetters(word) if len(letters) > 2: # make case-insensitive letters = TextEncoder().decodeText( TextEncoder.lower(TextEncoder().encodeWtext(letters))) filtered = filterString(letters, letters[0]) if filtered == letters: notify.info('word "%s" uses only one letter' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCGeneric for word in wordList(name): problem = perWord(word) if problem: return problem def checkDashes(name): def validDash(index, name=name): # if the dash is at the beginning or the end, fail if (index == 0) or (i == len(name) - 1): return 0 # dash must be surrounded by letters on both sides if not (name[i - 1].isalpha()): return 0 if not (name[i + 1].isalpha()): return 0 return 1 i = 0 while 1: i = name.find('-', i, len(name)) if i < 0: return None if not validDash(i): notify.info('name makes invalid use of dashes') return OTPLocalizer.NCDashUsage i += 1 def checkCommas(name): def validComma(index, name=name): # if the comma is at the beginning or the end, fail if (index == 0) or (i == len(name) - 1): return OTPLocalizer.NCCommaEdge # comma must follow a word and be followed by a space if (name[i - 1].isspace()): return OTPLocalizer.NCCommaAfterWord if not (name[i + 1].isspace()): return OTPLocalizer.NCCommaUsage return None i = 0 while 1: i = name.find(',', i, len(name)) if i < 0: return None problem = validComma(i) if problem: notify.info('name makes invalid use of commas') return problem i += 1 def checkPeriods(name): """ periods are allowed at the end of words, or in two-letter words, like 'J.T.' """ words = wordList(name) for word in words: # strip off any trailing commas if word[-1] == ',': word = word[:-1] numPeriods = word.count('.') if not numPeriods: continue letters = justLetters(word) numLetters = len(letters) # word must end in '.' if word[-1] != '.': notify.info('word "%s" does not end in a period' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage # max periods is 2 if numPeriods > 2: notify.info('word "%s" has too many periods' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods == 2: # 2nd and 4th characters should be periods if not ((word[1] == '.') and (word[3] == '.')): notify.info('word "%s" does not fit the J.T. pattern' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage return None def checkApostrophes(name): words = wordList(name) for word in words: numApos = word.count("'") if numApos > 2: notify.info('word "%s" has too many apostrophes.' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCApostrophes numApos = name.count("'") if numApos > 3: notify.info('name has too many apostrophes.') return OTPLocalizer.NCApostrophes def tooManyWords(name): if len(wordList(name)) > 4: notify.info('name has too many words') return OTPLocalizer.NCTooManyWords def allCaps(name): # MICKEY MOUSE letters = justLetters(name) # J.T. -> OK if len(letters) > 2: upperLetters = TextEncoder().decodeText( TextEncoder.upper(TextEncoder().encodeWtext(letters))) # some unicode characters can't be capitalized for i in xrange(len(upperLetters)): if not upperLetters[0].isupper(): # at least one letter is not upper-case # name is not all-caps # excessive capitalization will be caught by mixedCase() return if upperLetters == letters: notify.info('name is all caps') return OTPLocalizer.NCAllCaps def mixedCase(name): # MiCkeY MoUsE words = wordList(name) for word in words: if len(word) > 2: # allow McQuack capitals = justUpper(word) if len(capitals) > 2: notify.info('name has mixed case') return OTPLocalizer.NCMixedCase def checkJapanese(name): # Japan allows ASCII space, hiragana, katakana, and half-width katakana, # but, allows not ASCII and kanji(CJK) characters for a name # All Japanese characters are three-byte-encoded utf-8 characters from unicode # Reference: http://unicode.org/charts/ asciiSpace = range(0x20, 0x21) asciiDigits = range(0x30, 0x40) hiragana = range(0x3041, 0x30A0) katakana = range(0x30A1, 0x3100) halfwidthKatakana = range(0xFF65, 0xFFA0) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 # Return None if name is OK, error string if name is not OK for char in (ord(char) for char in te.decodeText(name)): if char not in allowedUtf8: # Notify error string, if not allowed utf-8 character if char in asciiDigits: notify.info('name contains not allowed ascii digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains not allowed utf8 char: 0x%04x' % char) return OTPLocalizer.NCBadCharacter % te.encodeWtext( unichr(char)) else: # Restrict the number of characters, if three-byte-encoded utf-8 character # The full-width characters would fit into a single display cell, # and the half-width characters would fit two to a display cell if char in halfwidthCharacter: dc += 0.5 else: dc += 1 # Japan restricts the number of the characters, if occupied less then two display cell # and more then eight display cell. if (dc < 2): notify.info('name is too short: %0.1f' % dc) return OTPLocalizer.NCTooShort elif (dc > 8): notify.info( 'name has been occupied more than eight display cells: %0.1f' % dc) return OTPLocalizer.NCGeneric def repeatedChars(name): count = 1 lastChar = None i = 0 while i < len(name): char = name[i] i += 1 if char == lastChar: # character is repeating count += 1 else: count = 1 lastChar = char if count > 2: notify.info('character %s is repeated too many times' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCRepeatedChar % TextEncoder().encodeWtext( char) checks = [ printableChars, badCharacters, fontHasCharacters, longEnough, emptyName, hasLetters, hasVowels, monoLetter, checkDashes, checkCommas, checkPeriods, checkApostrophes, tooManyWords, allCaps, mixedCase, repeatedChars, ] + otherCheckFuncs # checks that should be run on the reversed name string symmetricChecks = [] # make sure we are working with a wide-character version of the string name = TextEncoder().decodeText(name) notify.info('checking name "%s"...' % TextEncoder().encodeWtext(name)) # run through all the checks for check in checks: problem = check(name[:]) if (not problem) and (check in symmetricChecks): # check it backwards. nName = name[:] bName.reverse() problem = check(bName) print "problem = %s" % (problem) if problem: return problem return None
return None # prevent log spam during testing severity = notify.getSeverity() notify.setSeverity(NSError) # these tests can be removed or replaced for international versions of the codebase # long enough assert checkName('J') assert not checkName('Jo') # empty name assert checkName('') assert checkName('\t') assert checkName(TextEncoder().encodeWtext(u'\xa0')) assert checkName(TextEncoder().encodeWtext(u'\u1680')) assert checkName(TextEncoder().encodeWtext(u'\u2001')) # printable chars for i in xrange(32): assert checkName(chr(i)) assert checkName(chr(0x7f)) # bad characters for c in '!"#$%&()*+/:;<=>?@[\]^_`{|}~': assert checkName('Bob' + c) # has letters assert checkName(',...,') # katakana = range(0x30A1, 0x30FB) #assert not checkName(TextEncoder().encodeWtext(u'\u30a1\u30a2')) # has vowels assert checkName('Qwrt')
fontHasCharacters, longEnough, emptyName, hasLetters, hasVowels, monoLetter, checkDashes, checkCommas, checkPeriods, checkApostrophes, tooManyWords, allCaps, mixedCase, repeatedChars] + otherCheckFuncs symmetricChecks = [] name = TextEncoder().decodeText(name) notify.info('checking name "%s"...' % TextEncoder().encodeWtext(name)) for check in checks: problem = check(name[:]) if not problem and check in symmetricChecks: nName = name[:] bName.reverse() problem = check(bName) print 'problem = %s' % problem if problem: return problem continue severity = notify.getSeverity()
def match(npcName, name=name): name = TextEncoder().encodeWtext(name) name = string.strip(name) return TextEncoder.upper(npcName) == TextEncoder.upper(name)
def checkName(name, otherCheckFuncs=[], font=None): def longEnough(name): if len(name) < 2: notify.info('name is too short') return OTPLocalizer.NCTooShort def emptyName(name): if name.strip() == '': notify.info('name is empty') return OTPLocalizer.NCTooShort def printableChars(name): for char in name: if ord(char) < 128 and char not in string.printable: notify.info('name contains non-printable char #%s' % ord(char)) return OTPLocalizer.NCGeneric validAsciiChars = set(".,'-" + string.letters + string.whitespace) def _validCharacter(c, validAsciiChars=validAsciiChars, font=font): if c in validAsciiChars: return True if c.isalpha() or c.isspace(): return True return False def badCharacters(name, _validCharacter=_validCharacter): for char in name: if not _validCharacter(char): if char in string.digits: notify.info('name contains digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCBadCharacter % TextEncoder( ).encodeWtext(char) def fontHasCharacters(name, font=font): if font: tn = TextNode('NameCheck') tn.setFont(font) for c in name: if not tn.hasCharacter(ord(c)): notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c)) return OTPLocalizer.NCBadCharacter % TextEncoder( ).encodeWtext(c) def hasLetters(name): words = wordList(name) for word in words: letters = justLetters(word) if len(letters) == 0: notify.info('word "%s" has no letters' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedLetters def hasVowels(name): def perWord(word): if '.' in word: return None for char in word: if ord(char) >= 128: return None letters = filterString(word, string.letters) if len(letters) > 2: vowels = filterString(letters, 'aeiouyAEIOUY') if len(vowels) == 0: notify.info('word "%s" has no vowels' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCNeedVowels return None for word in wordList(name): problem = perWord(word) if problem: return problem def monoLetter(name): def perWord(word): word = word letters = justLetters(word) if len(letters) > 2: letters = TextEncoder().decodeText( TextEncoder.lower(TextEncoder().encodeWtext(letters))) filtered = filterString(letters, letters[0]) if filtered == letters: notify.info('word "%s" uses only one letter' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCGeneric for word in wordList(name): problem = perWord(word) if problem: return problem def checkDashes(name): def validDash(index, name=name): if index == 0 or i == len(name) - 1: return 0 if not name[i - 1].isalpha(): return 0 if not name[i + 1].isalpha(): return 0 return 1 i = 0 while 1: i = name.find('-', i, len(name)) if i < 0: return None if not validDash(i): notify.info('name makes invalid use of dashes') return OTPLocalizer.NCDashUsage i += 1 def checkCommas(name): def validComma(index, name=name): if index == 0 or i == len(name) - 1: return OTPLocalizer.NCCommaEdge if name[i - 1].isspace(): return OTPLocalizer.NCCommaAfterWord if not name[i + 1].isspace(): return OTPLocalizer.NCCommaUsage return None i = 0 while 1: i = name.find(',', i, len(name)) if i < 0: return None problem = validComma(i) if problem: notify.info('name makes invalid use of commas') return problem i += 1 def checkPeriods(name): words = wordList(name) for word in words: if word[-1] == ',': word = word[:-1] numPeriods = word.count('.') if not numPeriods: continue letters = justLetters(word) numLetters = len(letters) if word[-1] != '.': notify.info('word "%s" does not end in a period' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods > 2: notify.info('word "%s" has too many periods' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage if numPeriods == 2: if not (word[1] == '.' and word[3] == '.'): notify.info('word "%s" does not fit the J.T. pattern' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCPeriodUsage return None def checkApostrophes(name): words = wordList(name) for word in words: numApos = word.count("'") if numApos > 2: notify.info('word "%s" has too many apostrophes.' % TextEncoder().encodeWtext(word)) return OTPLocalizer.NCApostrophes numApos = name.count("'") if numApos > 3: notify.info('name has too many apostrophes.') return OTPLocalizer.NCApostrophes def tooManyWords(name): if len(wordList(name)) > 4: notify.info('name has too many words') return OTPLocalizer.NCTooManyWords def allCaps(name): letters = justLetters(name) if len(letters) > 2: upperLetters = TextEncoder().decodeText( TextEncoder.upper(TextEncoder().encodeWtext(letters))) for i in xrange(len(upperLetters)): if not upperLetters[0].isupper(): return if upperLetters == letters: notify.info('name is all caps') return OTPLocalizer.NCAllCaps def mixedCase(name): words = wordList(name) for word in words: if len(word) > 2: capitals = justUpper(word) if len(capitals) > 2: notify.info('name has mixed case') return OTPLocalizer.NCMixedCase def checkJapanese(name): asciiSpace = range(32, 33) asciiDigits = range(48, 64) hiragana = range(12353, 12448) katakana = range(12449, 12544) halfwidthKatakana = range(65381, 65440) halfwidthCharacter = set(asciiSpace + halfwidthKatakana) allowedUtf8 = set(asciiSpace + hiragana + katakana + halfwidthKatakana) te = TextEncoder() dc = 0.0 for char in (ord(char) for char in te.decodeText(name)): if char not in allowedUtf8: if char in asciiDigits: notify.info('name contains not allowed ascii digits') return OTPLocalizer.NCNoDigits else: notify.info('name contains not allowed utf8 char: 0x%04x' % char) return OTPLocalizer.NCBadCharacter % te.encodeWtext( unichr(char)) elif char in halfwidthCharacter: dc += 0.5 else: dc += 1 if dc < 2: notify.info('name is too short: %0.1f' % dc) return OTPLocalizer.NCTooShort elif dc > 8: notify.info( 'name has been occupied more than eight display cells: %0.1f' % dc) return OTPLocalizer.NCGeneric def repeatedChars(name): count = 1 lastChar = None i = 0 while i < len(name): char = name[i] i += 1 if char == lastChar: count += 1 else: count = 1 lastChar = char if count > 2: notify.info('character %s is repeated too many times' % TextEncoder().encodeWtext(char)) return OTPLocalizer.NCRepeatedChar % TextEncoder().encodeWtext( char) return checks = [ printableChars, badCharacters, fontHasCharacters, longEnough, emptyName, hasLetters, hasVowels, monoLetter, checkDashes, checkCommas, checkPeriods, checkApostrophes, tooManyWords, allCaps, mixedCase, repeatedChars ] + otherCheckFuncs symmetricChecks = [] name = TextEncoder().decodeText(name) notify.info('checking name "%s"...' % TextEncoder().encodeWtext(name)) for check in checks: problem = check(name[:]) if not problem and check in symmetricChecks: nName = name[:] bName.reverse() problem = check(bName) print 'problem = %s' % problem if problem: return problem return None