Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up decklist template and add latestPrinting getter to card model #137

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading