fix fuzzy map key romanization performance
This commit is contained in:
parent
54c30d4775
commit
016859897f
@ -6,7 +6,9 @@ from d4dj_utils.master.card_master import CardMaster
|
|||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
from main import masters
|
from main import masters
|
||||||
from miyu_bot.commands.common.emoji import rarity_emoji_ids
|
from miyu_bot.commands.common.emoji import rarity_emoji_ids, attribute_emoji_ids_by_attribute_id, \
|
||||||
|
unit_emoji_ids_by_unit_id, parameter_bonus_emoji_ids_by_parameter_id
|
||||||
|
from miyu_bot.commands.common.formatting import format_info
|
||||||
from miyu_bot.commands.common.master_asset_manager import hash_master
|
from miyu_bot.commands.common.master_asset_manager import hash_master
|
||||||
from miyu_bot.commands.common.reaction_message import run_tabbed_message
|
from miyu_bot.commands.common.reaction_message import run_tabbed_message
|
||||||
|
|
||||||
@ -28,11 +30,15 @@ class Card(commands.Cog):
|
|||||||
self.logger.info(f'Searching for card "{arg}".')
|
self.logger.info(f'Searching for card "{arg}".')
|
||||||
card = masters.cards.get(arg, ctx)
|
card = masters.cards.get(arg, ctx)
|
||||||
|
|
||||||
|
if card.rarity_id >= 3:
|
||||||
embeds = [self.get_card_embed(card, 0), self.get_card_embed(card, 1)]
|
embeds = [self.get_card_embed(card, 0), self.get_card_embed(card, 1)]
|
||||||
asyncio.ensure_future(run_tabbed_message(ctx, self.rarity_emoji, embeds, starting_index=1))
|
asyncio.ensure_future(run_tabbed_message(ctx, self.rarity_emoji, embeds, starting_index=1))
|
||||||
|
else:
|
||||||
|
embeds = [self.get_card_embed(card, 0)]
|
||||||
|
asyncio.ensure_future(run_tabbed_message(ctx, self.rarity_emoji[:1], embeds, starting_index=0))
|
||||||
|
|
||||||
def get_card_embed(self, card: CardMaster, limit_break):
|
def get_card_embed(self, card: CardMaster, limit_break):
|
||||||
embed = discord.Embed(title=f'{card.rarity_id}★ {card.name} {card.character.full_name_english}')
|
embed = discord.Embed(title=self.format_card_name(card))
|
||||||
|
|
||||||
card_hash = hash_master(card)
|
card_hash = hash_master(card)
|
||||||
icon_path = card.icon_path(limit_break)
|
icon_path = card.icon_path(limit_break)
|
||||||
@ -43,8 +49,29 @@ class Card(commands.Cog):
|
|||||||
embed.set_thumbnail(url=thumb_url)
|
embed.set_thumbnail(url=thumb_url)
|
||||||
embed.set_image(url=art_url)
|
embed.set_image(url=art_url)
|
||||||
|
|
||||||
|
embed.add_field(name='Info',
|
||||||
|
value=format_info({
|
||||||
|
'Rarity': f'{card.rarity_id}★',
|
||||||
|
'Character': f'{card.character.full_name_english}',
|
||||||
|
'Attribute': f'{self.bot.get_emoji(attribute_emoji_ids_by_attribute_id[card.attribute_id])} {card.attribute.en_name}',
|
||||||
|
'Unit': f'{self.bot.get_emoji(unit_emoji_ids_by_unit_id[card.character.unit_id])} {card.character.unit.name}',
|
||||||
|
'Release Date': f'{card.start_datetime}',
|
||||||
|
}),
|
||||||
|
inline=False)
|
||||||
|
embed.add_field(name='Parameters',
|
||||||
|
value=format_info({
|
||||||
|
f'Total': f'{"{:,}".format(card.max_power_with_limit_break)}',
|
||||||
|
f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[1])} Heart': f'{"{:,}".format(card.max_parameters_with_limit_break[0])}',
|
||||||
|
f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[2])} Technique': f'{"{:,}".format(card.max_parameters_with_limit_break[1])}',
|
||||||
|
f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[3])} Physical': f'{"{:,}".format(card.max_parameters_with_limit_break[2])}',
|
||||||
|
}),
|
||||||
|
inline=False)
|
||||||
|
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
def format_card_name(self, card):
|
||||||
|
return f'{card.rarity_id}★ {card.name} {card.character.full_name_english}'
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.add_cog(Card(bot))
|
bot.add_cog(Card(bot))
|
||||||
|
@ -8,14 +8,14 @@ difficulty_emoji_ids = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# \:buff_power: \:buff_heart: \:buff_technique: \:buff_physical:
|
# \:buff_power: \:buff_heart: \:buff_technique: \:buff_physical:
|
||||||
parameter_bonus_emoji_Ids = {
|
parameter_bonus_emoji_ids = {
|
||||||
'all': 792930826735583293,
|
'all': 792930826735583293,
|
||||||
'heart': 792096971040620564,
|
'heart': 792096971040620564,
|
||||||
'technique': 792096971090558986,
|
'technique': 792096971090558986,
|
||||||
'physical': 792096971002216488,
|
'physical': 792096971002216488,
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_bonus_emoji_ids_by_parameter_id = {i: v for i, v in enumerate(parameter_bonus_emoji_Ids.values())}
|
parameter_bonus_emoji_ids_by_parameter_id = {i: v for i, v in enumerate(parameter_bonus_emoji_ids.values())}
|
||||||
|
|
||||||
unit_emoji_ids = {
|
unit_emoji_ids = {
|
||||||
'happy_around': 792069679442821121,
|
'happy_around': 792069679442821121,
|
||||||
|
@ -14,7 +14,7 @@ class FuzzyFilteredMap:
|
|||||||
self.filter = filter_function or (lambda n: True)
|
self.filter = filter_function or (lambda n: True)
|
||||||
self.matcher = matcher or FuzzyMatcher()
|
self.matcher = matcher or FuzzyMatcher()
|
||||||
self._values = {}
|
self._values = {}
|
||||||
self.max_length = 0
|
self.length_cutoff = 0
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self._stale = True
|
self._stale = True
|
||||||
self.additive_only_filter = additive_only_filter
|
self.additive_only_filter = additive_only_filter
|
||||||
@ -42,22 +42,29 @@ class FuzzyFilteredMap:
|
|||||||
def has_exact(self, key):
|
def has_exact(self, key):
|
||||||
return romanize(key) in self._values
|
return romanize(key) in self._values
|
||||||
|
|
||||||
|
def has_exact_unprocessed(self, key):
|
||||||
|
return key in self._values
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
k = romanize(key)
|
k = romanize(key)
|
||||||
self._values.__delitem__(k)
|
self._values.__delitem__(k)
|
||||||
self._stale = True
|
self._stale = True
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
k = romanize(key)
|
self.set_unprocessed(romanize(key), value)
|
||||||
self._values[k] = value
|
|
||||||
self.max_length = max(self.max_length, math.ceil(len(k) * 1.1))
|
def set_unprocessed(self, key, value):
|
||||||
self.matcher.set_max_length(self.max_length)
|
self._values[key] = value
|
||||||
|
new_cutoff = math.ceil(len(key) * 1.1)
|
||||||
|
if new_cutoff > self.length_cutoff:
|
||||||
|
self.length_cutoff = new_cutoff
|
||||||
|
self.matcher.set_max_length(new_cutoff)
|
||||||
self._stale = True
|
self._stale = True
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
start_time = timeit.default_timer()
|
start_time = timeit.default_timer()
|
||||||
key = romanize(key)
|
key = romanize(key)
|
||||||
if len(key) > self.max_length:
|
if len(key) > self.length_cutoff:
|
||||||
self.logger.debug(f'Rejected key "{key}" due to length.')
|
self.logger.debug(f'Rejected key "{key}" due to length.')
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@ -73,7 +80,7 @@ class FuzzyFilteredMap:
|
|||||||
|
|
||||||
def get_sorted(self, key: str):
|
def get_sorted(self, key: str):
|
||||||
start_time = timeit.default_timer()
|
start_time = timeit.default_timer()
|
||||||
if len(key) > self.max_length:
|
if len(key) > self.length_cutoff:
|
||||||
self.logger.debug(f'Rejected key "{key}" due to length.')
|
self.logger.debug(f'Rejected key "{key}" due to length.')
|
||||||
return []
|
return []
|
||||||
key = romanize(key)
|
key = romanize(key)
|
||||||
@ -197,13 +204,14 @@ def strip_vowels(s):
|
|||||||
return re.sub('[aeoiu]', '', s)
|
return re.sub('[aeoiu]', '', s)
|
||||||
|
|
||||||
|
|
||||||
|
_kks = pykakasi.kakasi()
|
||||||
|
|
||||||
|
|
||||||
def romanize(s: str) -> str:
|
def romanize(s: str) -> str:
|
||||||
kks = pykakasi.kakasi()
|
|
||||||
s = str(s)
|
s = str(s)
|
||||||
s = re.sub('[\']', '', s)
|
s = re.sub('[\'・]', '', s)
|
||||||
s = re.sub('[・]', ' ', s)
|
|
||||||
s = re.sub('[A-Za-z]+', lambda ele: f' {ele[0]} ', s)
|
s = re.sub('[A-Za-z]+', lambda ele: f' {ele[0]} ', s)
|
||||||
s = re.sub('[0-9]+', lambda ele: f' {ele[0]} ', s)
|
s = re.sub('[0-9]+', lambda ele: f' {ele[0]} ', s)
|
||||||
s = ' '.join(c['hepburn'].strip().lower() for c in kks.convert(s))
|
s = ' '.join(c['hepburn'].strip().lower() for c in _kks.convert(s))
|
||||||
s = re.sub(r'[^a-zA-Z0-9_ ]+', '', s)
|
s = re.sub(r'[^a-zA-Z0-9_ ]+', '', s)
|
||||||
return ' '.join(s.split())
|
return ' '.join(s.split())
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
from timeit import default_timer
|
||||||
from typing import Callable, Any, Optional
|
from typing import Callable, Any, Optional
|
||||||
|
|
||||||
from d4dj_utils.manager.asset_manager import AssetManager
|
from d4dj_utils.manager.asset_manager import AssetManager
|
||||||
from d4dj_utils.master.master_asset import MasterDict, MasterAsset
|
from d4dj_utils.master.master_asset import MasterDict, MasterAsset
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap
|
from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap, romanize
|
||||||
|
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
|
||||||
@ -14,33 +15,21 @@ import datetime as dt
|
|||||||
class MasterFilterManager:
|
class MasterFilterManager:
|
||||||
def __init__(self, manager: AssetManager):
|
def __init__(self, manager: AssetManager):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
self.music = MasterFilter(
|
||||||
@property
|
|
||||||
@lru_cache(None)
|
|
||||||
def music(self):
|
|
||||||
return MasterFilter(
|
|
||||||
self.manager.music_master,
|
self.manager.music_master,
|
||||||
naming_function=lambda m: f'{m.name} {m.special_unit_name}',
|
naming_function=lambda m: f'{m.name} {m.special_unit_name}',
|
||||||
filter_function=lambda m: m.is_released,
|
filter_function=lambda m: m.is_released,
|
||||||
fallback_naming_function=lambda m: m.id,
|
fallback_naming_function=lambda m: m.id,
|
||||||
)
|
)
|
||||||
|
self.events = MasterFilter(
|
||||||
@property
|
|
||||||
@lru_cache(None)
|
|
||||||
def events(self):
|
|
||||||
return MasterFilter(
|
|
||||||
self.manager.event_master,
|
self.manager.event_master,
|
||||||
naming_function=lambda e: e.name,
|
naming_function=lambda e: e.name,
|
||||||
filter_function=lambda e: e.start_datetime < dt.datetime.now(
|
filter_function=lambda e: e.start_datetime < dt.datetime.now(
|
||||||
dt.timezone.utc) + dt.timedelta(hours=12),
|
dt.timezone.utc) + dt.timedelta(hours=12),
|
||||||
)
|
)
|
||||||
|
self.cards = MasterFilter(
|
||||||
@property
|
|
||||||
@lru_cache(None)
|
|
||||||
def cards(self):
|
|
||||||
return MasterFilter(
|
|
||||||
self.manager.card_master,
|
self.manager.card_master,
|
||||||
naming_function=lambda c: c.name,
|
naming_function=lambda c: f'{c.rarity_id}★ {c.name} {c.character.full_name_english}',
|
||||||
filter_function=lambda c: c.is_released,
|
filter_function=lambda c: c.is_released,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,13 +41,15 @@ class MasterFilter:
|
|||||||
self.default_filter = FuzzyFilteredMap(filter_function)
|
self.default_filter = FuzzyFilteredMap(filter_function)
|
||||||
self.unrestricted_filter = FuzzyFilteredMap()
|
self.unrestricted_filter = FuzzyFilteredMap()
|
||||||
for master in masters.values():
|
for master in masters.values():
|
||||||
name = naming_function(master)
|
name = romanize(naming_function(master))
|
||||||
if self.default_filter.has_exact(name) and fallback_naming_function:
|
if fallback_naming_function and self.default_filter.has_exact_unprocessed(name):
|
||||||
name = fallback_naming_function(master)
|
name = romanize(fallback_naming_function(master))
|
||||||
if self.default_filter.has_exact(name):
|
if self.default_filter.has_exact_unprocessed(name):
|
||||||
continue
|
continue
|
||||||
self.default_filter[name] = master
|
elif self.default_filter.has_exact_unprocessed(name):
|
||||||
self.unrestricted_filter[name] = master
|
continue
|
||||||
|
self.default_filter.set_unprocessed(name, master)
|
||||||
|
self.unrestricted_filter.set_unprocessed(name, master)
|
||||||
|
|
||||||
def get(self, name_or_id: str, ctx: Optional[commands.Context]):
|
def get(self, name_or_id: str, ctx: Optional[commands.Context]):
|
||||||
if ctx and ctx.channel.id in no_filter_channels:
|
if ctx and ctx.channel.id in no_filter_channels:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user