public override bool Filter(IReadOnlyEntity entity, QueryParameter param)
        {
            var card = entity.GetComponent(KoikatuCharacterCard.TypeCode);

            if (card == null)
            {
                return(true);
            }

            if (param.Template == Parameters.Name)
            {
                var value = param.Value as string;
                if (string.IsNullOrWhiteSpace(value))
                {
                    return(true);
                }

                var normalizedValue = StringUtil.NormalizeString(value);
                var lastName        = StringUtil.NormalizeString(card.LastName);
                var firstName       = StringUtil.NormalizeString(card.FirstName);
                var nickname        = StringUtil.NormalizeString(card.Nickname);

                return(StringUtil.TestOperatorString(normalizedValue, query =>
                                                     nickname.FuzzyContains(query) ||
                                                     $"{lastName}{firstName}".FuzzyContains(query) ||
                                                     $"{lastName} {firstName}".FuzzyContains(query) ||
                                                     $"{firstName}{lastName}".FuzzyContains(query) ||
                                                     $"{firstName} {lastName}".FuzzyContains(query)));
            }
            else if (param.Template == Parameters.Sex)
            {
                return(param.FilterSelection(card.Sex));
            }
            else if (param.Template == Parameters.Personality)
            {
                return(param.FilterSelection(card.Personality));
            }
            else if (param.Template == Parameters.ClubActivities)
            {
                return(param.FilterSelection(card.ClubActivity));
            }
            else if (param.Template == Parameters.BloodType)
            {
                return(param.FilterSelection(card.BloodType));
            }
            else if (param.Template == Parameters.TeethType)
            {
                return(param.FilterSelection(card.TeethType));
            }
            else if (param.Template == Parameters.HeightType)
            {
                return(param.FilterSelection(card.HeightType));
            }
            else if (param.Template == Parameters.BustSizeType)
            {
                return(param.FilterSelection(card.BustSizeType));
            }
            else if (param.Template == Parameters.HairStyle)
            {
                return(param.FilterSelection(card.HairStyle));
            }
            else if (param.Template == Parameters.SkinType)
            {
                return(param.FilterSelection(card.SkinType));
            }
            else if (param.Template == Parameters.SkinColorType)
            {
                return(Palettes.Skin.GetAdjectives(card.SkinColor).Any(param.FilterSelection));
            }
            else if (param.Template == Parameters.HairColorType)
            {
                return(card.HairColors
                       .Select(i => Palettes.Hair.GetAdjectives(i))
                       .SelectMany(i => i)
                       .Any(param.FilterSelection));
            }
            else if (param.Template == Parameters.InverseSkinColorType)
            {
                return(param.Selection.Count == 0 ||
                       !Palettes.Skin.GetAdjectives(card.SkinColor).Any(param.FilterSelection));
            }
            else if (param.Template == Parameters.InverseHairColorType)
            {
                return(param.Selection.Count == 0 ||
                       !card.HairColors
                       .Select(i => Palettes.Hair.GetAdjectives(i))
                       .SelectMany(i => i)
                       .Any(param.FilterSelection));
            }
            else
            {
                return(true);
            }
        }