97 lines
2.3 KiB
JavaScript
97 lines
2.3 KiB
JavaScript
|
|
'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: <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()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
count() {
|
|||
|
|
return this.cards.reduce((total, card) => total + card.count, 0)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
plainObject() {
|
|||
|
|
return {
|
|||
|
|
name: this.name,
|
|||
|
|
note: this.note,
|
|||
|
|
cards: this.cards
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|