Decklist Aggregator
by Cody Bennett
HTML
<script src="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap"></script>
<main>
<header>
<h1>Decklist Aggregator</h1>
</header>
<section>
<h2>Select decklist files</h2>
<input type="file" id="decks" name="decks" multiple="multiple" />
</section>
<section>
<h2>Generated deck</h2>
<textarea id="aggregated-deck" rows="10"></textarea>
</section>
<section>
<p>
<button type="button" id="download">Download Deck</button>
</p>
</section>
</main>
CSS
*,
*::before,
*::after {
box-sizing: inherit;
color: inherit;
font-family: inherit;
margin: 0;
padding: 0;
}
body {
color: rgb(17 17 17 / 0.8);
font-family: 'Montserrat', sans-serif;
}
h1, h2, button {
color: #111;
font-weight: 700;
}
h1 {
text-align: center;
}
h2 {
font-size: 1em;
}
button {
background: none;
border: none;
cursor: pointer;
outline: none;
text-decoration: underline;
}
textarea {
width: 100%;
}
p {
text-align: justify;
}
a {
color: #4457c9;
text-decoration: none;
}
main {
display: grid;
grid-gap: 16px;
margin: 16px auto;
max-width: 696px;
}
@media only screen and (max-width: 696px) {
main {
max-width: 90%;
}
}
JavaScript
function parseFile(file) {
const cardsWithTotals = file.split('\n');
const main = {};
const sideboard = {};
let isSideboard = false;
for (let i = 0; i < cardsWithTotals.length; i++) {
const cardWithTotal = cardsWithTotals[i].trim();
if (!cardWithTotal || cardWithTotal === 'Sideboard') {
isSideboard = true;
continue;
}
const card = cardWithTotal.match(/(\d+)\s+(.*)/);
if (!card) return false;
const total = card[1];
const cardName = card[2];
if (isSideboard) {
sideboard[cardName] = parseInt(total);
} else {
main[cardName] = parseInt(total);
}
}
return {
main,
sideboard
};
}
function numberedCards(cards) {
const numbered = [];
for (const card in cards) {
for (let i = 1; i <= cards[card]; i++) {
numbered.push(`${i} ${card}`);
}
}
return numbered;
}
function sumCards(allCards, deck) {
for (let i = 0; i < deck.length; i++) {
const card = deck[i];
if (!allCards[card]) allCards[card] = 0;
allCards[card]++;
}
return allCards;
}
function sortCards(cards) {
const list = [];
for (const card in cards) {
const auxCard = card.split(/(\d+) (.*)/);
list.push({
total: cards[card],
name: auxCard[2],
number: auxCard[1],
});
}
return list.sort((a, b) => b.total - a.total);
}
function aggregateDeck(cards, limit) {
let total = 0,
card;
const deck = {};
for (let i = 0; i < cards.length; i++) {
card = cards[i].name;
if (!deck[card]) deck[card] = 0;
deck[card]++;
total++;
if (total >= limit) break;
}
const deckAsArray = [];
for (card in deck) {
deckAsArray.push({
total: deck[card],
card
});
}
return deckAsArray;
}
function printDeck(main, sideboard) {
return `${printCards(main)}\n${printCards(sideboard)}`
}
function printCards(cards) {
let output = '';
for (let i = 0; i < cards.length; i++) {
output += cards[i].total + ' ' +...