reworked card database

This commit is contained in:
Max-Wilhelm Bruker 2009-06-20 00:22:50 +02:00
parent be9ac2e061
commit 9b1adf2dc1
10 changed files with 327 additions and 113 deletions

View file

@ -3,22 +3,47 @@
#include <QDirIterator>
#include <QFile>
#include <QTextStream>
#include <QSettings>
CardInfo::CardInfo(const QString &_name, const QString &_manacost, const QString &_cardtype, const QString &_powtough, const QStringList &_text)
: name(_name), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), pixmap(NULL)
CardSet::CardSet(const QString &_shortName, const QString &_longName)
: shortName(_shortName), longName(_longName)
{
updateSortKey();
}
CardInfo::CardInfo(QDataStream &stream)
: pixmap(NULL)
void CardSet::loadFromStream(QDataStream &stream)
{
stream >> shortName >> longName;
updateSortKey();
qDebug(QString("set loaded: %1, %2").arg(shortName).arg(longName).toLatin1());
}
void CardSet::saveToStream(QDataStream &stream)
{
stream << shortName << longName;
}
void CardSet::setSortKey(unsigned int _sortKey)
{
sortKey = _sortKey;
QSettings settings;
settings.beginGroup("sets");
settings.beginGroup(shortName);
settings.setValue("sortkey", sortKey);
}
void CardSet::updateSortKey()
{
QSettings settings;
settings.beginGroup("sets");
settings.beginGroup(shortName);
sortKey = settings.value("sortkey", 0).toInt();
}
CardInfo::CardInfo(CardDatabase *_db, const QString &_name, const QString &_manacost, const QString &_cardtype, const QString &_powtough, const QStringList &_text)
: db(_db), name(_name), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), pixmap(NULL)
{
stream >> name
>> editions
>> manacost
>> cardtype
>> powtough
>> text;
}
CardInfo::~CardInfo()
@ -64,12 +89,20 @@ QString CardInfo::getMainCardType() const
return result;
}
void CardInfo::addEdition(const QString &edition)
void CardInfo::addToSet(CardSet *set)
{
if (!editions.contains(edition))
editions << edition;
set->append(this);
sets << set;
}
class CardInfo::SetCompareFunctor {
public:
inline bool operator()(CardSet *a, CardSet *b) const
{
return a->getSortKey() < b->getSortKey();
}
};
QPixmap *CardInfo::loadPixmap()
{
if (pixmap)
@ -79,13 +112,19 @@ QPixmap *CardInfo::loadPixmap()
pixmap->load("../pics/back.jpg");
return pixmap;
}
qDebug(QString("CardDatabase: loading pixmap for '%1'").arg(getName()).toLatin1());
for (int i = 0; i < editions.size(); i++) {
qSort(sets.begin(), sets.end(), SetCompareFunctor());
QString debugOutput = QString("CardDatabase: loading pixmap for '%1' from ").arg(getName());
for (int i = 0; i < sets.size(); i++)
debugOutput.append(QString("%1, ").arg(sets[i]->getShortName()));
qDebug(debugOutput.toLatin1());
for (int i = 0; i < sets.size(); i++) {
// Fire // Ice, Circle of Protection: Red
QString correctedName = getName().remove(" // ").remove(":");
if (pixmap->load(QString("../pics/%1/%2.full.jpg").arg(editions.at(i)).arg(correctedName)))
if (pixmap->load(QString("../pics/%1/%2.full.jpg").arg(sets[i]->getShortName()).arg(correctedName)))
return pixmap;
if (pixmap->load(QString("../pics/%1/%2%3.full.jpg").arg(editions.at(i)).arg(correctedName).arg(1)))
if (pixmap->load(QString("../pics/%1/%2%3.full.jpg").arg(sets[i]->getShortName()).arg(correctedName).arg(1)))
return pixmap;
}
return pixmap;
@ -95,11 +134,8 @@ QPixmap *CardInfo::getPixmap(QSize size)
{
qDebug(QString("CardInfo::getPixmap(%1, %2) for %3").arg(size.width()).arg(size.height()).arg(getName()).toLatin1());
QPixmap *cachedPixmap = scaledPixmapCache.value(size.width());
if (cachedPixmap) {
qDebug("cache HIT");
if (cachedPixmap)
return cachedPixmap;
}
qDebug("cache MISS");
QPixmap *bigPixmap = loadPixmap();
if (bigPixmap->isNull())
return 0;
@ -108,10 +144,28 @@ QPixmap *CardInfo::getPixmap(QSize size)
return result;
}
void CardInfo::loadFromStream(QDataStream &stream)
{
QStringList setNames;
stream >> name
>> setNames
>> manacost
>> cardtype
>> powtough
>> text;
for (int i = 0; i < setNames.size(); i++)
addToSet(db->getSet(setNames[i]));
}
void CardInfo::saveToStream(QDataStream &stream)
{
QStringList setNames;
for (int i = 0; i < sets.size(); i++)
setNames << sets[i]->getShortName();
stream << name
<< editions
<< setNames
<< manacost
<< cardtype
<< powtough
@ -120,6 +174,8 @@ void CardInfo::saveToStream(QDataStream &stream)
CardDatabase::CardDatabase()
{
noCard = new CardInfo(this);
noCard->loadPixmap(); // cache pixmap for card back
}
CardDatabase::~CardDatabase()
@ -129,57 +185,57 @@ CardDatabase::~CardDatabase()
void CardDatabase::clear()
{
QHashIterator<QString, CardInfo *> i(hash);
QHashIterator<QString, CardSet *> setIt(setHash);
while (setIt.hasNext()) {
setIt.next();
delete setIt.value();
}
setHash.clear();
QHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
delete i.value();
}
hash.clear();
cardHash.clear();
}
CardInfo *CardDatabase::getCard(const QString &cardName)
{
if (hash.contains(cardName))
return hash.value(cardName);
if (cardName.isEmpty())
return noCard;
else if (cardHash.contains(cardName))
return cardHash.value(cardName);
else {
qDebug(QString("CardDatabase: card not found: %1").arg(cardName).toLatin1());
CardInfo *newCard = new CardInfo(cardName);
newCard->addEdition("TK");
hash.insert(cardName, newCard);
CardInfo *newCard = new CardInfo(this, cardName);
newCard->addToSet(getSet("TK"));
cardHash.insert(cardName, newCard);
return newCard;
}
}
QList<CardInfo *>CardDatabase::getCardList()
CardSet *CardDatabase::getSet(const QString &setName)
{
QList<CardInfo *> cardList;
QHashIterator<QString, CardInfo *> i(hash);
while (i.hasNext()) {
i.next();
cardList.append(i.value());
if (setHash.contains(setName))
return setHash.value(setName);
else {
qDebug(QString("CardDatabase: set not found: %1").arg(setName).toLatin1());
CardSet *newSet = new CardSet(setName);
setHash.insert(setName, newSet);
return newSet;
}
return cardList;
}
void CardDatabase::importOracle()
void CardDatabase::importOracleFile(const QString &fileName, CardSet *set)
{
clear();
QDir dir("../db");
// XXX User soll selber auswählen können, welche Karten ihm am besten gefallen.
// XXX Muss momentan schmutzig über Zahlen vor den Dateinamen gemacht werden.
dir.setSorting(QDir::Name | QDir::IgnoreCase);
QFileInfoList files = dir.entryInfoList(QStringList() << "*.txt");
for (int k = 0; k < files.size(); k++) {
QFileInfo i = files[k];
QString edition = i.fileName().mid(i.fileName().indexOf('_') + 1);
edition = edition.left(edition.indexOf('.'));
QFile file(i.filePath());
QFile file(fileName);
file.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream in(&file);
while (!in.atEnd()) {
QString cardname = in.readLine();
if (cardname.isEmpty())
continue;
QString manacost = in.readLine();
QString cardtype, powtough;
QStringList text;
@ -202,21 +258,38 @@ void CardDatabase::importOracle()
line = in.readLine();
}
CardInfo *card;
if (hash.contains(cardname))
card = hash.value(cardname);
if (cardHash.contains(cardname))
card = cardHash.value(cardname);
else {
card = new CardInfo(cardname, manacost, cardtype, powtough, text);
hash.insert(cardname, card);
card = new CardInfo(this, cardname, manacost, cardtype, powtough, text);
cardHash.insert(cardname, card);
}
card->addEdition(edition);
card->addToSet(set);
}
}
void CardDatabase::importOracleDir()
{
clear();
QDir dir("../db");
// XXX User soll selber auswählen können, welche Karten ihm am besten gefallen.
// XXX Muss momentan schmutzig über Zahlen vor den Dateinamen gemacht werden.
dir.setSorting(QDir::Name | QDir::IgnoreCase);
QFileInfoList files = dir.entryInfoList(QStringList() << "*.txt");
for (int k = 0; k < files.size(); k++) {
QFileInfo i = files[k];
QString shortName = i.fileName().left(i.fileName().indexOf('_'));
QString longName = i.fileName().mid(i.fileName().indexOf('_') + 1);
longName = longName.left(longName.indexOf('.'));
CardSet *set = new CardSet(shortName, longName);
setHash.insert(shortName, set);
importOracleFile(i.filePath(), set);
}
qDebug(QString("CardDatabase: %1 cards imported").arg(hash.size()).toLatin1());
CardInfo *empty = new CardInfo();
empty->loadPixmap(); // cache pixmap for card back
hash.insert("", empty);
qDebug(QString("CardDatabase: %1 cards imported").arg(cardHash.size()).toLatin1());
}
int CardDatabase::loadFromFile(const QString &fileName)
@ -226,9 +299,10 @@ int CardDatabase::loadFromFile(const QString &fileName)
QDataStream in(&file);
in.setVersion(QDataStream::Qt_4_4);
quint32 _magicNumber, _fileVersion, cardCount;
quint32 _magicNumber, _fileVersion, setCount, cardCount;
in >> _magicNumber
>> _fileVersion
>> setCount
>> cardCount;
if (_magicNumber != magicNumber)
@ -237,11 +311,20 @@ int CardDatabase::loadFromFile(const QString &fileName)
return -2;
clear();
hash.reserve(cardCount);
for (unsigned int i = 0; i < cardCount; i++) {
CardInfo *newCard = new CardInfo(in);
hash.insert(newCard->getName(), newCard);
setHash.reserve(setCount);
qDebug(QString("setCount = %1").arg(setCount).toLatin1());
for (unsigned int i = 0; i < setCount; i++) {
CardSet *newSet = new CardSet;
newSet->loadFromStream(in);
setHash.insert(newSet->getShortName(), newSet);
}
cardHash.reserve(cardCount);
for (unsigned int i = 0; i < cardCount; i++) {
CardInfo *newCard = new CardInfo(this);
newCard->loadFromStream(in);
cardHash.insert(newCard->getName(), newCard);
}
qDebug(QString("%1 cards in %2 sets loaded").arg(cardCount).arg(setHash.size()).toLatin1());
return cardCount;
}
@ -255,9 +338,15 @@ bool CardDatabase::saveToFile(const QString &fileName)
out << (quint32) magicNumber
<< (quint32) fileVersion
<< (quint32) hash.size();
<< (quint32) setHash.size()
<< (quint32) cardHash.size();
QHashIterator<QString, CardInfo *> i(hash);
QHashIterator<QString, CardSet *> setIt(setHash);
while (setIt.hasNext()) {
setIt.next();
setIt.value()->saveToStream(out);
}
QHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
i.value()->saveToStream(out);

View file

@ -5,11 +5,33 @@
#include <QPixmap>
#include <QMap>
#include <QDataStream>
#include <QList>
class CardDatabase;
class CardInfo;
class CardSet : public QList<CardInfo *> {
private:
QString shortName, longName;
unsigned int sortKey;
public:
CardSet(const QString &_shortName = QString(), const QString &_longName = QString());
QString getShortName() const { return shortName; }
QString getLongName() const { return longName; }
int getSortKey() const { return sortKey; }
void setSortKey(unsigned int _sortKey);
void updateSortKey();
void loadFromStream(QDataStream &stream);
void saveToStream(QDataStream &stream);
};
class CardInfo {
private:
class SetCompareFunctor;
CardDatabase *db;
QString name;
QStringList editions;
QList<CardSet *> sets;
QString manacost;
QString cardtype;
QString powtough;
@ -17,29 +39,32 @@ private:
QPixmap *pixmap;
QMap<int, QPixmap *> scaledPixmapCache;
public:
CardInfo(const QString &_name = QString(),
CardInfo(CardDatabase *_db,
const QString &_name = QString(),
const QString &_manacost = QString(),
const QString &_cardtype = QString(),
const QString &_powtough = QString(),
const QStringList &_text = QStringList());
CardInfo(QDataStream &stream);
~CardInfo();
QString getName() const { return name; }
QStringList getEditions() const { return editions; }
QList<CardSet *> getSets() const { return sets; }
QString getManacost() const { return manacost; }
QString getCardType() const { return cardtype; }
QString getPowTough() const { return powtough; }
QStringList getText() const { return text; }
QString getMainCardType() const;
void addEdition(const QString &edition);
void addToSet(CardSet *set);
QPixmap *loadPixmap();
QPixmap *getPixmap(QSize size);
void loadFromStream(QDataStream &stream);
void saveToStream(QDataStream &stream);
};
class CardDatabase {
private:
QHash<QString, CardInfo *> hash;
QHash<QString, CardInfo *> cardHash;
QHash<QString, CardSet *> setHash;
CardInfo *noCard;
static const unsigned int magicNumber = 0x12345678;
static const unsigned int fileVersion = 1;
public:
@ -47,8 +72,10 @@ public:
~CardDatabase();
void clear();
CardInfo *getCard(const QString &cardName = QString());
QList<CardInfo *> getCardList();
void importOracle();
CardSet *getSet(const QString &setName);
QList<CardInfo *> getCardList() { return cardHash.values(); }
void importOracleFile(const QString &fileName, CardSet *set);
void importOracleDir();
int loadFromFile(const QString &fileName);
bool saveToFile(const QString &fileName);
};

View file

@ -33,7 +33,13 @@ QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const
CardInfo *card = cardList.at(index.row());
switch (index.column()){
case 0: return card->getName();
case 1: return card->getEditions().join(", ");
case 1: {
QStringList setList;
QList<CardSet *> sets = card->getSets();
for (int i = 0; i < sets.size(); i++)
setList << sets[i]->getShortName();
return setList.join(", ");
}
case 2: return card->getManacost();
case 3: return card->getCardType();
case 4: return card->getPowTough();
@ -68,7 +74,7 @@ public:
bool result;
switch (column) {
case 0: result = (a->getName() < b->getName()); break;
case 1: result = (a->getEditions().join("") < b->getEditions().join("")); break;
case 1: result = (a->getSets().at(0)->getShortName() < b->getSets().at(0)->getShortName()); break;
case 2: result = (a->getManacost() < b->getManacost()); break;
case 3: result = (a->getCardType() < b->getCardType()); break;
case 4: result = (a->getPowTough() < b->getPowTough()); break;

View file

@ -12,8 +12,8 @@
#include "playerarea.h"
#include "counter.h"
Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName)
: QObject(), actionsMenu(_actionsMenu), cardMenu(_cardMenu), db(_db), client(_client), scene(_scene), started(false)
Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName, QObject *parent)
: QObject(parent), actionsMenu(_actionsMenu), cardMenu(_cardMenu), db(_db), client(_client), scene(_scene), started(false)
{
QRectF sr = scene->sceneRect();
localPlayer = addPlayer(playerId, playerName, QPointF(0, sr.y() + sr.height() / 2 + 2), true);

View file

@ -74,7 +74,7 @@ signals:
void logSetDoesntUntap(QString playerName, QString cardName, bool doesntUntap);
void logDumpZone(QString playerName, QString zoneName, QString zoneOwner, int numberCards);
public:
Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName);
Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName, QObject *parent = 0);
~Game();
Player *getLocalPlayer() const { return localPlayer; }
void restartGameDialog();

View file

@ -22,9 +22,10 @@
#include <QApplication>
#include <QTextCodec>
#include <QtPlugin>
#include "window_main.h"
#include <stdio.h>
#include "window_main.h"
//Q_IMPORT_PLUGIN(qjpeg)
void myMessageOutput(QtMsgType type, const char *msg)

View file

@ -120,6 +120,14 @@ void MainWindow::actDeckEditor()
deckEditor->show();
}
void MainWindow::actFullScreen(bool checked)
{
if (checked)
setWindowState(windowState() | Qt::WindowFullScreen);
else
setWindowState(windowState() & ~Qt::WindowFullScreen);
}
void MainWindow::actExit()
{
close();
@ -149,7 +157,7 @@ void MainWindow::buttonSay()
void MainWindow::playerIdReceived(int id, QString name)
{
game = new Game(db, client, scene, actionsMenu, cardMenu, id, name);
game = new Game(db, client, scene, actionsMenu, cardMenu, id, name, this);
connect(game, SIGNAL(hoverCard(QString)), this, SLOT(hoverCard(QString)));
connect(game, SIGNAL(playerAdded(Player *)), this, SLOT(playerAdded(Player *)));
connect(game, SIGNAL(playerRemoved(Player *)), this, SLOT(playerRemoved(Player *)));
@ -187,6 +195,10 @@ void MainWindow::createActions()
connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
aDeckEditor = new QAction(tr("&Deck editor"), this);
connect(aDeckEditor, SIGNAL(triggered()), this, SLOT(actDeckEditor()));
aFullScreen = new QAction(tr("&Full screen"), this);
aFullScreen->setShortcut(tr("F4"));
aFullScreen->setCheckable(true);
connect(aFullScreen, SIGNAL(toggled(bool)), this, SLOT(actFullScreen(bool)));
aExit = new QAction(tr("&Exit"), this);
connect(aExit, SIGNAL(triggered()), this, SLOT(actExit()));
@ -208,6 +220,8 @@ void MainWindow::createMenus()
gameMenu->addSeparator();
gameMenu->addAction(aDeckEditor);
gameMenu->addSeparator();
gameMenu->addAction(aFullScreen);
gameMenu->addSeparator();
gameMenu->addAction(aExit);
actionsMenu = menuBar()->addMenu(tr("&Actions"));
@ -224,7 +238,8 @@ MainWindow::MainWindow(QWidget *parent)
db = new CardDatabase;
int cardCount = db->loadFromFile("../cards.dat");
qDebug(QString("%1 cards loaded").arg(cardCount).toLatin1());
// db->importOracleDir();
// db->saveToFile("../cards.dat");
scene = new QGraphicsScene(0, 0, 952, 1024, this);
view = new GameView(scene);
@ -253,7 +268,7 @@ MainWindow::MainWindow(QWidget *parent)
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(view);
mainLayout->setStretchFactor(view, 10);
// mainLayout->setStretchFactor(view, 10);
mainLayout->addLayout(verticalLayout);
QWidget *centralWidget = new QWidget;
@ -280,6 +295,4 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::closeEvent(QCloseEvent */*event*/)
{
delete game;
delete db;
}

View file

@ -56,6 +56,7 @@ private slots:
void actRestartGame();
void actLeaveGame();
void actDeckEditor();
void actFullScreen(bool checked);
void actExit();
void updateSceneSize();
@ -66,7 +67,7 @@ private:
void createActions();
void createMenus();
QMenu *gameMenu, *actionsMenu, *cardMenu;
QAction *aConnect, *aDisconnect, *aGames, *aRestartGame, *aLeaveGame, *aDeckEditor, *aExit;
QAction *aConnect, *aDisconnect, *aGames, *aRestartGame, *aLeaveGame, *aDeckEditor, *aFullScreen, *aExit;
QAction *aCloseMostRecentZoneView;
CardInfoWidget *cardInfo;

10
crystalkeep.sh Normal file
View file

@ -0,0 +1,10 @@
#!/bin/bash
while read; do
filename=`echo $REPLY | cut '-d,' -f 1`
edition=`echo $REPLY | cut '-d,' -f 2`
editionLong=`echo $REPLY | cut '-d,' -f 3`
wget http://www.crystalkeep.com/magic/rules/oracle/oracle-$filename.txt
mv oracle-$filename.txt "${edition}_${editionLong}.txt"
done

67
crystalkeep.txt Normal file
View file

@ -0,0 +1,67 @@
10,10E,Tenth Edition
ar,ARB,Alara Reborn
cf,CFX,Conflux
sa,ALA,Shards of Alara
et,EVE,Eventide
sm,SHM,Shadowmoor
mt,MOR,Morningtide
lo,LRW,Lorwyn
9th,9E,Ninth Edition
8th,8E,Eighth Edition
fs,FUT,Future Sight
pc,PLC,Planar Chaos
ts,TSP,Time Spiral
cs,CS,Coldsnap
di,DIS,Dissension
gp,GP,Guildpact
ra,RAV,Ravnica
sk,SOK,Saviors of Kamigawa
bk,BOK,Betrayers of Kamigawa
ck,CHK,Champions of Kamigawa
fd,FD,Fifth Dawn
ds,DS,Darksteel
mr,MR,Mirrodin
sc,SC,Scourge
le,LE,Legions
on,ON,Onslaught
7th,7E,Seventh Edition
6th,6E,Sixth Edition
5th,5E,Fifth Edition
4th,4E,Fourth Edition
rv,R,Revised Edition
lu,U,Unlimited Edition
lu,B,Limited Edition
ju,JU,Judgment
to,TO,Torment
od,OD,Odyssey
ap,AP,Apocalypse
ps,PS,Planeshift
in,IN,Invasion
py,PY,Prophecy
ne,NE,Nemesis
mm,MM,Mercadian Masques
ud,UD,Urza's Destiny
ul,UL,Urza's Legacy
us,US,Urza's Saga
ex,EX,Exodus
sh,SH,Stronghold
te,TE,Tempest
wl,WL,Weatherlight
vi,VI,Visions
mi,MI,Mirage
al,AL,Alliances
hl,HL,Homelands
ia,IA,Ice Age
ch,CH,Chronicles
fe,FE,Fallen Empires
dk,DK,The Dark
lg,LG,Legends
aq,AQ,Antiquities
an,AN,Arabian Nights
pt,PT,Portal
pt2,P2,Portal: Second Age
pt3,P3,Portal: Three Kingdoms
st,ST,Starter
st2,ST2K,Starter 2000
ug,UG,Unglued
uh,UNH,Unhinged