refactor to allow for sorting by property of choice

This commit is contained in:
RickyRister 2024-11-28 22:36:32 -08:00
parent 37bb1367db
commit 2c3a15208a
4 changed files with 84 additions and 25 deletions

View file

@ -31,18 +31,49 @@ CardItem *CardList::findCard(const int cardId) const
return nullptr; return nullptr;
} }
void CardList::sort(int flags) /**
* @brief sorts the list by using string comparison on properties extracted from the CardItem
* The cards are compared using each property in order.
* If two cards have the same value for a property, then the next property in the list is used.
*
* @param option the option to compare the cards by, in order of usage.
*/
void CardList::sortBy(const QList<SortOption> &option)
{ {
auto comparator = [flags](CardItem *a, CardItem *b) { // early return if we know we won't be sorting
if (flags & SortByType) { if (option.isEmpty()) {
QString t1 = a->getInfo() ? a->getInfo()->getMainCardType() : QString(); return;
QString t2 = b->getInfo() ? b->getInfo()->getMainCardType() : QString(); }
if ((t1 == t2) && (flags & SortByName))
return a->getName() < b->getName(); auto comparator = [&option](CardItem *a, CardItem *b) {
return t1 < t2; for (auto prop : option) {
} else auto extractor = getExtractorFor(prop);
return a->getName() < b->getName(); QString t1 = extractor(a);
QString t2 = extractor(b);
if (t1 != t2) {
return t1 < t2;
}
}
return false;
}; };
std::sort(begin(), end(), comparator); std::sort(begin(), end(), comparator);
} }
/**
* @brief returns the function that extracts the given property from the CardItem.
*/
std::function<QString(CardItem *)> CardList::getExtractorFor(SortOption option)
{
switch (option) {
case NoSort:
return [](CardItem *c) { return ""; };
case SortByName:
return [](CardItem *c) { return c->getName(); };
case SortByType:
return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getMainCardType() : ""; };
case SortByManaValue:
// getCmc returns the int as a string. We pad with 0's so that string comp also works on it
return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getCmc().rightJustified(4, '0') : ""; };
}
}

View file

@ -11,10 +11,12 @@ protected:
bool contentsKnown; bool contentsKnown;
public: public:
enum SortFlags enum SortOption
{ {
SortByName = 1, NoSort,
SortByType = 2 SortByName,
SortByType,
SortByManaValue
}; };
CardList(bool _contentsKnown); CardList(bool _contentsKnown);
CardItem *findCard(const int cardId) const; CardItem *findCard(const int cardId) const;
@ -22,7 +24,10 @@ public:
{ {
return contentsKnown; return contentsKnown;
} }
void sort(int flags = SortByName);
void sortBy(const QList<SortOption> &options);
static std::function<QString(CardItem *)> getExtractorFor(SortOption option);
}; };
#endif #endif

View file

@ -113,11 +113,28 @@ void ZoneViewZone::reorganizeCards()
cards[i]->setId(i); cards[i]->setId(i);
CardList cardsToDisplay(cards); CardList cardsToDisplay(cards);
if (sortByName || sortByType)
cardsToDisplay.sort((sortByName ? CardList::SortByName : 0) | (sortByType ? CardList::SortByType : 0));
auto gridSize = positionCardsForDisplay(cardsToDisplay, pileView && sortByType); // sort cards
QList<CardList::SortOption> sortOptions;
if (sortByType) {
sortOptions << CardList::SortByType;
}
if (sortByName) {
sortOptions << CardList::SortByName;
}
cardsToDisplay.sortBy(sortOptions);
// position cards
GridSize gridSize;
if (pileView && sortByType) {
gridSize = positionCardsForDisplay(cardsToDisplay, CardList::SortByType);
} else {
gridSize = positionCardsForDisplay(cardsToDisplay);
}
// determine bounding rect
qreal aleft = 0; qreal aleft = 0;
qreal atop = 0; qreal atop = 0;
qreal awidth = gridSize.cols * CARD_WIDTH + (CARD_WIDTH / 2) + HORIZONTAL_PADDING; qreal awidth = gridSize.cols * CARD_WIDTH + (CARD_WIDTH / 2) + HORIZONTAL_PADDING;
@ -132,24 +149,30 @@ void ZoneViewZone::reorganizeCards()
* @brief Sets the position of each card to the proper position for the view * @brief Sets the position of each card to the proper position for the view
* *
* @param cards The cards to reposition. Will modify the cards in the list. * @param cards The cards to reposition. Will modify the cards in the list.
* @param groupByType Whether to make piles by card type. If true, then expects `cards` to be sorted by type. * @param pileOption Property used to group cards for the piles. Expects `cards` to be sorted by that property. Pass in
* NoSort to not make piles.
* *
* @returns The number of rows and columns to display * @returns The number of rows and columns to display
*/ */
ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, bool groupByType) ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, CardList::SortOption pileOption)
{ {
int cardCount = cards.size(); int cardCount = cards.size();
if (groupByType) {
if (pileOption != CardList::NoSort) {
int row = 0; int row = 0;
int col = 0; int col = 0;
int longestRow = 0; int longestRow = 0;
QString lastCardType;
QString lastColumnProp;
const auto extractor = CardList::getExtractorFor(pileOption);
for (int i = 0; i < cardCount; i++) { for (int i = 0; i < cardCount; i++) {
CardItem *c = cards.at(i); CardItem *c = cards.at(i);
QString cardType = c->getInfo() ? c->getInfo()->getMainCardType() : ""; QString columnProp = extractor(c);
if (i) { // if not the first card if (i) { // if not the first card
if (cardType == lastCardType) if (columnProp == lastColumnProp)
row++; // add below current card row++; // add below current card
else { // if no match then move card to next column else { // if no match then move card to next column
col++; col++;
@ -157,7 +180,7 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, bo
} }
} }
lastCardType = cardType; lastColumnProp = columnProp;
qreal x = col * CARD_WIDTH; qreal x = col * CARD_WIDTH;
qreal y = row * CARD_HEIGHT / 3; qreal y = row * CARD_HEIGHT / 3;
c->setPos(HORIZONTAL_PADDING + x, VERTICAL_PADDING + y); c->setPos(HORIZONTAL_PADDING + x, VERTICAL_PADDING + y);

View file

@ -41,7 +41,7 @@ private:
int cols; int cols;
}; };
GridSize positionCardsForDisplay(CardList &cards, bool groupByType = false); GridSize positionCardsForDisplay(CardList &cards, CardList::SortOption pileOption = CardList::NoSort);
public: public:
ZoneViewZone(Player *_p, ZoneViewZone(Player *_p,