Analyze deck on tappedout Fix small bug in deckstats interface
This commit is contained in:
parent
680277ad6a
commit
7f28a7e844
10 changed files with 310 additions and 21 deletions
|
@ -80,6 +80,7 @@ SET(cockatrice_SOURCES
|
||||||
src/tab_logs.cpp
|
src/tab_logs.cpp
|
||||||
src/replay_timeline_widget.cpp
|
src/replay_timeline_widget.cpp
|
||||||
src/deckstats_interface.cpp
|
src/deckstats_interface.cpp
|
||||||
|
src/tappedout_interface.cpp
|
||||||
src/chatview.cpp
|
src/chatview.cpp
|
||||||
src/userlist.cpp
|
src/userlist.cpp
|
||||||
src/userinfobox.cpp
|
src/userinfobox.cpp
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "deck_loader.h"
|
#include "deck_loader.h"
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
const QStringList DeckLoader::fileNameFilters = QStringList()
|
const QStringList DeckLoader::fileNameFilters = QStringList()
|
||||||
<< QObject::tr("Common deck formats (*.cod *.dec *.txt *.mwDeck)")
|
<< QObject::tr("Common deck formats (*.cod *.dec *.txt *.mwDeck)")
|
||||||
|
@ -108,3 +110,89 @@ DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName)
|
||||||
}
|
}
|
||||||
return PlainTextFormat;
|
return PlainTextFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DeckLoader::saveToStream_Plain(QTextStream &out)
|
||||||
|
{
|
||||||
|
saveToStream_DeckHeader(out);
|
||||||
|
|
||||||
|
// loop zones
|
||||||
|
for (int i = 0; i < getRoot()->size(); i++) {
|
||||||
|
const InnerDecklistNode *zoneNode =
|
||||||
|
dynamic_cast<InnerDecklistNode *>(getRoot()->at(i));
|
||||||
|
|
||||||
|
saveToStream_DeckZone(out, zoneNode);
|
||||||
|
|
||||||
|
// end of zone
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckLoader::saveToStream_DeckHeader(QTextStream &out)
|
||||||
|
{
|
||||||
|
if(!getName().isEmpty())
|
||||||
|
out << "// " << getName() << "\n\n";
|
||||||
|
if(!getComments().isEmpty())
|
||||||
|
{
|
||||||
|
QStringList commentRows = getComments().split(QRegExp("\n|\r\n|\r"));
|
||||||
|
foreach(QString row, commentRows)
|
||||||
|
out << "// " << row << "\n";
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckLoader::saveToStream_DeckZone(QTextStream &out, const InnerDecklistNode *zoneNode)
|
||||||
|
{
|
||||||
|
// group cards by card type and count the subtotals
|
||||||
|
QMultiMap<QString, DecklistCardNode*> cardsByType;
|
||||||
|
QMap<QString, int> cardTotalByType;
|
||||||
|
int cardTotal = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < zoneNode->size(); j++) {
|
||||||
|
DecklistCardNode *card =
|
||||||
|
dynamic_cast<DecklistCardNode *>(
|
||||||
|
zoneNode->at(j)
|
||||||
|
);
|
||||||
|
|
||||||
|
CardInfo *info = db->getCard(card->getName());
|
||||||
|
QString cardType = info ? info->getMainCardType() : "unknown";
|
||||||
|
|
||||||
|
cardsByType.insert(cardType, card);
|
||||||
|
|
||||||
|
if(cardTotalByType.contains(cardType))
|
||||||
|
cardTotalByType[cardType] += card->getNumber();
|
||||||
|
else
|
||||||
|
cardTotalByType[cardType] = card->getNumber();
|
||||||
|
|
||||||
|
cardTotal += card->getNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "// " << cardTotal << " " << zoneNode->getVisibleName() << "\n";
|
||||||
|
|
||||||
|
// print cards to stream
|
||||||
|
foreach(QString cardType, cardsByType.uniqueKeys())
|
||||||
|
{
|
||||||
|
|
||||||
|
out << "// " << cardTotalByType[cardType] << " " << cardType << "\n";
|
||||||
|
QList <DecklistCardNode*> cards = cardsByType.values(cardType);
|
||||||
|
|
||||||
|
saveToStream_DeckZoneCards(out, zoneNode, cards);
|
||||||
|
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckLoader::saveToStream_DeckZoneCards(QTextStream &out, const InnerDecklistNode *zoneNode, QList <DecklistCardNode*> cards)
|
||||||
|
{
|
||||||
|
// QMultiMap sorts values in reverse order
|
||||||
|
for(int i = cards.size() - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
DecklistCardNode* card = cards[i];
|
||||||
|
|
||||||
|
if (zoneNode->getName() == "side")
|
||||||
|
out << "SB: ";
|
||||||
|
|
||||||
|
out << card->getNumber() << " " << card->getName() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,14 @@ public:
|
||||||
bool loadFromFile(const QString &fileName, FileFormat fmt);
|
bool loadFromFile(const QString &fileName, FileFormat fmt);
|
||||||
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
|
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
|
||||||
bool saveToFile(const QString &fileName, FileFormat fmt);
|
bool saveToFile(const QString &fileName, FileFormat fmt);
|
||||||
|
|
||||||
|
// overload
|
||||||
|
bool saveToStream_Plain(QTextStream &out);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void saveToStream_DeckHeader(QTextStream &out);
|
||||||
|
void saveToStream_DeckZone(QTextStream &out, const InnerDecklistNode *zoneNode);
|
||||||
|
void saveToStream_DeckZoneCards(QTextStream &out, const InnerDecklistNode *zoneNode, QList <DecklistCardNode*> cards);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,7 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
QRegExp rx("<meta property=\"og:url\" content=\"([^\"]+)\"/>");
|
QRegExp rx("<meta property=\"og:url\" content=\"([^\"]+)\"/>");
|
||||||
if (!rx.indexIn(data)) {
|
if (-1 == rx.indexIn(data)) {
|
||||||
QMessageBox::critical(0, tr("Error"), tr("The reply from the server could not be parsed."));
|
QMessageBox::critical(0, tr("Error"), tr("The reply from the server could not be parsed."));
|
||||||
deleteLater();
|
deleteLater();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "priceupdater.h"
|
#include "priceupdater.h"
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
#include "deckstats_interface.h"
|
#include "deckstats_interface.h"
|
||||||
|
#include "tappedout_interface.h"
|
||||||
#include "abstractclient.h"
|
#include "abstractclient.h"
|
||||||
#include "pending_command.h"
|
#include "pending_command.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
|
@ -226,8 +227,15 @@ void TabDeckEditor::createMenus()
|
||||||
aPrintDeck = new QAction(QString(), this);
|
aPrintDeck = new QAction(QString(), this);
|
||||||
connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck()));
|
connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck()));
|
||||||
|
|
||||||
aAnalyzeDeck = new QAction(QString(), this);
|
aAnalyzeDeckDeckstats = new QAction(QString(), this);
|
||||||
connect(aAnalyzeDeck, SIGNAL(triggered()), this, SLOT(actAnalyzeDeck()));
|
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckDeckstats()));
|
||||||
|
|
||||||
|
aAnalyzeDeckTappedout = new QAction(QString(), this);
|
||||||
|
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckTappedout()));
|
||||||
|
|
||||||
|
analyzeDeckMenu = new QMenu(this);
|
||||||
|
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
|
||||||
|
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
|
||||||
|
|
||||||
aClose = new QAction(QString(), this);
|
aClose = new QAction(QString(), this);
|
||||||
connect(aClose, SIGNAL(triggered()), this, SLOT(closeRequest()));
|
connect(aClose, SIGNAL(triggered()), this, SLOT(closeRequest()));
|
||||||
|
@ -250,7 +258,7 @@ void TabDeckEditor::createMenus()
|
||||||
deckMenu->addAction(aSaveDeckToClipboard);
|
deckMenu->addAction(aSaveDeckToClipboard);
|
||||||
deckMenu->addSeparator();
|
deckMenu->addSeparator();
|
||||||
deckMenu->addAction(aPrintDeck);
|
deckMenu->addAction(aPrintDeck);
|
||||||
deckMenu->addAction(aAnalyzeDeck);
|
deckMenu->addMenu(analyzeDeckMenu);
|
||||||
deckMenu->addSeparator();
|
deckMenu->addSeparator();
|
||||||
deckMenu->addAction(aClearFilterOne);
|
deckMenu->addAction(aClearFilterOne);
|
||||||
deckMenu->addAction(aClearFilterAll);
|
deckMenu->addAction(aClearFilterAll);
|
||||||
|
@ -444,7 +452,7 @@ void TabDeckEditor::refreshShortcuts()
|
||||||
aSaveDeckAs->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeckAs"));
|
aSaveDeckAs->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeckAs"));
|
||||||
aLoadDeckFromClipboard->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
aLoadDeckFromClipboard->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
||||||
aPrintDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aPrintDeck"));
|
aPrintDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aPrintDeck"));
|
||||||
aAnalyzeDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aAnalyzeDeck"));
|
aAnalyzeDeckDeckstats->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aAnalyzeDeck"));
|
||||||
aClose->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aClose"));
|
aClose->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aClose"));
|
||||||
aResetLayout->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aResetLayout"));
|
aResetLayout->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aResetLayout"));
|
||||||
aClearFilterAll->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aClearFilterAll"));
|
aClearFilterAll->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aClearFilterAll"));
|
||||||
|
@ -536,7 +544,11 @@ void TabDeckEditor::retranslateUi()
|
||||||
aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard..."));
|
aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard..."));
|
||||||
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
||||||
aPrintDeck->setText(tr("&Print deck..."));
|
aPrintDeck->setText(tr("&Print deck..."));
|
||||||
aAnalyzeDeck->setText(tr("&Analyze deck on deckstats.net"));
|
|
||||||
|
analyzeDeckMenu->setTitle(tr("&Analyze deck online"));
|
||||||
|
aAnalyzeDeckDeckstats->setText(tr("deckstats.net"));
|
||||||
|
aAnalyzeDeckTappedout->setText(tr("tappedout.net"));
|
||||||
|
|
||||||
aClose->setText(tr("&Close"));
|
aClose->setText(tr("&Close"));
|
||||||
|
|
||||||
aAddCard->setText(tr("Add card to &maindeck"));
|
aAddCard->setText(tr("Add card to &maindeck"));
|
||||||
|
@ -751,7 +763,7 @@ void TabDeckEditor::actPrintDeck()
|
||||||
dlg->exec();
|
dlg->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actAnalyzeDeck()
|
void TabDeckEditor::actAnalyzeDeckDeckstats()
|
||||||
{
|
{
|
||||||
DeckStatsInterface *interface = new DeckStatsInterface(
|
DeckStatsInterface *interface = new DeckStatsInterface(
|
||||||
*databaseModel->getDatabase(),
|
*databaseModel->getDatabase(),
|
||||||
|
@ -760,6 +772,15 @@ void TabDeckEditor::actAnalyzeDeck()
|
||||||
interface->analyzeDeck(deckModel->getDeckList());
|
interface->analyzeDeck(deckModel->getDeckList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::actAnalyzeDeckTappedout()
|
||||||
|
{
|
||||||
|
TappedOutInterface *interface = new TappedOutInterface(
|
||||||
|
*databaseModel->getDatabase(),
|
||||||
|
this
|
||||||
|
); // it deletes itself when done
|
||||||
|
interface->analyzeDeck(deckModel->getDeckList());
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actClearFilterAll()
|
void TabDeckEditor::actClearFilterAll()
|
||||||
{
|
{
|
||||||
databaseDisplayModel->clearFilterAll();
|
databaseDisplayModel->clearFilterAll();
|
||||||
|
|
|
@ -52,7 +52,8 @@ class TabDeckEditor : public Tab {
|
||||||
void actLoadDeckFromClipboard();
|
void actLoadDeckFromClipboard();
|
||||||
void actSaveDeckToClipboard();
|
void actSaveDeckToClipboard();
|
||||||
void actPrintDeck();
|
void actPrintDeck();
|
||||||
void actAnalyzeDeck();
|
void actAnalyzeDeckDeckstats();
|
||||||
|
void actAnalyzeDeckTappedout();
|
||||||
|
|
||||||
void actClearFilterAll();
|
void actClearFilterAll();
|
||||||
void actClearFilterOne();
|
void actClearFilterOne();
|
||||||
|
@ -112,8 +113,8 @@ private:
|
||||||
QTreeView *filterView;
|
QTreeView *filterView;
|
||||||
QWidget *filterBox;
|
QWidget *filterBox;
|
||||||
|
|
||||||
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu;
|
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *analyzeDeckMenu;
|
||||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose;
|
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose;
|
||||||
QAction *aClearFilterAll, *aClearFilterOne;
|
QAction *aClearFilterAll, *aClearFilterOne;
|
||||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;// *aUpdatePrices;
|
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;// *aUpdatePrices;
|
||||||
QAction *aResetLayout;
|
QAction *aResetLayout;
|
||||||
|
|
125
cockatrice/src/tappedout_interface.cpp
Normal file
125
cockatrice/src/tappedout_interface.cpp
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#include "tappedout_interface.h"
|
||||||
|
#include "decklist.h"
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
TappedOutInterface::TappedOutInterface(
|
||||||
|
CardDatabase &_cardDatabase,
|
||||||
|
QObject *parent
|
||||||
|
) : QObject(parent), cardDatabase(_cardDatabase)
|
||||||
|
{
|
||||||
|
manager = new QNetworkAccessManager(this);
|
||||||
|
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
QMessageBox::critical(0, tr("Error"), reply->errorString());
|
||||||
|
reply->deleteLater();
|
||||||
|
deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if(reply->hasRawHeader("Location"))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the reply contains a "Location" header, a relative URL to the deck on TappedOut
|
||||||
|
* can be extracted from the header. The http status is a 302 "redirect".
|
||||||
|
*/
|
||||||
|
QString deckUrl = reply->rawHeader("Location");
|
||||||
|
qDebug() << "Tappedout: good reply, http status" << httpStatus << "location" << deckUrl;
|
||||||
|
QDesktopServices::openUrl("http://tappedout.net" + deckUrl);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Otherwise, the deck has not been parsed correctly. Error messages can be extracted
|
||||||
|
* from the html. Css pseudo selector for errors: $("div.alert-danger > ul > li")
|
||||||
|
*/
|
||||||
|
QString data(reply->readAll());
|
||||||
|
QString errorMessage = tr("Unable to analyze the deck.");
|
||||||
|
|
||||||
|
QRegExp rx("<div class=\"alert alert-danger.*<ul>(.*)</ul>");
|
||||||
|
rx.setMinimal(true);
|
||||||
|
int found = rx.indexIn(data);
|
||||||
|
if(found >= 0)
|
||||||
|
{
|
||||||
|
QString errors = rx.cap(1);
|
||||||
|
QRegExp rx2("<li>(.*)</li>");
|
||||||
|
rx2.setMinimal(true);
|
||||||
|
|
||||||
|
found = rx2.indexIn(errors);
|
||||||
|
int captures = rx2.captureCount();
|
||||||
|
for(int i = 1; i <= captures; i++)
|
||||||
|
{
|
||||||
|
errorMessage += QString("\n") + rx2.cap(i).remove(QRegExp("<[^>]*>")).simplified();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size() << "message" << errorMessage;
|
||||||
|
|
||||||
|
QMessageBox::critical(0, tr("Error"), errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TappedOutInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||||
|
{
|
||||||
|
DeckList mainboard, sideboard;
|
||||||
|
copyDeckSplitMainAndSide(*deck, mainboard, sideboard);
|
||||||
|
|
||||||
|
QUrl params;
|
||||||
|
QUrlQuery urlQuery;
|
||||||
|
urlQuery.addQueryItem("name", deck->getName());
|
||||||
|
urlQuery.addQueryItem("mainboard", mainboard.writeToString_Plain(false));
|
||||||
|
urlQuery.addQueryItem("sideboard", sideboard.writeToString_Plain(false));
|
||||||
|
params.setQuery(urlQuery);
|
||||||
|
data->append(params.query(QUrl::EncodeReserved));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TappedOutInterface::analyzeDeck(DeckList *deck)
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
getAnalyzeRequestData(deck, &data);
|
||||||
|
|
||||||
|
QNetworkRequest request(QUrl("http://tappedout.net/mtg-decks/paste/"));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
manager->post(request, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CopyMainOrSide {
|
||||||
|
CardDatabase &cardDatabase;
|
||||||
|
DeckList &mainboard, &sideboard;
|
||||||
|
|
||||||
|
CopyMainOrSide(CardDatabase &_cardDatabase, DeckList &_mainboard, DeckList &_sideboard)
|
||||||
|
: cardDatabase(_cardDatabase), mainboard(_mainboard), sideboard(_sideboard) {};
|
||||||
|
|
||||||
|
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const
|
||||||
|
{
|
||||||
|
CardInfo * dbCard = cardDatabase.getCard(card->getName());
|
||||||
|
if (!dbCard || dbCard->getIsToken())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DecklistCardNode *addedCard;
|
||||||
|
if(node->getName() == "side")
|
||||||
|
addedCard = sideboard.addCard(card->getName(), node->getName());
|
||||||
|
else
|
||||||
|
addedCard = mainboard.addCard(card->getName(), node->getName());
|
||||||
|
addedCard->setNumber(card->getNumber());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
||||||
|
{
|
||||||
|
CopyMainOrSide copyMainOrSide(cardDatabase, mainboard, sideboard);
|
||||||
|
source.forEachCard(copyMainOrSide);
|
||||||
|
}
|
34
cockatrice/src/tappedout_interface.h
Normal file
34
cockatrice/src/tappedout_interface.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef TAPPEDOUT_INTERFACE_H
|
||||||
|
#define TAPPEDOUT_INTERFACE_H
|
||||||
|
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "decklist.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QByteArray;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QNetworkReply;
|
||||||
|
class DeckList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TappedOutInterface exists in order to support the "Analyze on TappedOut" feature.
|
||||||
|
* An http POST request is sent and the result is retrieved from the reply. Parsing
|
||||||
|
* logic is implemented in TappedOutInterface::queryFinished().
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TappedOutInterface : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager *manager;
|
||||||
|
|
||||||
|
CardDatabase &cardDatabase;
|
||||||
|
void copyDeckSplitMainAndSide(const DeckList &source, DeckList& mainboard, DeckList& sideboard);
|
||||||
|
private slots:
|
||||||
|
void queryFinished(QNetworkReply *reply);
|
||||||
|
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
|
||||||
|
public:
|
||||||
|
TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
|
||||||
|
void analyzeDeck(DeckList *deck);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -514,10 +514,20 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
|
||||||
bool inSideboard = false;
|
bool inSideboard = false;
|
||||||
|
|
||||||
int okRows = 0;
|
int okRows = 0;
|
||||||
|
bool titleFound = false;
|
||||||
while (!in.atEnd()) {
|
while (!in.atEnd()) {
|
||||||
QString line = in.readLine().simplified();
|
QString line = in.readLine().simplified();
|
||||||
if (line.startsWith("//"))
|
if (line.startsWith("//"))
|
||||||
|
{
|
||||||
|
if(!titleFound)
|
||||||
|
{
|
||||||
|
name = line.mid(2).trimmed();
|
||||||
|
titleFound = true;
|
||||||
|
} else if(okRows == 0) {
|
||||||
|
comments += line.mid(2).trimmed() + "\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
InnerDecklistNode *zone;
|
InnerDecklistNode *zone;
|
||||||
if (line.startsWith("Sideboard", Qt::CaseInsensitive)) {
|
if (line.startsWith("Sideboard", Qt::CaseInsensitive)) {
|
||||||
|
@ -600,14 +610,15 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
|
||||||
|
|
||||||
struct WriteToStream {
|
struct WriteToStream {
|
||||||
QTextStream &stream;
|
QTextStream &stream;
|
||||||
|
bool prefixSideboardCards;
|
||||||
|
|
||||||
WriteToStream(QTextStream &_stream) : stream(_stream) {}
|
WriteToStream(QTextStream &_stream, bool _prefixSideboardCards) : stream(_stream), prefixSideboardCards(_prefixSideboardCards) {}
|
||||||
|
|
||||||
void operator()(
|
void operator()(
|
||||||
const InnerDecklistNode *node,
|
const InnerDecklistNode *node,
|
||||||
const DecklistCardNode *card
|
const DecklistCardNode *card
|
||||||
) {
|
) {
|
||||||
if (node->getName() == "side") {
|
if (prefixSideboardCards && node->getName() == "side") {
|
||||||
stream << "SB: ";
|
stream << "SB: ";
|
||||||
}
|
}
|
||||||
stream << QString("%1 %2\n").arg(
|
stream << QString("%1 %2\n").arg(
|
||||||
|
@ -618,24 +629,24 @@ struct WriteToStream {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool DeckList::saveToStream_Plain(QTextStream &out)
|
bool DeckList::saveToStream_Plain(QTextStream &out, bool prefixSideboardCards)
|
||||||
{
|
{
|
||||||
WriteToStream writeToStream(out);
|
WriteToStream writeToStream(out, prefixSideboardCards);
|
||||||
forEachCard(writeToStream);
|
forEachCard(writeToStream);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeckList::saveToFile_Plain(QIODevice *device)
|
bool DeckList::saveToFile_Plain(QIODevice *device, bool prefixSideboardCards)
|
||||||
{
|
{
|
||||||
QTextStream out(device);
|
QTextStream out(device);
|
||||||
return saveToStream_Plain(out);
|
return saveToStream_Plain(out, prefixSideboardCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DeckList::writeToString_Plain()
|
QString DeckList::writeToString_Plain(bool prefixSideboardCards)
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
QTextStream out(&result);
|
QTextStream out(&result);
|
||||||
saveToStream_Plain(out);
|
saveToStream_Plain(out, prefixSideboardCards);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,9 +153,9 @@ public:
|
||||||
bool saveToFile_Native(QIODevice *device);
|
bool saveToFile_Native(QIODevice *device);
|
||||||
bool loadFromStream_Plain(QTextStream &stream);
|
bool loadFromStream_Plain(QTextStream &stream);
|
||||||
bool loadFromFile_Plain(QIODevice *device);
|
bool loadFromFile_Plain(QIODevice *device);
|
||||||
bool saveToStream_Plain(QTextStream &stream);
|
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards);
|
||||||
bool saveToFile_Plain(QIODevice *device);
|
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards=true);
|
||||||
QString writeToString_Plain();
|
QString writeToString_Plain(bool prefixSideboardCards=true);
|
||||||
|
|
||||||
void cleanList();
|
void cleanList();
|
||||||
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
||||||
|
|
Loading…
Reference in a new issue