185 lines
4 KiB
JavaScript
185 lines
4 KiB
JavaScript
'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: <anything>:[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)
|
||
}
|
||
}
|