From aa036b169e0775f0e0f2b2e6d9014d6a78117f6d Mon Sep 17 00:00:00 2001 From: Carlo Morgenstern Date: Sun, 24 Oct 2021 18:43:23 +0200 Subject: [PATCH] CardCreator reworked init to load everything in parallel --- create-card.js | 209 ++++++++++++++++++++++--------------------------- 1 file changed, 93 insertions(+), 116 deletions(-) diff --git a/create-card.js b/create-card.js index 67aa27a..0c0bfb5 100644 --- a/create-card.js +++ b/create-card.js @@ -144,86 +144,63 @@ class CardCreator { */ async ensureInit() { if (this.initPromise == null) this.initPromise = this.init(); - + await this.initPromise; } async init() { - this.bgImage = await loadImage(absolute('./resources/background.png')); + const commonImagesPromise = Promise.all([ + loadImage(absolute('./resources/background.png')), + loadImage(absolute('./resources/minion.png')), + loadImage(absolute('./resources/mount.png')), + loadImage(absolute('./resources/ilvl-icon.png')), + loadImage(absolute('./resources/shadow.png')), + ]).then(([background, minion, mount, ilvl, shadow]) => { + this.images = { + background, minion, mount, ilvl, shadow, + }; + }); - this.imgMinion = await loadImage(absolute('./resources/minion.png')); - this.imgMount = await loadImage(absolute('./resources/mount.png')); - this.imgIlvl = await loadImage(absolute('./resources/ilvl-icon.png')); - this.imgShadow = await loadImage(absolute('./resources/shadow.png')); + const classJobs = [ + 'alchemist', 'armorer', 'blacksmith', 'carpenter', 'culinarian', 'goldsmith', 'leatherworker', 'weaver', + 'botanist', 'fisher', 'miner', + 'gladiator', 'paladin', 'marauder', 'warrior', 'darkknight', 'gunbreaker', + 'conjurer', 'whitemage', 'scholar', 'astrologian', + 'archer', 'bard', 'machinist', 'dancer', + 'lancer', 'dragoon', 'pugilist', 'monk', 'rogue', 'ninja', 'samurai', + 'thaumaturge', 'blackmage', 'arcanist', 'summoner', 'redmage', + 'bluemage', + ]; - this.imgAlchemist = await loadImage(absolute('./resources/class-jobs-icons/alchemist.png')); - this.imgArmorer = await loadImage(absolute('./resources/class-jobs-icons/armorer.png')); - this.imgBlacksmith = await loadImage(absolute('./resources/class-jobs-icons/blacksmith.png')); - this.imgCarpenter = await loadImage(absolute('./resources/class-jobs-icons/carpenter.png')); - this.imgCulinarian = await loadImage(absolute('./resources/class-jobs-icons/culinarian.png')); - this.imgGoldsmith = await loadImage(absolute('./resources/class-jobs-icons/goldsmith.png')); - this.imgLeatherworker = await loadImage(absolute('./resources/class-jobs-icons/leatherworker.png')); - this.imgWeaver = await loadImage(absolute('./resources/class-jobs-icons/weaver.png')); + const classJobIconsPromise = Promise.all( + classJobs.map(name => loadImage(absolute(`./resources/class-jobs-icons/${name}.png`))) + ).then(images => { + this.cjIcons = {}; + images.forEach((image, index) => this.cjIcons[classJobs[index]] = image); + }); - this.imgBotanist = await loadImage(absolute('./resources/class-jobs-icons/botanist.png')); - this.imgFisher = await loadImage(absolute('./resources/class-jobs-icons/fisher.png')); - this.imgMiner = await loadImage(absolute('./resources/class-jobs-icons/miner.png')); + const jobBackgroundsPromise = Promise.all( + Array.from({ length: 38 }, (_, index) => loadImage(absolute(`./resources/class-jobs-backgrounds/${index + 1}.png`))) + ).then(images => this.jobBackgrounds = images); - this.imgGladiator = await loadImage(absolute('./resources/class-jobs-icons/gladiator.png')); - this.imgPaladin = await loadImage(absolute('./resources/class-jobs-icons/paladin.png')); - this.imgMarauder = await loadImage(absolute('./resources/class-jobs-icons/marauder.png')); - this.imgWarrior = await loadImage(absolute('./resources/class-jobs-icons/warrior.png')); - this.imgDarkKnight = await loadImage(absolute('./resources/class-jobs-icons/darkknight.png')); - this.imgGunbreaker = await loadImage(absolute('./resources/class-jobs-icons/gunbreaker.png')); + const ilevelFilterPromise = createIlvlFilter(this.xivApiKey).then(filterIds => this.ilvlFilterIds = filterIds); - this.imgConjurer = await loadImage(absolute('./resources/class-jobs-icons/conjurer.png')); - this.imgWhitemage = await loadImage(absolute('./resources/class-jobs-icons/whitemage.png')); - this.imgScholar = await loadImage(absolute('./resources/class-jobs-icons/scholar.png')); - this.imgAstrologian = await loadImage(absolute('./resources/class-jobs-icons/astrologian.png')); + const minionCountPromise = fetch(`https://ffxivcollect.com/api/minions/`) + .then(response => response.json()) + .then(data => this.minionCount = data.count); - this.imgArcher = await loadImage(absolute('./resources/class-jobs-icons/archer.png')); - this.imgBard = await loadImage(absolute('./resources/class-jobs-icons/bard.png')); - this.imgMachinist = await loadImage(absolute('./resources/class-jobs-icons/machinist.png')); - this.imgDancer = await loadImage(absolute('./resources/class-jobs-icons/dancer.png')); + const mountCountPromise = fetch(`https://ffxivcollect.com/api/mounts/`) + .then(response => response.json()) + .then(data => this.mountCount = data.count); - this.imgLancer = await loadImage(absolute('./resources/class-jobs-icons/lancer.png')); - this.imgDragoon = await loadImage(absolute('./resources/class-jobs-icons/dragoon.png')); - this.imgPugilist = await loadImage(absolute('./resources/class-jobs-icons/pugilist.png')); - this.imgMonk = await loadImage(absolute('./resources/class-jobs-icons/monk.png')); - this.imgRogue = await loadImage(absolute('./resources/class-jobs-icons/rogue.png')); - this.imgNinja = await loadImage(absolute('./resources/class-jobs-icons/ninja.png')); - this.imgSamurai = await loadImage(absolute('./resources/class-jobs-icons/samurai.png')); - - this.imgThaumaturge = await loadImage(absolute('./resources/class-jobs-icons/thaumaturge.png')); - this.imgBlackmage = await loadImage(absolute('./resources/class-jobs-icons/blackmage.png')); - this.imgArcanist = await loadImage(absolute('./resources/class-jobs-icons/arcanist.png')); - this.imgSummoner = await loadImage(absolute('./resources/class-jobs-icons/summoner.png')); - this.imgRedmage = await loadImage(absolute('./resources/class-jobs-icons/redmage.png')); - - this.imgBluemage = await loadImage(absolute('./resources/class-jobs-icons/bluemage.png')); - - this.imgJobBg = {}; - for (let i = 1; i <= 38; i++) { - this.imgJobBg[i] = await loadImage(absolute(`./resources/class-jobs-backgrounds/${i}.png`)); - } - - this.ilvlFilterIds = await createIlvlFilter(this.xivApiKey); - - await this.countMountsMinions(); - } - - async countMountsMinions() { - const minionResponse = await fetch(`https://ffxivcollect.com/api/minions/`); - const minionData = await minionResponse.json(); - - this.countMinion = minionData.count; - - const mountResponse = await fetch(`https://ffxivcollect.com/api/mounts/`); - const mountData = await mountResponse.json(); - - this.countMount = mountData.count; - - console.log(`Refreshed counts: ${this.countMinion} - ${this.countMount}`); + await Promise.all([ + commonImagesPromise, + classJobIconsPromise, + jobBackgroundsPromise, + ilevelFilterPromise, + minionCountPromise, + mountCountPromise, + ]); } async createCrest(crestAry) { @@ -347,7 +324,7 @@ class CardCreator { const portrait = await loadImage(data.Character.Portrait); - ctx.drawImage(this.bgImage, 0, 0, canvasSize.width, canvasSize.height + 2); + ctx.drawImage(this.images.background, 0, 0, canvasSize.width, canvasSize.height + 2); ctx.drawImage(portrait, 0, 120, 441, 600); @@ -365,9 +342,9 @@ class CardCreator { // BLU returns a null UnlockedState.ID so we can't use it to pick the job image. if (data.Character.ActiveClassJob.UnlockedState.ID != null) { - ctx.drawImage(this.imgJobBg[data.Character.ActiveClassJob.UnlockedState.ID], 450, 4, rectFullWidth, 110); + ctx.drawImage(this.jobBackgrounds[data.Character.ActiveClassJob.UnlockedState.ID], 450, 4, rectFullWidth, 110); } else { - ctx.drawImage(this.imgJobBg[36], 450, 4, rectFullWidth, 110); + ctx.drawImage(this.jobBackgrounds[36], 450, 4, rectFullWidth, 110); } ctx.fillRect(rectStartX, rectStartRow2Y, rectHalfWidth, rectHeightRow2); @@ -407,8 +384,8 @@ class CardCreator { ctx.font = smed; const ilvl = this.getItemLevel(data.Character.GearSet.Gear); - ctx.drawImage(this.imgShadow, 441 - 143, 110, 170, 90); - ctx.drawImage(this.imgIlvl, 441 - 92, 132, 24, 27); + ctx.drawImage(this.images.shadow, 441 - 143, 110, 170, 90); + ctx.drawImage(this.images.ilvl, 441 - 92, 132, 24, 27); ctx.fillText(ilvl, 441 - 65, 155); ctx.fillStyle = white; @@ -470,12 +447,12 @@ class CardCreator { // Minion & Mount percentages let mountsPct = '0'; if (data.Mounts !== null) { - mountsPct = Math.ceil((data.Mounts.length / this.countMount) * 100); + mountsPct = Math.ceil((data.Mounts.length / this.mountCount) * 100); } let minionsPct = '0'; if (data.Minions !== null) { - minionsPct = Math.ceil((data.Minions.length / this.countMinion) * 100); + minionsPct = Math.ceil((data.Minions.length / this.minionCount) * 100); } const mountsMeasure = ctx.measureText(`${mountsPct}%`); @@ -490,8 +467,8 @@ class CardCreator { ctx.fillText(strings.mounts, 480 + mountsMeasure.width + 5, textMountMinionY); ctx.fillText(strings.minions, 685 + minionsMeasure.width + 5, textMountMinionY); - ctx.drawImage(this.imgMount, 620, iconMountMinionY, 32, 32); - ctx.drawImage(this.imgMinion, 834, iconMountMinionY, 19, 32); + ctx.drawImage(this.images.mount, 620, iconMountMinionY, 32, 32); + ctx.drawImage(this.images.minion, 834, iconMountMinionY, 19, 32); ctx.fillStyle = white; @@ -501,48 +478,48 @@ class CardCreator { ctx.textAlign = 'center'; let cJobsRowTextX = jobsRowTextStartX; - ctx.drawImage(this.imgAlchemist, 480, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.alchemist, 480, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[24].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgArmorer, 510, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.armorer, 510, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[20].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgBlacksmith, 540, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.blacksmith, 540, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[19].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgCarpenter, 570, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.carpenter, 570, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[18].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgCulinarian, 600, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.culinarian, 600, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[25].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgGoldsmith, 630, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.goldsmith, 630, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[21].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgLeatherworker, 660, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.leatherworker, 660, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[22].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgWeaver, 690, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.weaver, 690, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[23].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSpacer; // Gathering - ctx.drawImage(this.imgBotanist, 750, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.botanist, 750, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[27].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgFisher, 780, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.fisher, 780, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[28].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgMiner, 810, jobsRowIcon3Y, 30, 30); + ctx.drawImage(this.cjIcons.miner, 810, jobsRowIcon3Y, 30, 30); ctx.fillText(data.Character.ClassJobs[26].Level, cJobsRowTextX, jobsRowText3Y); cJobsRowTextX += jobsRowTextSize; @@ -550,39 +527,39 @@ class CardCreator { cJobsRowTextX = jobsRowTextStartX; if (data.Character.ClassJobs[0].UnlockedState.ID == 19) { - ctx.drawImage(this.imgPaladin, 480, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.paladin, 480, jobsRowIcon1Y, 30, 30); } else { - ctx.drawImage(this.imgGladiator, 480, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.gladiator, 480, jobsRowIcon1Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[0].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; if (data.Character.ClassJobs[1].UnlockedState.ID == 21) { - ctx.drawImage(this.imgWarrior, 510, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.warrior, 510, jobsRowIcon1Y, 30, 30); } else { - ctx.drawImage(this.imgMarauder, 510, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.marauder, 510, jobsRowIcon1Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[1].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgDarkKnight, 540, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.darkknight, 540, jobsRowIcon1Y, 30, 30); ctx.fillText(data.Character.ClassJobs[2].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgGunbreaker, 570, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.gunbreaker, 570, jobsRowIcon1Y, 30, 30); ctx.fillText(data.Character.ClassJobs[3].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSpacer; // Healers if (data.Character.ClassJobs[8].UnlockedState.ID == 24) { - ctx.drawImage(this.imgWhitemage, 630, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.whitemage, 630, jobsRowIcon1Y, 30, 30); } else { - ctx.drawImage(this.imgConjurer, 630, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.conjurer, 630, jobsRowIcon1Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[8].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgScholar, 660, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.scholar, 660, jobsRowIcon1Y, 30, 30); if (data.Character.ClassJobs[9].Level >= 30) { ctx.fillText(data.Character.ClassJobs[9].Level, cJobsRowTextX, jobsRowText1Y); } else { @@ -590,25 +567,25 @@ class CardCreator { } cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgAstrologian, 690, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.astrologian, 690, jobsRowIcon1Y, 30, 30); ctx.fillText(data.Character.ClassJobs[10].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSpacer; // DPS // Ranged if (data.Character.ClassJobs[11].UnlockedState.ID == 23) { - ctx.drawImage(this.imgBard, 750, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.bard, 750, jobsRowIcon1Y, 30, 30); } else { - ctx.drawImage(this.imgArcher, 750, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.archer, 750, jobsRowIcon1Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[11].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgMachinist, 780, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.machinist, 780, jobsRowIcon1Y, 30, 30); ctx.fillText(data.Character.ClassJobs[12].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgDancer, 810, jobsRowIcon1Y, 30, 30); + ctx.drawImage(this.cjIcons.dancer, 810, jobsRowIcon1Y, 30, 30); ctx.fillText(data.Character.ClassJobs[13].Level, cJobsRowTextX, jobsRowText1Y); cJobsRowTextX += jobsRowTextSize; @@ -616,56 +593,56 @@ class CardCreator { cJobsRowTextX = jobsRowTextStartX; if (data.Character.ClassJobs[5].UnlockedState.ID == 22) { - ctx.drawImage(this.imgDragoon, 480, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.dragoon, 480, jobsRowIcon2Y, 30, 30); } else { - ctx.drawImage(this.imgLancer, 480, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.lancer, 480, jobsRowIcon2Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[5].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; if (data.Character.ClassJobs[4].UnlockedState.ID == 20) { - ctx.drawImage(this.imgMonk, 510, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.monk, 510, jobsRowIcon2Y, 30, 30); } else { - ctx.drawImage(this.imgPugilist, 510, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.pugilist, 510, jobsRowIcon2Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[4].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; if (data.Character.ClassJobs[6].UnlockedState.ID == 30) { - ctx.drawImage(this.imgNinja, 540, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.ninja, 540, jobsRowIcon2Y, 30, 30); } else { - ctx.drawImage(this.imgRogue, 540, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.rogue, 540, jobsRowIcon2Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[6].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgSamurai, 570, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.samurai, 570, jobsRowIcon2Y, 30, 30); ctx.fillText(data.Character.ClassJobs[7].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSpacer; // Caster if (data.Character.ClassJobs[14].UnlockedState.ID == 25) { - ctx.drawImage(this.imgBlackmage, 630, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.blackmage, 630, jobsRowIcon2Y, 30, 30); } else { - ctx.drawImage(this.imgThaumaturge, 630, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.thaumaturge, 630, jobsRowIcon2Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[14].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; if (data.Character.ClassJobs[15].UnlockedState.ID == 27) { - ctx.drawImage(this.imgSummoner, 660, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.summoner, 660, jobsRowIcon2Y, 30, 30); } else { - ctx.drawImage(this.imgArcanist, 660, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.arcanist, 660, jobsRowIcon2Y, 30, 30); } ctx.fillText(data.Character.ClassJobs[15].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; - ctx.drawImage(this.imgRedmage, 690, jobsRowIcon2Y, 30, 30); + ctx.drawImage(this.cjIcons.redmage, 690, jobsRowIcon2Y, 30, 30); ctx.fillText(data.Character.ClassJobs[16].Level, cJobsRowTextX, jobsRowText2Y); cJobsRowTextX += jobsRowTextSize; // Limited - ctx.drawImage(this.imgBluemage, 780, jobsRowIcon2Y, 33, 33); + ctx.drawImage(this.cjIcons.bluemage, 780, jobsRowIcon2Y, 33, 33); ctx.fillText(data.Character.ClassJobs[17].Level, 796, jobsRowText2Y); ctx.textAlign = 'left';