Add code for loading sets and saving them locally
This commit is contained in:
parent
19f2e16c41
commit
2677a51872
13 changed files with 243 additions and 7 deletions
|
@ -11,12 +11,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buefy": "^0.8.2",
|
"buefy": "^0.8.2",
|
||||||
"core-js": "^2.6.5",
|
"core-js": "^2.6.5",
|
||||||
|
"idb": "^4.0.4",
|
||||||
"register-service-worker": "^1.6.2",
|
"register-service-worker": "^1.6.2",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-class-component": "^7.0.2",
|
"vue-class-component": "^7.0.2",
|
||||||
"vue-property-decorator": "^8.1.0",
|
"vue-property-decorator": "^8.1.0",
|
||||||
"vue-router": "^3.0.3",
|
"vue-router": "^3.0.3",
|
||||||
"vuex": "^3.0.1"
|
"vuex": "^3.0.1",
|
||||||
|
"vuex-class": "^0.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^3.11.0",
|
"@vue/cli-plugin-babel": "^3.11.0",
|
||||||
|
|
41
src/App.vue
41
src/App.vue
|
@ -1,16 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<main>
|
<main v-if="loaded">
|
||||||
<TopBar v-if="!isFullscreen" />
|
<TopBar v-if="!isFullscreen" />
|
||||||
<router-view />
|
<router-view />
|
||||||
</main>
|
</main>
|
||||||
|
<main class="loading-box" v-else>
|
||||||
|
<h1 class="loading-message" v-if="loading">{{ loading }}</h1>
|
||||||
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
|
main.loading-box {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.loading-message {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-property-decorator";
|
import { Component, Vue } from "vue-property-decorator";
|
||||||
import TopBar from "./components/Navigation/TopBar.vue";
|
import { Action, Getter } from "vuex-class";
|
||||||
|
import TopBar from "@/components/Navigation/TopBar.vue";
|
||||||
|
import { loadSets } from "@/mlpccg/set";
|
||||||
|
import { AppState } from "./store/types";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -18,8 +35,26 @@ import TopBar from "./components/Navigation/TopBar.vue";
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export default class App extends Vue {
|
export default class App extends Vue {
|
||||||
|
@Action showLoading!: (msg: string) => void;
|
||||||
|
@Action hideLoading!: () => void;
|
||||||
|
@Action setLoaded!: (loaded: boolean) => void;
|
||||||
|
@Getter loaded!: boolean;
|
||||||
|
@Getter loading!: string | null;
|
||||||
|
|
||||||
private get isFullscreen(): boolean {
|
private get isFullscreen(): boolean {
|
||||||
return this.$route.meta && this.$route.meta.fullscreen;
|
return this.$route.meta && this.$route.meta.fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private mounted() {
|
||||||
|
// Load all sets
|
||||||
|
this.loadCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async loadCards() {
|
||||||
|
this.showLoading("Downloading data for all sets");
|
||||||
|
await loadSets();
|
||||||
|
this.hideLoading();
|
||||||
|
this.setLoaded(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,4 +3,13 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
@import "~bulma/sass/utilities/derived-variables";
|
@import "~bulma/sass/utilities/derived-variables";
|
||||||
@import "~bulma";
|
@import "~bulma";
|
||||||
@import "~buefy/src/scss/buefy";
|
@import "~buefy/src/scss/buefy";
|
||||||
|
|
||||||
|
html {
|
||||||
|
scrollbar-color: #404245 #2f3132;
|
||||||
|
background-color: #2a2c2e;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: white;
|
||||||
|
}
|
5
src/mlpccg/card.ts
Normal file
5
src/mlpccg/card.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const imgBaseURL = "https://mcg.zyg.ovh/images/cards/";
|
||||||
|
|
||||||
|
export function cardImageURL(cardid: string): string {
|
||||||
|
return `${imgBaseURL}${cardid}.webp`;
|
||||||
|
}
|
35
src/mlpccg/database.ts
Normal file
35
src/mlpccg/database.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { DBSchema, openDB } from "idb";
|
||||||
|
import { Card } 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const cardDBName = "card-db";
|
||||||
|
|
||||||
|
export async function openCardDB() {
|
||||||
|
return await openDB<CardDB>(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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
47
src/mlpccg/set.ts
Normal file
47
src/mlpccg/set.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { SetFile } from "./types";
|
||||||
|
import { openCardDB } from "./database";
|
||||||
|
|
||||||
|
const baseURL = "https://mcg.zyg.ovh/setdata/";
|
||||||
|
const allSets = [
|
||||||
|
"PR",
|
||||||
|
"CN",
|
||||||
|
"RR",
|
||||||
|
"CS",
|
||||||
|
"CG",
|
||||||
|
"AD",
|
||||||
|
"EO",
|
||||||
|
"HM",
|
||||||
|
"MT",
|
||||||
|
"DE",
|
||||||
|
"SB",
|
||||||
|
"FF",
|
||||||
|
"Promo"
|
||||||
|
];
|
||||||
|
|
||||||
|
export async function loadSets() {
|
||||||
|
const db = await openCardDB();
|
||||||
|
const itemcount = await db.count("card");
|
||||||
|
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))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadSet(setid: string): Promise<SetFile> {
|
||||||
|
const setfile = await fetch(`${baseURL}${setid.toLowerCase()}.json`);
|
||||||
|
const setdata: SetFile = await setfile.json();
|
||||||
|
setdata.Cards = setdata.Cards.map(c => {
|
||||||
|
c.Set = setid;
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
return setdata;
|
||||||
|
}
|
28
src/mlpccg/types.ts
Normal file
28
src/mlpccg/types.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
export type Rarity = "C" | "U" | "R" | "SR" | "UR" | "RR";
|
||||||
|
|
||||||
|
export type PowerRequirement = { [key: string]: number };
|
||||||
|
|
||||||
|
export interface SetFile {
|
||||||
|
Name: string;
|
||||||
|
Cards: Card[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Card {
|
||||||
|
ID: string;
|
||||||
|
Set: string;
|
||||||
|
Name: string;
|
||||||
|
Subname: string;
|
||||||
|
Element: string[];
|
||||||
|
Keywords: string[];
|
||||||
|
Traits: string[];
|
||||||
|
Requirement?: PowerRequirement;
|
||||||
|
Cost?: number;
|
||||||
|
Power?: number;
|
||||||
|
Type: string;
|
||||||
|
Text: string;
|
||||||
|
Rarity: Rarity;
|
||||||
|
ProblemBonus?: number;
|
||||||
|
ProblemOpponentPower?: number;
|
||||||
|
ProblemRequirement?: PowerRequirement;
|
||||||
|
Boosted?: Card;
|
||||||
|
}
|
18
src/store/actions.ts
Normal file
18
src/store/actions.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { ActionTree } from "vuex";
|
||||||
|
import { AppState } from "./types";
|
||||||
|
|
||||||
|
const actions: ActionTree<AppState, AppState> = {
|
||||||
|
showLoading({ commit }, message: string) {
|
||||||
|
commit("setLoading", message);
|
||||||
|
},
|
||||||
|
|
||||||
|
hideLoading({ commit }) {
|
||||||
|
commit("setLoading", "");
|
||||||
|
},
|
||||||
|
|
||||||
|
setLoaded({ commit }, loaded: boolean) {
|
||||||
|
commit("setLoaded", loaded);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default actions;
|
17
src/store/getters.ts
Normal file
17
src/store/getters.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { GetterTree } from "vuex";
|
||||||
|
import { AppState } from "./types";
|
||||||
|
|
||||||
|
const getters: GetterTree<AppState, AppState> = {
|
||||||
|
loaded(state): boolean {
|
||||||
|
return state.loaded;
|
||||||
|
},
|
||||||
|
|
||||||
|
loading(state): string | null {
|
||||||
|
if (state.loading) {
|
||||||
|
return state.loadingMessage;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getters;
|
|
@ -4,8 +4,19 @@ import { AppState } from "./types";
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
import actions from "./actions";
|
||||||
|
import mutations from "./mutations";
|
||||||
|
import getters from "./getters";
|
||||||
|
|
||||||
const store: StoreOptions<AppState> = {
|
const store: StoreOptions<AppState> = {
|
||||||
state: {},
|
state: {
|
||||||
|
loaded: false,
|
||||||
|
loading: false,
|
||||||
|
loadingMessage: ""
|
||||||
|
},
|
||||||
|
actions,
|
||||||
|
mutations,
|
||||||
|
getters,
|
||||||
modules: {}
|
modules: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
15
src/store/mutations.ts
Normal file
15
src/store/mutations.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { MutationTree } from "vuex";
|
||||||
|
import { AppState } from "./types";
|
||||||
|
|
||||||
|
const mutations: MutationTree<AppState> = {
|
||||||
|
setLoaded(state, loaded: boolean) {
|
||||||
|
state.loaded = loaded;
|
||||||
|
},
|
||||||
|
|
||||||
|
setLoading(state, message: string) {
|
||||||
|
state.loading = message != "";
|
||||||
|
state.loadingMessage = message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default mutations;
|
|
@ -1 +1,5 @@
|
||||||
export interface AppState {}
|
export interface AppState {
|
||||||
|
loaded: boolean;
|
||||||
|
loading: boolean;
|
||||||
|
loadingMessage: string;
|
||||||
|
}
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -4453,6 +4453,11 @@ icss-utils@^2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss "^6.0.1"
|
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:
|
ieee754@^1.1.4:
|
||||||
version "1.1.13"
|
version "1.1.13"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
|
||||||
|
@ -8814,6 +8819,11 @@ vue@^2.6.10:
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
|
||||||
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
|
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
|
||||||
|
|
||||||
|
vuex-class@^0.3.2:
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/vuex-class/-/vuex-class-0.3.2.tgz#c7e96a076c1682137d4d23a8dcfdc63f220e17a8"
|
||||||
|
integrity sha512-m0w7/FMsNcwJgunJeM+wcNaHzK2KX1K1rw2WUQf7Q16ndXHo7pflRyOV/E8795JO/7fstyjH3EgqBI4h4n4qXQ==
|
||||||
|
|
||||||
vuex@^3.0.1:
|
vuex@^3.0.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.1.tgz#0c264bfe30cdbccf96ab9db3177d211828a5910e"
|
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.1.tgz#0c264bfe30cdbccf96ab9db3177d211828a5910e"
|
||||||
|
|
Loading…
Reference in a new issue