Skip to content

Commit

Permalink
Merge pull request #137 from NetrunnerDB/decklist-loading
Browse files Browse the repository at this point in the history
Clean up decklist template and add latestPrinting getter to card model
  • Loading branch information
locks authored Nov 5, 2024
2 parents af1aaf7 + deb0784 commit 67240de
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 177 deletions.
87 changes: 83 additions & 4 deletions app/components/deck/writeup.gjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import Component from '@glimmer/component';
import { get } from '@ember/helper';
import { and } from 'netrunnerdb/utils/template-operators';
import gt from 'ember-truth-helpers/helpers/gt';
import notEq from 'ember-truth-helpers/helpers/not-eq';
import Component from '@glimmer/component';
import Icon from '../icon';
import CardLinkTo from '../card/link-to';
import InfluencePips from '../card/influence-pips';

export default class Writeup extends Component {
// Sorts a decklist's cards into an array of arrays of objects:
// [[{
// name
// cardTypeId
// cards
// count
// }]]
// Each top level array represents a column on the decklist view
// Each nested array represents the types (or subtypes) of cards within each subtype
formatCards(cards, cardTypes, decklist) {
let row1CardTypes = cardTypes.filter((type) =>
[
Expand Down Expand Up @@ -87,9 +97,75 @@ export default class Writeup extends Component {
return [row1Cards, row2Cards];
}

// Counts the number of individual cards in a decklist are from a list of distinct cards
countCards(cards, decklist) {
let count = 0;
cards.forEach((card) => {
count += decklist.cardSlots[card.id];
});
return count;
}

// Collect the ice from a list of cards and separate them by subtype
formatIce(cards) {
cards = cards.filter((card) => card.cardTypeId == 'ice');

let barriers = [];
let codeGates = [];
let sentries = [];
let multis = [];
let misc = [];

cards.forEach((card) => {
let isBarrier = card.cardSubtypeIds.includes('barrier');
let isCodeGate = card.cardSubtypeIds.includes('code_gate');
let isSentry = card.cardSubtypeIds.includes('sentry');

if (
(isBarrier && isCodeGate) ||
(isBarrier && isSentry) ||
(isCodeGate && isSentry)
) {
multis.push(card);
} else if (isBarrier) {
barriers.push(card);
} else if (isCodeGate) {
codeGates.push(card);
} else if (isSentry) {
sentries.push(card);
} else {
misc.push(card);
}
});

return { barriers, codeGates, sentries, multis, misc };
}

// Collect the programs from a list of cards and separate them by icebreaker vs non-icebreaker
formatPrograms(cards) {
cards = cards.filter((card) => card.cardTypeId == 'program');

let icebreakers = cards.filter((card) =>
card.cardSubtypeIds.includes('icebreaker'),
);
let misc = cards.filter(
(card) => !card.cardSubtypeIds.includes('icebreaker'),
);

return { icebreakers, misc };
}

get cardsByCategory() {
return this.formatCards(
this.args.decklist.cards,
this.args.cardTypes,
this.args.decklist,
);
}

<template>
<div class='row mt-4 ms-4'>
{{#each @cards as |col|}}
{{#each this.cardsByCategory as |col|}}
<div class='col-6'>
{{#each col as |category|}}
{{#if category.cards}}
Expand All @@ -101,8 +177,11 @@ export default class Writeup extends Component {
<ul class='list-unstyled secondary mt-2'>
{{#each category.cards as |card|}}
<li>
{{this.quantity card.id}}x
<CardLinkTo @printing={{card.printing}}>
{{get @decklist.cardSlots card.id}}&times;
<CardLinkTo
@printing={{card.latestPrinting}}
@card={{card}}
>
{{card.title}}
{{#if
(and
Expand Down
8 changes: 8 additions & 0 deletions app/models/card.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,12 @@ export default class CardModel extends Model {
@hasMany('card-subtype', { async: true, inverse: 'cards' }) cardSubtypes;
@hasMany('printing', { async: false, inverse: 'card' }) printings;
@hasMany('ruling', { async: true, inverse: 'card' }) rulings;

get latestPrinting() {
let print = this.printings.find(
(print) => print.id == this.latestPrintingId,
);

return print ?? this.printings[0];
}
}
6 changes: 2 additions & 4 deletions app/models/decklist.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ export default class CardCycleModel extends Model {
@attr influenceSpent;

get identityCard() {
return this.store.findRecord('card', this.identityCardId, {
include: 'printings',
});
return this.cards.find((card) => card.id === this.identityCardId);
}

@hasMany('card', { async: true, inverse: null }) cards;
@hasMany('card', { async: false, inverse: null }) cards;
}
167 changes: 2 additions & 165 deletions app/routes/decklist.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class DecklistRoute extends Route {
let cardTypes = await this.store.findAll('cardType');

let decklist = await this.store.findRecord('decklist', params.id, {
include: 'cards',
include: 'cards,cards.printings',
});

let cards = decklist.cards.map((card) => {
Expand Down Expand Up @@ -43,169 +43,6 @@ export default class DecklistRoute extends Route {
),
);

return hash({
decklist: decklist,
cardTypes: cardTypes,
cardsByCategory: this.formatCards(cards, cardTypes, decklist),
cardsByType: cardsByType,
countsByType: countsByType,
printings: printings,
});
}

// Counts the number of individual cards in a decklist are from a list of distinct cards
countCards(cards, decklist) {
let count = 0;
cards.forEach((card) => {
count += decklist.cardSlots[card.id];
});
return count;
}

// Sorts a decklist's cards into an array of arrays of objects:
// [[{
// name
// cardTypeId
// cards
// count
// }]]
// Each top level array represents a column on the decklist view
// Each nested array represents the types (or subtypes) of cards within each subtype
formatCards(cards, cardTypes, decklist) {
let row1CardTypes = cardTypes.filter((type) =>
[
'agenda',
'asset',
'operation',
'upgrade',
'event',
'hardware',
'resource',
].includes(type.id),
);
let row2CardTypes = cardTypes.filter((type) =>
['ice', 'program'].includes(type.id),
);

let row1Cards = row1CardTypes.map((type) => {
let cs = cards.filter((card) => card.cardTypeId == type.id);
return {
name: type.name,
cardTypeId: type.id,
cards: cs,
count: this.countCards(cs, decklist),
};
});

let row2Cards = [];
row2CardTypes.forEach((type) => {
if (type.id == 'ice') {
let data = this.formatIce(cards);
row2Cards.push({
name: 'Barrier',
cardTypeId: 'ice',
cards: data.barriers,
count: this.countCards(data.barriers, decklist),
});
row2Cards.push({
name: 'Code Gate',
cardTypeId: 'ice',
cards: data.codeGates,
count: this.countCards(data.codeGates, decklist),
});
row2Cards.push({
name: 'Sentry',
cardTypeId: 'ice',
cards: data.sentries,
count: this.countCards(data.sentries, decklist),
});
row2Cards.push({
name: 'Multi',
cardTypeId: 'ice',
cards: data.multis,
count: this.countCards(data.multis, decklist),
});
row2Cards.push({
name: 'Other',
cardTypeId: 'ice',
cards: data.misc,
count: this.countCards(data.misc, decklist),
});
} else {
let data = this.formatPrograms(cards);
row2Cards.push({
name: 'Icebreaker',
cardTypeId: 'program',
cards: data.icebreakers,
count: this.countCards(data.icebreakers, decklist),
});
row2Cards.push({
name: 'Program',
cardTypeId: 'program',
cards: data.misc,
count: this.countCards(data.misc, decklist),
});
}
});

return [row1Cards, row2Cards];
}

// Collect the ice from a list of cards and separate them by subtype
formatIce(cards) {
cards = cards.filter((card) => card.cardTypeId == 'ice');

let barriers = [];
let codeGates = [];
let sentries = [];
let multis = [];
let misc = [];

cards.forEach((card) => {
let isBarrier = card.cardSubtypeIds.includes('barrier');
let isCodeGate = card.cardSubtypeIds.includes('code_gate');
let isSentry = card.cardSubtypeIds.includes('sentry');

if (
(isBarrier && isCodeGate) ||
(isBarrier && isSentry) ||
(isCodeGate && isSentry)
) {
multis.push(card);
} else if (isBarrier) {
barriers.push(card);
} else if (isCodeGate) {
codeGates.push(card);
} else if (isSentry) {
sentries.push(card);
} else {
misc.push(card);
}
});

return {
barriers: barriers,
codeGates: codeGates,
sentries: sentries,
multis: multis,
misc: misc,
};
}

// Collect the programs from a list of cards and separate them by icebreaker vs non-icebreaker
formatPrograms(cards) {
cards = cards.filter((card) => card.cardTypeId == 'program');

let icebreakers = cards.filter((card) =>
card.cardSubtypeIds.includes('icebreaker'),
);
let misc = cards.filter(
(card) => !card.cardSubtypeIds.includes('icebreaker'),
);

return {
icebreakers: icebreakers,
misc: misc,
};
return hash({ decklist, cardTypes, cardsByType, countsByType, printings });
}
}
3 changes: 0 additions & 3 deletions app/routes/faction.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ export default class FactionRoute extends Route {
})
.then((ids) => {
ids.forEach((id) => {
id.latestPrinting = id.printings.find(
(p) => p.id == id.latestPrintingId,
);
id.decklists = this.store.query('decklist', {
filter: { identity_card_id: id.id },
sort: '-created_at',
Expand Down
2 changes: 1 addition & 1 deletion app/templates/decklist.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
{{#if (eq this.displayType "writeup")}}
<Deck::Writeup
@decklist={{@model.decklist}}
@cards={{@model.cardsByCategory}}
@cardTypes={{@model.cardTypes}}
/>
{{/if}}
</div>
Expand Down

0 comments on commit 67240de

Please sign in to comment.