legendary/legendary/utils/aliasing.py

102 lines
3.2 KiB
Python

from string import ascii_lowercase, digits
# Aliases generated:
# - name lowercase (without TM etc.)
# - same, but without spaces
# - same, but roman numerals are replaced
# if name has >= 2 parts:
# - initials
# - initials, but roman numerals are intact
# - initials, but roman numerals are replaced with number
# if ':' in name:
# - run previous recursively with everything before ":"
# if single 'f' in long word:
# - split word (this is mainly for cases like Battlfront -> BF)
# the first word longer than 1 character that isn't "the", "for", or "of" will also be added
allowed_characters = ascii_lowercase+digits
roman = {
'i': '1',
'ii': '2',
'iii': '3',
'iv': '4',
'v': '5',
'vi': '6',
'vii': '7',
'viii': '8',
'ix': '9',
'x': '10',
'xi': '11',
'xii': '12',
'xiii': '13',
'xiv': '14',
'xv': '15',
'xvi': '16',
'xvii': '17',
'xviii': '18',
'xix': '19',
'xx': '20'
}
def _filter(input):
return ''.join(l for l in input if l in allowed_characters)
def generate_aliases(game_name, game_folder=None, split_words=True, app_name=None):
# normalise and split name, then filter for legal characters
game_parts = [_filter(p) for p in game_name.lower().split()]
# filter out empty parts
game_parts = [p for p in game_parts if p]
_aliases = [
game_name.lower().strip(),
' '.join(game_parts),
''.join(game_parts),
''.join(roman.get(p, p) for p in game_parts),
]
# single word abbreviation
try:
first_word = next(i for i in game_parts if i not in ('for', 'the', 'of'))
if len(first_word) > 1:
_aliases.append(first_word)
except StopIteration:
pass
# remove subtitle from game
if ':' in game_name:
_aliases.extend(generate_aliases(game_name.partition(':')[0]))
if '-' in game_name:
_aliases.extend(generate_aliases(game_name.replace('-', ' ')))
# include folder name for alternative short forms
if game_folder:
_aliases.extend(generate_aliases(game_folder, split_words=False))
# include lowercase version of app name in aliases
if app_name:
_aliases.append(app_name.lower())
# include initialisms
if len(game_parts) > 1:
_aliases.append(''.join(p[0] for p in game_parts))
_aliases.append(''.join(p[0] if p not in roman else p for p in game_parts))
_aliases.append(''.join(roman.get(p, p[0]) for p in game_parts))
# Attempt to address cases like "Battlefront" being shortened to "BF"
if split_words:
new_game_parts = []
for word in game_parts:
if len(word) >= 8 and word[3:-3].count('f') == 1:
word_middle = word[3:-3]
word_split = ' f'.join(word_middle.split('f'))
word = word[0:3] + word_split + word[-3:]
new_game_parts.extend(word.split())
else:
new_game_parts.append(word)
if len(new_game_parts) > 1:
_aliases.append(''.join(p[0] for p in new_game_parts))
_aliases.append(''.join(p[0] if p not in roman else p for p in new_game_parts))
_aliases.append(''.join(roman.get(p, p[0]) for p in new_game_parts))
# return sorted uniques
return sorted(set(_aliases))