From aa16811c503b8422725da3fd82a00abc8ad32ac9 Mon Sep 17 00:00:00 2001 From: qwewqa <198e559dbd446d973355f415bdfa34@gmail.com> Date: Thu, 21 Jan 2021 09:22:23 -0500 Subject: [PATCH] exclude aliases from appearing as duplicates --- miyu_bot/bot/master_asset_manager.py | 16 ++++++------ miyu_bot/commands/common/fuzzy_matching.py | 30 +++++++++++++++------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/miyu_bot/bot/master_asset_manager.py b/miyu_bot/bot/master_asset_manager.py index f1baa02..d42751a 100644 --- a/miyu_bot/bot/master_asset_manager.py +++ b/miyu_bot/bot/master_asset_manager.py @@ -44,21 +44,21 @@ class MasterFilter: self.default_filter = FuzzyFilteredMap(filter_function) self.unrestricted_filter = FuzzyFilteredMap() for master in masters.values(): - name = romanize(naming_function(master)) - if fallback_naming_function and self.default_filter.has_exact_unprocessed(name): + name = naming_function(master) + if fallback_naming_function and self.default_filter.has_exact(name): name = romanize(fallback_naming_function(master)) - if self.default_filter.has_exact_unprocessed(name): + if self.default_filter.has_exact(name): continue - elif self.default_filter.has_exact_unprocessed(name): + elif self.default_filter.has_exact(name): continue - self.default_filter.set_unprocessed(name, master) - self.unrestricted_filter.set_unprocessed(name, master) + self.default_filter[name] = master + self.unrestricted_filter[name] = master if aliases: for alias, mid in aliases.items(): master = masters[mid] alias = romanize(alias) - self.default_filter.set_unprocessed(alias, master) - self.unrestricted_filter.set_unprocessed(alias, master) + self.default_filter.alias(alias, master) + self.unrestricted_filter.alias(alias, master) def get(self, name_or_id: Union[str, int], ctx: Optional[commands.Context]): if ctx and ctx.channel.id in no_filter_channels: diff --git a/miyu_bot/commands/common/fuzzy_matching.py b/miyu_bot/commands/common/fuzzy_matching.py index 0602033..c79c9ee 100644 --- a/miyu_bot/commands/common/fuzzy_matching.py +++ b/miyu_bot/commands/common/fuzzy_matching.py @@ -42,18 +42,13 @@ class FuzzyFilteredMap: def has_exact(self, key): return romanize(key) in self._values - def has_exact_unprocessed(self, key): - return key in self._values - def __delitem__(self, key): k = romanize(key) self._values.__delitem__(k) self._stale = True def __setitem__(self, key, value): - self.set_unprocessed(romanize(key), value) - - def set_unprocessed(self, key, value): + key = romanize(key) self._values[key] = value new_cutoff = math.ceil(len(key) * 1.1) if new_cutoff > self.length_cutoff: @@ -61,6 +56,9 @@ class FuzzyFilteredMap: self.matcher.set_max_length(new_cutoff) self._stale = True + def alias(self, key, value): + self[key] = _Alias(value) + def __getitem__(self, key): start_time = timeit.default_timer() key = romanize(key) @@ -73,6 +71,8 @@ class FuzzyFilteredMap: ((matcher.score(key, item[0]), item) for item in self.filtered_items) if score <= 0)[1][1] self.logger.info(f'Found key "{key}" in time {timeit.default_timer() - start_time}.') + if isinstance(result, _Alias): + return result.value return result except ValueError: self.logger.info(f'Found no results for key "{key}" in time {timeit.default_timer() - start_time}.') @@ -84,12 +84,24 @@ class FuzzyFilteredMap: self.logger.debug(f'Rejected key "{key}" due to length.') return [] key = romanize(key) - values = [item[1] for score, item in + values = [item[1].value if isinstance(item[1], _Alias) else item[1] for score, item in sorted( (self.matcher.score(key, item[0]), item) for item in self.filtered_items) if score <= 0] + seen = set() + unique = [] + for value in values: + if id(value) in seen: + continue + unique.append(value) + seen.add(id(value)) self.logger.info(f'Searched key "{key}" in time {timeit.default_timer() - start_time}.') - return values + return unique + + +class _Alias: + def __init__(self, value): + self.value = value class FuzzyDictValuesView: @@ -100,7 +112,7 @@ class FuzzyDictValuesView: return item in self._map._values.values() and self._map.filter(item) def __iter__(self): - yield from (v for _, v in self._map.filtered_items) + yield from (v for _, v in self._map.filtered_items if not isinstance(v, _Alias)) @dataclass