automatic pony name and balloon style name spelling correction

This commit is contained in:
Mattias Andrée 2012-10-22 13:17:42 +02:00
parent 78fc2bda35
commit de0813f523

View file

@ -259,17 +259,19 @@ class Ponysay():
Returns one file with full path, names is filter for names, also accepts filepaths Returns one file with full path, names is filter for names, also accepts filepaths
@param names:list<str> Ponies to choose from, may be `None` @param names:list<str> Ponies to choose from, may be `None`
@param alt:bool For method internal use...
@return :str The file name of a pony @return :str The file name of a pony
''' '''
def __getponypath(self, names = None): def __getponypath(self, names = None, alt = False):
ponies = {} ponies = {}
## List all pony files, without the .pony ending ## List all pony files, without the .pony ending
for ponydir in ponydirs: for ponydir in ponydirs:
for ponyfile in os.listdir(ponydir): for ponyfile in os.listdir(ponydir):
pony = ponyfile[:-5] if endswith(ponyfile, ".pony"):
if pony not in ponies: pony = ponyfile[:-5]
ponies[pony] = ponydir + ponyfile if pony not in ponies:
ponies[pony] = ponydir + ponyfile
## Support for explicit pony file names ## Support for explicit pony file names
if not names == None: if not names == None:
@ -284,6 +286,11 @@ class Ponysay():
## Select a random pony of the choosen onles ## Select a random pony of the choosen onles
pony = names[random.randrange(0, len(names))] pony = names[random.randrange(0, len(names))]
if pony not in ponies: if pony not in ponies:
if not alt:
autocorrect = SpelloCorrecter(ponydirs, '.pony')
(alternatives, dist) = autocorrect.correct(pony)
if len(alternatives) > 0:
return self.__getponypath(alternatives, True)
sys.stderr.write('I have never heard of anypony named %s\n' % (pony)); sys.stderr.write('I have never heard of anypony named %s\n' % (pony));
exit(1) exit(1)
else: else:
@ -405,7 +412,6 @@ class Ponysay():
c -= 1 c -= 1
columns[c] = columns[c][:-diff] columns[c] = columns[c][:-diff]
diff -= 1 diff -= 1
pass
## Create rows from columns ## Create rows from columns
lines = [] lines = []
@ -601,9 +607,10 @@ class Ponysay():
Returns one file with full path, names is filter for style names, also accepts filepaths Returns one file with full path, names is filter for style names, also accepts filepaths
@param names:list<str> Balloons to choose from, may be `None` @param names:list<str> Balloons to choose from, may be `None`
@param alt:bool For method internal use
@param :str The file name of the balloon, will be `None` iff `names` is `None` @param :str The file name of the balloon, will be `None` iff `names` is `None`
''' '''
def __getballoonpath(self, names): def __getballoonpath(self, names, alt = False):
## Stop if their is no choosen balloon ## Stop if their is no choosen balloon
if names is None: if names is None:
return None return None
@ -633,6 +640,11 @@ class Ponysay():
## Select a random balloon of the choosen ones ## Select a random balloon of the choosen ones
balloon = names[random.randrange(0, len(names))] balloon = names[random.randrange(0, len(names))]
if balloon not in balloons: if balloon not in balloons:
if not alt:
autocorrect = SpelloCorrecter(balloondirs, '.think' if isthink else '.say')
alternatives = autocorrect.correct(balloon)[0]
if len(alternatives) > 0:
return self.__getponypath(alternatives, True)
sys.stderr.write('That balloon style %s does not exist\n' % (balloon)); sys.stderr.write('That balloon style %s does not exist\n' % (balloon));
exit(1) exit(1)
else: else:
@ -1981,20 +1993,36 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
continue continue
proper = filename[:-len(ending)] proper = filename[:-len(ending)]
if dictionaryEnd == 0: if self.dictionaryEnd == 0:
dictionaryEnd = len(self.dictionary) self.dictionaryEnd = len(self.dictionary)
self.reusable = [0] * dictionaryEnd + self.reusable self.reusable = [0] * self.dictionaryEnd + self.reusable
self.dictionary = [None] * dictionaryEnd + self.dictionary self.dictionary = [None] * self.dictionaryEnd + self.dictionary
self.dictionaryEnd -= 1
self.dictionary[self.dictionaryEnd] = proper
dictionaryEnd -= 1
dictionary[dictionaryEnd] = proper
prevCommon = min(len(previous), len(proper)) prevCommon = min(len(previous), len(proper))
for i in range(0, prevCommon): for i in range(0, prevCommon):
if previous[i] != proper[i]: if previous[i] != proper[i]:
prevCommon = i prevCommon = i
break break
previous = dictionary[dictionaryEnd] previous = proper
reusable[dictionaryEnd] = prevCommon self.reusable[self.dictionaryEnd] = prevCommon
#part = self.dictionary[self.dictionaryEnd : len(self.dictionary) - 1]
#part.sort()
#self.dictionary[self.dictionaryEnd : len(self.dictionary) - 1] = part
#
#index = len(self.dictionary) - 1
#while index >= self.dictionaryEnd:
# proper = self.dictionary[index]
# prevCommon = min(len(previous), len(proper))
# for i in range(0, prevCommon):
# if previous[i] != proper[i]:
# prevCommon = i
# break
# previous = proper
# self.reusable[self.dictionaryEnd] = prevCommon
# index -= 1;
''' '''
@ -2004,11 +2032,11 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
@return (words, distance):(list<string>, int) A list the closest spellings and the weighted distance @return (words, distance):(list<string>, int) A list the closest spellings and the weighted distance
''' '''
def correct(self, used): def correct(self, used):
if len(used) < 127: if len(used) > 127:
return ([used], 0) return ([used], 0)
__correct(used) self.__correct(used)
return (seld.corrections, self.closestDistance) return (self.corrections, self.closestDistance)
''' '''
@ -2025,7 +2053,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
proper = None proper = None
prevCommon = 0 prevCommon = 0
d = len(self.dictionary) d = len(self.dictionary) - 1
while d > self.dictionaryEnd: while d > self.dictionaryEnd:
d -= 1 d -= 1
proper = self.dictionary[d] proper = self.dictionary[d]
@ -2041,7 +2069,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
skip = min(prevLen, len(proper)) skip = min(prevLen, len(proper))
i = prevCommon i = prevCommon
while i < skip: while i < skip:
for u in range(0, usedLen): for u in range(0, usedLen):
if (used[u] == previous[i]) or (used[u] == proper[i]): if (used[u] == previous[i]) or (used[u] == proper[i]):
skip = i skip = i
@ -2054,13 +2082,13 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
common = i common = i
break break
distance = self.__distance(proper, skip, proper.length, used, common, usedLen) distance = self.__distance(proper, skip, len(proper), used, common, usedLen)
if self.closestDistance > distance: if self.closestDistance > distance:
self.closestDistance = distance self.closestDistance = distance
corrections = [proper] self.corrections = [proper]
elif self.closestDistance == distance: elif self.closestDistance == distance:
corrections.append(proper) self.corrections.append(proper)
previous = proper; previous = proper;
if distance >= 0x7FFFFF00: if distance >= 0x7FFFFF00:
@ -2102,13 +2130,14 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
if my[x] in self.weights: if my[x] in self.weights:
if p in self.weights[u]: if p in self.weights[u]:
cw = self.weights[u][p] cw = self.weights[u][p]
x += 1
myy[x] = min(cw + change, 1 + min(remove, add)) myy[x] = min(cw + change, 1 + min(remove, add))
if best > myy[x]: if best > myy[x]:
best = myy[x] best = myy[x]
if best > self.closestDistance: if best > self.closestDistance:
return 0x7FFFFFFF | y return 0x7FFFFF00 | y
my = myy my = myy
return my[xn] return my[xn]