'use strict' import CardsDB from '@/plugins/ffdecks' export default class { constructor(id) { this.id = id this.name = '' this.note = '' this.cards = [] } populate() { for (let card of this.cards) { card.dbentry = CardsDB[card.serial] } } from_object(obj) { if (obj) { this.name = obj.name this.note = obj.note this.cards = obj.cards } } plainObject() { let plainCards = [] for (let card of this.cards) { plainCards.push({ serial: card.serial, count: card.count }) } return { name: this.name, note: this.note, cards: plainCards } } from_deckList(str) { // select all lines containing card serial numbers let cardLinesRE = /^.*\b\d+-0*\d{1,3}[A-Z]?\b.*$/gm let cardLines = str.match(cardLinesRE) let cardCounts = {} cardLines.forEach(cardLine => { // extract serial (guaranteed to be in here!) let serialRE = /\b(\d+)-0*(\d{1,3})[A-Z]?\b/i let serial = serialRE.exec(cardLine) // force format 'x-xxx' serial = `${serial[1]}-${serial[2].padStart(3, '0')}` // strip out serial number cardLine = cardLine.replace(serialRE, '') let countREs = [ // prioritize a count with "times" symbol *, x, × /\b([0-9]+)(?:[*×]|[x]\b)/, /(?:[*×]|\b[x])([0-9]+)\b/, // next priority: count with whitespace /\s+([0-9]+)\s+/, /\s+([0-9]+)\b/, /\b([0-9]+)\s+/, // least priority: any simple number /\b([0-9]+)\b/ ] // fallback value let count = 1 for (let countRE of countREs) { let data = countRE.exec(cardLine) if (data) { count = Number(data[1]) break } } // count copies if (!cardCounts[serial]) { cardCounts[serial] = 0 } cardCounts[serial] += count }) // push card data into deck this.cards = [] for (let serial in cardCounts) { this.cards.push({ serial: serial, count: cardCounts[serial] }) } // strip out lines with serial numbers str = str.replace(cardLinesRE, '') // then strip out anything after the first empty line str = str.replace(/^[\s]*$[^]*/m, '') // select the line containing 'deck name:' // and its successor (ffdecks format) let metaRE = /^Deck Name: (.+)$[\s]*?^(.+)$/m let metaData = metaRE.exec(str) // fallback this.name = 'Unnamed Deck' this.note = '' if (!metaData) { // use lax format: :[deck name][newline][note] metaRE = /[^]*?:(.+)$[\s]*?^([^]*)/m metaData = metaRE.exec(str) } // look again, I am not an else! if (metaData) { // extract matches this.name = metaData[1].trim() this.note = metaData[2].trim() } } parts() { let retval = ['Forwards', 'Backups', 'Summons, Monsters & more'].map( item => ({ heading: item, cards: [], count: 0 }) ) for (let card of this.cards) { let target switch (card.dbentry.type) { case 'Forward': target = 0 break case 'Backup': target = 1 break default: target = 2 break } retval[target].cards.push(card) retval[target].count += card.count } for (let part of retval) { part.cards.sort( (card_l, card_r) => card_l.dbentry.cost - card_r.dbentry.cost ) } return retval } deckList() { let lines = [] // begin with deck name and note lines.push('Deck Name: ' + this.name) lines.push(this.note) lines.push('') // list each deck part for (let part of this.parts()) { lines.push(`${part.heading} (${part.count}):`) for (let card of part.cards) lines.push(`${card.count}x ${card.serial} "${card.dbentry.name}"`) lines.push('') } return lines.join('\n') } count() { return this.cards.reduce((total, card) => total + card.count, 0) } }