#include "oracleimporter.h" #if QT_VERSION < 0x050000 #include #else #include #endif #include #include "qt-json/json.h" OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) : CardDatabase(parent), dataDir(_dataDir) { } bool OracleImporter::readSetsFromByteArray(const QByteArray &data) { QList newSetList; bool ok; setsMap = QtJson::Json::parse(QString(data), ok).toMap(); if (!ok) { qDebug() << "error: QtJson::Json::parse()"; return 0; } QListIterator it(setsMap.values()); QVariantMap map; QString edition; QString editionLong; QVariant editionCards; QString setType; QDate releaseDate; while (it.hasNext()) { map = it.next().toMap(); edition = map.value("code").toString(); editionLong = map.value("name").toString(); editionCards = map.value("cards"); setType = map.value("type").toString(); // capitalize set type if(setType.length() > 0) setType[0] = setType[0].toUpper(); releaseDate = map.value("releaseDate").toDate(); newSetList.append(SetToDownload(edition, editionLong, editionCards, setType, releaseDate)); } qSort(newSetList); if (newSetList.isEmpty()) return false; allSets = newSetList; return true; } CardInfo *OracleImporter::addCard(const QString &setName, QString cardName, bool isToken, int cardId, QString &cardCost, QString &cmc, const QString &cardType, const QString &cardPT, int cardLoyalty, const QString &cardText, const QStringList & colors, const QStringList & relatedCards, bool upsideDown ) { QStringList cardTextRows = cardText.split("\n"); // Workaround for card name weirdness cardName = cardName.replace("Æ", "AE"); cardName = cardName.replace("’", "'"); CardInfo * card; if (cards.contains(cardName)) { card = cards.value(cardName); } else { // Remove {} around mana costs cardCost.remove(QChar('{')); cardCost.remove(QChar('}')); // detect mana generator artifacts bool mArtifact = false; if (cardType.endsWith("Artifact")) for (int i = 0; i < cardTextRows.size(); ++i) if (cardTextRows[i].contains("{T}") && cardTextRows[i].contains("to your mana pool")) mArtifact = true; // detect cards that enter the field tapped bool cipt = cardText.contains("Hideaway") || (cardText.contains(cardName + " enters the battlefield tapped") && !cardText.contains(cardName + " enters the battlefield tapped unless")); // insert the card and its properties card = new CardInfo(this, cardName, isToken, cardCost, cmc, cardType, cardPT, cardText, colors, relatedCards, upsideDown, cardLoyalty, cipt); int tableRow = 1; QString mainCardType = card->getMainCardType(); if ((mainCardType == "Land") || mArtifact) tableRow = 0; else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) tableRow = 3; else if (mainCardType == "Creature") tableRow = 2; card->setTableRow(tableRow); cards.insert(cardName, card); } card->setMuId(setName, cardId); return card; } void OracleImporter::extractColors(const QStringList & in, QStringList & out) { foreach(QString c, in) { if (c == "White") out << "W"; else if (c == "Blue") out << "U"; else if (c == "Black") out << "B"; else if (c == "Red") out << "R"; else if (c == "Green") out << "G"; else qDebug() << "error: unknown color:" << c; } } int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data) { int cards = 0; QListIterator it(data.toList()); QVariantMap map; QString cardName; QString cardCost; QString cmc; QString cardType; QString cardPT; QString cardText; QStringList colors; QStringList relatedCards; int cardId; int cardLoyalty; bool upsideDown = false; QMap splitCards; while (it.hasNext()) { map = it.next().toMap(); QString layout = map.value("layout").toString(); if(layout == "token") continue; if(layout == "split") { // Enqueue split card for later handling cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; if (cardId) splitCards.insertMulti(cardId, map); continue; } // normal cards handling cardName = map.contains("name") ? map.value("name").toString() : QString(""); cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); cmc = map.contains("cmc") ? map.value("cmc").toString() : QString("0"); cardType = map.contains("type") ? map.value("type").toString() : QString(""); cardPT = map.contains("power") || map.contains("toughness") ? map.value("power").toString() + QString('/') + map.value("toughness").toString() : QString(""); cardText = map.contains("text") ? map.value("text").toString() : QString(""); cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; relatedCards = map.contains("names") ? map.value("names").toStringList() : QStringList(); relatedCards.removeAll(cardName); if(0 == QString::compare(map.value("layout").toString(), QString("flip"), Qt::CaseInsensitive)) { QStringList cardNames = map.contains("names") ? map.value("names").toStringList() : QStringList(); upsideDown = (cardNames.indexOf(cardName) > 0); } else { upsideDown = false; } colors.clear(); extractColors(map.value("colors").toStringList(), colors); CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, upsideDown); if (!set->contains(card)) { card->addToSet(set); cards++; } } // split cards handling - get all unique card muids QList muids = splitCards.uniqueKeys(); foreach(int muid, muids) { // get all cards for this specific muid QList maps = splitCards.values(muid); QStringList names; // now, reorder the cards using the ordered list of names QMap orderedMaps; foreach(QVariantMap map, maps) { if(names.isEmpty()) names = map.contains("names") ? map.value("names").toStringList() : QStringList(); QString name = map.value("name").toString(); int index = names.indexOf(name); orderedMaps.insertMulti(index, map); } // clean variables cardName = ""; cardCost = ""; cmc = ""; cardType = ""; cardPT = ""; cardText = ""; colors.clear(); // this is currently an integer; can't accept 2 values cardLoyalty = 0; // loop cards and merge their contents QString prefix = QString(" // "); QString prefix2 = QString("\n\n---\n\n"); foreach(QVariantMap map, orderedMaps.values()) { if(map.contains("name")) { if(!cardName.isEmpty()) cardName += prefix; cardName += map.value("name").toString(); } if(map.contains("manaCost")) { if(!cardCost.isEmpty()) cardCost += prefix; cardCost += map.value("manaCost").toString(); } if(map.contains("cmc")) { if(!cmc.isEmpty()) cmc += prefix; cmc += map.value("cmc").toString(); } if(map.contains("type")) { if(!cardType.isEmpty()) cardType += prefix; cardType += map.value("type").toString(); } if(map.contains("power") || map.contains("toughness")) { if(!cardPT.isEmpty()) cardPT += prefix; cardPT += map.value("power").toString() + QString('/') + map.value("toughness").toString(); } if(map.contains("text")) { if(!cardText.isEmpty()) cardText += prefix2; cardText += map.value("text").toString(); } extractColors(map.value("colors").toStringList(), colors); } colors.removeDuplicates(); relatedCards = QStringList(); upsideDown = false; // add the card CardInfo *card = addCard(set->getShortName(), cardName, false, muid, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, upsideDown); if (!set->contains(card)) { card->addToSet(set); cards++; } } return cards; } int OracleImporter::startImport() { clear(); int setCards = 0, setIndex= 0; QListIterator it(allSets); const SetToDownload * curSet; // add an empty set for tokens CardSet *tokenSet = new CardSet(TOKENS_SETNAME, tr("Dummy set containing tokens"), "Tokens"); sets.insert(TOKENS_SETNAME, tokenSet); while (it.hasNext()) { curSet = & it.next(); CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName(), curSet->getSetType(), curSet->getReleaseDate()); if (!sets.contains(set->getShortName())) sets.insert(set->getShortName(), set); int setCards = importTextSpoiler(set, curSet->getCards()); ++setIndex; emit setIndexChanged(setCards, setIndex, curSet->getLongName()); } emit setIndexChanged(setCards, setIndex, QString()); // total number of sets return setIndex; }