diff --git a/frontend/src/classes/Deck.js b/frontend/src/classes/Deck.js new file mode 100644 index 0000000..51143b9 --- /dev/null +++ b/frontend/src/classes/Deck.js @@ -0,0 +1,96 @@ +'use strict' + +export default class { + constructor(str) { + // select all lines containing card serial numbers + let cardLinesRE = /^.*\b\d-\d{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-\d{3})[A-Z]?\b/i + let serial = serialRE.exec(cardLine)[1] + + // 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 i = 0; i < countREs.length; i++) { + let data = countREs[i].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 = [] + Object.keys(cardCounts).forEach(serial => { + 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() + } + } + + count() { + return this.cards.reduce((total, card) => total + card.count, 0) + } + + plainObject() { + return { + name: this.name, + note: this.note, + cards: this.cards + } + } +} diff --git a/frontend/src/components/forms/DeckEditor.vue b/frontend/src/components/forms/DeckEditor.vue index 14d542d..cf8e040 100644 --- a/frontend/src/components/forms/DeckEditor.vue +++ b/frontend/src/components/forms/DeckEditor.vue @@ -49,6 +49,7 @@