This repository has been archived on 2024-04-29. You can view files and clone it, but cannot push or open issues or pull requests.
node-fftcg/frontend/src/components/forms/DeckEditor.vue

208 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<v-container v-if="visible">
<v-card flat>
<v-alert :value="count !== 50" type="warning">
{{ count }} cards detected! (Decks should have exactly 50 cards)
</v-alert>
<v-alert :value="maximum > 3" type="warning">
Card with {{ maximum }} copies detected! (Cards should not have more
than 3 copies)
</v-alert>
<v-textarea
ref="textarea"
label="Edit Deck"
:value="value"
rows="35"
hint="Change card counts and/or serial numbers. Names will be updated accordingly!"
style="font-family: monospace"
@input="checked = false"
>
</v-textarea>
<v-card-actions>
<v-btn color="error" @click.native="close">
<v-icon>cancel</v-icon>
cancel
</v-btn>
<v-spacer></v-spacer>
<v-btn color="info" @click.native="check">
<v-icon>check</v-icon>
validate
</v-btn>
<v-btn color="success" @click.native="save" :disabled="!checked">
<v-icon>save</v-icon>
save
</v-btn>
</v-card-actions>
</v-card>
</v-container>
</template>
<script>
import * as Cookies from 'js-cookie'
import axios from '@/plugins/axios'
export default {
name: 'DeckEditor',
props: {
id: Number,
value: String,
visible: Boolean
},
data: () => ({
count: 50,
maximum: 0,
checked: false
}),
computed: {
session: () => Cookies.get('session'),
new_deck() {
try {
return this.parse_deck(this.$refs.textarea)
} catch (e) {
return this.parse_deck(this.value)
}
}
},
methods: {
parse_deck(deck_string) {
let retval = {
name: '',
note: '',
cards: [],
count: 0
}
// select all lines containing card serial numbers
let cardLinesRE = /^.*\b\d-\d{3}[A-Z]?\b.*$/gm
let cardLines = deck_string.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
retval.count += count
})
// push card data into deck
Object.keys(cardCounts).forEach(serial => {
retval.cards.push({
serial: serial,
count: cardCounts[serial]
})
})
// strip out lines with serial numbers
deck_string = deck_string.replace(cardLinesRE, '')
// select the line containing 'deck name:'
// and its successor (ffdecks format)
let metaRE = /^Deck Name: (.+)$[\s]*?^(.+)$/m
let metaData = metaRE.exec(deck_string)
// fallback
retval.name = 'Unnamed Deck'
retval.note = ''
if (!metaData) {
// no ffdecks format found: strip out anything after the first empty line
deck_string = deck_string.replace(/^[\s]*$[^]*/m, '')
// use lax format: <anything>:[deck name][newline][note]
metaRE = /[^]*?:(.+)$[\s]*?^([^]*)/m
metaData = metaRE.exec(deck_string)
}
// look again, I am not an else!
if (metaData) {
// extract matches
retval.name = metaData[1].trim()
retval.note = metaData[2].trim()
}
return retval
},
close() {
this.checked = false
this.$emit('close')
},
check() {
let new_deck = this.parse_deck(this.$refs.textarea.lazyValue)
// count number of cards
this.count = new_deck.count
// find most frequent card
this.maximum = 0
new_deck.cards.forEach(card => {
if (card.count > this.maximum) this.maximum = card.count
})
// deck has now been checked
this.checked = true
},
save() {
let new_deck = this.parse_deck(this.$refs.textarea.lazyValue)
axios
.post('/decks/modify', {
session: this.session,
deckID: this.id,
deckCards: new_deck
})
.then(response => {
if (response.data.success) {
this.$emit('change', new_deck)
this.close()
}
})
}
}
}
</script>