176 lines
4.5 KiB
TypeScript
176 lines
4.5 KiB
TypeScript
import Dexie from "dexie";
|
|
import { Card, CardFilter, StoredImage } from "./types";
|
|
import { cardFullName } from "./card";
|
|
|
|
class CardDatabase extends Dexie {
|
|
public cards: Dexie.Table<Card, string>;
|
|
public images: Dexie.Table<StoredImage, string>;
|
|
|
|
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<void> {
|
|
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<Card, string>;
|
|
|
|
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<Card[]> {
|
|
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();
|
|
}
|