diff --git a/package.json b/package.json index fee1c7c..4ade14f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "buefy": "^0.8.2", "core-js": "^2.6.5", - "idb": "^4.0.4", + "dexie": "^2.0.4", "register-service-worker": "^1.6.2", "vue": "^2.6.10", "vue-class-component": "^7.0.2", diff --git a/src/App.vue b/src/App.vue index 60f68c6..79d6ce9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,6 +28,7 @@ import { Action, Getter } from "vuex-class"; import TopBar from "@/components/Navigation/TopBar.vue"; import { loadSets } from "@/mlpccg/set"; import { AppState } from "./store/types"; +import { getCards } from "./mlpccg/database"; @Component({ components: { diff --git a/src/mlpccg/database.ts b/src/mlpccg/database.ts index 7ca0a86..641f702 100644 --- a/src/mlpccg/database.ts +++ b/src/mlpccg/database.ts @@ -1,35 +1,137 @@ -import { DBSchema, openDB } from "idb"; -import { Card } from "./types"; +import Dexie from "dexie"; +import { Card, CardFilter } from "./types"; -interface CardDB extends DBSchema { - card: { - key: string; - value: Card; - indexes: { - "by-set": string; - "by-element": string[]; - "by-type": string; - "by-cost": number; - "by-power": number; - "by-rarity": string; - }; - }; +class CardDatabase extends Dexie { + public cards: Dexie.Table; + + public constructor() { + super("CardDatabase"); + this.version(1).stores({ + cards: "ID,Set,Type,Cost,Power" + }); + this.cards = this.table("cards"); + } } -const cardDBName = "card-db"; +export let Database = new CardDatabase(); -export async function openCardDB() { - return await openDB(cardDBName, 1, { - upgrade(db) { - const cardStore = db.createObjectStore("card", { - keyPath: "ID" - }); - cardStore.createIndex("by-set", "Set"); - cardStore.createIndex("by-element", "Element"); - cardStore.createIndex("by-type", "Type"); - cardStore.createIndex("by-cost", "Cost"); - cardStore.createIndex("by-power", "Power"); - cardStore.createIndex("by-rarity", "Rarity"); +export async function getCards(filter: CardFilter) { + 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(); } - }); + } + + return await query + .filter(x => { + if (filter.Name) { + if ( + !`${x.Name}, ${x.Subname}` + .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; + } + } + } + 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; + }) + .toArray(); } diff --git a/src/mlpccg/set.ts b/src/mlpccg/set.ts index 1609c17..694a360 100644 --- a/src/mlpccg/set.ts +++ b/src/mlpccg/set.ts @@ -1,5 +1,5 @@ import { SetFile } from "./types"; -import { openCardDB } from "./database"; +import { Database } from "./database"; const baseURL = "https://mcg.zyg.ovh/setdata/"; const allSets = [ @@ -19,20 +19,17 @@ const allSets = [ ]; export async function loadSets() { - const db = await openCardDB(); - const itemcount = await db.count("card"); + const itemcount = await Database.cards.count(); if (itemcount > 100) { // DB already filled, exit early return; } const sets = await Promise.all(allSets.map(set => downloadSet(set))); await Promise.all( - sets.map( - async set => - await Promise.all( - set.Cards.map(async card => await db.put("card", card)) - ) - ) + sets.map(async set => { + console.log(`Processing cards from ${set.Name}`); + return await Database.cards.bulkPut(set.Cards); + }) ); } diff --git a/src/mlpccg/types.ts b/src/mlpccg/types.ts index e879ba6..2630a48 100644 --- a/src/mlpccg/types.ts +++ b/src/mlpccg/types.ts @@ -26,3 +26,15 @@ export interface Card { ProblemRequirement?: PowerRequirement; Boosted?: Card; } + +export interface CardFilter { + Name?: string; + Traits?: string[]; + Rules?: string; + Elements?: string[]; + Sets?: string[]; + Types?: string[]; + Costs?: number[]; + Powers?: number[]; + Rarities?: string[]; +} diff --git a/yarn.lock b/yarn.lock index 7b5d3c5..937f079 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2955,6 +2955,11 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +dexie@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/dexie/-/dexie-2.0.4.tgz#6027a5e05879424e8f9979d8c14e7420f27e3a11" + integrity sha512-aQ/s1U2wHxwBKRrt2Z/mwFNHMQWhESerFsMYzE+5P5OsIe5o1kgpFMWkzKTtkvkyyEni6mWr/T4HUJuY9xIHLA== + diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -4453,11 +4458,6 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" -idb@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/idb/-/idb-4.0.4.tgz#f0c06f58bd78fe557e4de944fd6ba6a3240faa8e" - integrity sha512-ZYsaBSNub2yAnjvmRKudQlMIPqZQIefAOwNIPeXC+RLIeXYFc0UNQqONKNuQeBNf8oBOV5L75yJ9zFISjHVj4g== - ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"