From 2c3a15208a016c9b8aa5a79e90185fb634ac712b Mon Sep 17 00:00:00 2001 From: RickyRister Date: Thu, 28 Nov 2024 22:36:32 -0800 Subject: [PATCH] refactor to allow for sorting by property of choice --- cockatrice/src/game/cards/card_list.cpp | 51 ++++++++++++++++++++----- cockatrice/src/game/cards/card_list.h | 13 +++++-- cockatrice/src/game/zones/view_zone.cpp | 43 ++++++++++++++++----- cockatrice/src/game/zones/view_zone.h | 2 +- 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/cockatrice/src/game/cards/card_list.cpp b/cockatrice/src/game/cards/card_list.cpp index f35a0d842..385643fb3 100644 --- a/cockatrice/src/game/cards/card_list.cpp +++ b/cockatrice/src/game/cards/card_list.cpp @@ -31,18 +31,49 @@ CardItem *CardList::findCard(const int cardId) const 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 &option) { - auto comparator = [flags](CardItem *a, CardItem *b) { - if (flags & SortByType) { - QString t1 = a->getInfo() ? a->getInfo()->getMainCardType() : QString(); - QString t2 = b->getInfo() ? b->getInfo()->getMainCardType() : QString(); - if ((t1 == t2) && (flags & SortByName)) - return a->getName() < b->getName(); - return t1 < t2; - } else - return a->getName() < b->getName(); + // early return if we know we won't be sorting + if (option.isEmpty()) { + return; + } + + auto comparator = [&option](CardItem *a, CardItem *b) { + for (auto prop : option) { + auto extractor = getExtractorFor(prop); + QString t1 = extractor(a); + QString t2 = extractor(b); + if (t1 != t2) { + return t1 < t2; + } + } + return false; }; std::sort(begin(), end(), comparator); } + +/** + * @brief returns the function that extracts the given property from the CardItem. + */ +std::function 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') : ""; }; + } +} \ No newline at end of file diff --git a/cockatrice/src/game/cards/card_list.h b/cockatrice/src/game/cards/card_list.h index d48e4c3d2..cbfb3ecff 100644 --- a/cockatrice/src/game/cards/card_list.h +++ b/cockatrice/src/game/cards/card_list.h @@ -11,10 +11,12 @@ protected: bool contentsKnown; public: - enum SortFlags + enum SortOption { - SortByName = 1, - SortByType = 2 + NoSort, + SortByName, + SortByType, + SortByManaValue }; CardList(bool _contentsKnown); CardItem *findCard(const int cardId) const; @@ -22,7 +24,10 @@ public: { return contentsKnown; } - void sort(int flags = SortByName); + + void sortBy(const QList &options); + + static std::function getExtractorFor(SortOption option); }; #endif diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game/zones/view_zone.cpp index 6f238527f..6ee7b2084 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game/zones/view_zone.cpp @@ -113,11 +113,28 @@ void ZoneViewZone::reorganizeCards() cards[i]->setId(i); 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 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 atop = 0; 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 * * @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 */ -ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, bool groupByType) +ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, CardList::SortOption pileOption) { int cardCount = cards.size(); - if (groupByType) { + + if (pileOption != CardList::NoSort) { int row = 0; int col = 0; int longestRow = 0; - QString lastCardType; + + QString lastColumnProp; + + const auto extractor = CardList::getExtractorFor(pileOption); + for (int i = 0; i < cardCount; 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 (cardType == lastCardType) + if (columnProp == lastColumnProp) row++; // add below current card else { // if no match then move card to next column col++; @@ -157,7 +180,7 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, bo } } - lastCardType = cardType; + lastColumnProp = columnProp; qreal x = col * CARD_WIDTH; qreal y = row * CARD_HEIGHT / 3; c->setPos(HORIZONTAL_PADDING + x, VERTICAL_PADDING + y); diff --git a/cockatrice/src/game/zones/view_zone.h b/cockatrice/src/game/zones/view_zone.h index 9179c477b..2e28fbb72 100644 --- a/cockatrice/src/game/zones/view_zone.h +++ b/cockatrice/src/game/zones/view_zone.h @@ -41,7 +41,7 @@ private: int cols; }; - GridSize positionCardsForDisplay(CardList &cards, bool groupByType = false); + GridSize positionCardsForDisplay(CardList &cards, CardList::SortOption pileOption = CardList::NoSort); public: ZoneViewZone(Player *_p,