From 0f32dada153a561de1861adb3e1e45772dfef80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Wed, 15 Jan 2025 22:25:26 +0100 Subject: [PATCH] EDHREC in client mockup. --- .../edhrec_commander_api_response.cpp | 44 +++++++ .../edhrec_commander_api_response.h | 28 +++++ ...commander_api_response_archidekt_links.cpp | 43 +++++++ ...c_commander_api_response_archidekt_links.h | 32 +++++ ...r_api_response_average_deck_statistics.cpp | 14 +++ ...der_api_response_average_deck_statistics.h | 22 ++++ ..._commander_api_response_card_container.cpp | 48 ++++++++ ...ec_commander_api_response_card_container.h | 41 +++++++ ...ec_commander_api_response_card_details.cpp | 31 +++++ ...hrec_commander_api_response_card_details.h | 29 +++++ ...dhrec_commander_api_response_card_list.cpp | 32 +++++ .../edhrec_commander_api_response_card_list.h | 26 ++++ ...rec_commander_api_response_card_prices.cpp | 29 +++++ ...dhrec_commander_api_response_card_prices.h | 38 ++++++ ...mmander_api_response_commander_details.cpp | 86 ++++++++++++++ ...commander_api_response_commander_details.h | 85 +++++++++++++ ...i_response_card_details_display_widget.cpp | 15 +++ ...api_response_card_details_display_widget.h | 22 ++++ ..._api_response_card_list_display_widget.cpp | 27 +++++ ...er_api_response_card_list_display_widget.h | 22 ++++ ..._commander_api_response_display_widget.cpp | 25 ++++ ...ec_commander_api_response_display_widget.h | 20 ++++ .../src/client/tabs/api/edhrec/tab_edhrec.cpp | 112 ++++++++++++++++++ .../src/client/tabs/api/edhrec/tab_edhrec.h | 38 ++++++ .../src/client/tabs/tab_deck_editor.cpp | 4 +- cockatrice/src/client/tabs/tab_supervisor.cpp | 12 ++ cockatrice/src/client/tabs/tab_supervisor.h | 2 + 27 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.h create mode 100644 cockatrice/src/client/tabs/api/edhrec/tab_edhrec.cpp create mode 100644 cockatrice/src/client/tabs/api/edhrec/tab_edhrec.h diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp new file mode 100644 index 000000000..10895ea42 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp @@ -0,0 +1,44 @@ +#include "edhrec_commander_api_response.h" + +#include + +void EdhrecCommanderApiResponse::fromJson(const QJsonObject &json) +{ + // Parse the collapsed DeckStatistics + deckStats.fromJson(json); + + // Parse Archidekt section + QJsonArray archidektJson = json.value("archidekt").toArray(); + archidekt.fromJson(archidektJson); + + // Parse other fields + similar = json.value("similar").toObject(); + header = json.value("header").toString(); + panels = json.value("panels").toObject(); + description = json.value("description").toString(); + QJsonObject containerJson = json.value("container").toObject(); + container.fromJson(containerJson); +} + +void EdhrecCommanderApiResponse::debugPrint() const +{ + qDebug() << "Deck Statistics:"; + qDebug() << " Creature:" << deckStats.creature; + qDebug() << " Instant:" << deckStats.instant; + qDebug() << " Sorcery:" << deckStats.sorcery; + qDebug() << " Artifact:" << deckStats.artifact; + qDebug() << " Enchantment:" << deckStats.enchantment; + qDebug() << " Battle:" << deckStats.battle; + qDebug() << " Planeswalker:" << deckStats.planeswalker; + qDebug() << " Land:" << deckStats.land; + qDebug() << " Basic:" << deckStats.basic; + qDebug() << " Nonbasic:" << deckStats.nonbasic; + + archidekt.debugPrint(); + + qDebug() << "Similar:" << similar; + qDebug() << "Header:" << header; + qDebug() << "Panels:" << panels; + qDebug() << "Description:" << description; + container.debugPrint(); +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.h new file mode 100644 index 000000000..91cf3afbc --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.h @@ -0,0 +1,28 @@ +#ifndef DECKDATA_H +#define DECKDATA_H + +#include "edhrec_commander_api_response_archidekt_links.h" +#include "edhrec_commander_api_response_average_deck_statistics.h" +#include "edhrec_commander_api_response_card_container.h" + +#include +#include +#include + +// Represents the main structure of the JSON +class EdhrecCommanderApiResponse +{ +public: + EdhrecCommanderApiResponseAverageDeckStatistics deckStats; + EdhrecCommanderApiResponseArchidektLinks archidekt; + QJsonObject similar; + QString header; + QJsonObject panels; + QString description; + EdhrecCommanderApiResponseCardContainer container; + + void fromJson(const QJsonObject &json); + void debugPrint() const; +}; + +#endif // DECKDATA_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp new file mode 100644 index 000000000..aac540f90 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp @@ -0,0 +1,43 @@ +#include "edhrec_commander_api_response_archidekt_links.h" + +#include +#include +#include +#include + +void EdhrecCommanderApiResponseArchidektLink::fromJson(const QJsonObject &json) +{ + c = json.value("c").toString(); + f = json.value("f").toInt(0); + q = json.value("q").toInt(0); + u = json.value("u").toString(); +} + +void EdhrecCommanderApiResponseArchidektLink::debugPrint() const +{ + qDebug() << " C:" << c; + qDebug() << " F:" << f; + qDebug() << " Q:" << q; + qDebug() << " U:" << u; +} + +void EdhrecCommanderApiResponseArchidektLinks::fromJson(const QJsonArray &json) +{ + entries.clear(); + for (const QJsonValue &value : json) { + if (value.isObject()) { + QJsonObject entryJson = value.toObject(); + EdhrecCommanderApiResponseArchidektLink entry; + entry.fromJson(entryJson); + entries.append(entry); + } + } +} + +void EdhrecCommanderApiResponseArchidektLinks::debugPrint() const +{ + qDebug() << "Archidekt Entries:"; + for (const auto &entry : entries) { + entry.debugPrint(); + } +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.h new file mode 100644 index 000000000..537dbb1fc --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.h @@ -0,0 +1,32 @@ +#ifndef ARCHIDEKTENTRY_H +#define ARCHIDEKTENTRY_H + +#include +#include +#include +#include + +// Represents a single Archidekt entry +class EdhrecCommanderApiResponseArchidektLink +{ +public: + QString c; + int f = 0; + int q = 0; + QString u; + + void fromJson(const QJsonObject &json); + void debugPrint() const; +}; + +// Represents the Archidekt section as a list of entries +class EdhrecCommanderApiResponseArchidektLinks +{ +public: + QVector entries; + + void fromJson(const QJsonArray &json); + void debugPrint() const; +}; + +#endif // ARCHIDEKTENTRY_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp new file mode 100644 index 000000000..1685a6b03 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp @@ -0,0 +1,14 @@ +#include "edhrec_commander_api_response_average_deck_statistics.h" + +void EdhrecCommanderApiResponseAverageDeckStatistics::fromJson(const QJsonObject &json) { + creature = json.value("creature").toInt(0); + instant = json.value("instant").toInt(0); + sorcery = json.value("sorcery").toInt(0); + artifact = json.value("artifact").toInt(0); + enchantment = json.value("enchantment").toInt(0); + battle = json.value("battle").toInt(0); + planeswalker = json.value("planeswalker").toInt(0); + land = json.value("land").toInt(0); + basic = json.value("basic").toInt(0); + nonbasic = json.value("nonbasic").toInt(0); +} \ No newline at end of file diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.h new file mode 100644 index 000000000..5c95a8547 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.h @@ -0,0 +1,22 @@ +#ifndef AVERAGE_DECK_STATISTICS_H +#define AVERAGE_DECK_STATISTICS_H + +#include + +// Represents the typical deck statistics (collapsed section) +struct EdhrecCommanderApiResponseAverageDeckStatistics { + int creature = 0; + int instant = 0; + int sorcery = 0; + int artifact = 0; + int enchantment = 0; + int battle = 0; + int planeswalker = 0; + int land = 0; + int basic = 0; + int nonbasic = 0; + + void fromJson(const QJsonObject &json); + +}; +#endif //AVERAGE_DECK_STATISTICS_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp new file mode 100644 index 000000000..8bf65f4ab --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp @@ -0,0 +1,48 @@ +#include "edhrec_commander_api_response_card_container.h" + +#include +#include + +void EdhrecCommanderApiResponseCardContainer::fromJson(const QJsonObject &json) +{ + // Parse breadcrumb + QJsonArray breadcrumbArray = json.value("breadcrumb").toArray(); + for (const QJsonValue &breadcrumbValue : breadcrumbArray) { + breadcrumb.push_back(breadcrumbValue.toObject()); + } + + description = json.value("description").toString(); + QJsonObject jsonDict = json.value("json_dict").toObject(); + card.fromJson(jsonDict.value("card").toObject()); + QJsonArray cardlistsArray = jsonDict.value("cardlists").toArray(); + + for (const QJsonValue &cardlistValue : cardlistsArray) { + QJsonObject cardlistObj = cardlistValue.toObject(); + QJsonArray cardviewsArray = cardlistObj.value("cardviews").toArray(); + EdhrecCommanderApiResponseCardList cardView; + cardView.fromJson(cardlistValue.toObject()); + cardlists.push_back(cardView); + } + + keywords = json.value("keywords").toString(); + title = json.value("title").toString(); +} + +void EdhrecCommanderApiResponseCardContainer::debugPrint() const +{ + qDebug() << "Breadcrumb:"; + for (const auto &breadcrumbEntry : breadcrumb) { + qDebug() << breadcrumbEntry; + } + + qDebug() << "Description:" << description; + card.debugPrint(); + + qDebug() << "Cardlists:"; + for (const auto &cardlist : cardlists) { + cardlist.debugPrint(); + } + + qDebug() << "Keywords:" << keywords; + qDebug() << "Title:" << title; +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.h new file mode 100644 index 000000000..3d84107c0 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.h @@ -0,0 +1,41 @@ +#ifndef CONTAINER_ENTRY_H +#define CONTAINER_ENTRY_H + +#include "edhrec_commander_api_response_card_list.h" +#include "edhrec_commander_api_response_commander_details.h" + +#include +#include +#include +#include +#include + +class EdhrecCommanderApiResponseCardContainer { +public: + // Constructor + EdhrecCommanderApiResponseCardContainer() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + // Getter methods for deck container + const QString& getDescription() const { return description; } + const QVector& getBreadcrumb() const { return breadcrumb; } + const EdhrecCommanderApiResponseCommanderDetails& getCommanderDetails() const { return card; } + const QVector& getCardlists() const { return cardlists; } + const QString& getKeywords() const { return keywords; } + const QString& getTitle() const { return title; } + +private: + QString description; + QVector breadcrumb; + EdhrecCommanderApiResponseCommanderDetails card; + QVector cardlists; + QString keywords; + QString title; +}; + +#endif // CONTAINER_ENTRY_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp new file mode 100644 index 000000000..4313f5fe3 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp @@ -0,0 +1,31 @@ +#include "edhrec_commander_api_response_card_details.h" +#include + +EdhrecCommanderApiResponseCardDetails::EdhrecCommanderApiResponseCardDetails() + : synergy(0.0), inclusion(0), numDecks(0), potentialDecks(0) {} + +void EdhrecCommanderApiResponseCardDetails::fromJson(const QJsonObject &json) { + // Parse the fields from the JSON object + name = json.value("name").toString(); + sanitized = json.value("sanitized").toString(); + sanitizedWo = json.value("sanitized_wo").toString(); + url = json.value("url").toString(); + synergy = json.value("synergy").toDouble(0.0); + inclusion = json.value("inclusion").toInt(0); + label = json.value("label").toString(); + numDecks = json.value("num_decks").toInt(0); + potentialDecks = json.value("potential_decks").toInt(0); +} + +void EdhrecCommanderApiResponseCardDetails::debugPrint() const { + // Print out all the fields for debugging + qDebug() << "Name:" << name; + qDebug() << "Sanitized:" << sanitized; + qDebug() << "Sanitized Wo:" << sanitizedWo; + qDebug() << "URL:" << url; + qDebug() << "Synergy:" << synergy; + qDebug() << "Inclusion:" << inclusion; + qDebug() << "Label:" << label; + qDebug() << "Num Decks:" << numDecks; + qDebug() << "Potential Decks:" << potentialDecks; +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.h new file mode 100644 index 000000000..82d85824b --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.h @@ -0,0 +1,29 @@ +#ifndef CARD_VIEW_H +#define CARD_VIEW_H + +#include +#include + +class EdhrecCommanderApiResponseCardDetails +{ +public: + QString name; + QString sanitized; + QString sanitizedWo; + QString url; + double synergy; + int inclusion; + QString label; + int numDecks; + int potentialDecks; + + EdhrecCommanderApiResponseCardDetails(); + + // Method to populate the object from a JSON object + void fromJson(const QJsonObject &json); + + // Debug method to print out the data + void debugPrint() const; +}; + +#endif // CARD_VIEW_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp new file mode 100644 index 000000000..97c13dd5c --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp @@ -0,0 +1,32 @@ +#include "edhrec_commander_api_response_card_list.h" +#include + +EdhrecCommanderApiResponseCardList::EdhrecCommanderApiResponseCardList() +{ +} + +void EdhrecCommanderApiResponseCardList::fromJson(const QJsonObject &json) +{ + // Parse the header from the JSON object + header = json.value("header").toString(); + + // Parse the cardviews array and populate cardViews + QJsonArray cardviewsArray = json.value("cardviews").toArray(); + for (const QJsonValue &value : cardviewsArray) { + QJsonObject cardviewObj = value.toObject(); + EdhrecCommanderApiResponseCardDetails cardView; + cardView.fromJson(cardviewObj); + cardViews.append(cardView); + } +} + +void EdhrecCommanderApiResponseCardList::debugPrint() const +{ + // Print out the header + qDebug() << "Header:" << header; + + // Print out all the CardView objects + for (const EdhrecCommanderApiResponseCardDetails &cardView : cardViews) { + cardView.debugPrint(); + } +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.h new file mode 100644 index 000000000..ef91586bc --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.h @@ -0,0 +1,26 @@ +#ifndef CARD_LIST_H +#define CARD_LIST_H + +#include "edhrec_commander_api_response_card_details.h" + +#include +#include +#include +#include + +class EdhrecCommanderApiResponseCardList { +public: + QString header; + QList cardViews; + + // Default constructor + EdhrecCommanderApiResponseCardList(); + + // Method to populate the object from a JSON object + void fromJson(const QJsonObject &json); + + // Debug method to print out the data + void debugPrint() const; +}; + +#endif // CARD_LIST_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp new file mode 100644 index 000000000..2570e8852 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp @@ -0,0 +1,29 @@ +#include "edhrec_commander_api_response_card_prices.h" + +void CardPrices::fromJson(const QJsonObject &json) +{ + // Parse prices from various sources + cardhoarder = json.value("cardhoarder").toObject(); + cardkingdom = json.value("cardkingdom").toObject(); + cardmarket = json.value("cardmarket").toObject(); + face2face = json.value("face2face").toObject(); + manapool = json.value("manapool").toObject(); + mtgstocks = json.value("mtgstocks").toObject(); + scg = json.value("scg").toObject(); + tcgl = json.value("tcgl").toObject(); + tcgplayer = json.value("tcgplayer").toObject(); +} + +void CardPrices::debugPrint() const +{ + qDebug() << "Card Prices:"; + qDebug() << "Cardhoarder:" << cardhoarder; + qDebug() << "Cardkingdom:" << cardkingdom; + qDebug() << "Cardmarket:" << cardmarket; + qDebug() << "Face2Face:" << face2face; + qDebug() << "Manapool:" << manapool; + qDebug() << "Mtgstocks:" << mtgstocks; + qDebug() << "SCG:" << scg; + qDebug() << "TCGL:" << tcgl; + qDebug() << "Tcgplayer:" << tcgplayer; +} diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.h new file mode 100644 index 000000000..a5ba16026 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.h @@ -0,0 +1,38 @@ +#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H +#define EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H + +#include + +class CardPrices { +public: + // Constructor + CardPrices() = default; + + // Parse prices from JSON + void fromJson(const QJsonObject &json); + void debugPrint() const; + + // Getter methods for card prices + const QJsonObject& getCardhoarder() const { return cardhoarder; } + const QJsonObject& getCardkingdom() const { return cardkingdom; } + const QJsonObject& getCardmarket() const { return cardmarket; } + const QJsonObject& getFace2face() const { return face2face; } + const QJsonObject& getManapool() const { return manapool; } + const QJsonObject& getMtgstocks() const { return mtgstocks; } + const QJsonObject& getScg() const { return scg; } + const QJsonObject& getTcgl() const { return tcgl; } + const QJsonObject& getTcgplayer() const { return tcgplayer; } + +private: + QJsonObject cardhoarder; + QJsonObject cardkingdom; + QJsonObject cardmarket; + QJsonObject face2face; + QJsonObject manapool; + QJsonObject mtgstocks; + QJsonObject scg; + QJsonObject tcgl; + QJsonObject tcgplayer; +}; + +#endif //EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp new file mode 100644 index 000000000..4ef2a30ee --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp @@ -0,0 +1,86 @@ +#include "edhrec_commander_api_response_commander_details.h" + +void EdhrecCommanderApiResponseCommanderDetails::fromJson(const QJsonObject &json) { + // Parse card-related data + aetherhubUri = json.value("aetherhub_uri").toString(); + archidektUri = json.value("archidekt_uri").toString(); + cmc = json.value("cmc").toInt(0); + colorIdentity = json.value("color_identity").toArray(); + combos = json.value("combos").toBool(false); + deckstatsUri = json.value("deckstats_uri").toString(); + + // Parse image URIs + QJsonArray imageUrisArray = json.value("image_uris").toArray(); + for (const QJsonValue &imageValue : imageUrisArray) { + QJsonObject imageObject = imageValue.toObject(); + imageUris.push_back(imageObject.value("normal").toString()); + imageUris.push_back(imageObject.value("art_crop").toString()); + } + + inclusion = json.value("inclusion").toInt(0); + isCommander = json.value("is_commander").toBool(false); + label = json.value("label").toString(); + layout = json.value("layout").toString(); + legalCommander = json.value("legal_commander").toBool(false); + moxfieldUri = json.value("moxfield_uri").toString(); + mtggoldfishUri = json.value("mtggoldfish_uri").toString(); + name = json.value("name").toString(); + names = json.value("names").toArray(); + numDecks = json.value("num_decks").toInt(0); + potentialDecks = json.value("potential_decks").toInt(0); + precon = json.value("precon").toString(); + + // Parse prices + prices.fromJson(json.value("prices").toObject()); + + primaryType = json.value("primary_type").toString(); + rarity = json.value("rarity").toString(); + salt = json.value("salt").toDouble(0.0); + sanitized = json.value("sanitized").toString(); + sanitizedWo = json.value("sanitized_wo").toString(); + scryfallUri = json.value("scryfall_uri").toString(); + spellbookUri = json.value("spellbook_uri").toString(); + type = json.value("type").toString(); + url = json.value("url").toString(); +} + +void EdhrecCommanderApiResponseCommanderDetails::debugPrint() const { + qDebug() << "Card Data:"; + qDebug() << "Aetherhub URI:" << aetherhubUri; + qDebug() << "Archidekt URI:" << archidektUri; + qDebug() << "CMC:" << cmc; + qDebug() << "Color Identity:" << colorIdentity; + qDebug() << "Combos:" << combos; + qDebug() << "Deckstats URI:" << deckstatsUri; + + qDebug() << "Image URIs:"; + for (const auto &uri : imageUris) { + qDebug() << uri; + } + + qDebug() << "Inclusion:" << inclusion; + qDebug() << "Is Commander:" << isCommander; + qDebug() << "Label:" << label; + qDebug() << "Layout:" << layout; + qDebug() << "Legal Commander:" << legalCommander; + qDebug() << "Moxfield URI:" << moxfieldUri; + qDebug() << "MTGGoldfish URI:" << mtggoldfishUri; + qDebug() << "Name:" << name; + qDebug() << "Names:" << names; + qDebug() << "Number of Decks:" << numDecks; + qDebug() << "Potential Decks:" << potentialDecks; + qDebug() << "Precon:" << precon; + + // Print the prices using the debugPrint method from CardPrices + prices.debugPrint(); + + qDebug() << "Primary Type:" << primaryType; + qDebug() << "Rarity:" << rarity; + qDebug() << "Salt:" << salt; + qDebug() << "Sanitized:" << sanitized; + qDebug() << "Sanitized WO:" << sanitizedWo; + qDebug() << "Scryfall URI:" << scryfallUri; + qDebug() << "Spellbook URI:" << spellbookUri; + qDebug() << "Type:" << type; + qDebug() << "URL:" << url; +} \ No newline at end of file diff --git a/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.h b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.h new file mode 100644 index 000000000..62a7adeae --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.h @@ -0,0 +1,85 @@ +#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H +#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H + +#include "edhrec_commander_api_response_card_prices.h" + +#include +#include +#include +#include + +class EdhrecCommanderApiResponseCommanderDetails { +public: + // Constructor + EdhrecCommanderApiResponseCommanderDetails() = default; + + // Parse card-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + // Getters for the card data + const QString& getAetherhubUri() const { return aetherhubUri; } + const QString& getArchidektUri() const { return archidektUri; } + int getCmc() const { return cmc; } + const QJsonArray& getColorIdentity() const { return colorIdentity; } + bool isCombos() const { return combos; } + const QString& getDeckstatsUri() const { return deckstatsUri; } + const QVector& getImageUris() const { return imageUris; } + int getInclusion() const { return inclusion; } + bool getIsCommander() const { return isCommander; } + const QString& getLabel() const { return label; } + const QString& getLayout() const { return layout; } + bool getLegalCommander() const { return legalCommander; } + const QString& getMoxfieldUri() const { return moxfieldUri; } + const QString& getMtggoldfishUri() const { return mtggoldfishUri; } + const QString& getName() const { return name; } + const QJsonArray& getNames() const { return names; } + int getNumDecks() const { return numDecks; } + int getPotentialDecks() const { return potentialDecks; } + const QString& getPrecon() const { return precon; } + const CardPrices& getPrices() const { return prices; } + const QString& getPrimaryType() const { return primaryType; } + const QString& getRarity() const { return rarity; } + double getSalt() const { return salt; } + const QString& getSanitized() const { return sanitized; } + const QString& getSanitizedWo() const { return sanitizedWo; } + const QString& getScryfallUri() const { return scryfallUri; } + const QString& getSpellbookUri() const { return spellbookUri; } + const QString& getType() const { return type; } + const QString& getUrl() const { return url; } + +private: + QString aetherhubUri; + QString archidektUri; + int cmc = 0; + QJsonArray colorIdentity; + bool combos = false; + QString deckstatsUri; + QVector imageUris; + int inclusion = 0; + bool isCommander = false; + QString label; + QString layout; + bool legalCommander = false; + QString moxfieldUri; + QString mtggoldfishUri; + QString name; + QJsonArray names; + int numDecks = 0; + int potentialDecks = 0; + QString precon; + CardPrices prices; + QString primaryType; + QString rarity; + double salt = 0.0; + QString sanitized; + QString sanitizedWo; + QString scryfallUri; + QString spellbookUri; + QString type; + QString url; +}; + +#endif //EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp new file mode 100644 index 000000000..20dcc4fbb --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp @@ -0,0 +1,15 @@ +#include "edhrec_commander_api_response_card_details_display_widget.h" + +#include "../../../../game/cards/card_database_manager.h" + +EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCardDetailsDisplayWidget( + QWidget *parent, + EdhrecCommanderApiResponseCardDetails toDisplay) + : QWidget(parent) +{ + layout = new QHBoxLayout(this); + setLayout(layout); + cardPictureWidget = new CardInfoPictureWidget(this); + cardPictureWidget->setCard(CardDatabaseManager::getInstance()->getCard(toDisplay.name)); + layout->addWidget(cardPictureWidget); +} diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.h b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.h new file mode 100644 index 000000000..84537d88d --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.h @@ -0,0 +1,22 @@ +#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H +#define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H + +#include "../../../ui/widgets/cards/card_info_picture_widget.h" +#include "api_response/edhrec_commander_api_response_card_details.h" + +#include +#include + +class EdhrecCommanderApiResponseCardDetailsDisplayWidget : public QWidget +{ + Q_OBJECT +public: + explicit EdhrecCommanderApiResponseCardDetailsDisplayWidget(QWidget *parent, + EdhrecCommanderApiResponseCardDetails toDisplay); + +private: + QHBoxLayout *layout; + CardInfoPictureWidget *cardPictureWidget; +}; + +#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp new file mode 100644 index 000000000..eed4b03d1 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp @@ -0,0 +1,27 @@ +#include "edhrec_commander_api_response_card_list_display_widget.h" + +#include "edhrec_commander_api_response_card_details_display_widget.h" + +#include + +EdhrecCommanderApiResponseCardListDisplayWidget::EdhrecCommanderApiResponseCardListDisplayWidget( + QWidget *parent, + EdhrecCommanderApiResponseCardList toDisplay) + : QWidget(parent) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + + auto header = new QLabel(this); + header->setText(toDisplay.header); + + flowWidget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); + + foreach (EdhrecCommanderApiResponseCardDetails card_detail, toDisplay.cardViews) { + auto widget = new EdhrecCommanderApiResponseCardDetailsDisplayWidget(flowWidget, card_detail); + flowWidget->addWidget(widget); + } + + layout->addWidget(header); + layout->addWidget(flowWidget); +} diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.h b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.h new file mode 100644 index 000000000..4efb9bf32 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.h @@ -0,0 +1,22 @@ +#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H +#define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H + +#include "../../../ui/widgets/general/layout_containers/flow_widget.h" +#include "api_response/edhrec_commander_api_response_card_list.h" + +#include +#include + +class EdhrecCommanderApiResponseCardListDisplayWidget : public QWidget +{ + Q_OBJECT +public: + explicit EdhrecCommanderApiResponseCardListDisplayWidget(QWidget *parent, + EdhrecCommanderApiResponseCardList toDisplay); + +private: + QVBoxLayout *layout; + FlowWidget *flowWidget; +}; + +#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp new file mode 100644 index 000000000..38441e782 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp @@ -0,0 +1,25 @@ +#include "edhrec_commander_api_response_display_widget.h" + +#include "../../../../game/cards/card_database_manager.h" +#include "../../../ui/widgets/cards/card_info_picture_widget.h" +#include "api_response/edhrec_commander_api_response.h" +#include "edhrec_commander_api_response_card_list_display_widget.h" + +EdhrecCommanderApiResponseDisplayWidget::EdhrecCommanderApiResponseDisplayWidget(QWidget *parent, + EdhrecCommanderApiResponse response) + : QWidget(parent) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + + auto commanderPicture = new CardInfoPictureWidget(this); + commanderPicture->setCard( + CardDatabaseManager::getInstance()->getCard(response.container.getCommanderDetails().getName())); + layout->addWidget(commanderPicture); + + auto edhrec_commander_api_response_card_lists = response.container.getCardlists(); + foreach (EdhrecCommanderApiResponseCardList card_list, edhrec_commander_api_response_card_lists) { + auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list); + layout->addWidget(cardListDisplayWidget); + } +} \ No newline at end of file diff --git a/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.h b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.h new file mode 100644 index 000000000..3d61da5e2 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.h @@ -0,0 +1,20 @@ +#ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H +#define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H + +#include "api_response/edhrec_commander_api_response.h" + +#include +#include + +class EdhrecCommanderApiResponseDisplayWidget : public QWidget +{ + Q_OBJECT + +public: + explicit EdhrecCommanderApiResponseDisplayWidget(QWidget *parent, EdhrecCommanderApiResponse response); + +private: + QVBoxLayout *layout; +}; + +#endif // EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.cpp b/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.cpp new file mode 100644 index 000000000..f4bb234e4 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.cpp @@ -0,0 +1,112 @@ +#include "tab_edhrec.h" + +#include "api_response/edhrec_commander_api_response.h" +#include "edhrec_commander_api_response_display_widget.h" + +#include +#include +#include +#include +#include +#include +#include + +TabEdhRec::TabEdhRec(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) +{ + setMinimumSize(0, 0); + container = new QWidget(this); + layout = new QHBoxLayout(this); + container->setLayout(layout); + setCentralWidget(container); + flowWidget = new FlowWidget(container, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + layout->addWidget(flowWidget); + networkManager = new QNetworkAccessManager(this); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + networkManager->setTransferTimeout(); // Use Qt's default timeout +#endif + + networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); + connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *))); +} + +void TabEdhRec::retranslateUi() +{ +} + +void TabEdhRec::setCard(CardInfoPtr _cardToQuery) +{ + cardToQuery = _cardToQuery; + + if (!cardToQuery) { + qDebug() << "Invalid card information provided."; + return; + } + + QString cardName = cardToQuery->getName(); // Assuming `getName()` fetches the card's name. + QString formattedName = cardName.toLower().replace(" ", "-").remove(QRegularExpression("[^a-z0-9\\-]")); + + QString url = QString("https://json.edhrec.com/pages/commanders/%1.json").arg(formattedName); + + QNetworkRequest request{QUrl(url)}; + + networkManager->get(request); // Issue the GET request. +} + +void TabEdhRec::processApiJson(QNetworkReply *reply) +{ + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Network error occurred:" << reply->errorString(); + reply->deleteLater(); + return; + } + + QByteArray responseData = reply->readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData); + + if (!jsonDoc.isObject()) { + qDebug() << "Invalid JSON response received."; + reply->deleteLater(); + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + // qDebug() << jsonObj; + + EdhrecCommanderApiResponse deckData; + deckData.fromJson(jsonObj); + + auto widget = new EdhrecCommanderApiResponseDisplayWidget(this, deckData); + flowWidget->addWidget(widget); + + reply->deleteLater(); + update(); +} + +void TabEdhRec::prettyPrintJson(const QJsonValue &value, int indentLevel) +{ + const QString indent(indentLevel * 2, ' '); // Adjust spacing as needed for pretty printing + + if (value.isObject()) { + QJsonObject obj = value.toObject(); + for (auto it = obj.begin(); it != obj.end(); ++it) { + qDebug().noquote() << indent + it.key() + ":"; + prettyPrintJson(it.value(), indentLevel + 1); + } + } else if (value.isArray()) { + QJsonArray array = value.toArray(); + for (int i = 0; i < array.size(); ++i) { + qDebug().noquote() << indent + QString("[%1]:").arg(i); + prettyPrintJson(array[i], indentLevel + 1); + } + } else if (value.isString()) { + qDebug().noquote() << indent + "\"" + value.toString() + "\""; + } else if (value.isDouble()) { + qDebug().noquote() << indent + QString::number(value.toDouble()); + } else if (value.isBool()) { + qDebug().noquote() << indent + (value.toBool() ? "true" : "false"); + } else if (value.isNull()) { + qDebug().noquote() << indent + "null"; + } +} diff --git a/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.h b/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.h new file mode 100644 index 000000000..109a82d12 --- /dev/null +++ b/cockatrice/src/client/tabs/api/edhrec/tab_edhrec.h @@ -0,0 +1,38 @@ +#ifndef TAB_EDHREC_H +#define TAB_EDHREC_H + +#include "../../../../game/cards/card_database.h" +#include "../../../ui/widgets/general/layout_containers/flow_widget.h" +#include "../../tab.h" + +#include +#include + +class TabEdhRec : public Tab +{ + Q_OBJECT +public: + explicit TabEdhRec(TabSupervisor *_tabSupervisor); + + void retranslateUi() override; + QString getTabText() const override + { + auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName(); + return tr("EDHREC: ") + cardName; + } + + QNetworkAccessManager *networkManager; + +public slots: + void processApiJson(QNetworkReply *reply); + void prettyPrintJson(const QJsonValue &value, int indentLevel); + void setCard(CardInfoPtr _cardToQuery); + +private: + QWidget *container; + FlowWidget *flowWidget; + QHBoxLayout *layout; + CardInfoPtr cardToQuery; +}; + +#endif // TAB_EDHREC_H diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index 0152566ab..ef493d5a2 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -541,14 +541,16 @@ void TabDeckEditor::databaseCustomMenu(QPoint point) const CardInfoPtr info = currentCardInfo(); // add to deck and sideboard options - QAction *addToDeck, *addToSideboard, *selectPrinting; + QAction *addToDeck, *addToSideboard, *selectPrinting, *edhRec; addToDeck = menu.addAction(tr("Add to Deck")); addToSideboard = menu.addAction(tr("Add to Sideboard")); selectPrinting = menu.addAction(tr("Select Printing")); + edhRec = menu.addAction(tr("Show on EDHREC")); connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard())); connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard())); connect(selectPrinting, &QAction::triggered, this, [this, info] { this->showPrintingSelector(); }); + connect(edhRec, &QAction::triggered, this, [this, info] { this->tabSupervisor->addEdhrecTab(info); }); // filling out the related cards submenu auto *relatedMenu = new QMenu(tr("Show Related cards")); diff --git a/cockatrice/src/client/tabs/tab_supervisor.cpp b/cockatrice/src/client/tabs/tab_supervisor.cpp index c71d37a46..48ea04c3b 100644 --- a/cockatrice/src/client/tabs/tab_supervisor.cpp +++ b/cockatrice/src/client/tabs/tab_supervisor.cpp @@ -720,6 +720,18 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen) return tab; } +TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr cardToQuery) +{ + TabEdhRec *tab = new TabEdhRec(this); + if (cardToQuery) + tab->setCard(cardToQuery); + // connect(tab, &TabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed); + // connect(tab, &TabDeckEditor::openDeckEditor, this, &TabSupervisor::addDeckEditorTab); + myAddTab(tab); + setCurrentWidget(tab); + return tab; +} + void TabSupervisor::deckEditorClosed(TabDeckEditor *tab) { if (tab == currentWidget()) diff --git a/cockatrice/src/client/tabs/tab_supervisor.h b/cockatrice/src/client/tabs/tab_supervisor.h index 3925807fb..02fd8ef12 100644 --- a/cockatrice/src/client/tabs/tab_supervisor.h +++ b/cockatrice/src/client/tabs/tab_supervisor.h @@ -3,6 +3,7 @@ #include "../../deck/deck_loader.h" #include "../../server/user/user_list_proxy.h" +#include "api/edhrec/tab_edhrec.h" #include "visual_deck_storage/tab_deck_storage_visual.h" #include @@ -143,6 +144,7 @@ signals: public slots: TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen); + TabEdhRec *addEdhrecTab(CardInfoPtr cardToQuery); void openReplay(GameReplay *replay); void maximizeMainWindow(); private slots: