@flesh-and-blood/search 4.1.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/filters.d.ts +15 -2
- package/dist/filters.js +92 -60
- package/dist/helpers.d.ts +0 -2
- package/dist/helpers.js +0 -8
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/related.d.ts +1 -1
- package/dist/search.d.ts +1 -0
- package/dist/search.js +16 -16
- package/dist/searchIndex.d.ts +26 -0
- package/dist/searchIndex.js +85 -0
- package/package.json +4 -4
package/dist/filters.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Foiling, Hero, Rarity, Release, Treatment } from "@flesh-and-blood/types";
|
|
2
|
+
import { SearchIndex } from "./searchIndex.js";
|
|
2
3
|
export interface AppliedFilter {
|
|
3
4
|
filterToPropertyMapping: FilterToPropertyMapping;
|
|
4
5
|
values: string[];
|
|
6
|
+
/**
|
|
7
|
+
* The same strings as `values`, for filters whose match is exact membership
|
|
8
|
+
* rather than a comparison, so a card costs one lookup instead of a scan.
|
|
9
|
+
* Consumers read `values`; this is the matcher's copy.
|
|
10
|
+
*/
|
|
11
|
+
valuesSet?: Set<string>;
|
|
5
12
|
isAnd?: boolean;
|
|
6
13
|
isOr?: boolean;
|
|
7
14
|
modifier?: Modifier;
|
|
@@ -25,6 +32,12 @@ export interface FilterToPropertyMapping {
|
|
|
25
32
|
isBoolean?: boolean;
|
|
26
33
|
isDate?: boolean;
|
|
27
34
|
isMeta?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The card stores this property the way a filter value is written, so the
|
|
37
|
+
* matcher compares it as stored instead of stripping punctuation and case
|
|
38
|
+
* from it first.
|
|
39
|
+
*/
|
|
40
|
+
isNormalized?: boolean;
|
|
28
41
|
modifier?: Modifier;
|
|
29
42
|
partialMatch?: boolean;
|
|
30
43
|
specialProperty?: string;
|
|
@@ -103,7 +116,7 @@ export declare const filtersToCardPropertyMappings: {
|
|
|
103
116
|
x: FilterToPropertyMapping;
|
|
104
117
|
year: FilterToPropertyMapping;
|
|
105
118
|
};
|
|
106
|
-
export declare const getKeywordsAndAppliedFiltersFromText: (text: string,
|
|
119
|
+
export declare const getKeywordsAndAppliedFiltersFromText: (text: string, index: SearchIndex, additionalHeroes?: Hero[], additionalSets?: Release[], today?: string) => {
|
|
107
120
|
appliedFilters: AppliedFilter[];
|
|
108
121
|
attributes: {
|
|
109
122
|
artists: string[];
|
package/dist/filters.js
CHANGED
|
@@ -12,11 +12,11 @@ import { getAbbreviation } from "./abbreviations.js";
|
|
|
12
12
|
import { getExcludedMetaFilters, getMetaFilters } from "./metaFilters.js";
|
|
13
13
|
import { multiWordShorthands, singleWordShorthands } from "./shorthands.js";
|
|
14
14
|
import { PUNCTUATION } from "./constants.js";
|
|
15
|
-
import { getCardByName } from "./helpers.js";
|
|
16
15
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
getCardsByName,
|
|
17
|
+
getCardsReferencedBy,
|
|
18
|
+
getCardsReferencing
|
|
19
|
+
} from "./searchIndex.js";
|
|
20
20
|
const availableModifiers = [">=", ">", "<=", "<"];
|
|
21
21
|
const availableExclusions = ["!", "-"];
|
|
22
22
|
const arcaneFilter = {
|
|
@@ -38,6 +38,26 @@ const bondFilter = {
|
|
|
38
38
|
property: "bonds",
|
|
39
39
|
isArray: true
|
|
40
40
|
};
|
|
41
|
+
const cardIdentifierFilter = {
|
|
42
|
+
property: "cardIdentifier",
|
|
43
|
+
isString: true,
|
|
44
|
+
isNormalized: true
|
|
45
|
+
};
|
|
46
|
+
const getRelationAppliedFilter = (cardIdentifiers, {
|
|
47
|
+
isAnd,
|
|
48
|
+
isExcluded,
|
|
49
|
+
isOptional,
|
|
50
|
+
modifier
|
|
51
|
+
}) => ({
|
|
52
|
+
filterToPropertyMapping: cardIdentifierFilter,
|
|
53
|
+
values: [...cardIdentifiers],
|
|
54
|
+
valuesSet: cardIdentifiers,
|
|
55
|
+
isAnd,
|
|
56
|
+
isOr: true,
|
|
57
|
+
modifier,
|
|
58
|
+
isExcluded,
|
|
59
|
+
isOptional
|
|
60
|
+
});
|
|
41
61
|
const chainFilter = {
|
|
42
62
|
property: "n/a"
|
|
43
63
|
};
|
|
@@ -299,7 +319,8 @@ const getSearchCriteria = (text) => {
|
|
|
299
319
|
}
|
|
300
320
|
return searchCriteria;
|
|
301
321
|
};
|
|
302
|
-
const
|
|
322
|
+
const CHAIN_EXPANSION_LIMIT = 20;
|
|
323
|
+
const getKeywordsAndAppliedFiltersFromText = (text, index, additionalHeroes = [], additionalSets = [], today = getTodayAsReleaseDate()) => {
|
|
303
324
|
let expandedText = text.trim().toLowerCase();
|
|
304
325
|
for (const { expanded: filters, shorthands } of multiWordShorthands) {
|
|
305
326
|
for (const shorthand of shorthands) {
|
|
@@ -341,7 +362,7 @@ const getKeywordsAndAppliedFiltersFromText = (text, cards, additionalHeroes = []
|
|
|
341
362
|
if (hasFilter(criteria)) {
|
|
342
363
|
const [unparsedFilterKey, unparsedFilterValue] = criteria.split(":");
|
|
343
364
|
let { modifier, values, isAnd, isOr } = getFilterValuesAndModifier(unparsedFilterValue);
|
|
344
|
-
|
|
365
|
+
const { filterKey, isExcluded, isOptional, isMeta } = getFilterKeyAndExcludedOrOptional(unparsedFilterKey);
|
|
345
366
|
let areValuesAlreadyApplied = false;
|
|
346
367
|
if (isMeta) {
|
|
347
368
|
if (["rarity", "r"].includes(filterKey)) {
|
|
@@ -365,71 +386,81 @@ const getKeywordsAndAppliedFiltersFromText = (text, cards, additionalHeroes = []
|
|
|
365
386
|
);
|
|
366
387
|
} else {
|
|
367
388
|
if (["chain"].includes(filterKey)) {
|
|
368
|
-
const
|
|
369
|
-
const
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
389
|
+
const chainedCardIdentifiers = /* @__PURE__ */ new Set();
|
|
390
|
+
const cardsToExpand = [];
|
|
391
|
+
const namesToExpand = /* @__PURE__ */ new Set();
|
|
392
|
+
const addToChain = (card) => {
|
|
393
|
+
chainedCardIdentifiers.add(card.cardIdentifier);
|
|
394
|
+
if (!namesToExpand.has(card.name)) {
|
|
395
|
+
namesToExpand.add(card.name);
|
|
396
|
+
cardsToExpand.push(card);
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
const addRelatedCardToChain = (card) => {
|
|
376
400
|
if (!card.types.includes(Type.Hero)) {
|
|
377
|
-
|
|
378
|
-
names.add(name);
|
|
379
|
-
if (!relatedCardNames.includes(name)) {
|
|
380
|
-
relatedCardNames.push(name);
|
|
381
|
-
}
|
|
401
|
+
addToChain(card);
|
|
382
402
|
}
|
|
383
403
|
};
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
404
|
+
for (const value of values) {
|
|
405
|
+
if (value) {
|
|
406
|
+
for (const seedCard of getCardsByName(index, value)) {
|
|
407
|
+
addToChain(seedCard);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
let expansions = 0;
|
|
412
|
+
for (const cardToExpand of cardsToExpand) {
|
|
413
|
+
if (expansions > CHAIN_EXPANSION_LIMIT) {
|
|
387
414
|
break;
|
|
388
415
|
}
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
) || [];
|
|
395
|
-
referencingCards.forEach(addToSetAndRelated);
|
|
416
|
+
for (const referencedCard of getCardsReferencedBy(
|
|
417
|
+
index,
|
|
418
|
+
cardToExpand
|
|
419
|
+
)) {
|
|
420
|
+
addRelatedCardToChain(referencedCard);
|
|
396
421
|
}
|
|
397
|
-
|
|
422
|
+
const isSeed = expansions === 0;
|
|
423
|
+
if (isSeed) {
|
|
424
|
+
for (const referencingCard of getCardsReferencing(
|
|
425
|
+
index,
|
|
426
|
+
cardToExpand
|
|
427
|
+
)) {
|
|
428
|
+
addRelatedCardToChain(referencingCard);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
expansions++;
|
|
398
432
|
}
|
|
399
|
-
|
|
433
|
+
appliedFilters.push(
|
|
434
|
+
getRelationAppliedFilter(chainedCardIdentifiers, {
|
|
435
|
+
isAnd,
|
|
436
|
+
isExcluded,
|
|
437
|
+
isOptional,
|
|
438
|
+
modifier
|
|
439
|
+
})
|
|
440
|
+
);
|
|
441
|
+
areValuesAlreadyApplied = true;
|
|
400
442
|
} else if (["referencedby", "references"].includes(filterKey)) {
|
|
401
443
|
const isNamedByFilter = ["referencedby"].includes(filterKey);
|
|
402
|
-
const
|
|
403
|
-
values
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
...getReferencedCards(
|
|
411
|
-
getCardByName(relatedCardName, cards),
|
|
412
|
-
cards
|
|
413
|
-
)
|
|
414
|
-
);
|
|
415
|
-
}
|
|
416
|
-
} else {
|
|
417
|
-
const cardsByReferencedCardIdentifier = getCardsByReferencedCardIdentifier(cards);
|
|
418
|
-
for (const relatedCardName of relatedCardNames) {
|
|
419
|
-
const relatedCard = getCardByName(relatedCardName, cards);
|
|
420
|
-
if (relatedCard) {
|
|
421
|
-
const referencingCards = cardsByReferencedCardIdentifier.get(
|
|
422
|
-
relatedCard.cardIdentifier
|
|
423
|
-
) || [];
|
|
424
|
-
relatedCards.push(...referencingCards);
|
|
444
|
+
const relatedCardIdentifiers = /* @__PURE__ */ new Set();
|
|
445
|
+
for (const value of values) {
|
|
446
|
+
if (value) {
|
|
447
|
+
for (const namedCard of getCardsByName(index, value)) {
|
|
448
|
+
const cardsInRelation = isNamedByFilter ? getCardsReferencedBy(index, namedCard) : getCardsReferencing(index, namedCard);
|
|
449
|
+
for (const relatedCard of cardsInRelation) {
|
|
450
|
+
relatedCardIdentifiers.add(relatedCard.cardIdentifier);
|
|
451
|
+
}
|
|
425
452
|
}
|
|
426
453
|
}
|
|
427
454
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
455
|
+
appliedFilters.push(
|
|
456
|
+
getRelationAppliedFilter(relatedCardIdentifiers, {
|
|
457
|
+
isAnd,
|
|
458
|
+
isExcluded,
|
|
459
|
+
isOptional,
|
|
460
|
+
modifier
|
|
461
|
+
})
|
|
432
462
|
);
|
|
463
|
+
areValuesAlreadyApplied = true;
|
|
433
464
|
} else if (["art", "artist"].includes(filterKey)) {
|
|
434
465
|
artists = values;
|
|
435
466
|
} else if (["print", "prints", "printing", "printings"].includes(filterKey)) {
|
|
@@ -507,9 +538,10 @@ const getKeywordsAndAppliedFiltersFromText = (text, cards, additionalHeroes = []
|
|
|
507
538
|
} else if (["pitch", "p", "color"].includes(filterKey)) {
|
|
508
539
|
values = getPitchValuesFromText(values);
|
|
509
540
|
}
|
|
510
|
-
|
|
541
|
+
const filterToPropertyMapping = filtersToCardPropertyMappings[filterKey];
|
|
542
|
+
if (filterToPropertyMapping && !areValuesAlreadyApplied) {
|
|
511
543
|
appliedFilters.push({
|
|
512
|
-
filterToPropertyMapping
|
|
544
|
+
filterToPropertyMapping,
|
|
513
545
|
values,
|
|
514
546
|
isAnd,
|
|
515
547
|
isOr,
|
package/dist/helpers.d.ts
CHANGED
package/dist/helpers.js
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { PUNCTUATION } from "./constants.js";
|
|
2
|
-
const getCardByName = (name, cards) => {
|
|
3
|
-
let card = cards.find((card2) => getCleanText(card2.name) === name);
|
|
4
|
-
if (!card) {
|
|
5
|
-
card = cards.find((card2) => getCleanText(card2.name).includes(name));
|
|
6
|
-
}
|
|
7
|
-
return card;
|
|
8
|
-
};
|
|
9
2
|
const getCleanText = (text) => getNormalizedText(text.toLowerCase().trim().replace(PUNCTUATION, ""));
|
|
10
3
|
const getNormalizedText = (text) => text.normalize("NFD").replace(/\p{Diacritic}/gu, "");
|
|
11
4
|
export {
|
|
12
|
-
getCardByName,
|
|
13
5
|
getCleanText,
|
|
14
6
|
getNormalizedText
|
|
15
7
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var sr=Object.create;var Y=Object.defineProperty;var or=Object.getOwnPropertyDescriptor;var nr=Object.getOwnPropertyNames;var lr=Object.getPrototypeOf,cr=Object.prototype.hasOwnProperty;var pr=(e,r)=>{for(var t in r)Y(e,t,{get:r[t],enumerable:!0})},we=(e,r,t,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of nr(r))!cr.call(e,a)&&a!==t&&Y(e,a,{get:()=>r[a],enumerable:!(i=or(r,a))||i.enumerable});return e};var dr=(e,r,t)=>(t=e!=null?sr(lr(e)):{},we(r||!e||!e.__esModule?Y(t,"default",{value:e,enumerable:!0}):t,e)),ur=e=>we(Y({},"__esModule",{value:!0}),e);var lt={};pr(lt,{FilterProperty:()=>Se,PUNCTUATION:()=>u,RARITY_VALUES_MAPPING:()=>Ae,abbreviations:()=>pe,availableExclusions:()=>er,availableModifiers:()=>Xe,default:()=>ir,filterCard:()=>ar,filtersToCardPropertyMappings:()=>oe,getAbbreviation:()=>J,getAbbreviationByCard:()=>fr,getCardByName:()=>j,getCardsByReferencedCardIdentifier:()=>te,getCleanText:()=>be,getExcludedMetaFilters:()=>ue,getKeywordsAndAppliedFiltersFromText:()=>Te,getMetaFilters:()=>de,getNormalizedText:()=>z,getOtherPitches:()=>wr,getReferencedCards:()=>re,getTokensReferencedByCards:()=>Sr,multiWordShorthands:()=>ge,shorthands:()=>fe,singleWordShorthands:()=>he});module.exports=ur(lt);var ne=require("@flesh-and-blood/types"),Pe=dr(require("fuse.js"),1);var u=/[!"#$%&'’(),./:;<=>?@[\]^_`|~]/g;var l=require("@flesh-and-blood/types");var J=e=>pe.find(({abbreviations:r})=>r.find(t=>t.toLowerCase()===e)),fr=e=>pe.find(({card:r})=>r.toLowerCase()===e.name.toLowerCase()),pe=[{abbreviations:["10k"],card:"10,000 Year Reunion"},{abbreviations:["Pajamas","PJs"],card:"Alluvion Constellas"},{abbreviations:["Slippy","Arakni Slipped Through the Cracks","Arakni, Slipped Through the Cracks"],card:"Arakni, 5L!p3d 7hRu 7h3 cR4X"},{abbreviations:["Dullcap"],card:"Arcanite Skullcap"},{abbreviations:["ALS"],card:"Arc Light Sentinel"},{abbreviations:["AoW"],card:"Art of War"},{abbreviations:["BBD"],card:"Barraging Beatdown"},{abbreviations:["BBS"],card:"Big Blue Sky"},{abbreviations:["Starvo"],card:"Bravo, Star of the Show"},{abbreviations:["BEB"],card:"Bull's Eye Bracers"},{abbreviations:["BLW"],card:"Be Like Water"},{abbreviations:["BoJ"],card:"Balance of Justice"},{abbreviations:["BOHH"],card:"Blood on Her Hands"},{abbreviations:["BRB"],card:"Bloodrush Bellow"},{abbreviations:["Breezies"],card:"Breeze Rider Boots"},{abbreviations:["BTA"],card:"Burn Them All"},{abbreviations:["CStrike","C-Strike","C Strike"],card:"Celestial Cataclysm"},{abbreviations:["CBelly"],card:"Cerebellum Processor"},{abbreviations:["CLF"],card:"Channel Lake Frigid"},{abbreviations:["CLV"],card:"Channel Lightning Valley"},{abbreviations:["CMH"],card:"Channel Mount Heroic"},{abbreviations:["CMI"],card:"Channel Mount Isen"},{abbreviations:["CMT"],card:"Channel the Millennium Tree"},{abbreviations:["CnC","C&C"],card:"Command and Conquer"},{abbreviations:["Sea and Sea"],card:"Conqueror of the High Seas"},{abbreviations:["CYB"],card:"Count Your Blessings"},{abbreviations:["Cat","Kitty"],card:"Crouching Tiger"},{abbreviations:["CoD"],card:"Crown of Dominion"},{abbreviations:["CoP"],card:"Crown of Providence"},{abbreviations:["CtW"],card:"Crush the Weak"},{abbreviations:["DD"],card:"Death Dealer"},{abbreviations:["DnD"],card:"Devotion Never Dies"},{abbreviations:["DIO"],card:"Dash I/O"},{abbreviations:["EBTT"],card:"Even Bigger Than That!"},{abbreviations:["NewNigma"],card:"Enigma, New Moon"},{abbreviations:["EPot","E Pot"],card:"Energy Potion"},{abbreviations:["EStrike","E-Strike","E Strike"],card:"Enlightened Strike"},{abbreviations:["FFS"],card:"Fyendal's Fighting Spirit"},{abbreviations:["FoN"],card:"Force of Nature"},{abbreviations:["Frosty","\u{1F976}","\u{1F9CA}","\u2744\uFE0F"],card:"Frostbite"},{abbreviations:["Yum yum"],card:"Fruits of the Forest"},{abbreviations:["GnT"],card:"Give and Take"},{abbreviations:["Habibi"],card:"Hanabi Blaster"},{abbreviations:["HMH"],card:"Hope Merchant's Hood"},{abbreviations:["HoI"],card:"Heart of Ice"},{abbreviations:["Pumpkin"],card:"Jack-o'-lantern"},{abbreviations:["RKO","Cheato"],card:"Kayo, Underhanded Cheat"},{abbreviations:["KKBB"],card:"Knick Knack Bric-a-brac"},{abbreviations:["BStrike"],card:"Levels of Enlightenment"},{abbreviations:["LAG","Twominaris"],card:"Luminaris, Angel's Glow"},{abbreviations:["LCF","Newminaris"],card:"Luminaris, Celestial Fury"},{abbreviations:["LDE"],card:"Last Ditch Effort"},{abbreviations:["LtC"],card:"Lead the Charge"},{abbreviations:["LNW"],card:"Leave No Witnesses"},{abbreviations:["LFaL","L4aL"],card:"Life for a Life"},{abbreviations:["LiT"],card:"Lost in Thought"},{abbreviations:["MMB"],card:"Mage Master Boots"},{abbreviations:["MaxV"],card:"Maximum Velocity"},{abbreviations:["MoM"],card:"Mask of Momentum"},{abbreviations:["MoPL"],card:"Mask of the Pouncing Lynx"},{abbreviations:["MnG"],card:"Meat and Greet"},{abbreviations:["Cake","\u{1F382}"],card:"Ninth Blade of the Blood Oath"},{abbreviations:["PoM"],card:"Peace of Mind"},{abbreviations:["P-Bone"],card:"Performance Bonus"},{abbreviations:["PF","\u{1F525}"],card:"Phoenix Flame"},{abbreviations:["PtW"],card:"Poison the Well"},{abbreviations:["Thanos","Infinity Gauntlet"],card:"Polarity Reversal Script"},{abbreviations:["DPot","D Pot"],card:"Potion of D\xE9j\xE0 Vu"},{abbreviations:["Ponder Run"],card:"Premeditate"},{abbreviations:["Qi Unbound"],card:"Qi Unleashed"},{abbreviations:["RitL"],card:"Red in the Ledger"},{abbreviations:["Cats","Ghost cat","Ghost cats"],card:"Restless Coalescence"},{abbreviations:["Eugene"],card:"Rhinar, Reckless Rampage",isHidden:!0},{abbreviations:["SSGB"],card:"Sandscour Greatbow"},{abbreviations:["SSP"],card:"Sand Sketched Plan"},{abbreviations:["SFaS","S4aS"],card:"Scar for a Scar"},{abbreviations:["Tyler"],card:"Scurv, Stowaway",isHidden:!0},{abbreviations:["SWOMB"],card:"Shifting Winds of the Mystic Beast"},{abbreviations:["Snaps"],card:"Snapdragon Scalers"},{abbreviations:["SWK"],card:"Spinning Wheel Kick"},{abbreviations:["SFTL"],card:"Swing Fist, Think Later"},{abbreviations:["TTT"],card:"Take the Tempo"},{abbreviations:["Ultron"],card:"Teklovossen, the Mechropotent"},{abbreviations:["ToS"],card:"Test of Strength"},{abbreviations:["TAYG"],card:"That All You Got?"},{abbreviations:["TROM"],card:"This Round's on Me"},{abbreviations:["3oak"],card:"Three of a Kind"},{abbreviations:["Pox Malone","Post Malone"],card:"Virulent Touch"},{abbreviations:["Cast Homes"],card:"Visit Goldmane Estate"},{abbreviations:["Frosty Hammer"],card:"Winter's Wail"},{abbreviations:["Wreckless Wing"],card:"War Cry of Bellona"},{abbreviations:["ZTS"],card:"Zero to Sixty"}];var x=require("@flesh-and-blood/types");var Se=(i=>(i.BannedFormats="bannedFormats",i.LegalFormats="legalFormats",i.LegalHeroes="legalHeroes",i))(Se||{}),ee=Array.from(Array(50).keys()).map(e=>`${e}`),gr=[{format:x.Format.ClassicConstructed,nicknames:["cc","classic"]},{format:x.Format.LivingLegend,nicknames:["cc ll","classic constructed ll","ll cc","ll","living legend"]},{format:x.Format.SilverAge,nicknames:["sage"]},{format:x.Format.GoldenAge,nicknames:["gage"]},{format:x.Format.UltimatePitFight,nicknames:["upf"]}],hr=Object.values(x.Format).map(e=>{let r=gr.find(({format:i})=>i===e),t=e.toLowerCase().replaceAll(u,"");return r?{...r,format:t}:{format:t}}),br=[{hero:x.Hero.DataDoll,nicknames:["data","datadoll"]},{hero:x.Hero.Dorinthea,nicknames:["dori"]},{hero:x.Hero.Genis,nicknames:["genis"]},{hero:x.Hero.GravyBones,nicknames:["gravy"]},{hero:x.Hero.Iyslander,nicknames:["islander"]}],mr=Object.values(x.Hero).map(e=>{let r=br.find(({hero:i})=>i===e),t=e.toLowerCase().replaceAll(u,"");return r?{...r,hero:t}:{hero:t}}),Q=["common","rare","super rare","majestic","legendary","fabled"],yr=(e,r,t,i)=>{let a=[];if(!r)a.push(...e);else for(let s of e)switch(r){case">=":{let o=!1;for(let n of Q)o?a.push(n):n===s&&(o=!0,a.push(n));break}case">":{let o=!1;for(let n of Q)o?a.push(n):n===s&&(o=!0);break}case"<=":{let o=!1;for(let n of Q.slice().reverse())o?a.push(n):n===s&&(o=!0,a.push(n));break}case"<":{let o=!1;for(let n of Q.slice().reverse())o?a.push(n):n===s&&(o=!0);break}default:break}return{filterToPropertyMapping:{nestedProperty:"rarity",property:"printings",isArray:!0},isExcluded:t,isOptional:i,isOr:!0,values:a}},ke=(e,r,t,i,a)=>{let s=i.map(g=>({hero:g.toLowerCase().replaceAll(u,"")})),o=[],n=[],c=[];for(let g of e){let f=hr.find(({format:C,nicknames:M})=>C===g||!!M&&M.includes(g));if(f)n.push(f.format);else{let C=mr.find(({hero:M,nicknames:A})=>M===g||!!A&&A.includes(g))||s.find(({hero:M})=>M===g);C&&c.push(C.hero)}}let b=a||"legalFormats";return n.length>0&&o.push({filterToPropertyMapping:{property:b,isArray:!0},values:n,isOr:!0,isExcluded:r,isOptional:t}),c.length>0&&o.push({filterToPropertyMapping:{property:"legalHeroes",isArray:!0},values:c,isOr:!0,isExcluded:r,isOptional:t}),o},Cr=(e,r,t,i)=>ke(e,r,t,i,"bannedFormats"),de=(e,r,t,i,a,s)=>{let o=[];return vr(t)?o.push(...ke(i,e,r,s)):Tr(t)?o.push(...Cr(i,e,r,s)):xr(t)&&o.push(yr(i,a,e,r)),o},K=[{filterToPropertyMapping:{property:"cost",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialCost",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]}],I=[{filterToPropertyMapping:{property:"defense",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialDefense",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["hero","placeholder","token","weapon"]}],Z=[{filterToPropertyMapping:{property:"pitch",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]},{filterToPropertyMapping:{property:"isCardBack",isBoolean:!0},isExcluded:!0,values:["true"]}],V=[{filterToPropertyMapping:{property:"power",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialPower",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token"]}],X=[{filterToPropertyMapping:{property:"talents",isArray:!0},isExcluded:!0,values:Object.values(x.Talent).map(e=>e.toLowerCase())}],Fr={"!co":K,"-co":K,"!cost":K,"-cost":K,"!color":K,"-color":K,"!b":I,"-b":I,"!block":I,"-block":I,"!d":I,"-d":I,"!def":I,"-def":I,"!defense":I,"-defense":I,"!pitch":Z,"-pitch":Z,"!p":Z,"-p":Z,"!attack":V,"-attack":V,"!power":V,"-power":V,"!pwr":V,"-pwr":V,"!pow":V,"-pow":V,"!talents":X,"-talents":X,"!tal":X,"-tal":X},ue=e=>{let r=[],t=Fr[e];return t&&r.push(...t),r},Mr=["l","legal","hero"],vr=e=>Mr.includes(e),Ar=["banned"],Tr=e=>Ar.includes(e),Pr=["r","rarity"],xr=e=>Pr.includes(e);var N=require("@flesh-and-blood/types"),fe=[{description:"Attack actions",expanded:["st:attack"],filters:{subtypes:[N.Subtype.Attack]},isCardProperty:!1,shorthands:["AA"]},{description:"Arcane barrier",expanded:['k:"arcane barrier"'],filters:{keywords:[N.Keyword.ArcaneBarrier]},isCardProperty:!1,shorthands:["AB"]},{description:"Attack reactions",expanded:['t:"attack reaction"'],filters:{types:[N.Type.AttackReaction]},isCardProperty:!1,shorthands:["AR"]},{description:"Defense reactions",expanded:['t:"defense reaction"'],filters:{types:[N.Type.DefenseReaction]},isCardProperty:!1,shorthands:["DR"]},{description:"Gain life",expanded:["gain {h}"],filters:{functionalText:"gain {h}"},isCardProperty:!1,shorthands:["Gain life","Gains life"]},{description:"Go again",expanded:['k:"go again"'],filters:{keywords:[N.Keyword.GoAgain]},isCardProperty:!1,shorthands:["GA"]},{description:"Non-attack actions",expanded:["t:action","st:non-attack"],filters:{subtypes:[N.Subtype.NonAttack],types:[N.Type.Action]},isCardProperty:!1,shorthands:["NAA"]},{description:"Plus defense",expanded:["+ {d}"],filters:{functionalText:"+ {d}"},isCardProperty:!1,shorthands:["Pump defense","Pumps defense","Buff defense","Buffs defense"]},{description:"Spellvoid",expanded:['k:"spellvoid"'],filters:{keywords:[N.Keyword.Spellvoid]},isCardProperty:!1,shorthands:["SV"]}],ge=fe.filter(({shorthands:e})=>e.some(r=>r.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(r=>r.includes(" ")).map(r=>r.toLowerCase()).sort((r,t)=>t.length-r.length)})),he=fe.filter(({shorthands:e})=>e.some(r=>!r.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(r=>!r.includes(" ")).map(r=>r.toLowerCase()).sort((r,t)=>t.length-r.length)}));var j=(e,r)=>{let t=r.find(i=>be(i.name)===e);return t||(t=r.find(i=>be(i.name).includes(e))),t},be=e=>z(e.toLowerCase().trim().replace(u,"")),z=e=>e.normalize("NFD").replace(/\p{Diacritic}/gu,"");var wr=(e,r)=>{let t=[];if(e)for(let i of r){let a=i.name===e.name,s=i.cardIdentifier!==e.cardIdentifier,o=i.pitch!==e.pitch;a&&s&&o&&t.push(i)}return t},re=(e,r)=>{let t=new Set(e?.referencedCards),i=[];for(let a of r)t.has(a.cardIdentifier)&&i.push(a);return i},te=e=>{let r=new Map;for(let t of e)for(let i of t.referencedCards||[]){let a=r.get(i);a?a.push(t):r.set(i,[t])}return r},Sr=(e,r)=>{let t=new Set;for(let a of e)for(let s of a.createdExtras||[])t.add(s);let i=[];for(let a of r)t.has(a.cardIdentifier)&&i.push(a);return i};var Xe=[">=",">","<=","<"],er=["!","-"],kr={property:"arcane",specialProperty:"specialArcane",isNumber:!0,partialMatch:!0},me={property:"artists",isArray:!0,partialMatch:!0},Le={property:"n/a",isMeta:!0},Re={property:"bonds",isArray:!0},Lr={property:"n/a"},Ee={property:"classes",isArray:!0,partialMatch:!0},Be={property:"cost",specialProperty:"specialCost",isNumber:!0,partialMatch:!0},$={property:"defense",specialProperty:"specialDefense",isNumber:!0},Ne={property:"flows",isArray:!0},Ie={nestedProperty:"foiling",property:"printings",isArray:!0},De={property:"fusions",isArray:!0},Oe={property:"intellect",isNumber:!0},He={property:"keywords",isArray:!0},ye={property:"n/a",isMeta:!0},Ve={property:"life",specialProperty:"specialLife",isNumber:!0},ve={property:"meta",isArray:!0},Ge={property:"name",isString:!0,partialMatch:!0},Ce={property:"pitch",isNumber:!0},We={property:"firstReleaseDate",isDate:!0},ie={property:"power",specialProperty:"specialPower",isNumber:!0},Rr={property:"setIdentifiers",isArray:!0,partialMatch:!0},Ue={property:"n/a",isMeta:!0},Er={property:"n/a"},Br={property:"n/a"},Ke={property:"sets",isArray:!0,partialMatch:!0},Fe={property:"shorthands",isArray:!0,partialMatch:!0},ae={property:"specializations",isArray:!0,partialMatch:!0},je={property:"subtypes",isArray:!0},qe={property:"types",isArray:!0},ze={property:"talents",isArray:!0},Nr={property:"functionalText",isString:!0,partialMatch:!0},Ir={property:"traits",isArray:!0,partialMatch:!0},Dr={property:"typeText",isString:!0,partialMatch:!0},se={nestedProperty:"treatments",property:"printings",isArray:!0,isNestedPropertyArray:!0},Or={property:"firstReleaseDate",isString:!0,partialMatch:!0},oe={arcane:kr,a:me,artist:me,art:me,attack:ie,b:$,block:$,banned:Le,bond:Re,bonds:Re,c:Ee,class:Ee,chain:Lr,co:Be,cost:Be,color:Ce,d:$,def:$,defense:$,flow:Ne,flows:Ne,f:De,fusion:De,foil:Ie,foiling:Ie,i:Oe,intellect:Oe,is:ve,k:He,keyword:He,l:ye,legal:ye,hero:ye,li:Ve,life:Ve,meta:ve,n:Ge,name:Ge,p:Ce,pitch:Ce,pwr:ie,pow:ie,power:ie,print:Rr,r:Ue,rarity:Ue,referencedby:Er,references:Br,rf:Le,s:Ke,set:Ke,short:Fe,shorthand:Fe,shorthands:Fe,sp:ae,spec:ae,specialization:ae,specializations:ae,st:je,subtype:je,t:qe,type:qe,tal:ze,talent:ze,text:Nr,trait:Ir,treat:se,treatment:se,var:se,variation:se,x:Dr,year:Or},Hr=[{text:l.Release.ClassicBattlesRhinarDorinthea.toLowerCase(),override:l.Release.ClassicBattlesRhinarDorinthea.toLowerCase().replaceAll(u,"")}],Vr=e=>{let r=[],t=e.replaceAll("\u201D",'"');for(let{text:a,override:s}of Hr)t.includes(a)&&(t=t.replace(a,s));if(J(t)?.card)r.push(t);else{let a=t.split(/[ ]+/),s="",o=0;for(let n of a)o===2&&(r.push(s.trim().replaceAll('"',"")),s="",o=0),o<2&&n.split('"').length===2?(s+=" "+n,o++):o===0&&s===""?r.push(n):o===1&&(s+=" "+n);o===2&&(r.push(s.trim().replaceAll('"',"")),s="",o=0)}return r},Te=(e,r,t=[],i=[],a=zr())=>{let s=e.trim().toLowerCase();for(let{expanded:w,shorthands:k}of ge)for(let p of k)if(s.includes(p)){s=s.replace(p,w.join(" "));break}for(let[w,k]of Object.entries(l.setToSetIdentifierMappings))s.includes(w.toLowerCase())&&(s=s.replace(w.toLowerCase(),k[0]));let o=Vr(s),n=[];for(let w of o){let k=he.find(({shorthands:p})=>p.includes(w));k&&!k.isCardProperty?n.push(...k.expanded):n.push(w)}let c=[],b=[],g=[],f=[],C=!1,M=[],A=[],R=[],G=[];for(let w of n)if(Xr(w)){let[k,p]=w.split(":"),{modifier:D,values:d,isAnd:h,isOr:T}=Qr(p),{filterKey:y,isExcluded:E,isOptional:B,isMeta:ce}=Zr(k),q=!1;if(ce){if(["rarity","r"].includes(y)){let v=Jr(d);E||(A=[...v]),d=v.map(L=>L.toLowerCase())}["legal","l","hero"].includes(y),c.push(...de(E,B,y,d,D,t))}else{if(["chain"].includes(y)){let v=F=>F.name.toLowerCase().replaceAll(u,""),L=d.map(F=>j(F,r)).filter(F=>!!F).map(v),S=new Set(L);y="name",T=!0;let P=20,O=0,H=F=>{if(!F.types.includes(l.Type.Hero)){let W=v(F);S.add(W),L.includes(W)||L.push(W)}},U=te(r);for(let F of L){if(O>P)break;let W=j(F,r);re(W,r).forEach(H),O===0&&W&&(U.get(W.cardIdentifier)||[]).forEach(H),O++}d=Array.from(S)}else if(["referencedby","references"].includes(y)){let v=["referencedby"].includes(y),L=[...d].filter(P=>!!P);d=[],y="name",T=!0;let S=[];if(v)for(let P of L)S.push(...re(j(P,r),r));else{let P=te(r);for(let O of L){let H=j(O,r);if(H){let U=P.get(H.cardIdentifier)||[];S.push(...U)}}}d.push(...S.map(({name:P})=>P.toLowerCase().replaceAll(u,"")))}else if(["art","artist"].includes(y))b=d;else if(["print","prints","printing","printings"].includes(y))M=d;else if(["is","meta"].includes(y)){let v=[],L=[],S=[],P=[];for(let F of d)Kr.includes(F)?v.push(F):jr.includes(F)?L.push(F):qr.includes(F)?S.push(F):P.push(F);v.length>0&&(c.push({filterToPropertyMapping:ve,values:[l.Meta.Reprint.toLowerCase().replaceAll(u,"")],isAnd:h,isOr:T,isExcluded:!E,isOptional:B}),q=P.length===0);let O=L.length>0;O&&c.push({filterToPropertyMapping:We,values:[a],isAnd:h,isOr:T,isExcluded:E,isOptional:B});let H=S.length>0;H&&c.push({filterToPropertyMapping:We,values:[a],isAnd:h,isOr:T,isExcluded:!E,isOptional:B}),(O||H)&&(q=P.length===0);let U=$r(P);d=U.map(F=>F.toLowerCase().replaceAll(u,"")),U.includes(l.Meta.Expansion)&&!E&&(C=!0)}else["foiling","foil"].includes(y)?(f=_r(d),d=f.map(v=>v.toLowerCase())):["treat","treatment","var","variation"].includes(y)?(G=Yr(d),d=G.map(v=>v.toLowerCase())):["set","s"].includes(y)?(R=Gr(d,i),d=R.map(v=>v.toLowerCase().replaceAll(u,""))):["pitch","p","color"].includes(y)&&(d=Ur(d));oe[y]&&!q&&c.push({filterToPropertyMapping:oe[y],values:d,isAnd:h,isOr:T,modifier:D,isExcluded:E,isOptional:B})}}else if(w){let k=J(w)?.card,p=ue(w);k?g.push(`"${k.toLowerCase().replace(u,"")}"`):p&&p.length>0?c.push(...p):g.push(w.replace(u,""))}return{appliedFilters:c,attributes:{artists:b,foilings:f,isExpansionSlot:C,prints:M,rarities:A,releases:R,treatments:G},keywords:g}},Gr=(e,r=[])=>{let t=[];for(let i of e)t.push(...Wr(i,r));return t},Wr=(e,r=[])=>{let t=[],i=Object.values(l.Release).find(a=>a.toLowerCase().replaceAll(u,"")===e);if(i&&t.push(i),t.length===0){let a=l.setIdentifierToSetMappings[e];a&&t.push(a)}if(t.length===0){let a=Object.values(l.Release).filter(s=>s.toLowerCase().includes(e));a.length>0&&t.push(...a)}if(t.length===0){let a=r.find(s=>s.toLowerCase().replaceAll(u,"")===e);a&&t.push(a)}return t},Me={purple:4,blue:3,yellow:2,red:1,white:0},Ur=e=>{let r=[];for(let t of e)Me[t]||Me[t]===0?r.push(Me[t].toString()):r.push(t);return r},Kr=["unique"],jr=["preview","spoiler","unreleased"],qr=["released"],zr=()=>{let e=new Date,r=`${e.getMonth()+1}`.padStart(2,"0"),t=`${e.getDate()}`.padStart(2,"0");return`${e.getFullYear()}-${r}-${t}`},$e={dual:l.Meta.DualClass,exp:l.Meta.Expansion,expansion:l.Meta.Expansion,expansionSlot:l.Meta.Expansion,rainbow:l.Meta.Rainbow,reprint:l.Meta.Reprint,reprints:l.Meta.Reprint},$r=e=>{let r=[];for(let t of e)$e[t]?r.push($e[t]):l.Meta[t]&&r.push(l.Meta[t]);if(e.length>0&&r.length===0){for(let t of Object.values(l.Meta))for(let i of e)if(t.toLowerCase().includes(i)){r.push(t);break}}return r},_e={r:l.Foiling.Rainbow,rf:l.Foiling.Rainbow,rainbow:l.Foiling.Rainbow,c:l.Foiling.Cold,cf:l.Foiling.Cold,cold:l.Foiling.Cold,g:l.Foiling.Gold,gf:l.Foiling.Gold,gold:l.Foiling.Gold},_r=e=>{let r=[];for(let t of e)_e[t]&&r.push(_e[t]);return r},Ye={...Object.values(l.Treatment).reduce((e,r)=>(e[r.toLowerCase()]=r,e),{}),aa:l.Treatment.AA,alt:l.Treatment.AA,"alt art":l.Treatment.AA,ab:l.Treatment.AB,"alt border":l.Treatment.AB,at:l.Treatment.AT,"alt text":l.Treatment.AT,ea:l.Treatment.EA,extended:l.Treatment.EA,"extended art":l.Treatment.EA,fa:l.Treatment.FA,full:l.Treatment.FA,"full art":l.Treatment.FA},Yr=e=>{let r=[];for(let t of e)Ye[t]?r.push(Ye[t]):l.Treatment[t.toUpperCase()]&&r.push(l.Treatment[t.toUpperCase()]);return r},Ae={b:l.Rarity.Basic,c:l.Rarity.Common,f:l.Rarity.Fabled,l:l.Rarity.Legendary,m:l.Rarity.Majestic,p:l.Rarity.Promo,r:l.Rarity.Rare,s:l.Rarity.SuperRare,t:l.Rarity.Token,v:l.Rarity.Marvel},Jr=e=>{let r=[];for(let t of e)Ae[t]?r.push(Ae[t]):r.push(t);return r},Qr=e=>{let r=[],t,i,a=Xe.find(s=>e.includes(s));if(a){let[,s]=e.split(a);Je(s)?(t=!0,r.push(...s.trim().split("+").map(o=>o.replace(u,"")))):Qe(s)?(i=!0,r.push(...s.trim().split(",").map(o=>o.replace(u,"")))):r.push(s.trim().replace(u,""))}else Je(e)?(t=!0,r.push(...e.trim().split("+").map(s=>s.replace(u,"")))):Qe(e)?(i=!0,r.push(...e.trim().split(",").map(s=>s.replace(u,"")))):e.startsWith('"')&&e.endsWith('"')?r.push(e.trim().replaceAll('"',"").replace(u,"")):r.push(e.trim().replace(u,""));return{modifier:a,values:r,isAnd:t,isOr:i}},Zr=e=>{let r=et(e);if(r){let[,t]=e.split(r);return{filterKey:t,isExcluded:!0,isOptional:!1,isMeta:Ze(t)}}else return{filterKey:e,isExcluded:!1,isOptional:!1,isMeta:Ze(e)}},Xr=e=>e.indexOf(":")>=0,Je=e=>e.indexOf("+")>=0,Qe=e=>e.indexOf(",")>=0,Ze=e=>!!oe[e]?.isMeta,et=e=>er.find(r=>e.includes(r))?.slice(0,1);var m=require("@flesh-and-blood/types"),rr={artists:["Hoodwill"],cardIdentifier:"fangs-a-lot-blue",classes:[m.Class.Generic],defaultImage:"FNG000",firstReleaseDate:"2022-06-02",functionalText:"If Fangs A Lot is put into your banished zone from your graveyard, instead put it into your hand.",legalFormats:[],legalHeroes:[m.Hero.Kayo,m.Hero.Levia,m.Hero.Rhinar],printings:[{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000",print:"FNG000",rarity:m.Rarity.Rare,set:m.Release.Promos},{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000_Marvel",print:`FNG000-${m.Treatment.FA}`,rarity:m.Rarity.Marvel,set:m.Release.Promos,treatment:m.Treatment.FA}],name:"Fangs A Lot",rarities:[m.Rarity.Rare,m.Rarity.Marvel],rarity:m.Rarity.Rare,sets:[m.Release.Promos],setIdentifiers:["FNG000"],specialImage:"FNG000_Marvel",subtypes:[m.Subtype.Attack],types:[m.Type.Action],typeText:"Generic Action - Attack"},tr=[{keyword:rr.name.toLowerCase(),card:rr}];var xe=class{constructor(r,t=[],i=[],a=!1){this.log=(r,...t)=>{this.debug&&console.log(r,...t)};this.search=(r,t)=>{let i,{appliedFilters:a,attributes:s,keywords:o}=Te(r,this.cards,this.additionalHeroes,this.additionalSets),n=o.join(" "),c=t?tr.filter(p=>p.keyword===n):[];if(c.length>0?i=c.map(({card:p})=>p):o.length?i=this.fuse.search(n).map(p=>p.item):i=[...this.cards],a.length&&(i=i.filter(p=>p&&ar(p,a))),o.length===0){let p="";if(s.releases.length===1)try{let h=s.releases[0];p=ne.setToSetIdentifierMappings[h][0].toUpperCase()}catch(h){console.error("Error getting set identifier from search",h)}if(!p&&s.prints.length===1)try{let h=s.prints[0];ne.setIdentifierToSetMappings[h]&&(p=h.toUpperCase())}catch(h){console.error("Error getting set identifier from search",h)}p?i.sort((h,T)=>{let y=h.setIdentifiers.find(B=>B.includes(p))?.replace(p,""),E=T.setIdentifiers.find(B=>B.includes(p))?.replace(p,"");return y&&E?y.localeCompare(E):-1}):i.sort((h,T)=>h.name===T.name?`${h.pitch}`.localeCompare(`${T.pitch}`):h.name.localeCompare(T.name))}else{let p=[],D=[],d=o.map(h=>h.toLowerCase().replace(u,"")).join(" ");for(let h of i)h.name.toLowerCase().replace(u,"")===d?p.push(h):D.push(h);i=[...p,...D]}let b,{artists:g,isExpansionSlot:f,foilings:C,prints:M,rarities:A,releases:R,treatments:G}=s;(g.length>0||f||C.length>0||M.length>0||A.length>0||R.length>0||G.length>0)&&(b=i.map(p=>{let D=p.printings.filter(d=>{let h=!!d.image,T=g.length===0||g.some(S=>d.artists.find(P=>P.replace(u,"").toLowerCase().includes(S))),y=!f||f===d.isExpansionSlot,E=C.length===0||C.includes(d.foiling),B=M.length===0||M.some(S=>d.identifier.includes(S.toUpperCase())),ce=A.length===0||A.includes(d.rarity),q=R.length===0||R.includes(d.set),v=G.length===0||d.treatments?.some(S=>G.includes(S));return h&&T&&y&&E&&B&&ce&&q&&v});return{...p,matchingPrintings:D}}));let k=b?.length>0?b:i;return{appliedFilters:a,attributes:s,keywords:o,searchResults:k}};let s={getFn:(o,n)=>{let c=Pe.default.config.getFn(o,n);return c&&(Array.isArray(c)?c.map(b=>z(b.replace(u,""))):z(c).replace(u,""))},ignoreLocation:!0,includeScore:!0,keys:[{name:"name",weight:10},{name:"functionalText",weight:6},{name:"shorthands",weight:4},{name:"setIdentifiers",weight:2},{name:"traits",weight:4},{name:"typeText",weight:6}],threshold:.15,useExtendedSearch:!0};this.additionalHeroes=t,this.additionalSets=i,this.cards=[...r],this.debug=a,this.fuse=new Pe.default([...r],s)}},ir=xe,ar=(e,r)=>{let t=!0,i=!1;for(let a of r){let s=a.isOptional,{isNumber:o,isString:n,isArray:c,isBoolean:b,isDate:g}=a.filterToPropertyMapping;if(o){let f=rt(e,a);s?f&&(i=!0):t=t&&f}else if(n){let f=tt(e,a);s?f&&(i=!0):t=t&&f}else if(c){let f=it(e,a,r);s?f&&(i=!0):t=t&&f}else if(b){let f=at(e,a);s?f&&(i=!0):t=t&&f}else if(g){let f=st(e,a);s?f&&(i=!0):t=t&&f}}return t},rt=(e,r)=>{if(_(r,e)){let{values:t,modifier:i,isExcluded:a,filterToPropertyMapping:{partialMatch:s}}=r,o=le(e,r);if(o!=null&&!isNaN(o))if(o=parseInt(o),i)switch(i){case">=":{let n=t?.some(c=>o>=parseInt(c));return a?!n:n}case">":{let n=t?.some(c=>o>parseInt(c));return a?!n:n}case"<=":{let n=t?.some(c=>o<=parseInt(c));return a?!n:n}case"<":{let n=t?.some(c=>o<parseInt(c));return a?!n:n}default:return!1}else{let n=t?.some(c=>o===parseInt(c));return a?!n:n}else{let n=nt(e,r)?.toLowerCase(),c=s?t?.some(b=>n?.includes(b)):t?.some(b=>n===b);return a?!c:c}}else return!0},tt=(e,r)=>{if(_(r,e)){let{values:t,isAnd:i,isExcluded:a,filterToPropertyMapping:{partialMatch:s}}=r,o=le(e,r)?.replaceAll(u,"");if(s){let n=i?t?.every(c=>o?.toLowerCase().includes(c)):t?.some(c=>o?.toLowerCase().includes(c));return a?!n:n}else{let n=i?t?.every(c=>o?.toLowerCase()===c):t?.some(c=>o?.toLowerCase()===c);return a?!n:n}}else return!0},it=(e,r,t)=>{if(_(r,e)){let{values:i,isAnd:a,isExcluded:s,filterToPropertyMapping:{partialMatch:o}}=r,n=ot(e,r,t).map(c=>c?.replaceAll(u,""));if(o){let c=a?i.every(g=>n?.some(f=>f?.toLowerCase().includes(g))):i.some(g=>n?.some(f=>f?.toLowerCase().includes(g))),b=n.length===0;return s?!c||b:c}else{let c=a?i.every(b=>n?.some(g=>g?.toLowerCase()===b)):i.some(b=>n?.some(g=>g?.toLowerCase()===b));return s?!c:c}}else return!0},at=(e,r)=>{if(_(r,e)){let{isExcluded:t}=r,i=le(e,r);return t?!i:i}else return!0},st=(e,r)=>{if(_(r,e)){let{values:t,isExcluded:i}=r,a=le(e,r),s=t?.some(o=>a>o);return i?!s:s}else return!0},le=(e,r)=>{let{filterToPropertyMapping:t}=r;return e[t.property]},ot=(e,r,t)=>{let{filterToPropertyMapping:{isNestedPropertyArray:i,nestedProperty:a,property:s}}=r,o=e[s]||[],n=[],c=Object.keys(e.legalOverrides||{}).length>0,b=r.filterToPropertyMapping.property==="legalHeroes",g=t.find(({filterToPropertyMapping:C})=>C.property==="legalFormats");if(c&&b&&!!g){let C=new Set;for(let{format:M,heroes:A}of e.legalOverrides||[])if(g.values.includes(M.toLowerCase()))for(let R of A)C.add(R);n=Array.from(C)}if(n.length===0)if(a){let C=new Set;for(let M of o)if(i){let A=M[a]||[];for(let R of A)C.add(R)}else{let A=M[a];A&&C.add(A)}n=Array.from(C)}else n=o;return n},nt=(e,r)=>{let{filterToPropertyMapping:t}=r;return e[t.specialProperty]},_=({cardTypes:e},{types:r,subtypes:t})=>!e||e?.some(i=>r.map(a=>a.toLowerCase()).includes(i.toLowerCase())||t.map(a=>a.toLowerCase()).includes(i.toLowerCase()));0&&(module.exports={FilterProperty,PUNCTUATION,RARITY_VALUES_MAPPING,abbreviations,availableExclusions,availableModifiers,filterCard,filtersToCardPropertyMappings,getAbbreviation,getAbbreviationByCard,getCardByName,getCardsByReferencedCardIdentifier,getCleanText,getExcludedMetaFilters,getKeywordsAndAppliedFiltersFromText,getMetaFilters,getNormalizedText,getOtherPitches,getReferencedCards,getTokensReferencedByCards,multiWordShorthands,shorthands,singleWordShorthands});
|
|
1
|
+
var dr=Object.create;var Y=Object.defineProperty;var ur=Object.getOwnPropertyDescriptor;var fr=Object.getOwnPropertyNames;var gr=Object.getPrototypeOf,hr=Object.prototype.hasOwnProperty;var br=(e,r)=>{for(var t in r)Y(e,t,{get:r[t],enumerable:!0})},Be=(e,r,t,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of fr(r))!hr.call(e,i)&&i!==t&&Y(e,i,{get:()=>r[i],enumerable:!(a=ur(r,i))||a.enumerable});return e};var yr=(e,r,t)=>(t=e!=null?dr(gr(e)):{},Be(r||!e||!e.__esModule?Y(t,"default",{value:e,enumerable:!0}):t,e)),mr=e=>Be(Y({},"__esModule",{value:!0}),e);var yt={};br(yt,{FilterProperty:()=>Ie,PUNCTUATION:()=>f,RARITY_VALUES_MAPPING:()=>Pe,abbreviations:()=>de,availableExclusions:()=>or,availableModifiers:()=>sr,buildSearchIndex:()=>me,default:()=>cr,filterCard:()=>pr,filtersToCardPropertyMappings:()=>xe,getAbbreviation:()=>J,getAbbreviationByCard:()=>Cr,getCardsByName:()=>re,getCardsByReferencedCardIdentifier:()=>ye,getCardsReferencedBy:()=>ie,getCardsReferencing:()=>te,getCleanText:()=>z,getExcludedMetaFilters:()=>fe,getKeywordsAndAppliedFiltersFromText:()=>we,getMetaFilters:()=>ue,getNormalizedText:()=>q,getOtherPitches:()=>Rr,getReferencedCards:()=>Er,getTokensReferencedByCards:()=>Nr,multiWordShorthands:()=>he,shorthands:()=>ge,singleWordShorthands:()=>be});module.exports=mr(yt);var ne=require("@flesh-and-blood/types"),ke=yr(require("fuse.js"),1);var f=/[!"#$%&'’(),./:;<=>?@[\]^_`|~]/g;var l=require("@flesh-and-blood/types");var J=e=>de.find(({abbreviations:r})=>r.find(t=>t.toLowerCase()===e)),Cr=e=>de.find(({card:r})=>r.toLowerCase()===e.name.toLowerCase()),de=[{abbreviations:["10k"],card:"10,000 Year Reunion"},{abbreviations:["Pajamas","PJs"],card:"Alluvion Constellas"},{abbreviations:["Slippy","Arakni Slipped Through the Cracks","Arakni, Slipped Through the Cracks"],card:"Arakni, 5L!p3d 7hRu 7h3 cR4X"},{abbreviations:["Dullcap"],card:"Arcanite Skullcap"},{abbreviations:["ALS"],card:"Arc Light Sentinel"},{abbreviations:["AoW"],card:"Art of War"},{abbreviations:["BBD"],card:"Barraging Beatdown"},{abbreviations:["BBS"],card:"Big Blue Sky"},{abbreviations:["Starvo"],card:"Bravo, Star of the Show"},{abbreviations:["BEB"],card:"Bull's Eye Bracers"},{abbreviations:["BLW"],card:"Be Like Water"},{abbreviations:["BoJ"],card:"Balance of Justice"},{abbreviations:["BOHH"],card:"Blood on Her Hands"},{abbreviations:["BRB"],card:"Bloodrush Bellow"},{abbreviations:["Breezies"],card:"Breeze Rider Boots"},{abbreviations:["BTA"],card:"Burn Them All"},{abbreviations:["CStrike","C-Strike","C Strike"],card:"Celestial Cataclysm"},{abbreviations:["CBelly"],card:"Cerebellum Processor"},{abbreviations:["CLF"],card:"Channel Lake Frigid"},{abbreviations:["CLV"],card:"Channel Lightning Valley"},{abbreviations:["CMH"],card:"Channel Mount Heroic"},{abbreviations:["CMI"],card:"Channel Mount Isen"},{abbreviations:["CMT"],card:"Channel the Millennium Tree"},{abbreviations:["CnC","C&C"],card:"Command and Conquer"},{abbreviations:["Sea and Sea"],card:"Conqueror of the High Seas"},{abbreviations:["CYB"],card:"Count Your Blessings"},{abbreviations:["Cat","Kitty"],card:"Crouching Tiger"},{abbreviations:["CoD"],card:"Crown of Dominion"},{abbreviations:["CoP"],card:"Crown of Providence"},{abbreviations:["CtW"],card:"Crush the Weak"},{abbreviations:["DD"],card:"Death Dealer"},{abbreviations:["DnD"],card:"Devotion Never Dies"},{abbreviations:["DIO"],card:"Dash I/O"},{abbreviations:["EBTT"],card:"Even Bigger Than That!"},{abbreviations:["NewNigma"],card:"Enigma, New Moon"},{abbreviations:["EPot","E Pot"],card:"Energy Potion"},{abbreviations:["EStrike","E-Strike","E Strike"],card:"Enlightened Strike"},{abbreviations:["FFS"],card:"Fyendal's Fighting Spirit"},{abbreviations:["FoN"],card:"Force of Nature"},{abbreviations:["Frosty","\u{1F976}","\u{1F9CA}","\u2744\uFE0F"],card:"Frostbite"},{abbreviations:["Yum yum"],card:"Fruits of the Forest"},{abbreviations:["GnT"],card:"Give and Take"},{abbreviations:["Habibi"],card:"Hanabi Blaster"},{abbreviations:["HMH"],card:"Hope Merchant's Hood"},{abbreviations:["HoI"],card:"Heart of Ice"},{abbreviations:["Pumpkin"],card:"Jack-o'-lantern"},{abbreviations:["RKO","Cheato"],card:"Kayo, Underhanded Cheat"},{abbreviations:["KKBB"],card:"Knick Knack Bric-a-brac"},{abbreviations:["BStrike"],card:"Levels of Enlightenment"},{abbreviations:["LAG","Twominaris"],card:"Luminaris, Angel's Glow"},{abbreviations:["LCF","Newminaris"],card:"Luminaris, Celestial Fury"},{abbreviations:["LDE"],card:"Last Ditch Effort"},{abbreviations:["LtC"],card:"Lead the Charge"},{abbreviations:["LNW"],card:"Leave No Witnesses"},{abbreviations:["LFaL","L4aL"],card:"Life for a Life"},{abbreviations:["LiT"],card:"Lost in Thought"},{abbreviations:["MMB"],card:"Mage Master Boots"},{abbreviations:["MaxV"],card:"Maximum Velocity"},{abbreviations:["MoM"],card:"Mask of Momentum"},{abbreviations:["MoPL"],card:"Mask of the Pouncing Lynx"},{abbreviations:["MnG"],card:"Meat and Greet"},{abbreviations:["Cake","\u{1F382}"],card:"Ninth Blade of the Blood Oath"},{abbreviations:["PoM"],card:"Peace of Mind"},{abbreviations:["P-Bone"],card:"Performance Bonus"},{abbreviations:["PF","\u{1F525}"],card:"Phoenix Flame"},{abbreviations:["PtW"],card:"Poison the Well"},{abbreviations:["Thanos","Infinity Gauntlet"],card:"Polarity Reversal Script"},{abbreviations:["DPot","D Pot"],card:"Potion of D\xE9j\xE0 Vu"},{abbreviations:["Ponder Run"],card:"Premeditate"},{abbreviations:["Qi Unbound"],card:"Qi Unleashed"},{abbreviations:["RitL"],card:"Red in the Ledger"},{abbreviations:["Cats","Ghost cat","Ghost cats"],card:"Restless Coalescence"},{abbreviations:["Eugene"],card:"Rhinar, Reckless Rampage",isHidden:!0},{abbreviations:["SSGB"],card:"Sandscour Greatbow"},{abbreviations:["SSP"],card:"Sand Sketched Plan"},{abbreviations:["SFaS","S4aS"],card:"Scar for a Scar"},{abbreviations:["Tyler"],card:"Scurv, Stowaway",isHidden:!0},{abbreviations:["SWOMB"],card:"Shifting Winds of the Mystic Beast"},{abbreviations:["Snaps"],card:"Snapdragon Scalers"},{abbreviations:["SWK"],card:"Spinning Wheel Kick"},{abbreviations:["SFTL"],card:"Swing Fist, Think Later"},{abbreviations:["TTT"],card:"Take the Tempo"},{abbreviations:["Ultron"],card:"Teklovossen, the Mechropotent"},{abbreviations:["ToS"],card:"Test of Strength"},{abbreviations:["TAYG"],card:"That All You Got?"},{abbreviations:["TROM"],card:"This Round's on Me"},{abbreviations:["3oak"],card:"Three of a Kind"},{abbreviations:["Pox Malone","Post Malone"],card:"Virulent Touch"},{abbreviations:["Cast Homes"],card:"Visit Goldmane Estate"},{abbreviations:["Frosty Hammer"],card:"Winter's Wail"},{abbreviations:["Wreckless Wing"],card:"War Cry of Bellona"},{abbreviations:["ZTS"],card:"Zero to Sixty"}];var T=require("@flesh-and-blood/types");var Ie=(a=>(a.BannedFormats="bannedFormats",a.LegalFormats="legalFormats",a.LegalHeroes="legalHeroes",a))(Ie||{}),ee=Array.from(Array(50).keys()).map(e=>`${e}`),Fr=[{format:T.Format.ClassicConstructed,nicknames:["cc","classic"]},{format:T.Format.LivingLegend,nicknames:["cc ll","classic constructed ll","ll cc","ll","living legend"]},{format:T.Format.SilverAge,nicknames:["sage"]},{format:T.Format.GoldenAge,nicknames:["gage"]},{format:T.Format.UltimatePitFight,nicknames:["upf"]}],Mr=Object.values(T.Format).map(e=>{let r=Fr.find(({format:a})=>a===e),t=e.toLowerCase().replaceAll(f,"");return r?{...r,format:t}:{format:t}}),vr=[{hero:T.Hero.DataDoll,nicknames:["data","datadoll"]},{hero:T.Hero.Dorinthea,nicknames:["dori"]},{hero:T.Hero.Genis,nicknames:["genis"]},{hero:T.Hero.GravyBones,nicknames:["gravy"]},{hero:T.Hero.Iyslander,nicknames:["islander"]}],Ar=Object.values(T.Hero).map(e=>{let r=vr.find(({hero:a})=>a===e),t=e.toLowerCase().replaceAll(f,"");return r?{...r,hero:t}:{hero:t}}),Q=["common","rare","super rare","majestic","legendary","fabled"],Tr=(e,r,t,a)=>{let i=[];if(!r)i.push(...e);else for(let s of e)switch(r){case">=":{let o=!1;for(let n of Q)o?i.push(n):n===s&&(o=!0,i.push(n));break}case">":{let o=!1;for(let n of Q)o?i.push(n):n===s&&(o=!0);break}case"<=":{let o=!1;for(let n of Q.slice().reverse())o?i.push(n):n===s&&(o=!0,i.push(n));break}case"<":{let o=!1;for(let n of Q.slice().reverse())o?i.push(n):n===s&&(o=!0);break}default:break}return{filterToPropertyMapping:{nestedProperty:"rarity",property:"printings",isArray:!0},isExcluded:t,isOptional:a,isOr:!0,values:i}},Re=(e,r,t,a,i)=>{let s=a.map(d=>({hero:d.toLowerCase().replaceAll(f,"")})),o=[],n=[],c=[];for(let d of e){let p=Mr.find(({format:m,nicknames:F})=>m===d||!!F&&F.includes(d));if(p)n.push(p.format);else{let m=Ar.find(({hero:F,nicknames:M})=>F===d||!!M&&M.includes(d))||s.find(({hero:F})=>F===d);m&&c.push(m.hero)}}let g=i||"legalFormats";return n.length>0&&o.push({filterToPropertyMapping:{property:g,isArray:!0},values:n,isOr:!0,isExcluded:r,isOptional:t}),c.length>0&&o.push({filterToPropertyMapping:{property:"legalHeroes",isArray:!0},values:c,isOr:!0,isExcluded:r,isOptional:t}),o},Sr=(e,r,t,a)=>Re(e,r,t,a,"bannedFormats"),ue=(e,r,t,a,i,s)=>{let o=[];return wr(t)?o.push(...Re(a,e,r,s)):Lr(t)?o.push(...Sr(a,e,r,s)):Ir(t)&&o.push(Tr(a,i,e,r)),o},j=[{filterToPropertyMapping:{property:"cost",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialCost",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]}],O=[{filterToPropertyMapping:{property:"defense",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialDefense",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["hero","placeholder","token","weapon"]}],X=[{filterToPropertyMapping:{property:"pitch",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]},{filterToPropertyMapping:{property:"isCardBack",isBoolean:!0},isExcluded:!0,values:["true"]}],V=[{filterToPropertyMapping:{property:"power",isNumber:!0},isExcluded:!0,values:ee},{filterToPropertyMapping:{property:"specialPower",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token"]}],Z=[{filterToPropertyMapping:{property:"talents",isArray:!0},isExcluded:!0,values:Object.values(T.Talent).map(e=>e.toLowerCase())}],Pr={"!co":j,"-co":j,"!cost":j,"-cost":j,"!color":j,"-color":j,"!b":O,"-b":O,"!block":O,"-block":O,"!d":O,"-d":O,"!def":O,"-def":O,"!defense":O,"-defense":O,"!pitch":X,"-pitch":X,"!p":X,"-p":X,"!attack":V,"-attack":V,"!power":V,"-power":V,"!pwr":V,"-pwr":V,"!pow":V,"-pow":V,"!talents":Z,"-talents":Z,"!tal":Z,"-tal":Z},fe=e=>{let r=[],t=Pr[e];return t&&r.push(...t),r},xr=["l","legal","hero"],wr=e=>xr.includes(e),kr=["banned"],Lr=e=>kr.includes(e),Br=["r","rarity"],Ir=e=>Br.includes(e);var R=require("@flesh-and-blood/types"),ge=[{description:"Attack actions",expanded:["st:attack"],filters:{subtypes:[R.Subtype.Attack]},isCardProperty:!1,shorthands:["AA"]},{description:"Arcane barrier",expanded:['k:"arcane barrier"'],filters:{keywords:[R.Keyword.ArcaneBarrier]},isCardProperty:!1,shorthands:["AB"]},{description:"Attack reactions",expanded:['t:"attack reaction"'],filters:{types:[R.Type.AttackReaction]},isCardProperty:!1,shorthands:["AR"]},{description:"Defense reactions",expanded:['t:"defense reaction"'],filters:{types:[R.Type.DefenseReaction]},isCardProperty:!1,shorthands:["DR"]},{description:"Gain life",expanded:["gain {h}"],filters:{functionalText:"gain {h}"},isCardProperty:!1,shorthands:["Gain life","Gains life"]},{description:"Go again",expanded:['k:"go again"'],filters:{keywords:[R.Keyword.GoAgain]},isCardProperty:!1,shorthands:["GA"]},{description:"Non-attack actions",expanded:["t:action","st:non-attack"],filters:{subtypes:[R.Subtype.NonAttack],types:[R.Type.Action]},isCardProperty:!1,shorthands:["NAA"]},{description:"Plus defense",expanded:["+ {d}"],filters:{functionalText:"+ {d}"},isCardProperty:!1,shorthands:["Pump defense","Pumps defense","Buff defense","Buffs defense"]},{description:"Spellvoid",expanded:['k:"spellvoid"'],filters:{keywords:[R.Keyword.Spellvoid]},isCardProperty:!1,shorthands:["SV"]}],he=ge.filter(({shorthands:e})=>e.some(r=>r.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(r=>r.includes(" ")).map(r=>r.toLowerCase()).sort((r,t)=>t.length-r.length)})),be=ge.filter(({shorthands:e})=>e.some(r=>!r.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(r=>!r.includes(" ")).map(r=>r.toLowerCase()).sort((r,t)=>t.length-r.length)}));var z=e=>q(e.toLowerCase().trim().replace(f,"")),q=e=>e.normalize("NFD").replace(/\p{Diacritic}/gu,"");var Rr=(e,r)=>{let t=[];if(e)for(let a of r){let i=a.name===e.name,s=a.cardIdentifier!==e.cardIdentifier,o=a.pitch!==e.pitch;i&&s&&o&&t.push(a)}return t},Er=(e,r)=>{let t=new Set(e?.referencedCards),a=[];for(let i of r)t.has(i.cardIdentifier)&&a.push(i);return a},ye=e=>{let r=new Map;for(let t of e)for(let a of t.referencedCards||[]){let i=r.get(a);i?i.push(t):r.set(a,[t])}return r},Nr=(e,r)=>{let t=new Set;for(let i of e)for(let s of i.createdExtras||[])t.add(s);let a=[];for(let i of r)t.has(i.cardIdentifier)&&a.push(i);return a};var me=e=>{let r=new Map,t=new Map,a=[],i=new Map,s=0;for(let o of e){r.set(o.cardIdentifier,o),t.set(o.cardIdentifier,s),s++;let n=z(o.name),c=i.get(n);c?c.push(o):(i.set(n,[o]),a.push(n))}return{cards:e,cardByCardIdentifier:r,corpusPositionByCardIdentifier:t,cleanedNames:a,pitchCycleByCleanedName:i,referencingCardsByCardIdentifier:ye(e)}},Ce=(e,r)=>e.pitchCycleByCleanedName.get(z(r.name))||[],re=(e,r)=>{let t=z(r),a=e.pitchCycleByCleanedName.get(t);if(!a){let i=e.cleanedNames.find(s=>s.includes(t));i&&(a=e.pitchCycleByCleanedName.get(i))}return a||[]},Ee=(e,r)=>{let t=new Map;for(let i of r)for(let s of Ce(e,i))t.set(s.cardIdentifier,s);let a=({cardIdentifier:i})=>e.corpusPositionByCardIdentifier.get(i)||0;return[...t.values()].sort((i,s)=>a(i)-a(s))},te=(e,r)=>{let t=[];for(let a of Ce(e,r))t.push(...e.referencingCardsByCardIdentifier.get(a.cardIdentifier)||[]);return Ee(e,t)},ie=(e,r)=>{let t=[];for(let a of Ce(e,r))for(let i of a.referencedCards||[]){let s=e.cardByCardIdentifier.get(i);s&&t.push(s)}return Ee(e,t)};var sr=[">=",">","<=","<"],or=["!","-"],Dr={property:"arcane",specialProperty:"specialArcane",isNumber:!0,partialMatch:!0},Fe={property:"artists",isArray:!0,partialMatch:!0},Ne={property:"n/a",isMeta:!0},De={property:"bonds",isArray:!0},Or={property:"cardIdentifier",isString:!0,isNormalized:!0},Oe=(e,{isAnd:r,isExcluded:t,isOptional:a,modifier:i})=>({filterToPropertyMapping:Or,values:[...e],valuesSet:e,isAnd:r,isOr:!0,modifier:i,isExcluded:t,isOptional:a}),Hr={property:"n/a"},He={property:"classes",isArray:!0,partialMatch:!0},Ve={property:"cost",specialProperty:"specialCost",isNumber:!0,partialMatch:!0},_={property:"defense",specialProperty:"specialDefense",isNumber:!0},Ge={property:"flows",isArray:!0},We={nestedProperty:"foiling",property:"printings",isArray:!0},Ue={property:"fusions",isArray:!0},Ke={property:"intellect",isNumber:!0},je={property:"keywords",isArray:!0},Me={property:"n/a",isMeta:!0},ze={property:"life",specialProperty:"specialLife",isNumber:!0},Se={property:"meta",isArray:!0},qe={property:"name",isString:!0,partialMatch:!0},ve={property:"pitch",isNumber:!0},_e={property:"firstReleaseDate",isDate:!0},ae={property:"power",specialProperty:"specialPower",isNumber:!0},Vr={property:"setIdentifiers",isArray:!0,partialMatch:!0},$e={property:"n/a",isMeta:!0},Gr={property:"n/a"},Wr={property:"n/a"},Ye={property:"sets",isArray:!0,partialMatch:!0},Ae={property:"shorthands",isArray:!0,partialMatch:!0},se={property:"specializations",isArray:!0,partialMatch:!0},Je={property:"subtypes",isArray:!0},Qe={property:"types",isArray:!0},Xe={property:"talents",isArray:!0},Ur={property:"functionalText",isString:!0,partialMatch:!0},Kr={property:"traits",isArray:!0,partialMatch:!0},jr={property:"typeText",isString:!0,partialMatch:!0},oe={nestedProperty:"treatments",property:"printings",isArray:!0,isNestedPropertyArray:!0},zr={property:"firstReleaseDate",isString:!0,partialMatch:!0},xe={arcane:Dr,a:Fe,artist:Fe,art:Fe,attack:ae,b:_,block:_,banned:Ne,bond:De,bonds:De,c:He,class:He,chain:Hr,co:Ve,cost:Ve,color:ve,d:_,def:_,defense:_,flow:Ge,flows:Ge,f:Ue,fusion:Ue,foil:We,foiling:We,i:Ke,intellect:Ke,is:Se,k:je,keyword:je,l:Me,legal:Me,hero:Me,li:ze,life:ze,meta:Se,n:qe,name:qe,p:ve,pitch:ve,pwr:ae,pow:ae,power:ae,print:Vr,r:$e,rarity:$e,referencedby:Gr,references:Wr,rf:Ne,s:Ye,set:Ye,short:Ae,shorthand:Ae,shorthands:Ae,sp:se,spec:se,specialization:se,specializations:se,st:Je,subtype:Je,t:Qe,type:Qe,tal:Xe,talent:Xe,text:Ur,trait:Kr,treat:oe,treatment:oe,var:oe,variation:oe,x:jr,year:zr},qr=[{text:l.Release.ClassicBattlesRhinarDorinthea.toLowerCase(),override:l.Release.ClassicBattlesRhinarDorinthea.toLowerCase().replaceAll(f,"")}],_r=e=>{let r=[],t=e.replaceAll("\u201D",'"');for(let{text:i,override:s}of qr)t.includes(i)&&(t=t.replace(i,s));if(J(t)?.card)r.push(t);else{let i=t.split(/[ ]+/),s="",o=0;for(let n of i)o===2&&(r.push(s.trim().replaceAll('"',"")),s="",o=0),o<2&&n.split('"').length===2?(s+=" "+n,o++):o===0&&s===""?r.push(n):o===1&&(s+=" "+n);o===2&&(r.push(s.trim().replaceAll('"',"")),s="",o=0)}return r},$r=20,we=(e,r,t=[],a=[],i=rt())=>{let s=e.trim().toLowerCase();for(let{expanded:S,shorthands:P}of he)for(let u of P)if(s.includes(u)){s=s.replace(u,S.join(" "));break}for(let[S,P]of Object.entries(l.setToSetIdentifierMappings))s.includes(S.toLowerCase())&&(s=s.replace(S.toLowerCase(),P[0]));let o=_r(s),n=[];for(let S of o){let P=be.find(({shorthands:u})=>u.includes(S));P&&!P.isCardProperty?n.push(...P.expanded):n.push(S)}let c=[],g=[],d=[],p=[],m=!1,F=[],M=[],B=[],G=[];for(let S of n)if(lt(S)){let[P,u]=S.split(":"),{modifier:E,values:h,isAnd:b,isOr:x}=ot(u),{filterKey:C,isExcluded:w,isOptional:L,isMeta:ce}=nt(P),W=!1;if(ce){if(["rarity","r"].includes(C)){let U=st(h);w||(M=[...U]),h=U.map(v=>v.toLowerCase())}["legal","l","hero"].includes(C),c.push(...ue(w,L,C,h,E,t))}else{if(["chain"].includes(C)){let v=new Set,k=[],N=new Set,D=A=>{v.add(A.cardIdentifier),N.has(A.name)||(N.add(A.name),k.push(A))},K=A=>{A.types.includes(l.Type.Hero)||D(A)};for(let A of h)if(A)for(let I of re(r,A))D(I);let H=0;for(let A of k){if(H>$r)break;for(let pe of ie(r,A))K(pe);if(H===0)for(let pe of te(r,A))K(pe);H++}c.push(Oe(v,{isAnd:b,isExcluded:w,isOptional:L,modifier:E})),W=!0}else if(["referencedby","references"].includes(C)){let v=["referencedby"].includes(C),k=new Set;for(let N of h)if(N)for(let D of re(r,N)){let K=v?ie(r,D):te(r,D);for(let H of K)k.add(H.cardIdentifier)}c.push(Oe(k,{isAnd:b,isExcluded:w,isOptional:L,modifier:E})),W=!0}else if(["art","artist"].includes(C))g=h;else if(["print","prints","printing","printings"].includes(C))F=h;else if(["is","meta"].includes(C)){let v=[],k=[],N=[],D=[];for(let I of h)Xr.includes(I)?v.push(I):Zr.includes(I)?k.push(I):et.includes(I)?N.push(I):D.push(I);v.length>0&&(c.push({filterToPropertyMapping:Se,values:[l.Meta.Reprint.toLowerCase().replaceAll(f,"")],isAnd:b,isOr:x,isExcluded:!w,isOptional:L}),W=D.length===0);let K=k.length>0;K&&c.push({filterToPropertyMapping:_e,values:[i],isAnd:b,isOr:x,isExcluded:w,isOptional:L});let H=N.length>0;H&&c.push({filterToPropertyMapping:_e,values:[i],isAnd:b,isOr:x,isExcluded:!w,isOptional:L}),(K||H)&&(W=D.length===0);let A=tt(D);h=A.map(I=>I.toLowerCase().replaceAll(f,"")),A.includes(l.Meta.Expansion)&&!w&&(m=!0)}else["foiling","foil"].includes(C)?(p=it(h),h=p.map(v=>v.toLowerCase())):["treat","treatment","var","variation"].includes(C)?(G=at(h),h=G.map(v=>v.toLowerCase())):["set","s"].includes(C)?(B=Yr(h,a),h=B.map(v=>v.toLowerCase().replaceAll(f,""))):["pitch","p","color"].includes(C)&&(h=Qr(h));let U=xe[C];U&&!W&&c.push({filterToPropertyMapping:U,values:h,isAnd:b,isOr:x,modifier:E,isExcluded:w,isOptional:L})}}else if(S){let P=J(S)?.card,u=fe(S);P?d.push(`"${P.toLowerCase().replace(f,"")}"`):u&&u.length>0?c.push(...u):d.push(S.replace(f,""))}return{appliedFilters:c,attributes:{artists:g,foilings:p,isExpansionSlot:m,prints:F,rarities:M,releases:B,treatments:G},keywords:d}},Yr=(e,r=[])=>{let t=[];for(let a of e)t.push(...Jr(a,r));return t},Jr=(e,r=[])=>{let t=[],a=Object.values(l.Release).find(i=>i.toLowerCase().replaceAll(f,"")===e);if(a&&t.push(a),t.length===0){let i=l.setIdentifierToSetMappings[e];i&&t.push(i)}if(t.length===0){let i=Object.values(l.Release).filter(s=>s.toLowerCase().includes(e));i.length>0&&t.push(...i)}if(t.length===0){let i=r.find(s=>s.toLowerCase().replaceAll(f,"")===e);i&&t.push(i)}return t},Te={purple:4,blue:3,yellow:2,red:1,white:0},Qr=e=>{let r=[];for(let t of e)Te[t]||Te[t]===0?r.push(Te[t].toString()):r.push(t);return r},Xr=["unique"],Zr=["preview","spoiler","unreleased"],et=["released"],rt=()=>{let e=new Date,r=`${e.getMonth()+1}`.padStart(2,"0"),t=`${e.getDate()}`.padStart(2,"0");return`${e.getFullYear()}-${r}-${t}`},Ze={dual:l.Meta.DualClass,exp:l.Meta.Expansion,expansion:l.Meta.Expansion,expansionSlot:l.Meta.Expansion,rainbow:l.Meta.Rainbow,reprint:l.Meta.Reprint,reprints:l.Meta.Reprint},tt=e=>{let r=[];for(let t of e)Ze[t]?r.push(Ze[t]):l.Meta[t]&&r.push(l.Meta[t]);if(e.length>0&&r.length===0){for(let t of Object.values(l.Meta))for(let a of e)if(t.toLowerCase().includes(a)){r.push(t);break}}return r},er={r:l.Foiling.Rainbow,rf:l.Foiling.Rainbow,rainbow:l.Foiling.Rainbow,c:l.Foiling.Cold,cf:l.Foiling.Cold,cold:l.Foiling.Cold,g:l.Foiling.Gold,gf:l.Foiling.Gold,gold:l.Foiling.Gold},it=e=>{let r=[];for(let t of e)er[t]&&r.push(er[t]);return r},rr={...Object.values(l.Treatment).reduce((e,r)=>(e[r.toLowerCase()]=r,e),{}),aa:l.Treatment.AA,alt:l.Treatment.AA,"alt art":l.Treatment.AA,ab:l.Treatment.AB,"alt border":l.Treatment.AB,at:l.Treatment.AT,"alt text":l.Treatment.AT,ea:l.Treatment.EA,extended:l.Treatment.EA,"extended art":l.Treatment.EA,fa:l.Treatment.FA,full:l.Treatment.FA,"full art":l.Treatment.FA},at=e=>{let r=[];for(let t of e)rr[t]?r.push(rr[t]):l.Treatment[t.toUpperCase()]&&r.push(l.Treatment[t.toUpperCase()]);return r},Pe={b:l.Rarity.Basic,c:l.Rarity.Common,f:l.Rarity.Fabled,l:l.Rarity.Legendary,m:l.Rarity.Majestic,p:l.Rarity.Promo,r:l.Rarity.Rare,s:l.Rarity.SuperRare,t:l.Rarity.Token,v:l.Rarity.Marvel},st=e=>{let r=[];for(let t of e)Pe[t]?r.push(Pe[t]):r.push(t);return r},ot=e=>{let r=[],t,a,i=sr.find(s=>e.includes(s));if(i){let[,s]=e.split(i);tr(s)?(t=!0,r.push(...s.trim().split("+").map(o=>o.replace(f,"")))):ir(s)?(a=!0,r.push(...s.trim().split(",").map(o=>o.replace(f,"")))):r.push(s.trim().replace(f,""))}else tr(e)?(t=!0,r.push(...e.trim().split("+").map(s=>s.replace(f,"")))):ir(e)?(a=!0,r.push(...e.trim().split(",").map(s=>s.replace(f,"")))):e.startsWith('"')&&e.endsWith('"')?r.push(e.trim().replaceAll('"',"").replace(f,"")):r.push(e.trim().replace(f,""));return{modifier:i,values:r,isAnd:t,isOr:a}},nt=e=>{let r=ct(e);if(r){let[,t]=e.split(r);return{filterKey:t,isExcluded:!0,isOptional:!1,isMeta:ar(t)}}else return{filterKey:e,isExcluded:!1,isOptional:!1,isMeta:ar(e)}},lt=e=>e.indexOf(":")>=0,tr=e=>e.indexOf("+")>=0,ir=e=>e.indexOf(",")>=0,ar=e=>!!xe[e]?.isMeta,ct=e=>or.find(r=>e.includes(r))?.slice(0,1);var y=require("@flesh-and-blood/types"),nr={artists:["Hoodwill"],cardIdentifier:"fangs-a-lot-blue",classes:[y.Class.Generic],defaultImage:"FNG000",firstReleaseDate:"2022-06-02",functionalText:"If Fangs A Lot is put into your banished zone from your graveyard, instead put it into your hand.",legalFormats:[],legalHeroes:[y.Hero.Kayo,y.Hero.Levia,y.Hero.Rhinar],printings:[{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000",print:"FNG000",rarity:y.Rarity.Rare,set:y.Release.Promos},{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000_Marvel",print:`FNG000-${y.Treatment.FA}`,rarity:y.Rarity.Marvel,set:y.Release.Promos,treatment:y.Treatment.FA}],name:"Fangs A Lot",rarities:[y.Rarity.Rare,y.Rarity.Marvel],rarity:y.Rarity.Rare,sets:[y.Release.Promos],setIdentifiers:["FNG000"],specialImage:"FNG000_Marvel",subtypes:[y.Subtype.Attack],types:[y.Type.Action],typeText:"Generic Action - Attack"},lr=[{keyword:nr.name.toLowerCase(),card:nr}];var Le=class{constructor(r,t=[],a=[],i=!1){this.log=(r,...t)=>{this.debug&&console.log(r,...t)};this.search=(r,t)=>{let a,{appliedFilters:i,attributes:s,keywords:o}=we(r,this.index,this.additionalHeroes,this.additionalSets),n=o.join(" "),c=t?lr.filter(u=>u.keyword===n):[];if(c.length>0?a=c.map(({card:u})=>u):o.length?a=this.fuse.search(n).map(u=>u.item):a=[...this.cards],i.length&&(a=a.filter(u=>u&&pr(u,i))),o.length===0){let u="";if(s.releases.length===1)try{let b=s.releases[0];u=ne.setToSetIdentifierMappings[b][0].toUpperCase()}catch(b){console.error("Error getting set identifier from search",b)}if(!u&&s.prints.length===1)try{let b=s.prints[0];ne.setIdentifierToSetMappings[b]&&(u=b.toUpperCase())}catch(b){console.error("Error getting set identifier from search",b)}u?a.sort((b,x)=>{let C=b.setIdentifiers.find(L=>L.includes(u))?.replace(u,""),w=x.setIdentifiers.find(L=>L.includes(u))?.replace(u,"");return C&&w?C.localeCompare(w):-1}):a.sort((b,x)=>b.name===x.name?`${b.pitch}`.localeCompare(`${x.pitch}`):b.name.localeCompare(x.name))}else{let u=[],E=[],h=o.map(b=>b.toLowerCase().replace(f,"")).join(" ");for(let b of a)b.name.toLowerCase().replace(f,"")===h?u.push(b):E.push(b);a=[...u,...E]}let g,{artists:d,isExpansionSlot:p,foilings:m,prints:F,rarities:M,releases:B,treatments:G}=s;(d.length>0||p||m.length>0||F.length>0||M.length>0||B.length>0||G.length>0)&&(g=a.map(u=>{let E=u.printings.filter(h=>{let b=!!h.image,x=d.length===0||d.some(k=>h.artists.find(N=>N.replace(f,"").toLowerCase().includes(k))),C=!p||p===h.isExpansionSlot,w=m.length===0||m.includes(h.foiling),L=F.length===0||F.some(k=>h.identifier.includes(k.toUpperCase())),ce=M.length===0||M.includes(h.rarity),W=B.length===0||B.includes(h.set),U=G.length===0||h.treatments?.some(k=>G.includes(k));return b&&x&&C&&w&&L&&ce&&W&&U});return{...u,matchingPrintings:E}}));let P=g?.length>0?g:a;return{appliedFilters:i,attributes:s,keywords:o,searchResults:P}};let s={getFn:(o,n)=>{let c=ke.default.config.getFn(o,n);return c&&(Array.isArray(c)?c.map(g=>q(g.replace(f,""))):q(c).replace(f,""))},ignoreLocation:!0,includeScore:!0,keys:[{name:"name",weight:10},{name:"functionalText",weight:6},{name:"shorthands",weight:4},{name:"setIdentifiers",weight:2},{name:"traits",weight:4},{name:"typeText",weight:6}],threshold:.15,useExtendedSearch:!0};this.additionalHeroes=t,this.additionalSets=a,this.cards=[...r],this.debug=i,this.fuse=new ke.default([...r],s),this.index=me(this.cards)}},cr=Le,pr=(e,r)=>{let t=!0,a=!1;for(let i of r){let s=i.isOptional,{isNumber:o,isString:n,isArray:c,isBoolean:g,isDate:d}=i.filterToPropertyMapping;if(o){let p=pt(e,i);s?p&&(a=!0):t=t&&p}else if(n){let p=dt(e,i);s?p&&(a=!0):t=t&&p}else if(c){let p=ut(e,i,r);s?p&&(a=!0):t=t&&p}else if(g){let p=ft(e,i);s?p&&(a=!0):t=t&&p}else if(d){let p=gt(e,i);s?p&&(a=!0):t=t&&p}}return t},pt=(e,r)=>{if($(r,e)){let{values:t,modifier:a,isExcluded:i,filterToPropertyMapping:{partialMatch:s}}=r,o=le(e,r);if(o!=null&&!isNaN(o))if(o=parseInt(o),a)switch(a){case">=":{let n=t?.some(c=>o>=parseInt(c));return i?!n:n}case">":{let n=t?.some(c=>o>parseInt(c));return i?!n:n}case"<=":{let n=t?.some(c=>o<=parseInt(c));return i?!n:n}case"<":{let n=t?.some(c=>o<parseInt(c));return i?!n:n}default:return!1}else{let n=t?.some(c=>o===parseInt(c));return i?!n:n}else{let n=bt(e,r)?.toLowerCase(),c=s?t?.some(g=>n?.includes(g)):t?.some(g=>n===g);return i?!c:c}}else return!0},dt=(e,r)=>{if($(r,e)){let{values:t,valuesSet:a,isAnd:i,isExcluded:s,filterToPropertyMapping:{isNormalized:o,partialMatch:n}}=r,c=le(e,r),g=o?c:c?.replaceAll(f,"").toLowerCase();if(n){let d=i?t?.every(p=>g?.includes(p)):t?.some(p=>g?.includes(p));return s?!d:d}else{let d;return i?d=t?.every(p=>g===p):a?d=a.has(g):d=t?.some(p=>g===p),s?!d:d}}else return!0},ut=(e,r,t)=>{if($(r,e)){let{values:a,isAnd:i,isExcluded:s,filterToPropertyMapping:{partialMatch:o}}=r,n=ht(e,r,t).map(c=>c?.replaceAll(f,""));if(o){let c=i?a.every(d=>n?.some(p=>p?.toLowerCase().includes(d))):a.some(d=>n?.some(p=>p?.toLowerCase().includes(d))),g=n.length===0;return s?!c||g:c}else{let c=i?a.every(g=>n?.some(d=>d?.toLowerCase()===g)):a.some(g=>n?.some(d=>d?.toLowerCase()===g));return s?!c:c}}else return!0},ft=(e,r)=>{if($(r,e)){let{isExcluded:t}=r,a=le(e,r);return t?!a:a}else return!0},gt=(e,r)=>{if($(r,e)){let{values:t,isExcluded:a}=r,i=le(e,r),s=t?.some(o=>i>o);return a?!s:s}else return!0},le=(e,r)=>{let{filterToPropertyMapping:t}=r;return e[t.property]},ht=(e,r,t)=>{let{filterToPropertyMapping:{isNestedPropertyArray:a,nestedProperty:i,property:s}}=r,o=e[s]||[],n=[],c=Object.keys(e.legalOverrides||{}).length>0,g=r.filterToPropertyMapping.property==="legalHeroes",d=t.find(({filterToPropertyMapping:m})=>m.property==="legalFormats");if(c&&g&&!!d){let m=new Set;for(let{format:F,heroes:M}of e.legalOverrides||[])if(d.values.includes(F.toLowerCase()))for(let B of M)m.add(B);n=Array.from(m)}if(n.length===0)if(i){let m=new Set;for(let F of o)if(a){let M=F[i]||[];for(let B of M)m.add(B)}else{let M=F[i];M&&m.add(M)}n=Array.from(m)}else n=o;return n},bt=(e,r)=>{let{filterToPropertyMapping:t}=r;return e[t.specialProperty]},$=({cardTypes:e},{types:r,subtypes:t})=>!e||e?.some(a=>r.map(i=>i.toLowerCase()).includes(a.toLowerCase())||t.map(i=>i.toLowerCase()).includes(a.toLowerCase()));0&&(module.exports={FilterProperty,PUNCTUATION,RARITY_VALUES_MAPPING,abbreviations,availableExclusions,availableModifiers,buildSearchIndex,filterCard,filtersToCardPropertyMappings,getAbbreviation,getAbbreviationByCard,getCardsByName,getCardsByReferencedCardIdentifier,getCardsReferencedBy,getCardsReferencing,getCleanText,getExcludedMetaFilters,getKeywordsAndAppliedFiltersFromText,getMetaFilters,getNormalizedText,getOtherPitches,getReferencedCards,getTokensReferencedByCards,multiWordShorthands,shorthands,singleWordShorthands});
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/related.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare const getReferencedCards: (card: Card | undefined, cards: Card[])
|
|
|
8
8
|
* answers the reverse relation for every card in the corpus, so a page or a
|
|
9
9
|
* filter asking about several of them builds this once.
|
|
10
10
|
*/
|
|
11
|
-
export declare const getCardsByReferencedCardIdentifier: (cards:
|
|
11
|
+
export declare const getCardsByReferencedCardIdentifier: <CardType extends Card>(cards: CardType[]) => Map<string, CardType[]>;
|
|
12
12
|
/**
|
|
13
13
|
* The extras a set of cards brings, out of the ones available to them. A card
|
|
14
14
|
* carries what it creates, so the hero's own card has to be among the cards for
|
package/dist/search.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ declare class Search {
|
|
|
21
21
|
private cards;
|
|
22
22
|
private debug;
|
|
23
23
|
private fuse;
|
|
24
|
+
private index;
|
|
24
25
|
constructor(cards: DoubleSidedCard[], additionalHeroes?: Hero[], additionalSets?: Release[], debug?: boolean);
|
|
25
26
|
log: (message?: any, ...optionalParams: any[]) => void;
|
|
26
27
|
search: (text: string, includeMemes?: boolean) => SearchResults;
|
package/dist/search.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { memes } from "./memes.js";
|
|
11
11
|
import { getNormalizedText } from "./helpers.js";
|
|
12
12
|
import { FilterProperty } from "./metaFilters.js";
|
|
13
|
+
import { buildSearchIndex } from "./searchIndex.js";
|
|
13
14
|
class Search {
|
|
14
15
|
constructor(cards, additionalHeroes = [], additionalSets = [], debug = false) {
|
|
15
16
|
this.log = (message, ...optionalParams) => {
|
|
@@ -21,7 +22,7 @@ class Search {
|
|
|
21
22
|
let results;
|
|
22
23
|
const { appliedFilters, attributes, keywords } = getKeywordsAndAppliedFiltersFromText(
|
|
23
24
|
text,
|
|
24
|
-
this.
|
|
25
|
+
this.index,
|
|
25
26
|
this.additionalHeroes,
|
|
26
27
|
this.additionalSets
|
|
27
28
|
);
|
|
@@ -165,6 +166,7 @@ class Search {
|
|
|
165
166
|
this.cards = [...cards];
|
|
166
167
|
this.debug = debug;
|
|
167
168
|
this.fuse = new Fuse([...cards], searchOptions);
|
|
169
|
+
this.index = buildSearchIndex(this.cards);
|
|
168
170
|
}
|
|
169
171
|
}
|
|
170
172
|
var search_default = Search;
|
|
@@ -300,27 +302,25 @@ const getDoesCardMatchStringFilter = (card, filter) => {
|
|
|
300
302
|
} else {
|
|
301
303
|
const {
|
|
302
304
|
values,
|
|
305
|
+
valuesSet,
|
|
303
306
|
isAnd,
|
|
304
307
|
isExcluded: excluded,
|
|
305
|
-
filterToPropertyMapping: { partialMatch }
|
|
308
|
+
filterToPropertyMapping: { isNormalized, partialMatch }
|
|
306
309
|
} = filter;
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
""
|
|
310
|
-
);
|
|
310
|
+
const storedValue = getCardValue(card, filter);
|
|
311
|
+
const cardValue = isNormalized ? storedValue : storedValue?.replaceAll(PUNCTUATION, "").toLowerCase();
|
|
311
312
|
if (partialMatch) {
|
|
312
|
-
const isPartialMatch = isAnd ? values?.every(
|
|
313
|
-
(filterValue) => cardValue?.toLowerCase().includes(filterValue)
|
|
314
|
-
) : values?.some(
|
|
315
|
-
(filterValue) => cardValue?.toLowerCase().includes(filterValue)
|
|
316
|
-
);
|
|
313
|
+
const isPartialMatch = isAnd ? values?.every((filterValue) => cardValue?.includes(filterValue)) : values?.some((filterValue) => cardValue?.includes(filterValue));
|
|
317
314
|
return excluded ? !isPartialMatch : isPartialMatch;
|
|
318
315
|
} else {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
316
|
+
let isFullMatch;
|
|
317
|
+
if (isAnd) {
|
|
318
|
+
isFullMatch = values?.every((filterValue) => cardValue === filterValue);
|
|
319
|
+
} else if (valuesSet) {
|
|
320
|
+
isFullMatch = valuesSet.has(cardValue);
|
|
321
|
+
} else {
|
|
322
|
+
isFullMatch = values?.some((filterValue) => cardValue === filterValue);
|
|
323
|
+
}
|
|
324
324
|
return excluded ? !isFullMatch : isFullMatch;
|
|
325
325
|
}
|
|
326
326
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Card, DoubleSidedCard } from "@flesh-and-blood/types";
|
|
2
|
+
/**
|
|
3
|
+
* Lookups over a corpus, built once per `Search` instance. Every relation is
|
|
4
|
+
* keyed at the name level: a reference is between Cards, so a reference to or
|
|
5
|
+
* from one pitch counts for every pitch of that card.
|
|
6
|
+
*/
|
|
7
|
+
export interface SearchIndex {
|
|
8
|
+
cards: DoubleSidedCard[];
|
|
9
|
+
cardByCardIdentifier: Map<string, DoubleSidedCard>;
|
|
10
|
+
/** Corpus order, for restoring it after a lookup returns cards out of order. */
|
|
11
|
+
corpusPositionByCardIdentifier: Map<string, number>;
|
|
12
|
+
/** Distinct cleaned names, in the order the corpus first carries them. */
|
|
13
|
+
cleanedNames: string[];
|
|
14
|
+
pitchCycleByCleanedName: Map<string, DoubleSidedCard[]>;
|
|
15
|
+
referencingCardsByCardIdentifier: Map<string, DoubleSidedCard[]>;
|
|
16
|
+
}
|
|
17
|
+
export declare const buildSearchIndex: (cards: DoubleSidedCard[]) => SearchIndex;
|
|
18
|
+
/**
|
|
19
|
+
* Every pitch of the named card. An exact name wins; failing that the first
|
|
20
|
+
* name containing the text answers, so a fragment resolves to one card.
|
|
21
|
+
*/
|
|
22
|
+
export declare const getCardsByName: (index: SearchIndex, name: string) => DoubleSidedCard[];
|
|
23
|
+
/** The cards naming the card, at every pitch of both. */
|
|
24
|
+
export declare const getCardsReferencing: (index: SearchIndex, card: Card) => DoubleSidedCard[];
|
|
25
|
+
/** The cards the card names, at every pitch of both. */
|
|
26
|
+
export declare const getCardsReferencedBy: (index: SearchIndex, card: Card) => DoubleSidedCard[];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getCleanText } from "./helpers.js";
|
|
2
|
+
import { getCardsByReferencedCardIdentifier } from "./related.js";
|
|
3
|
+
const buildSearchIndex = (cards) => {
|
|
4
|
+
const cardByCardIdentifier = /* @__PURE__ */ new Map();
|
|
5
|
+
const corpusPositionByCardIdentifier = /* @__PURE__ */ new Map();
|
|
6
|
+
const cleanedNames = [];
|
|
7
|
+
const pitchCycleByCleanedName = /* @__PURE__ */ new Map();
|
|
8
|
+
let corpusPosition = 0;
|
|
9
|
+
for (const card of cards) {
|
|
10
|
+
cardByCardIdentifier.set(card.cardIdentifier, card);
|
|
11
|
+
corpusPositionByCardIdentifier.set(card.cardIdentifier, corpusPosition);
|
|
12
|
+
corpusPosition++;
|
|
13
|
+
const cleanedName = getCleanText(card.name);
|
|
14
|
+
const pitchCycle = pitchCycleByCleanedName.get(cleanedName);
|
|
15
|
+
if (pitchCycle) {
|
|
16
|
+
pitchCycle.push(card);
|
|
17
|
+
} else {
|
|
18
|
+
pitchCycleByCleanedName.set(cleanedName, [card]);
|
|
19
|
+
cleanedNames.push(cleanedName);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
cards,
|
|
24
|
+
cardByCardIdentifier,
|
|
25
|
+
corpusPositionByCardIdentifier,
|
|
26
|
+
cleanedNames,
|
|
27
|
+
pitchCycleByCleanedName,
|
|
28
|
+
referencingCardsByCardIdentifier: getCardsByReferencedCardIdentifier(cards)
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const getPitchCycle = (index, card) => index.pitchCycleByCleanedName.get(getCleanText(card.name)) || [];
|
|
32
|
+
const getCardsByName = (index, name) => {
|
|
33
|
+
const cleanedName = getCleanText(name);
|
|
34
|
+
let pitchCycle = index.pitchCycleByCleanedName.get(cleanedName);
|
|
35
|
+
if (!pitchCycle) {
|
|
36
|
+
const containingName = index.cleanedNames.find(
|
|
37
|
+
(candidate) => candidate.includes(cleanedName)
|
|
38
|
+
);
|
|
39
|
+
if (containingName) {
|
|
40
|
+
pitchCycle = index.pitchCycleByCleanedName.get(containingName);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return pitchCycle || [];
|
|
44
|
+
};
|
|
45
|
+
const getCardsWithPitchSiblings = (index, cards) => {
|
|
46
|
+
const cardByCardIdentifier = /* @__PURE__ */ new Map();
|
|
47
|
+
for (const card of cards) {
|
|
48
|
+
for (const pitch of getPitchCycle(index, card)) {
|
|
49
|
+
cardByCardIdentifier.set(pitch.cardIdentifier, pitch);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const getCorpusPosition = ({ cardIdentifier }) => index.corpusPositionByCardIdentifier.get(cardIdentifier) || 0;
|
|
53
|
+
return [...cardByCardIdentifier.values()].sort(
|
|
54
|
+
(first, second) => getCorpusPosition(first) - getCorpusPosition(second)
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
const getCardsReferencing = (index, card) => {
|
|
58
|
+
const referencingCards = [];
|
|
59
|
+
for (const pitch of getPitchCycle(index, card)) {
|
|
60
|
+
referencingCards.push(
|
|
61
|
+
...index.referencingCardsByCardIdentifier.get(pitch.cardIdentifier) || []
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return getCardsWithPitchSiblings(index, referencingCards);
|
|
65
|
+
};
|
|
66
|
+
const getCardsReferencedBy = (index, card) => {
|
|
67
|
+
const referencedCards = [];
|
|
68
|
+
for (const pitch of getPitchCycle(index, card)) {
|
|
69
|
+
for (const referencedCardIdentifier of pitch.referencedCards || []) {
|
|
70
|
+
const referencedCard = index.cardByCardIdentifier.get(
|
|
71
|
+
referencedCardIdentifier
|
|
72
|
+
);
|
|
73
|
+
if (referencedCard) {
|
|
74
|
+
referencedCards.push(referencedCard);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return getCardsWithPitchSiblings(index, referencedCards);
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
buildSearchIndex,
|
|
82
|
+
getCardsByName,
|
|
83
|
+
getCardsReferencedBy,
|
|
84
|
+
getCardsReferencing
|
|
85
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flesh-and-blood/search",
|
|
3
3
|
"description": "TypeScript search engine for Flesh and Blood cards",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "dist/index.cjs",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@flesh-and-blood/types": "^4.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@flesh-and-blood/cards": "^4.
|
|
50
|
-
"@flesh-and-blood/types": "^4.1.
|
|
49
|
+
"@flesh-and-blood/cards": "^4.2.0",
|
|
50
|
+
"@flesh-and-blood/types": "^4.1.1",
|
|
51
51
|
"@types/jest": "^29.5.11",
|
|
52
52
|
"@types/node": "^20.10.5",
|
|
53
53
|
"esbuild": "^0.19.10",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"FAB",
|
|
78
78
|
"FABTCG"
|
|
79
79
|
],
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "41a6b8eda11e89d0f75d56941a9d3a106abf0aa5"
|
|
81
81
|
}
|