import Dexie from "dexie"; import { Card, CardFilter, StoredImage } from "./types"; import { cardFullName } from "./card"; class CardDatabase extends Dexie { public cards: Dexie.Table; public images: Dexie.Table; public constructor() { super("CardDatabase"); this.version(1).stores({ cards: "ID,Set,Type,Cost,Power", images: "id" }); this.cards = this.table("cards"); this.images = this.table("images"); } } export let Database: CardDatabase | null = null; export async function initDB(): Promise { return new Promise(resolve => { if (Database == null) { Database = new CardDatabase(); Database.on("ready", async () => { resolve(); }); Database.open(); } else { resolve(); } }); } export async function getCards(filter: CardFilter) { if (Database == null) { throw new Error("Database was not initialized, init with 'initDB()'"); } let table = Database.cards; // Get best IDB index let query: Dexie.Collection; if (filter.Powers && filter.Powers.length > 0) { query = table.where("Power").anyOf(filter.Powers); } else if (filter.Costs && filter.Costs.length > 0) { query = table.where("Cost").anyOf(filter.Costs); } else if (filter.Sets && filter.Sets.length > 0) { query = table.where("Set").anyOf(filter.Sets); } else if (filter.Types && filter.Types.length > 0) { query = table.where("Type").anyOf(filter.Types); } else { if ( filter.Name || filter.Rules || filter.Traits || filter.Rarities || filter.Elements ) { query = table.toCollection(); } else { // Nothing to query, return everything return await table.toArray(); } } const results = query.filter(x => { if (filter.Name) { if ( !cardFullName(x) .toLowerCase() .includes(filter.Name.toLowerCase()) ) { return false; } } if (filter.Rules) { if ( !`${x.Keywords.join(" ~ ")} ~ ${x.Text}` .toLowerCase() .includes(filter.Rules.toLowerCase()) ) { return false; } } if (filter.Traits && filter.Traits.length > 0) { let found = false; for (const trait of x.Traits) { if (filter.Traits.includes(trait)) { found = true; break; } } if (!found) { return false; } } if (filter.Sets && filter.Sets.length > 0) { if (!filter.Sets.includes(x.Set)) { return false; } } if (filter.Types && filter.Types.length > 0) { if (!filter.Types.includes(x.Type)) { return false; } } if (filter.Elements && filter.Elements.length > 0) { let found = false; for (const element of x.Element) { if (filter.Elements.includes(element)) { found = true; break; } } if (x.Requirement) { for (const element in x.Requirement) { if (filter.Elements.includes(element)) { found = true; break; } } } if (x.ProblemRequirement) { for (const element in x.ProblemRequirement) { if (filter.Elements.includes(element)) { found = true; break; } } } // For "None" element searches, "nothing" is actually ok if ( filter.Elements.includes("None") && x.Element.length == 0 && (!x.Requirement || x.Requirement.length == 0) && (!x.ProblemRequirement || x.ProblemRequirement.length == 0) ) { found = true; } if (!found) { return false; } } if (filter.Powers && filter.Powers.length > 0) { if (typeof x.Power === "undefined" || !filter.Powers.includes(x.Power)) { return false; } } if (filter.Costs && filter.Costs.length > 0) { if (typeof x.Cost === "undefined" || !filter.Costs.includes(x.Cost)) { return false; } } if (filter.Rarities && filter.Rarities.length > 0) { if (!filter.Rarities.includes(x.Rarity)) { return false; } } return true; }); return await results.toArray(); } export async function cardFromIDs(cardIDs: string[]): Promise { if (Database == null) { throw new Error("Database was not initialized, init with 'initDB()'"); } let table = Database.cards; //TODO Replace with .bulkGet when upgrading to Dexie 3.x return await table .where("ID") .anyOf(cardIDs) .toArray(); }