Merge branch 'master' into cmake-overhaul
This commit is contained in:
commit
39e2bf06f5
41 changed files with 2619 additions and 831 deletions
|
@ -1,4 +1,10 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
|
||||
ADD_DEFINITIONS("-DSFMT_MEXP=19937")
|
||||
ENDIF()
|
||||
|
||||
add_subdirectory(common)
|
||||
if(WITH_SERVER)
|
||||
add_subdirectory(servatrice)
|
||||
|
|
|
@ -3,158 +3,174 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
|||
PROJECT(cockatrice)
|
||||
|
||||
SET(cockatrice_SOURCES
|
||||
src/abstractcounter.cpp
|
||||
src/counter_general.cpp
|
||||
src/dlg_creategame.cpp
|
||||
src/abstractcounter.cpp
|
||||
src/counter_general.cpp
|
||||
src/dlg_creategame.cpp
|
||||
src/dlg_filter_games.cpp
|
||||
src/dlg_connect.cpp
|
||||
src/dlg_create_token.cpp
|
||||
src/dlg_connect.cpp
|
||||
src/dlg_create_token.cpp
|
||||
src/dlg_edit_tokens.cpp
|
||||
src/abstractclient.cpp
|
||||
src/remoteclient.cpp
|
||||
src/main.cpp
|
||||
src/window_main.cpp
|
||||
src/gamesmodel.cpp
|
||||
src/player.cpp
|
||||
src/playertarget.cpp
|
||||
src/cardzone.cpp
|
||||
src/selectzone.cpp
|
||||
src/cardlist.cpp
|
||||
src/abstractcarditem.cpp
|
||||
src/carditem.cpp
|
||||
src/tablezone.cpp
|
||||
src/handzone.cpp
|
||||
src/handcounter.cpp
|
||||
src/carddatabase.cpp
|
||||
src/gameview.cpp
|
||||
src/gameselector.cpp
|
||||
src/decklistmodel.cpp
|
||||
src/deck_loader.cpp
|
||||
src/dlg_load_deck_from_clipboard.cpp
|
||||
src/dlg_load_remote_deck.cpp
|
||||
src/cardinfowidget.cpp
|
||||
src/messagelogwidget.cpp
|
||||
src/zoneviewzone.cpp
|
||||
src/zoneviewwidget.cpp
|
||||
src/pilezone.cpp
|
||||
src/stackzone.cpp
|
||||
src/carddragitem.cpp
|
||||
src/carddatabasemodel.cpp
|
||||
src/setsmodel.cpp
|
||||
src/window_sets.cpp
|
||||
src/abstractgraphicsitem.cpp
|
||||
src/abstractcarddragitem.cpp
|
||||
src/dlg_settings.cpp
|
||||
src/dlg_cardsearch.cpp
|
||||
src/phasestoolbar.cpp
|
||||
src/gamescene.cpp
|
||||
src/arrowitem.cpp
|
||||
src/arrowtarget.cpp
|
||||
src/tab.cpp
|
||||
src/tab_server.cpp
|
||||
src/tab_room.cpp
|
||||
src/tab_message.cpp
|
||||
src/tab_game.cpp
|
||||
src/tab_deck_storage.cpp
|
||||
src/tab_replays.cpp
|
||||
src/tab_supervisor.cpp
|
||||
src/tab_admin.cpp
|
||||
src/tab_userlists.cpp
|
||||
src/abstractclient.cpp
|
||||
src/remoteclient.cpp
|
||||
src/main.cpp
|
||||
src/window_main.cpp
|
||||
src/gamesmodel.cpp
|
||||
src/player.cpp
|
||||
src/playertarget.cpp
|
||||
src/cardzone.cpp
|
||||
src/selectzone.cpp
|
||||
src/cardlist.cpp
|
||||
src/abstractcarditem.cpp
|
||||
src/carditem.cpp
|
||||
src/tablezone.cpp
|
||||
src/handzone.cpp
|
||||
src/handcounter.cpp
|
||||
src/carddatabase.cpp
|
||||
src/keysignals.cpp
|
||||
src/gameview.cpp
|
||||
src/gameselector.cpp
|
||||
src/decklistmodel.cpp
|
||||
src/deck_loader.cpp
|
||||
src/dlg_load_deck_from_clipboard.cpp
|
||||
src/dlg_load_remote_deck.cpp
|
||||
src/cardinfowidget.cpp
|
||||
src/cardframe.cpp
|
||||
src/cardinfopicture.cpp
|
||||
src/cardinfotext.cpp
|
||||
src/filterbuilder.cpp
|
||||
src/cardfilter.cpp
|
||||
src/filtertreemodel.cpp
|
||||
src/filtertree.cpp
|
||||
src/messagelogwidget.cpp
|
||||
src/zoneviewzone.cpp
|
||||
src/zoneviewwidget.cpp
|
||||
src/pilezone.cpp
|
||||
src/stackzone.cpp
|
||||
src/carddragitem.cpp
|
||||
src/carddatabasemodel.cpp
|
||||
src/setsmodel.cpp
|
||||
src/window_sets.cpp
|
||||
src/abstractgraphicsitem.cpp
|
||||
src/abstractcarddragitem.cpp
|
||||
src/dlg_settings.cpp
|
||||
src/dlg_cardsearch.cpp
|
||||
src/phasestoolbar.cpp
|
||||
src/gamescene.cpp
|
||||
src/arrowitem.cpp
|
||||
src/arrowtarget.cpp
|
||||
src/tab.cpp
|
||||
src/tab_server.cpp
|
||||
src/tab_room.cpp
|
||||
src/tab_message.cpp
|
||||
src/tab_game.cpp
|
||||
src/tab_deck_storage.cpp
|
||||
src/tab_replays.cpp
|
||||
src/tab_supervisor.cpp
|
||||
src/tab_admin.cpp
|
||||
src/tab_userlists.cpp
|
||||
src/tab_deck_editor.cpp
|
||||
src/replay_timeline_widget.cpp
|
||||
src/deckstats_interface.cpp
|
||||
src/chatview.cpp
|
||||
src/userlist.cpp
|
||||
src/userinfobox.cpp
|
||||
src/chatview.cpp
|
||||
src/userlist.cpp
|
||||
src/userinfobox.cpp
|
||||
src/user_context_menu.cpp
|
||||
src/remotedecklist_treewidget.cpp
|
||||
src/remotereplaylist_treewidget.cpp
|
||||
src/deckview.cpp
|
||||
src/playerlistwidget.cpp
|
||||
src/pixmapgenerator.cpp
|
||||
src/settingscache.cpp
|
||||
src/localserver.cpp
|
||||
src/localserverinterface.cpp
|
||||
src/localclient.cpp
|
||||
src/priceupdater.cpp
|
||||
src/remotedecklist_treewidget.cpp
|
||||
src/remotereplaylist_treewidget.cpp
|
||||
src/deckview.cpp
|
||||
src/playerlistwidget.cpp
|
||||
src/pixmapgenerator.cpp
|
||||
src/settingscache.cpp
|
||||
src/localserver.cpp
|
||||
src/localserverinterface.cpp
|
||||
src/localclient.cpp
|
||||
src/priceupdater.cpp
|
||||
src/qt-json/json.cpp
|
||||
src/soundengine.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp
|
||||
)
|
||||
SET(cockatrice_HEADERS
|
||||
src/abstractcounter.h
|
||||
src/counter_general.h
|
||||
src/dlg_creategame.h
|
||||
src/dlg_filter_games.h
|
||||
src/dlg_connect.h
|
||||
src/dlg_create_token.h
|
||||
src/abstractcounter.h
|
||||
src/counter_general.h
|
||||
src/dlg_creategame.h
|
||||
src/dlg_filter_games.h
|
||||
src/dlg_connect.h
|
||||
src/dlg_create_token.h
|
||||
src/dlg_edit_tokens.h
|
||||
src/gamesmodel.h
|
||||
src/abstractclient.h
|
||||
src/remoteclient.h
|
||||
src/window_main.h
|
||||
src/cardzone.h
|
||||
src/selectzone.h
|
||||
src/player.h
|
||||
src/playertarget.h
|
||||
src/abstractcarditem.h
|
||||
src/carditem.h
|
||||
src/tablezone.h
|
||||
src/handzone.h
|
||||
src/handcounter.h
|
||||
src/carddatabase.h
|
||||
src/gameview.h
|
||||
src/gameselector.h
|
||||
src/decklistmodel.h
|
||||
src/deck_loader.h
|
||||
src/dlg_load_deck_from_clipboard.h
|
||||
src/dlg_load_remote_deck.h
|
||||
src/cardinfowidget.h
|
||||
src/messagelogwidget.h
|
||||
src/zoneviewzone.h
|
||||
src/zoneviewwidget.h
|
||||
src/pilezone.h
|
||||
src/stackzone.h
|
||||
src/carddragitem.h
|
||||
src/carddatabasemodel.h
|
||||
src/setsmodel.h
|
||||
src/window_sets.h
|
||||
src/abstractgraphicsitem.h
|
||||
src/abstractcarddragitem.h
|
||||
src/dlg_settings.h
|
||||
src/dlg_cardsearch.h
|
||||
src/phasestoolbar.h
|
||||
src/gamescene.h
|
||||
src/arrowitem.h
|
||||
src/arrowtarget.h
|
||||
src/tab.h
|
||||
src/tab_server.h
|
||||
src/tab_room.h
|
||||
src/tab_message.h
|
||||
src/tab_game.h
|
||||
src/tab_deck_storage.h
|
||||
src/tab_replays.h
|
||||
src/tab_supervisor.h
|
||||
src/tab_admin.h
|
||||
src/tab_userlists.h
|
||||
src/gamesmodel.h
|
||||
src/abstractclient.h
|
||||
src/remoteclient.h
|
||||
src/window_main.h
|
||||
src/cardzone.h
|
||||
src/selectzone.h
|
||||
src/player.h
|
||||
src/playertarget.h
|
||||
src/abstractcarditem.h
|
||||
src/carditem.h
|
||||
src/tablezone.h
|
||||
src/handzone.h
|
||||
src/handcounter.h
|
||||
src/carddatabase.h
|
||||
src/keysignals.h
|
||||
src/gameview.h
|
||||
src/gameselector.h
|
||||
src/decklistmodel.h
|
||||
src/deck_loader.h
|
||||
src/dlg_load_deck_from_clipboard.h
|
||||
src/dlg_load_remote_deck.h
|
||||
src/cardinfowidget.h
|
||||
src/cardframe.h
|
||||
src/cardinfopicture.h
|
||||
src/cardinfotext.h
|
||||
src/filterbuilder.h
|
||||
src/cardfilter.h
|
||||
src/filtertreemodel.h
|
||||
src/filtertree.h
|
||||
src/messagelogwidget.h
|
||||
src/zoneviewzone.h
|
||||
src/zoneviewwidget.h
|
||||
src/pilezone.h
|
||||
src/stackzone.h
|
||||
src/carddragitem.h
|
||||
src/carddatabasemodel.h
|
||||
src/setsmodel.h
|
||||
src/window_sets.h
|
||||
src/abstractgraphicsitem.h
|
||||
src/abstractcarddragitem.h
|
||||
src/dlg_settings.h
|
||||
src/dlg_cardsearch.h
|
||||
src/phasestoolbar.h
|
||||
src/gamescene.h
|
||||
src/arrowitem.h
|
||||
src/arrowtarget.h
|
||||
src/tab.h
|
||||
src/tab_server.h
|
||||
src/tab_room.h
|
||||
src/tab_message.h
|
||||
src/tab_game.h
|
||||
src/tab_deck_storage.h
|
||||
src/tab_replays.h
|
||||
src/tab_supervisor.h
|
||||
src/tab_admin.h
|
||||
src/tab_userlists.h
|
||||
src/tab_deck_editor.h
|
||||
src/replay_timeline_widget.h
|
||||
src/deckstats_interface.h
|
||||
src/chatview.h
|
||||
src/userlist.h
|
||||
src/userinfobox.h
|
||||
src/chatview.h
|
||||
src/userlist.h
|
||||
src/userinfobox.h
|
||||
src/user_context_menu.h
|
||||
src/remotedecklist_treewidget.h
|
||||
src/remotereplaylist_treewidget.h
|
||||
src/deckview.h
|
||||
src/playerlistwidget.h
|
||||
src/settingscache.h
|
||||
src/localserver.h
|
||||
src/localserverinterface.h
|
||||
src/localclient.h
|
||||
src/priceupdater.h
|
||||
src/soundengine.h
|
||||
src/pending_command.h
|
||||
src/remotedecklist_treewidget.h
|
||||
src/remotereplaylist_treewidget.h
|
||||
src/deckview.h
|
||||
src/playerlistwidget.h
|
||||
src/settingscache.h
|
||||
src/localserver.h
|
||||
src/localserverinterface.h
|
||||
src/localclient.h
|
||||
src/priceupdater.h
|
||||
src/soundengine.h
|
||||
src/pending_command.h
|
||||
)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "carddatabasemodel.h"
|
||||
#include "filtertree.h"
|
||||
|
||||
CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent)
|
||||
: QAbstractListModel(parent), db(_db)
|
||||
|
@ -109,6 +110,7 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
|
|||
: QSortFilterProxyModel(parent),
|
||||
isToken(ShowAll)
|
||||
{
|
||||
filterTree = NULL;
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
@ -116,7 +118,6 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
|
|||
bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
||||
{
|
||||
CardInfo const *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
|
||||
|
||||
if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken()))
|
||||
return false;
|
||||
|
||||
|
@ -144,6 +145,9 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex
|
|||
if (!cardTypes.contains(info->getMainCardType()))
|
||||
return false;
|
||||
|
||||
if (filterTree != NULL)
|
||||
return filterTree->acceptsCard(info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -153,5 +157,22 @@ void CardDatabaseDisplayModel::clearSearch()
|
|||
cardText.clear();
|
||||
cardTypes.clear();
|
||||
cardColors.clear();
|
||||
if (filterTree != NULL)
|
||||
filterTree->clear();
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void CardDatabaseDisplayModel::setFilterTree(FilterTree *filterTree)
|
||||
{
|
||||
if (this->filterTree != NULL)
|
||||
disconnect(this->filterTree, 0, this, 0);
|
||||
|
||||
this->filterTree = filterTree;
|
||||
connect(this->filterTree, SIGNAL(changed()), this, SLOT(filterTreeChanged()));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void CardDatabaseDisplayModel::filterTreeChanged()
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <QSet>
|
||||
#include "carddatabase.h"
|
||||
|
||||
class FilterTree;
|
||||
|
||||
class CardDatabaseModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -36,8 +38,10 @@ private:
|
|||
FilterBool isToken;
|
||||
QString cardNameBeginning, cardName, cardText;
|
||||
QSet<QString> cardNameSet, cardTypes, cardColors;
|
||||
FilterTree *filterTree;
|
||||
public:
|
||||
CardDatabaseDisplayModel(QObject *parent = 0);
|
||||
void setFilterTree(FilterTree *filterTree);
|
||||
void setIsToken(FilterBool _isToken) { isToken = _isToken; invalidate(); }
|
||||
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
|
||||
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
|
||||
|
@ -48,6 +52,8 @@ public:
|
|||
void clearSearch();
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
private slots:
|
||||
void filterTreeChanged();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
37
cockatrice/src/cardfilter.cpp
Normal file
37
cockatrice/src/cardfilter.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "cardfilter.h"
|
||||
|
||||
const char *CardFilter::typeName(Type t)
|
||||
{
|
||||
switch (t) {
|
||||
case TypeAnd:
|
||||
return "and";
|
||||
case TypeOr:
|
||||
return "or";
|
||||
case TypeAndNot:
|
||||
return "and not";
|
||||
case TypeOrNot:
|
||||
return "or not";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char *CardFilter::attrName(Attr a)
|
||||
{
|
||||
switch (a) {
|
||||
case AttrName:
|
||||
return "name";
|
||||
case AttrType:
|
||||
return "type";
|
||||
case AttrColor:
|
||||
return "color";
|
||||
case AttrText:
|
||||
return "text";
|
||||
case AttrSet:
|
||||
return "set";
|
||||
case AttrManaCost:
|
||||
return "mana cost";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
44
cockatrice/src/cardfilter.h
Normal file
44
cockatrice/src/cardfilter.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef CARDFILTER_H
|
||||
#define CARDFILTER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class CardFilter {
|
||||
public:
|
||||
enum Type {
|
||||
TypeAnd = 0,
|
||||
TypeOr,
|
||||
TypeAndNot,
|
||||
TypeOrNot,
|
||||
TypeEnd
|
||||
};
|
||||
|
||||
/* if you add an atribute here you also need to
|
||||
* add its string representation in attrName */
|
||||
enum Attr {
|
||||
AttrName = 0,
|
||||
AttrType,
|
||||
AttrColor,
|
||||
AttrText,
|
||||
AttrSet,
|
||||
AttrManaCost,
|
||||
AttrEnd
|
||||
};
|
||||
|
||||
private:
|
||||
enum Type t;
|
||||
enum Attr a;
|
||||
QString trm;
|
||||
|
||||
public:
|
||||
CardFilter(QString term, Type type, Attr attr) : trm(term), t(type), a(attr) {};
|
||||
|
||||
Type type() const { return t; }
|
||||
const QString &term() const { return trm; }
|
||||
Attr attr() const { return a; }
|
||||
|
||||
static const char *typeName(Type t);
|
||||
static const char *attrName(Attr a);
|
||||
};
|
||||
|
||||
#endif
|
59
cockatrice/src/cardframe.cpp
Normal file
59
cockatrice/src/cardframe.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "cardframe.h"
|
||||
|
||||
#include "carditem.h"
|
||||
#include "carddatabase.h"
|
||||
#include "main.h"
|
||||
#include "cardinfopicture.h"
|
||||
#include "cardinfotext.h"
|
||||
|
||||
CardFrame::CardFrame(int width, int height,
|
||||
const QString &cardName, QWidget *parent)
|
||||
: QStackedWidget(parent)
|
||||
, info(0)
|
||||
, cardTextOnly(false)
|
||||
{
|
||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||
setMaximumWidth(width);
|
||||
setMinimumWidth(width);
|
||||
setMaximumHeight(height);
|
||||
setMinimumHeight(height);
|
||||
pic = new CardInfoPicture(width);
|
||||
addWidget(pic);
|
||||
text = new CardInfoText();
|
||||
addWidget(text);
|
||||
connect(pic, SIGNAL(hasPictureChanged()), this, SLOT(hasPictureChanged()));
|
||||
setCard(db->getCard(cardName));
|
||||
}
|
||||
|
||||
void CardFrame::setCard(CardInfo *card)
|
||||
{
|
||||
if (info)
|
||||
disconnect(info, 0, this, 0);
|
||||
info = card;
|
||||
connect(info, SIGNAL(destroyed()), this, SLOT(clear()));
|
||||
text->setCard(info);
|
||||
pic->setCard(info);
|
||||
}
|
||||
|
||||
void CardFrame::setCard(const QString &cardName)
|
||||
{
|
||||
setCard(db->getCard(cardName));
|
||||
}
|
||||
|
||||
void CardFrame::setCard(AbstractCardItem *card)
|
||||
{
|
||||
setCard(card->getInfo());
|
||||
}
|
||||
|
||||
void CardFrame::clear()
|
||||
{
|
||||
setCard(db->getCard());
|
||||
}
|
||||
|
||||
void CardFrame::hasPictureChanged()
|
||||
{
|
||||
if (pic->hasPicture() && !cardTextOnly)
|
||||
setCurrentWidget(pic);
|
||||
else
|
||||
setCurrentWidget(text);
|
||||
}
|
36
cockatrice/src/cardframe.h
Normal file
36
cockatrice/src/cardframe.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef CARDFRAME_H
|
||||
#define CARDFRAME_H
|
||||
|
||||
#include <QStackedWidget>
|
||||
|
||||
class AbstractCardItem;
|
||||
class CardInfo;
|
||||
class CardInfoPicture;
|
||||
class CardInfoText;
|
||||
|
||||
class CardFrame : public QStackedWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
CardInfo *info;
|
||||
CardInfoPicture *pic;
|
||||
CardInfoText *text;
|
||||
bool cardTextOnly;
|
||||
|
||||
public:
|
||||
CardFrame(int width, int height, const QString &cardName = QString(),
|
||||
QWidget *parent = 0);
|
||||
void setCardTextOnly(bool status) { cardTextOnly = status; hasPictureChanged(); }
|
||||
|
||||
public slots:
|
||||
void setCard(CardInfo *card);
|
||||
void setCard(const QString &cardName);
|
||||
void setCard(AbstractCardItem *card);
|
||||
void clear();
|
||||
|
||||
private slots:
|
||||
void hasPictureChanged();
|
||||
void toggleCardTextOnly() { setCardTextOnly(!cardTextOnly); }
|
||||
};
|
||||
|
||||
#endif
|
53
cockatrice/src/cardinfopicture.cpp
Normal file
53
cockatrice/src/cardinfopicture.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "cardinfopicture.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include "carditem.h"
|
||||
#include "carddatabase.h"
|
||||
#include "main.h"
|
||||
|
||||
CardInfoPicture::CardInfoPicture(int maximumWidth, QWidget *parent)
|
||||
: QLabel(parent)
|
||||
, info(0)
|
||||
, noPicture(true)
|
||||
{
|
||||
setMaximumWidth(maximumWidth);
|
||||
}
|
||||
|
||||
void CardInfoPicture::setNoPicture(bool status)
|
||||
{
|
||||
if (noPicture != status) {
|
||||
noPicture = status;
|
||||
emit hasPictureChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void CardInfoPicture::setCard(CardInfo *card)
|
||||
{
|
||||
if (info)
|
||||
disconnect(info, 0, this, 0);
|
||||
info = card;
|
||||
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
|
||||
|
||||
updatePixmap();
|
||||
}
|
||||
|
||||
void CardInfoPicture::updatePixmap()
|
||||
{
|
||||
qreal aspectRatio = (qreal) CARD_HEIGHT / (qreal) CARD_WIDTH;
|
||||
qreal pixmapWidth = this->width();
|
||||
|
||||
if (pixmapWidth == 0) {
|
||||
setNoPicture(true);
|
||||
return;
|
||||
}
|
||||
|
||||
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio));
|
||||
if (resizedPixmap) {
|
||||
setNoPicture(false);
|
||||
this->setPixmap(*resizedPixmap);
|
||||
}
|
||||
else {
|
||||
setNoPicture(true);
|
||||
this->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
||||
}
|
||||
}
|
34
cockatrice/src/cardinfopicture.h
Normal file
34
cockatrice/src/cardinfopicture.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef CARDINFOPICTURE_H
|
||||
#define CARDINFOPICTURE_H
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class AbstractCardItem;
|
||||
class CardInfo;
|
||||
|
||||
class CardInfoPicture : public QLabel {
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void hasPictureChanged();
|
||||
|
||||
private:
|
||||
CardInfo *info;
|
||||
bool noPicture;
|
||||
|
||||
public:
|
||||
CardInfoPicture(int maximumWidth, QWidget *parent = 0);
|
||||
bool hasPicture() const { return !noPicture; }
|
||||
|
||||
private:
|
||||
void setNoPicture(bool status);
|
||||
|
||||
public slots:
|
||||
void setCard(CardInfo *card);
|
||||
|
||||
private slots:
|
||||
void updatePixmap();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
67
cockatrice/src/cardinfotext.cpp
Normal file
67
cockatrice/src/cardinfotext.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "cardinfotext.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QGridLayout>
|
||||
#include "carditem.h"
|
||||
#include "carddatabase.h"
|
||||
#include "main.h"
|
||||
|
||||
CardInfoText::CardInfoText(QWidget *parent)
|
||||
: QFrame(parent)
|
||||
, info(0)
|
||||
{
|
||||
nameLabel1 = new QLabel;
|
||||
nameLabel2 = new QLabel;
|
||||
nameLabel2->setWordWrap(true);
|
||||
manacostLabel1 = new QLabel;
|
||||
manacostLabel2 = new QLabel;
|
||||
manacostLabel2->setWordWrap(true);
|
||||
cardtypeLabel1 = new QLabel;
|
||||
cardtypeLabel2 = new QLabel;
|
||||
cardtypeLabel2->setWordWrap(true);
|
||||
powtoughLabel1 = new QLabel;
|
||||
powtoughLabel2 = new QLabel;
|
||||
loyaltyLabel1 = new QLabel;
|
||||
loyaltyLabel2 = new QLabel;
|
||||
|
||||
textLabel = new QTextEdit();
|
||||
textLabel->setReadOnly(true);
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
int row = 0;
|
||||
grid->addWidget(nameLabel1, row, 0);
|
||||
grid->addWidget(nameLabel2, row++, 1);
|
||||
grid->addWidget(manacostLabel1, row, 0);
|
||||
grid->addWidget(manacostLabel2, row++, 1);
|
||||
grid->addWidget(cardtypeLabel1, row, 0);
|
||||
grid->addWidget(cardtypeLabel2, row++, 1);
|
||||
grid->addWidget(powtoughLabel1, row, 0);
|
||||
grid->addWidget(powtoughLabel2, row++, 1);
|
||||
grid->addWidget(loyaltyLabel1, row, 0);
|
||||
grid->addWidget(loyaltyLabel2, row++, 1);
|
||||
grid->addWidget(textLabel, row, 0, -1, 2);
|
||||
grid->setRowStretch(row, 1);
|
||||
grid->setColumnStretch(1, 1);
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void CardInfoText::setCard(CardInfo *card)
|
||||
{
|
||||
nameLabel2->setText(card->getName());
|
||||
manacostLabel2->setText(card->getManaCost());
|
||||
cardtypeLabel2->setText(card->getCardType());
|
||||
powtoughLabel2->setText(card->getPowTough());
|
||||
loyaltyLabel2->setText(card->getLoyalty() > 0 ? QString::number(card->getLoyalty()) : QString());
|
||||
textLabel->setText(card->getText());
|
||||
}
|
||||
|
||||
void CardInfoText::retranslateUi()
|
||||
{
|
||||
nameLabel1->setText(tr("Name:"));
|
||||
manacostLabel1->setText(tr("Mana cost:"));
|
||||
cardtypeLabel1->setText(tr("Card type:"));
|
||||
powtoughLabel1->setText(tr("P / T:"));
|
||||
loyaltyLabel1->setText(tr("Loyalty:"));
|
||||
}
|
31
cockatrice/src/cardinfotext.h
Normal file
31
cockatrice/src/cardinfotext.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef CARDINFOTEXT_H
|
||||
#define CARDINFOTEXT_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class QLabel;
|
||||
class QTextEdit;
|
||||
class CardInfo;
|
||||
|
||||
class CardInfoText : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QLabel *nameLabel1, *nameLabel2;
|
||||
QLabel *manacostLabel1, *manacostLabel2;
|
||||
QLabel *cardtypeLabel1, *cardtypeLabel2;
|
||||
QLabel *powtoughLabel1, *powtoughLabel2;
|
||||
QLabel *loyaltyLabel1, *loyaltyLabel2;
|
||||
QTextEdit *textLabel;
|
||||
|
||||
CardInfo *info;
|
||||
|
||||
public:
|
||||
CardInfoText(QWidget *parent = 0);
|
||||
void retranslateUi();
|
||||
|
||||
public slots:
|
||||
void setCard(CardInfo *card);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -169,8 +169,7 @@ Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
|
|||
return 0;
|
||||
|
||||
Qt::ItemFlags result = Qt::ItemIsEnabled;
|
||||
if (getNode<DecklistModelCardNode *>(index))
|
||||
result |= Qt::ItemIsSelectable;
|
||||
result |= Qt::ItemIsSelectable;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -236,6 +235,38 @@ InnerDecklistNode *DeckListModel::createNodeIfNeeded(const QString &name, InnerD
|
|||
return newNode;
|
||||
}
|
||||
|
||||
DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName, const QString &zoneName) const
|
||||
{
|
||||
InnerDecklistNode *zoneNode, *typeNode;
|
||||
CardInfo *info;
|
||||
QString cardType;
|
||||
|
||||
zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
|
||||
if(!zoneNode)
|
||||
return NULL;
|
||||
|
||||
info = db->getCard(cardName);
|
||||
if(!info)
|
||||
return NULL;
|
||||
|
||||
cardType = info->getMainCardType();
|
||||
typeNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(cardType));
|
||||
if(!typeNode)
|
||||
return NULL;
|
||||
|
||||
return dynamic_cast<DecklistModelCardNode *>(typeNode->findChild(cardName));
|
||||
}
|
||||
|
||||
QModelIndex DeckListModel::findCard(const QString &cardName, const QString &zoneName) const
|
||||
{
|
||||
DecklistModelCardNode *cardNode;
|
||||
|
||||
cardNode = findCardNode(cardName, zoneName);
|
||||
if(!cardNode)
|
||||
return QModelIndex();
|
||||
return nodeToIndex(cardNode);
|
||||
}
|
||||
|
||||
QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneName)
|
||||
{
|
||||
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
|
||||
QModelIndex addCard(const QString &cardName, const QString &zoneName);
|
||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
void cleanList();
|
||||
|
@ -56,6 +57,7 @@ private:
|
|||
InnerDecklistNode *root;
|
||||
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
|
||||
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
|
||||
DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName) const;
|
||||
void emitRecursiveUpdates(const QModelIndex &index);
|
||||
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
|
||||
|
||||
|
|
84
cockatrice/src/filterbuilder.cpp
Normal file
84
cockatrice/src/filterbuilder.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include "filterbuilder.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "cardfilter.h"
|
||||
|
||||
FilterBuilder::FilterBuilder(QWidget *parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
QHBoxLayout *addFilter = new QHBoxLayout;
|
||||
|
||||
filterCombo = new QComboBox;
|
||||
for (i = 0; i < CardFilter::AttrEnd; i++)
|
||||
filterCombo->addItem(
|
||||
tr(CardFilter::attrName(static_cast<CardFilter::Attr>(i))),
|
||||
QVariant(i)
|
||||
);
|
||||
|
||||
typeCombo = new QComboBox;
|
||||
for (i = 0; i < CardFilter::TypeEnd; i++)
|
||||
typeCombo->addItem(
|
||||
tr(CardFilter::typeName(static_cast<CardFilter::Type>(i))),
|
||||
QVariant(i)
|
||||
);
|
||||
|
||||
QPushButton *ok = new QPushButton("+");
|
||||
ok->setMaximumSize(20, 20);
|
||||
|
||||
addFilter->addWidget(ok);
|
||||
addFilter->addWidget(typeCombo);
|
||||
addFilter->addWidget(filterCombo, Qt::AlignLeft);
|
||||
|
||||
edit = new QLineEdit;
|
||||
edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
layout->addLayout(addFilter);
|
||||
layout->addWidget(edit);
|
||||
|
||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
connect(edit, SIGNAL(returnPressed()), this, SLOT(emit_add()));
|
||||
connect(ok, SIGNAL(released()), this, SLOT(emit_add()));
|
||||
connect(filterCombo, SIGNAL(currentIndexChanged(int)), edit, SLOT(clear()));
|
||||
fltr = NULL;
|
||||
}
|
||||
|
||||
FilterBuilder::~FilterBuilder()
|
||||
{
|
||||
destroyFilter();
|
||||
}
|
||||
|
||||
void FilterBuilder::destroyFilter()
|
||||
{
|
||||
if (fltr)
|
||||
delete fltr;
|
||||
}
|
||||
|
||||
static int comboCurrentIntData(const QComboBox *combo)
|
||||
{
|
||||
return combo->itemData(combo->currentIndex()).toInt();
|
||||
}
|
||||
|
||||
void FilterBuilder::emit_add()
|
||||
{
|
||||
QString txt;
|
||||
|
||||
txt = edit->text();
|
||||
if (txt.length() < 1)
|
||||
return;
|
||||
|
||||
destroyFilter();
|
||||
fltr = new CardFilter(txt,
|
||||
static_cast<CardFilter::Type>(comboCurrentIntData(typeCombo)),
|
||||
static_cast<CardFilter::Attr>(comboCurrentIntData(filterCombo)));
|
||||
emit add(fltr);
|
||||
edit->clear();
|
||||
}
|
35
cockatrice/src/filterbuilder.h
Normal file
35
cockatrice/src/filterbuilder.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef FILTERBUILDER_H
|
||||
#define FILTERBUILDER_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class CardFilter;
|
||||
|
||||
class FilterBuilder : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QComboBox *typeCombo;
|
||||
QComboBox *filterCombo;
|
||||
QLineEdit *edit;
|
||||
CardFilter *fltr;
|
||||
|
||||
void destroyFilter();
|
||||
|
||||
public:
|
||||
FilterBuilder(QWidget *parent = 0);
|
||||
~FilterBuilder();
|
||||
|
||||
signals:
|
||||
void add(const CardFilter *f);
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void emit_add();
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
339
cockatrice/src/filtertree.cpp
Normal file
339
cockatrice/src/filtertree.cpp
Normal file
|
@ -0,0 +1,339 @@
|
|||
#include "filtertree.h"
|
||||
#include "cardfilter.h"
|
||||
#include "carddatabase.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
template <class T>
|
||||
FilterTreeNode *FilterTreeBranch<T>::nodeAt(int i) const
|
||||
{
|
||||
return ((childNodes.size() > i)? childNodes.at(i) : NULL);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void FilterTreeBranch<T>::deleteAt(int i)
|
||||
{
|
||||
preRemoveChild(this, i);
|
||||
delete childNodes.takeAt(i);
|
||||
postRemoveChild(this, i);
|
||||
nodeChanged();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int FilterTreeBranch<T>::childIndex(const FilterTreeNode *node) const
|
||||
{
|
||||
FilterTreeNode *unconst;
|
||||
T downcasted;
|
||||
|
||||
/* to do the dynamic cast to T we will lose const'ness, but we can
|
||||
* trust QList::indexOf */
|
||||
unconst = (FilterTreeNode *) node;
|
||||
downcasted = dynamic_cast<T>(unconst);
|
||||
if (downcasted == NULL)
|
||||
return -1;
|
||||
return childNodes.indexOf(downcasted);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
FilterTreeBranch<T>::~FilterTreeBranch()
|
||||
{
|
||||
while (!childNodes.isEmpty())
|
||||
delete childNodes.takeFirst();
|
||||
}
|
||||
|
||||
const FilterItemList *LogicMap::findTypeList(CardFilter::Type type) const
|
||||
{
|
||||
QList<FilterItemList *>::const_iterator i;
|
||||
|
||||
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++)
|
||||
if ((*i)->type == type)
|
||||
return *i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FilterItemList *LogicMap::typeList(CardFilter::Type type)
|
||||
{
|
||||
QList<FilterItemList *>::iterator i;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (i = childNodes.begin(); i != childNodes.end(); i++) {
|
||||
if ((*i)->type == type)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
if (i == childNodes.end()) {
|
||||
preInsertChild(this, count);
|
||||
i = childNodes.insert(i, new FilterItemList(type, this));
|
||||
postInsertChild(this, count);
|
||||
nodeChanged();
|
||||
}
|
||||
|
||||
return *i;
|
||||
}
|
||||
|
||||
FilterTreeNode *LogicMap::parent() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
int FilterItemList::termIndex(const QString &term) const
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < childNodes.count(); i++)
|
||||
if ((childNodes.at(i))->term == term)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
FilterTreeNode *FilterItemList::termNode(const QString &term)
|
||||
{
|
||||
int i, count;
|
||||
FilterItem *fi;
|
||||
|
||||
i = termIndex(term);
|
||||
if (i < 0) {
|
||||
fi = new FilterItem(term, this);
|
||||
count = childNodes.count();
|
||||
preInsertChild(this, count);
|
||||
childNodes.append(fi);
|
||||
postInsertChild(this, count);
|
||||
nodeChanged();
|
||||
return fi;
|
||||
}
|
||||
|
||||
return childNodes.at(i);
|
||||
}
|
||||
|
||||
bool FilterItemList::testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const
|
||||
{
|
||||
QList<FilterItem *>::const_iterator i;
|
||||
|
||||
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++) {
|
||||
if (!(*i)->isEnabled())
|
||||
continue;
|
||||
if (!(*i)->acceptCardAttr(info, attr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FilterItemList::testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const
|
||||
{
|
||||
// if any one in the list is true, return false
|
||||
return !testTypeOr(info, attr);
|
||||
}
|
||||
|
||||
bool FilterItemList::testTypeOr(const CardInfo *info, CardFilter::Attr attr) const
|
||||
{
|
||||
QList<FilterItem *>::const_iterator i;
|
||||
|
||||
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++) {
|
||||
if (!(*i)->isEnabled())
|
||||
continue;
|
||||
if ((*i)->acceptCardAttr(info, attr))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FilterItemList::testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const
|
||||
{
|
||||
// if any one in the list is false, return true
|
||||
return !testTypeAnd(info, attr);
|
||||
}
|
||||
|
||||
bool FilterItem::acceptName(const CardInfo *info) const
|
||||
{
|
||||
return info->getName().contains(term, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool FilterItem::acceptType(const CardInfo *info) const
|
||||
{
|
||||
return info->getCardType().contains(term, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool FilterItem::acceptColor(const CardInfo *info) const
|
||||
{
|
||||
QStringList::const_iterator i;
|
||||
bool status;
|
||||
|
||||
status = false;
|
||||
for (i = info->getColors().constBegin(); i != info->getColors().constEnd(); i++)
|
||||
if ((*i).contains(term, Qt::CaseInsensitive)) {
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool FilterItem::acceptText(const CardInfo *info) const
|
||||
{
|
||||
return info->getText().contains(term, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool FilterItem::acceptSet(const CardInfo *info) const
|
||||
{
|
||||
SetList::const_iterator i;
|
||||
bool status;
|
||||
|
||||
status = false;
|
||||
for (i = info->getSets().constBegin(); i != info->getSets().constEnd(); i++)
|
||||
if ((*i)->getShortName() == term
|
||||
|| (*i)->getLongName().contains(term, Qt::CaseInsensitive)) {
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool FilterItem::acceptManaCost(const CardInfo *info) const
|
||||
{
|
||||
return (info->getManaCost() == term);
|
||||
}
|
||||
|
||||
bool FilterItem::acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const
|
||||
{
|
||||
bool status;
|
||||
|
||||
switch (attr) {
|
||||
case CardFilter::AttrName:
|
||||
status = acceptName(info);
|
||||
break;
|
||||
case CardFilter::AttrType:
|
||||
status = acceptType(info);
|
||||
break;
|
||||
case CardFilter::AttrColor:
|
||||
status = acceptColor(info);
|
||||
break;
|
||||
case CardFilter::AttrText:
|
||||
status = acceptText(info);
|
||||
break;
|
||||
case CardFilter::AttrSet:
|
||||
status = acceptSet(info);
|
||||
break;
|
||||
case CardFilter::AttrManaCost:
|
||||
status = acceptManaCost(info);
|
||||
break;
|
||||
default:
|
||||
status = true; /* ignore this attribute */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* need to define these here to make QT happy, otherwise
|
||||
* moc doesnt find some of the FilterTreeBranch symbols.
|
||||
*/
|
||||
FilterTree::FilterTree() {}
|
||||
FilterTree::~FilterTree() {}
|
||||
|
||||
LogicMap *FilterTree::attrLogicMap(CardFilter::Attr attr)
|
||||
{
|
||||
QList<LogicMap *>::iterator i;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (i = childNodes.begin(); i != childNodes.end(); i++) {
|
||||
if ((*i)->attr == attr)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (i == childNodes.end()) {
|
||||
preInsertChild(this, count);
|
||||
i = childNodes.insert(i, new LogicMap(attr, this));
|
||||
postInsertChild(this, count);
|
||||
nodeChanged();
|
||||
}
|
||||
|
||||
return *i;
|
||||
}
|
||||
|
||||
FilterItemList *FilterTree::attrTypeList(CardFilter::Attr attr,
|
||||
CardFilter::Type type)
|
||||
{
|
||||
return attrLogicMap(attr)->typeList(type);
|
||||
}
|
||||
|
||||
int FilterTree::findTermIndex(CardFilter::Attr attr, CardFilter::Type type,
|
||||
const QString &term)
|
||||
{
|
||||
attrTypeList(attr, type)->termIndex(term);
|
||||
}
|
||||
|
||||
int FilterTree::findTermIndex(const CardFilter *f)
|
||||
{
|
||||
return findTermIndex(f->attr(), f->type(), f->term());
|
||||
}
|
||||
|
||||
FilterTreeNode *FilterTree::termNode(CardFilter::Attr attr, CardFilter::Type type,
|
||||
const QString &term)
|
||||
{
|
||||
return attrTypeList(attr, type)->termNode(term);
|
||||
}
|
||||
|
||||
FilterTreeNode *FilterTree::termNode(const CardFilter *f)
|
||||
{
|
||||
return termNode(f->attr(), f->type(), f->term());
|
||||
}
|
||||
|
||||
FilterTreeNode *FilterTree::attrTypeNode(CardFilter::Attr attr,
|
||||
CardFilter::Type type)
|
||||
{
|
||||
return attrTypeList(attr, type);
|
||||
}
|
||||
|
||||
bool FilterTree::testAttr(const CardInfo *info, const LogicMap *lm) const
|
||||
{
|
||||
const FilterItemList *fil;
|
||||
bool status;
|
||||
|
||||
status = true;
|
||||
|
||||
fil = lm->findTypeList(CardFilter::TypeAnd);
|
||||
if (fil != NULL && fil->isEnabled() && !fil->testTypeAnd(info, lm->attr))
|
||||
return false;
|
||||
|
||||
fil = lm->findTypeList(CardFilter::TypeAndNot);
|
||||
if (fil != NULL && fil->isEnabled() && !fil->testTypeAndNot(info, lm->attr))
|
||||
return false;
|
||||
|
||||
fil = lm->findTypeList(CardFilter::TypeOr);
|
||||
if (fil != NULL && fil->isEnabled()) {
|
||||
status = false;
|
||||
// if this is true we can return because it is OR'd with the OrNot list
|
||||
if (fil->testTypeOr(info, lm->attr))
|
||||
return true;
|
||||
}
|
||||
|
||||
fil = lm->findTypeList(CardFilter::TypeOrNot);
|
||||
if (fil != NULL && fil->isEnabled() && fil->testTypeOrNot(info, lm->attr))
|
||||
return true;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool FilterTree::acceptsCard(const CardInfo *info) const
|
||||
{
|
||||
QList<LogicMap *>::const_iterator i;
|
||||
|
||||
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++)
|
||||
if ((*i)->isEnabled() && !testAttr(info, *i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterTree::clear()
|
||||
{
|
||||
while(childCount() > 0)
|
||||
deleteAt(0);
|
||||
}
|
163
cockatrice/src/filtertree.h
Normal file
163
cockatrice/src/filtertree.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
#ifndef FILTERTREE_H
|
||||
#define FILTERTREE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
#include "cardfilter.h"
|
||||
|
||||
class CardInfo;
|
||||
|
||||
class FilterTreeNode {
|
||||
private:
|
||||
bool enabled;
|
||||
public:
|
||||
FilterTreeNode() : enabled(true) {}
|
||||
virtual bool isEnabled() const { return enabled; }
|
||||
virtual void enable() { enabled = true; nodeChanged(); }
|
||||
virtual void disable() { enabled = false; nodeChanged(); }
|
||||
virtual FilterTreeNode *parent() const { return NULL; }
|
||||
virtual FilterTreeNode *nodeAt(int i) const { return NULL; }
|
||||
virtual void deleteAt(int i) {}
|
||||
virtual int childCount() const { return 0; }
|
||||
virtual int childIndex(const FilterTreeNode *node) const { return -1; }
|
||||
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
|
||||
virtual QString text() const { return QString(textCStr()); }
|
||||
virtual bool isLeaf() const { return false; }
|
||||
virtual const char *textCStr() const { return ""; }
|
||||
virtual void nodeChanged() const {
|
||||
if (parent() != NULL) parent()->nodeChanged();
|
||||
}
|
||||
virtual void preInsertChild(const FilterTreeNode *p, int i) const {
|
||||
if (parent() != NULL) parent()->preInsertChild(p, i);
|
||||
}
|
||||
virtual void postInsertChild(const FilterTreeNode *p, int i) const {
|
||||
if (parent() != NULL) parent()->postInsertChild(p, i);
|
||||
}
|
||||
virtual void preRemoveChild(const FilterTreeNode *p, int i) const {
|
||||
if (parent() != NULL) parent()->preRemoveChild(p, i);
|
||||
}
|
||||
virtual void postRemoveChild(const FilterTreeNode *p, int i) const {
|
||||
if (parent() != NULL) parent()->postRemoveChild(p, i);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class FilterTreeBranch : public FilterTreeNode {
|
||||
protected:
|
||||
QList<T> childNodes;
|
||||
public:
|
||||
~FilterTreeBranch();
|
||||
FilterTreeNode *nodeAt(int i) const;
|
||||
void deleteAt(int i);
|
||||
int childCount() const { return childNodes.size(); }
|
||||
int childIndex(const FilterTreeNode *node) const;
|
||||
};
|
||||
|
||||
class FilterItemList;
|
||||
class FilterTree;
|
||||
class LogicMap : public FilterTreeBranch<FilterItemList *> {
|
||||
|
||||
private:
|
||||
FilterTree *const p;
|
||||
|
||||
public:
|
||||
const CardFilter::Attr attr;
|
||||
|
||||
LogicMap(CardFilter::Attr a, FilterTree *parent)
|
||||
: attr(a), p(parent) {}
|
||||
const FilterItemList *findTypeList(CardFilter::Type type) const;
|
||||
FilterItemList *typeList(CardFilter::Type type);
|
||||
FilterTreeNode *parent() const;
|
||||
const char* textCStr() const { return CardFilter::attrName(attr); }
|
||||
};
|
||||
|
||||
class FilterItem;
|
||||
class FilterItemList : public FilterTreeBranch<FilterItem *> {
|
||||
private:
|
||||
LogicMap *const p;
|
||||
public:
|
||||
const CardFilter::Type type;
|
||||
|
||||
FilterItemList(CardFilter::Type t, LogicMap *parent)
|
||||
: type(t), p(parent) {}
|
||||
CardFilter::Attr attr() const { return p->attr; }
|
||||
FilterTreeNode *parent() const { return p; }
|
||||
int termIndex(const QString &term) const;
|
||||
FilterTreeNode *termNode(const QString &term);
|
||||
const char *textCStr() const { return CardFilter::typeName(type); }
|
||||
|
||||
bool testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const;
|
||||
bool testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const;
|
||||
bool testTypeOr(const CardInfo *info, CardFilter::Attr attr) const;
|
||||
bool testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const;
|
||||
};
|
||||
|
||||
class FilterItem : public FilterTreeNode {
|
||||
private:
|
||||
FilterItemList *const p;
|
||||
public:
|
||||
const QString term;
|
||||
|
||||
FilterItem(QString trm, FilterItemList *parent)
|
||||
: p(parent), term(trm) {}
|
||||
|
||||
CardFilter::Attr attr() const { return p->attr(); }
|
||||
CardFilter::Type type() const { return p->type; }
|
||||
FilterTreeNode *parent() const { return p; }
|
||||
QString text() const { return term; }
|
||||
const char *textCStr() const { return term.toStdString().c_str(); }
|
||||
bool isLeaf() const { return true; }
|
||||
|
||||
bool acceptName(const CardInfo *info) const;
|
||||
bool acceptType(const CardInfo *info) const;
|
||||
bool acceptColor(const CardInfo *info) const;
|
||||
bool acceptText(const CardInfo *info) const;
|
||||
bool acceptSet(const CardInfo *info) const;
|
||||
bool acceptManaCost(const CardInfo *info) const;
|
||||
bool acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const;
|
||||
};
|
||||
|
||||
class FilterTree : public QObject, public FilterTreeBranch<LogicMap *> {
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void preInsertRow(const FilterTreeNode *parent, int i) const;
|
||||
void postInsertRow(const FilterTreeNode *parent, int i) const;
|
||||
void preRemoveRow(const FilterTreeNode *parent, int i) const;
|
||||
void postRemoveRow(const FilterTreeNode *parent, int i) const;
|
||||
void changed() const;
|
||||
|
||||
private:
|
||||
LogicMap *attrLogicMap(CardFilter::Attr attr);
|
||||
FilterItemList *attrTypeList(CardFilter::Attr attr,
|
||||
CardFilter::Type type);
|
||||
|
||||
bool testAttr(const CardInfo *info, const LogicMap *lm) const;
|
||||
|
||||
void nodeChanged() const { emit changed(); }
|
||||
void preInsertChild(const FilterTreeNode *p, int i) const { emit preInsertRow(p, i); }
|
||||
void postInsertChild(const FilterTreeNode *p, int i) const { emit postInsertRow(p, i); }
|
||||
void preRemoveChild(const FilterTreeNode *p, int i) const { emit preRemoveRow(p, i); }
|
||||
void postRemoveChild(const FilterTreeNode *p, int i) const { emit postRemoveRow(p, i); }
|
||||
|
||||
public:
|
||||
FilterTree();
|
||||
~FilterTree();
|
||||
int findTermIndex(CardFilter::Attr attr, CardFilter::Type type,
|
||||
const QString &term);
|
||||
int findTermIndex(const CardFilter *f);
|
||||
FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type,
|
||||
const QString &term);
|
||||
FilterTreeNode *termNode(const CardFilter *f);
|
||||
FilterTreeNode *attrTypeNode(CardFilter::Attr attr,
|
||||
CardFilter::Type type);
|
||||
const char *textCStr() { return "root"; }
|
||||
int index() const { return 0; }
|
||||
|
||||
bool acceptsCard(const CardInfo *info) const;
|
||||
void clear();
|
||||
};
|
||||
|
||||
#endif
|
272
cockatrice/src/filtertreemodel.cpp
Normal file
272
cockatrice/src/filtertreemodel.cpp
Normal file
|
@ -0,0 +1,272 @@
|
|||
#include <QFont>
|
||||
#include "filtertreemodel.h"
|
||||
#include "filtertree.h"
|
||||
#include "cardfilter.h"
|
||||
|
||||
FilterTreeModel::FilterTreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
fTree = new FilterTree;
|
||||
connect(fTree,
|
||||
SIGNAL(preInsertRow(const FilterTreeNode *, int)),
|
||||
this, SLOT(proxyBeginInsertRow(const FilterTreeNode *, int)));
|
||||
connect(fTree,
|
||||
SIGNAL(postInsertRow(const FilterTreeNode *, int)),
|
||||
this, SLOT(proxyEndInsertRow(const FilterTreeNode *, int)));
|
||||
connect(fTree,
|
||||
SIGNAL(preRemoveRow(const FilterTreeNode *, int)),
|
||||
this, SLOT(proxyBeginRemoveRow(const FilterTreeNode *, int)));
|
||||
connect(fTree,
|
||||
SIGNAL(postRemoveRow(const FilterTreeNode *, int)),
|
||||
this, SLOT(proxyEndRemoveRow(const FilterTreeNode *, int)));
|
||||
}
|
||||
|
||||
FilterTreeModel::~FilterTreeModel()
|
||||
{
|
||||
delete fTree;
|
||||
}
|
||||
|
||||
void FilterTreeModel::proxyBeginInsertRow(const FilterTreeNode *node, int i)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = node->index();
|
||||
if (idx >= 0)
|
||||
beginInsertRows(createIndex(idx, 0, (void *) node), i, i);
|
||||
}
|
||||
|
||||
void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = node->index();
|
||||
if (idx >= 0)
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = node->index();
|
||||
if (idx >= 0)
|
||||
beginRemoveRows(createIndex(idx, 0, (void *) node), i, i);
|
||||
}
|
||||
|
||||
void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = node->index();
|
||||
if (idx >= 0)
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const
|
||||
{
|
||||
void *ip;
|
||||
FilterTreeNode *node;
|
||||
|
||||
if (!idx.isValid())
|
||||
return fTree;
|
||||
|
||||
ip = idx.internalPointer();
|
||||
if (ip == NULL)
|
||||
return fTree;
|
||||
|
||||
node = static_cast<FilterTreeNode *>(ip);
|
||||
return node;
|
||||
}
|
||||
|
||||
void FilterTreeModel::addFilter(const CardFilter *f)
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
fTree->termNode(f);
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
int FilterTreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
const FilterTreeNode *node;
|
||||
int result;
|
||||
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
node = indexToNode(parent);
|
||||
if (node)
|
||||
result = node->childCount();
|
||||
else
|
||||
result = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int FilterTreeModel::columnCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const FilterTreeNode *node;
|
||||
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
if (index.column() >= columnCount())
|
||||
return QVariant();
|
||||
|
||||
node = indexToNode(index);
|
||||
if (node == NULL)
|
||||
return QVariant();
|
||||
|
||||
switch (role) {
|
||||
case Qt::FontRole:
|
||||
if (!node->isLeaf()) {
|
||||
QFont f;
|
||||
f.setBold(true);
|
||||
return f;
|
||||
}
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::StatusTipRole:
|
||||
case Qt::WhatsThisRole:
|
||||
if(!node->isLeaf())
|
||||
return tr(node->textCStr());
|
||||
else
|
||||
return node->text();
|
||||
case Qt::CheckStateRole:
|
||||
if (node->isEnabled())
|
||||
return Qt::Checked;
|
||||
else
|
||||
return Qt::Unchecked;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool FilterTreeModel::setData(const QModelIndex &index,
|
||||
const QVariant &value, int role)
|
||||
{
|
||||
FilterTreeNode *node;
|
||||
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
if (index.column() >= columnCount())
|
||||
return false;
|
||||
if (role != Qt::CheckStateRole )
|
||||
return false;
|
||||
|
||||
node = indexToNode(index);
|
||||
if (node == NULL || node == fTree)
|
||||
return false;
|
||||
|
||||
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||
if (state == Qt::Checked)
|
||||
node->enable();
|
||||
else
|
||||
node->disable();
|
||||
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags FilterTreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
const FilterTreeNode *node;
|
||||
Qt::ItemFlags result;
|
||||
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
node = indexToNode(index);
|
||||
if (node == NULL)
|
||||
return 0;
|
||||
|
||||
result = Qt::ItemIsEnabled;
|
||||
if (node == fTree)
|
||||
return result;
|
||||
|
||||
result |= Qt::ItemIsSelectable;
|
||||
result |= Qt::ItemIsUserCheckable;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QModelIndex FilterTreeModel::nodeIndex(const FilterTreeNode *node, int row, int column) const
|
||||
{
|
||||
FilterTreeNode *child;
|
||||
|
||||
if (column > 0 || row >= node->childCount())
|
||||
return QModelIndex();
|
||||
|
||||
child = node->nodeAt(row);
|
||||
return createIndex(row, column, child);
|
||||
}
|
||||
|
||||
QModelIndex FilterTreeModel::index(int row, int column,
|
||||
const QModelIndex &parent) const
|
||||
{
|
||||
const FilterTreeNode *node;
|
||||
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
node = indexToNode(parent);
|
||||
if (node == NULL)
|
||||
return QModelIndex();
|
||||
|
||||
return nodeIndex(node, row, column);
|
||||
}
|
||||
|
||||
QModelIndex FilterTreeModel::parent(const QModelIndex &ind) const
|
||||
{
|
||||
const FilterTreeNode *node;
|
||||
FilterTreeNode *parent;
|
||||
int row;
|
||||
QModelIndex idx;
|
||||
|
||||
if (!ind.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
node = indexToNode(ind);
|
||||
if (node == NULL || node == fTree)
|
||||
return QModelIndex();
|
||||
|
||||
parent = node->parent();
|
||||
if (parent) {
|
||||
row = parent->index();
|
||||
if (row < 0)
|
||||
return QModelIndex();
|
||||
idx = createIndex(row, 0, parent);
|
||||
return idx;
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool FilterTreeModel::removeRows(int row, int count, const QModelIndex & parent)
|
||||
{
|
||||
FilterTreeNode *node;
|
||||
int i, last;
|
||||
|
||||
last = row+count-1;
|
||||
if (!parent.isValid() || count < 1 || row < 0)
|
||||
return false;
|
||||
|
||||
node = indexToNode(parent);
|
||||
if (node == NULL || last >= node->childCount())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
node->deleteAt(row);
|
||||
|
||||
if (node != fTree && node->childCount() < 1)
|
||||
return removeRow(parent.row(), parent.parent());
|
||||
|
||||
return true;
|
||||
}
|
44
cockatrice/src/filtertreemodel.h
Normal file
44
cockatrice/src/filtertreemodel.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef FILTERTREEMODEL_H
|
||||
#define FILTERTREEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class FilterTree;
|
||||
class CardFilter;
|
||||
class FilterTreeNode;
|
||||
|
||||
class FilterTreeModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
private:
|
||||
FilterTree *fTree;
|
||||
|
||||
public slots:
|
||||
void addFilter(const CardFilter *f);
|
||||
|
||||
private slots:
|
||||
void proxyBeginInsertRow(const FilterTreeNode *, int);
|
||||
void proxyEndInsertRow(const FilterTreeNode *, int);
|
||||
void proxyBeginRemoveRow(const FilterTreeNode *, int);
|
||||
void proxyEndRemoveRow(const FilterTreeNode *, int);
|
||||
|
||||
private:
|
||||
FilterTreeNode *indexToNode(const QModelIndex &idx) const;
|
||||
QModelIndex nodeIndex(const FilterTreeNode *node, int row, int column) const;
|
||||
|
||||
public:
|
||||
FilterTreeModel(QObject *parent = 0);
|
||||
~FilterTreeModel();
|
||||
FilterTree *filterTree() const { return fTree; }
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole);
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QModelIndex parent(const QModelIndex &ind) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent) const;
|
||||
bool removeRows(int row, int count, const QModelIndex & parent);
|
||||
};
|
||||
|
||||
#endif
|
65
cockatrice/src/keysignals.cpp
Normal file
65
cockatrice/src/keysignals.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "keysignals.h"
|
||||
#include <QKeyEvent>
|
||||
|
||||
bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event) {
|
||||
QKeyEvent *kevent;
|
||||
|
||||
if(event->type() != QEvent::KeyPress)
|
||||
return false;
|
||||
|
||||
kevent = static_cast<QKeyEvent *>(event);
|
||||
switch(kevent->key()) {
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||
emit onCtrlAltEnter();
|
||||
else if (kevent->modifiers() & Qt::ControlModifier)
|
||||
emit onCtrlEnter();
|
||||
else
|
||||
emit onEnter();
|
||||
|
||||
break;
|
||||
case Qt::Key_Right:
|
||||
emit onRight();
|
||||
|
||||
break;
|
||||
case Qt::Key_Left:
|
||||
emit onLeft();
|
||||
|
||||
break;
|
||||
case Qt::Key_Delete:
|
||||
case Qt::Key_Backspace:
|
||||
emit onDelete();
|
||||
|
||||
break;
|
||||
case Qt::Key_Minus:
|
||||
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||
emit onCtrlAltMinus();
|
||||
|
||||
break;
|
||||
case Qt::Key_Equal:
|
||||
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||
emit onCtrlAltEqual();
|
||||
|
||||
break;
|
||||
case Qt::Key_BracketLeft:
|
||||
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||
emit onCtrlAltLBracket();
|
||||
|
||||
break;
|
||||
case Qt::Key_BracketRight:
|
||||
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||
emit onCtrlAltRBracket();
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
21
cockatrice/src/keysignals.h
Normal file
21
cockatrice/src/keysignals.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <QObject>
|
||||
#include <QEvent>
|
||||
|
||||
class KeySignals : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void onEnter();
|
||||
void onCtrlEnter();
|
||||
void onCtrlAltEnter();
|
||||
void onLeft();
|
||||
void onRight();
|
||||
void onDelete();
|
||||
void onCtrlAltMinus();
|
||||
void onCtrlAltEqual();
|
||||
void onCtrlAltLBracket();
|
||||
void onCtrlAltRBracket();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *, QEvent *event);
|
||||
};
|
|
@ -22,7 +22,6 @@
|
|||
#include "carddatabasemodel.h"
|
||||
#include "decklistmodel.h"
|
||||
#include "cardinfowidget.h"
|
||||
#include "dlg_cardsearch.h"
|
||||
#include "dlg_load_deck_from_clipboard.h"
|
||||
#include "dlg_edit_tokens.h"
|
||||
#include "main.h"
|
||||
|
@ -34,6 +33,9 @@
|
|||
#include "pending_command.h"
|
||||
#include "pb/response.pb.h"
|
||||
#include "pb/command_deck_upload.pb.h"
|
||||
#include "filtertreemodel.h"
|
||||
#include "cardframe.h"
|
||||
#include "filterbuilder.h"
|
||||
|
||||
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
|
@ -45,9 +47,6 @@ void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
|||
TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||
: Tab(_tabSupervisor, parent), modified(false)
|
||||
{
|
||||
aSearch = new QAction(QString(), this);
|
||||
aSearch->setIcon(QIcon(":/resources/icon_search.svg"));
|
||||
connect(aSearch, SIGNAL(triggered()), this, SLOT(actSearch()));
|
||||
aClearSearch = new QAction(QString(), this);
|
||||
aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg"));
|
||||
connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch()));
|
||||
|
@ -55,25 +54,36 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||
searchLabel = new QLabel();
|
||||
searchEdit = new SearchLineEdit;
|
||||
searchLabel->setBuddy(searchEdit);
|
||||
setFocusProxy(searchEdit);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
searchEdit->installEventFilter(&searchKeySignals);
|
||||
connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateSearch(const QString &)));
|
||||
connect(searchEdit, SIGNAL(returnPressed()), this, SLOT(actAddCard()));
|
||||
QToolButton *searchButton = new QToolButton;
|
||||
searchButton->setDefaultAction(aSearch);
|
||||
QToolButton *clearSearchButton = new QToolButton;
|
||||
clearSearchButton->setDefaultAction(aClearSearch);
|
||||
connect(&searchKeySignals, SIGNAL(onEnter()), this, SLOT(actAddCard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actAddCard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlAltRBracket()), this, SLOT(actAddCardToSideboard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrementCard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
|
||||
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
|
||||
|
||||
QToolBar *deckEditToolBar = new QToolBar;
|
||||
deckEditToolBar->setOrientation(Qt::Horizontal);
|
||||
deckEditToolBar->setIconSize(QSize(24, 24));
|
||||
|
||||
QHBoxLayout *searchLayout = new QHBoxLayout;
|
||||
searchLayout->addWidget(deckEditToolBar);
|
||||
searchLayout->addWidget(searchLabel);
|
||||
searchLayout->addWidget(searchEdit);
|
||||
searchLayout->addWidget(searchButton);
|
||||
searchLayout->addWidget(clearSearchButton);
|
||||
|
||||
databaseModel = new CardDatabaseModel(db, this);
|
||||
databaseDisplayModel = new CardDatabaseDisplayModel(this);
|
||||
databaseDisplayModel->setSourceModel(databaseModel);
|
||||
databaseDisplayModel->setFilterKeyColumn(0);
|
||||
databaseDisplayModel->sort(0, Qt::AscendingOrder);
|
||||
|
||||
databaseView = new QTreeView();
|
||||
databaseView->setFocusProxy(searchEdit);
|
||||
databaseView->setModel(databaseDisplayModel);
|
||||
databaseView->setUniformRowHeights(true);
|
||||
databaseView->setRootIsDecorated(false);
|
||||
|
@ -89,21 +99,33 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||
leftFrame->addLayout(searchLayout);
|
||||
leftFrame->addWidget(databaseView);
|
||||
|
||||
cardInfo = new CardInfoWidget(CardInfoWidget::ModeDeckEditor);
|
||||
cardInfo->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
cardInfo = new CardFrame(250, 356);
|
||||
aCardTextOnly = new QAction(QString(), this);
|
||||
aCardTextOnly->setCheckable(true);
|
||||
connect(aCardTextOnly, SIGNAL(triggered()), cardInfo, SLOT(toggleCardTextOnly()));
|
||||
|
||||
QToolBar *verticalToolBar = new QToolBar;
|
||||
verticalToolBar->setOrientation(Qt::Vertical);
|
||||
verticalToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
verticalToolBar->setIconSize(QSize(24, 24));
|
||||
QHBoxLayout *verticalToolBarLayout = new QHBoxLayout;
|
||||
verticalToolBarLayout->addStretch();
|
||||
verticalToolBarLayout->addWidget(verticalToolBar);
|
||||
verticalToolBarLayout->addStretch();
|
||||
filterModel = new FilterTreeModel();
|
||||
databaseDisplayModel->setFilterTree(filterModel->filterTree());
|
||||
filterView = new QTreeView;
|
||||
filterView->setModel(filterModel);
|
||||
filterView->setMaximumWidth(250);
|
||||
filterView->setUniformRowHeights(true);
|
||||
filterView->setHeaderHidden(true);
|
||||
filterView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(filterModel, SIGNAL(layoutChanged()), filterView, SLOT(expandAll()));
|
||||
connect(filterView, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
this, SLOT(filterViewCustomContextMenu(const QPoint &)));
|
||||
FilterBuilder *filterBuilder = new FilterBuilder;
|
||||
filterBuilder->setMaximumWidth(250);
|
||||
connect(filterBuilder, SIGNAL(add(const CardFilter *)), filterModel, SLOT(addFilter(const CardFilter *)));
|
||||
|
||||
QVBoxLayout *filter = new QVBoxLayout;
|
||||
filter->addWidget(filterBuilder, 0, Qt::AlignTop);
|
||||
filter->addWidget(filterView, 10);
|
||||
|
||||
QVBoxLayout *middleFrame = new QVBoxLayout;
|
||||
middleFrame->addWidget(cardInfo, 10);
|
||||
middleFrame->addLayout(verticalToolBarLayout);
|
||||
middleFrame->addWidget(cardInfo, 0, Qt::AlignTop);
|
||||
middleFrame->addLayout(filter, 10);
|
||||
|
||||
deckModel = new DeckListModel(this);
|
||||
connect(deckModel, SIGNAL(deckHashChanged()), this, SLOT(updateHash()));
|
||||
|
@ -111,7 +133,14 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||
deckView->setModel(deckModel);
|
||||
deckView->setUniformRowHeights(true);
|
||||
deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
deckView->installEventFilter(&deckViewKeySignals);
|
||||
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
|
||||
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
|
||||
connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement()));
|
||||
connect(&deckViewKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrement()));
|
||||
connect(&deckViewKeySignals, SIGNAL(onRight()), this, SLOT(actIncrement()));
|
||||
connect(&deckViewKeySignals, SIGNAL(onLeft()), this, SLOT(actDecrement()));
|
||||
connect(&deckViewKeySignals, SIGNAL(onDelete()), this, SLOT(actRemoveCard()));
|
||||
|
||||
nameLabel = new QLabel();
|
||||
nameEdit = new QLineEdit;
|
||||
|
@ -131,36 +160,36 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||
|
||||
grid->addWidget(commentsLabel, 1, 0);
|
||||
grid->addWidget(commentsEdit, 1, 1);
|
||||
|
||||
|
||||
grid->addWidget(hashLabel1, 2, 0);
|
||||
grid->addWidget(hashLabel, 2, 1);
|
||||
|
||||
// Update price
|
||||
aUpdatePrices = new QAction(QString(), this);
|
||||
aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png"));
|
||||
connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices()));
|
||||
// Update price
|
||||
aUpdatePrices = new QAction(QString(), this);
|
||||
aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png"));
|
||||
connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices()));
|
||||
if (!settingsCache->getPriceTagFeature())
|
||||
aUpdatePrices->setVisible(false);
|
||||
|
||||
QToolBar *deckToolBar = new QToolBar;
|
||||
deckToolBar->setOrientation(Qt::Vertical);
|
||||
deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
deckToolBar->setIconSize(QSize(24, 24));
|
||||
deckToolBar->addAction(aUpdatePrices);
|
||||
QHBoxLayout *deckToolbarLayout = new QHBoxLayout;
|
||||
deckToolbarLayout->addStretch();
|
||||
deckToolbarLayout->addWidget(deckToolBar);
|
||||
deckToolbarLayout->addStretch();
|
||||
|
||||
QToolBar *deckToolBar = new QToolBar;
|
||||
deckToolBar->setOrientation(Qt::Vertical);
|
||||
deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
deckToolBar->setIconSize(QSize(24, 24));
|
||||
deckToolBar->addAction(aUpdatePrices);
|
||||
QHBoxLayout *deckToolbarLayout = new QHBoxLayout;
|
||||
deckToolbarLayout->addStretch();
|
||||
deckToolbarLayout->addWidget(deckToolBar);
|
||||
deckToolbarLayout->addStretch();
|
||||
|
||||
QVBoxLayout *rightFrame = new QVBoxLayout;
|
||||
rightFrame->addLayout(grid);
|
||||
rightFrame->addWidget(deckView, 10);
|
||||
rightFrame->addLayout(deckToolbarLayout);
|
||||
rightFrame->addLayout(deckToolbarLayout);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
mainLayout->addLayout(leftFrame, 10);
|
||||
mainLayout->addLayout(middleFrame);
|
||||
mainLayout->addLayout(rightFrame, 10);
|
||||
mainLayout->addLayout(rightFrame);
|
||||
setLayout(mainLayout);
|
||||
|
||||
aNewDeck = new QAction(QString(), this);
|
||||
|
@ -214,34 +243,32 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||
dbMenu->addAction(aEditSets);
|
||||
dbMenu->addAction(aEditTokens);
|
||||
dbMenu->addSeparator();
|
||||
dbMenu->addAction(aSearch);
|
||||
dbMenu->addAction(aClearSearch);
|
||||
dbMenu->addAction(aCardTextOnly);
|
||||
addTabMenu(dbMenu);
|
||||
|
||||
aAddCard = new QAction(QString(), this);
|
||||
aAddCard->setIcon(QIcon(":/resources/arrow_right_green.svg"));
|
||||
connect(aAddCard, SIGNAL(triggered()), this, SLOT(actAddCard()));
|
||||
aAddCardToSideboard = new QAction(QString(), this);
|
||||
aAddCardToSideboard->setIcon(QIcon(":/resources/add_to_sideboard.svg"));
|
||||
aAddCardToSideboard->setIcon(QIcon(":/resources/add_to_sideboard.svg"));
|
||||
connect(aAddCardToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
|
||||
aRemoveCard = new QAction(QString(), this);
|
||||
aRemoveCard->setIcon(QIcon(":/resources/remove_row.svg"));
|
||||
aRemoveCard->setIcon(QIcon(":/resources/remove_row.svg"));
|
||||
connect(aRemoveCard, SIGNAL(triggered()), this, SLOT(actRemoveCard()));
|
||||
aIncrement = new QAction(QString(), this);
|
||||
aIncrement->setIcon(QIcon(":/resources/increment.svg"));
|
||||
aIncrement->setIcon(QIcon(":/resources/increment.svg"));
|
||||
connect(aIncrement, SIGNAL(triggered()), this, SLOT(actIncrement()));
|
||||
aDecrement = new QAction(QString(), this);
|
||||
aDecrement->setIcon(QIcon(":/resources/decrement.svg"));
|
||||
aDecrement->setIcon(QIcon(":/resources/decrement.svg"));
|
||||
connect(aDecrement, SIGNAL(triggered()), this, SLOT(actDecrement()));
|
||||
|
||||
verticalToolBar->addAction(aAddCard);
|
||||
verticalToolBar->addAction(aAddCardToSideboard);
|
||||
verticalToolBar->addAction(aRemoveCard);
|
||||
verticalToolBar->addAction(aIncrement);
|
||||
verticalToolBar->addAction(aDecrement);
|
||||
verticalToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
|
||||
dlgCardSearch = new DlgCardSearch(this);
|
||||
deckEditToolBar->addAction(aAddCard);
|
||||
deckEditToolBar->addAction(aAddCardToSideboard);
|
||||
deckEditToolBar->addAction(aRemoveCard);
|
||||
deckEditToolBar->addAction(aIncrement);
|
||||
deckEditToolBar->addAction(aDecrement);
|
||||
deckEditToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
|
||||
retranslateUi();
|
||||
|
||||
|
@ -255,7 +282,7 @@ TabDeckEditor::~TabDeckEditor()
|
|||
|
||||
void TabDeckEditor::retranslateUi()
|
||||
{
|
||||
aSearch->setText(tr("&Search..."));
|
||||
aCardTextOnly->setText(tr("Show card text only"));
|
||||
aClearSearch->setText(tr("&Clear search"));
|
||||
searchLabel->setText(tr("&Search for:"));
|
||||
|
||||
|
@ -264,11 +291,11 @@ void TabDeckEditor::retranslateUi()
|
|||
hashLabel1->setText(tr("Hash:"));
|
||||
|
||||
aUpdatePrices->setText(tr("&Update prices"));
|
||||
aUpdatePrices->setShortcut(tr("Ctrl+U"));
|
||||
|
||||
aNewDeck->setText(tr("&New deck"));
|
||||
aLoadDeck->setText(tr("&Load deck..."));
|
||||
aSaveDeck->setText(tr("&Save deck"));
|
||||
aUpdatePrices->setShortcut(tr("Ctrl+U"));
|
||||
|
||||
aNewDeck->setText(tr("&New deck"));
|
||||
aLoadDeck->setText(tr("&Load deck..."));
|
||||
aSaveDeck->setText(tr("&Save deck"));
|
||||
aSaveDeckAs->setText(tr("Save deck &as..."));
|
||||
aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard..."));
|
||||
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
||||
|
@ -278,9 +305,8 @@ void TabDeckEditor::retranslateUi()
|
|||
aClose->setShortcut(tr("Ctrl+Q"));
|
||||
|
||||
aAddCard->setText(tr("Add card to &maindeck"));
|
||||
aAddCard->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Return")) << QKeySequence(tr("Enter")));
|
||||
aAddCardToSideboard->setText(tr("Add card to &sideboard"));
|
||||
aAddCardToSideboard->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Return")) << QKeySequence(tr("Ctrl+Enter")));
|
||||
|
||||
aRemoveCard->setText(tr("&Remove row"));
|
||||
aRemoveCard->setShortcut(tr("Del"));
|
||||
aIncrement->setText(tr("&Increment number"));
|
||||
|
@ -497,17 +523,6 @@ void TabDeckEditor::actEditTokens()
|
|||
db->saveToFile(settingsCache->getTokenDatabasePath(), true);
|
||||
}
|
||||
|
||||
void TabDeckEditor::actSearch()
|
||||
{
|
||||
if (dlgCardSearch->exec()) {
|
||||
searchEdit->clear();
|
||||
databaseDisplayModel->setCardName(dlgCardSearch->getCardName());
|
||||
databaseDisplayModel->setCardText(dlgCardSearch->getCardText());
|
||||
databaseDisplayModel->setCardTypes(dlgCardSearch->getCardTypes());
|
||||
databaseDisplayModel->setCardColors(dlgCardSearch->getCardColors());
|
||||
}
|
||||
}
|
||||
|
||||
void TabDeckEditor::actClearSearch()
|
||||
{
|
||||
databaseDisplayModel->clearSearch();
|
||||
|
@ -520,21 +535,29 @@ void TabDeckEditor::recursiveExpand(const QModelIndex &index)
|
|||
deckView->expand(index);
|
||||
}
|
||||
|
||||
void TabDeckEditor::addCardHelper(QString zoneName)
|
||||
CardInfo *TabDeckEditor::currentCardInfo() const
|
||||
{
|
||||
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
return NULL;
|
||||
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
|
||||
|
||||
CardInfo *info = db->getCard(cardName);
|
||||
return db->getCard(cardName);
|
||||
}
|
||||
|
||||
void TabDeckEditor::addCardHelper(QString zoneName)
|
||||
{
|
||||
const CardInfo *info;
|
||||
|
||||
info = currentCardInfo();
|
||||
if(!info)
|
||||
return;
|
||||
if (info->getIsToken())
|
||||
zoneName = "tokens";
|
||||
|
||||
QModelIndex newCardIndex = deckModel->addCard(cardName, zoneName);
|
||||
|
||||
QModelIndex newCardIndex = deckModel->addCard(info->getName(), zoneName);
|
||||
recursiveExpand(newCardIndex);
|
||||
deckView->setCurrentIndex(newCardIndex);
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
|
@ -557,31 +580,57 @@ void TabDeckEditor::actRemoveCard()
|
|||
setModified(true);
|
||||
}
|
||||
|
||||
void TabDeckEditor::offsetCountAtIndex(const QModelIndex &idx, int offset)
|
||||
{
|
||||
if (!idx.isValid() || offset == 0)
|
||||
return;
|
||||
|
||||
const QModelIndex numberIndex = idx.sibling(idx.row(), 0);
|
||||
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
||||
const int new_count = count + offset;
|
||||
deckView->setCurrentIndex(numberIndex);
|
||||
if (new_count <= 0)
|
||||
deckModel->removeRow(idx.row(), idx.parent());
|
||||
else
|
||||
deckModel->setData(numberIndex, new_count, Qt::EditRole);
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
void TabDeckEditor::decrementCardHelper(QString zoneName)
|
||||
{
|
||||
const CardInfo *info;
|
||||
QModelIndex idx;
|
||||
|
||||
info = currentCardInfo();
|
||||
if(!info)
|
||||
return;
|
||||
if (info->getIsToken())
|
||||
zoneName = "tokens";
|
||||
|
||||
idx = deckModel->findCard(info->getName(), zoneName);
|
||||
offsetCountAtIndex(idx, -1);
|
||||
}
|
||||
|
||||
void TabDeckEditor::actDecrementCard()
|
||||
{
|
||||
decrementCardHelper("main");
|
||||
}
|
||||
|
||||
void TabDeckEditor::actDecrementCardFromSideboard()
|
||||
{
|
||||
decrementCardHelper("side");
|
||||
}
|
||||
|
||||
void TabDeckEditor::actIncrement()
|
||||
{
|
||||
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
|
||||
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
||||
deckView->setCurrentIndex(numberIndex);
|
||||
deckModel->setData(numberIndex, count + 1, Qt::EditRole);
|
||||
setModified(true);
|
||||
offsetCountAtIndex(currentIndex, 1);
|
||||
}
|
||||
|
||||
void TabDeckEditor::actDecrement()
|
||||
{
|
||||
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
|
||||
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
||||
deckView->setCurrentIndex(numberIndex);
|
||||
if (count == 1)
|
||||
deckModel->removeRow(currentIndex.row(), currentIndex.parent());
|
||||
else
|
||||
deckModel->setData(numberIndex, count - 1, Qt::EditRole);
|
||||
setModified(true);
|
||||
offsetCountAtIndex(currentIndex, -1);
|
||||
}
|
||||
|
||||
void TabDeckEditor::actUpdatePrices()
|
||||
|
@ -620,3 +669,31 @@ void TabDeckEditor::setModified(bool _modified)
|
|||
modified = _modified;
|
||||
emit tabTextChanged(this, getTabText());
|
||||
}
|
||||
|
||||
void TabDeckEditor::filterViewCustomContextMenu(const QPoint &point) {
|
||||
QMenu menu;
|
||||
QAction *action;
|
||||
QModelIndex idx;
|
||||
|
||||
idx = filterView->indexAt(point);
|
||||
if (!idx.isValid())
|
||||
return;
|
||||
|
||||
action = menu.addAction(QString("delete"));
|
||||
action->setData(point);
|
||||
connect(&menu, SIGNAL(triggered(QAction *)),
|
||||
this, SLOT(filterRemove(QAction *)));
|
||||
menu.exec(filterView->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void TabDeckEditor::filterRemove(QAction *action) {
|
||||
QPoint point;
|
||||
QModelIndex idx;
|
||||
|
||||
point = action->data().toPoint();
|
||||
idx = filterView->indexAt(point);
|
||||
if (!idx.isValid())
|
||||
return;
|
||||
|
||||
filterModel->removeRow(idx.row(), idx.parent());
|
||||
}
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
#include "tab.h"
|
||||
#include <QAbstractItemModel>
|
||||
#include <QLineEdit>
|
||||
#include "keysignals.h"
|
||||
|
||||
class CardDatabaseModel;
|
||||
class CardDatabaseDisplayModel;
|
||||
class DeckListModel;
|
||||
class QTreeView;
|
||||
class QTableView;
|
||||
class CardInfoWidget;
|
||||
class CardFrame;
|
||||
class QTextEdit;
|
||||
class DlgCardSearch;
|
||||
class QLabel;
|
||||
class DeckLoader;
|
||||
class Response;
|
||||
class FilterTreeModel;
|
||||
class CardInfo;
|
||||
|
||||
class SearchLineEdit : public QLineEdit {
|
||||
private:
|
||||
|
@ -49,7 +51,6 @@ private slots:
|
|||
void actEditSets();
|
||||
void actEditTokens();
|
||||
|
||||
void actSearch();
|
||||
void actClearSearch();
|
||||
|
||||
void actAddCard();
|
||||
|
@ -57,12 +58,20 @@ private slots:
|
|||
void actRemoveCard();
|
||||
void actIncrement();
|
||||
void actDecrement();
|
||||
void actUpdatePrices();
|
||||
void actDecrementCard();
|
||||
void actDecrementCardFromSideboard();
|
||||
|
||||
void finishedUpdatingPrices();
|
||||
void actUpdatePrices();
|
||||
|
||||
void finishedUpdatingPrices();
|
||||
void saveDeckRemoteFinished(const Response &r);
|
||||
void filterViewCustomContextMenu(const QPoint &point);
|
||||
void filterRemove(QAction *action);
|
||||
private:
|
||||
CardInfo *currentCardInfo() const;
|
||||
void addCardHelper(QString zoneName);
|
||||
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
||||
void decrementCardHelper(QString zoneName);
|
||||
void recursiveExpand(const QModelIndex &index);
|
||||
bool confirmClose();
|
||||
|
||||
|
@ -70,22 +79,27 @@ private:
|
|||
CardDatabaseDisplayModel *databaseDisplayModel;
|
||||
DeckListModel *deckModel;
|
||||
QTreeView *databaseView;
|
||||
|
||||
QTreeView *deckView;
|
||||
CardInfoWidget *cardInfo;
|
||||
KeySignals deckViewKeySignals;
|
||||
CardFrame *cardInfo;
|
||||
QLabel *searchLabel;
|
||||
SearchLineEdit *searchEdit;
|
||||
KeySignals searchKeySignals;
|
||||
|
||||
QLabel *nameLabel;
|
||||
QLineEdit *nameEdit;
|
||||
QLabel *commentsLabel;
|
||||
QTextEdit *commentsEdit;
|
||||
QLabel *hashLabel1;
|
||||
QLabel *hashLabel;
|
||||
DlgCardSearch *dlgCardSearch;
|
||||
FilterTreeModel *filterModel;
|
||||
QTreeView *filterView;
|
||||
|
||||
QMenu *deckMenu, *dbMenu;
|
||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose;
|
||||
QAction *aEditSets, *aEditTokens, *aSearch, *aClearSearch;
|
||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
|
||||
QAction *aEditSets, *aEditTokens, *aClearSearch, *aCardTextOnly;
|
||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
|
||||
|
||||
bool modified;
|
||||
public:
|
||||
|
|
|
@ -5,7 +5,6 @@ SET(common_SOURCES
|
|||
decklist.cpp
|
||||
get_pb_extension.cpp
|
||||
rng_abstract.cpp
|
||||
rng_qt.cpp
|
||||
rng_sfmt.cpp
|
||||
server.cpp
|
||||
server_abstractuserinterface.cpp
|
||||
|
@ -25,7 +24,6 @@ SET(common_SOURCES
|
|||
SET(common_HEADERS
|
||||
decklist.h
|
||||
rng_abstract.h
|
||||
rng_qt.h
|
||||
rng_sfmt.h
|
||||
server.h
|
||||
server_arrowtarget.h
|
||||
|
|
|
@ -7,9 +7,9 @@ QVector<int> RNG_Abstract::makeNumbersVector(int n, int min, int max)
|
|||
const int bins = max - min + 1;
|
||||
QVector<int> result(bins);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int number = getNumber(min, max);
|
||||
int number = rand(min, max);
|
||||
if ((number < min) || (number > max))
|
||||
qDebug() << "getNumber(" << min << "," << max << ") returned " << number;
|
||||
qDebug() << "rand(" << min << "," << max << ") returned " << number;
|
||||
else
|
||||
result[number - min]++;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ class RNG_Abstract : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
RNG_Abstract(QObject *parent = 0) : QObject(parent) { }
|
||||
virtual unsigned int getNumber(unsigned int min, unsigned int max) = 0;
|
||||
virtual unsigned int rand(int min, int max) = 0;
|
||||
QVector<int> makeNumbersVector(int n, int min, int max);
|
||||
double testRandom(const QVector<int> &numbers) const;
|
||||
};
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include "rng_qt.h"
|
||||
#include <QDateTime>
|
||||
#include <stdlib.h>
|
||||
|
||||
RNG_Qt::RNG_Qt(QObject *parent)
|
||||
: RNG_Abstract(parent)
|
||||
{
|
||||
int seed = QDateTime::currentDateTime().toTime_t();
|
||||
qsrand(seed);
|
||||
}
|
||||
|
||||
unsigned int RNG_Qt::getNumber(unsigned int min, unsigned int max)
|
||||
{
|
||||
int r = qrand();
|
||||
return min + (unsigned int) (((double) (max + 1 - min)) * r / (RAND_MAX + 1.0));
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef RNG_QT_H
|
||||
#define RNG_QT_H
|
||||
|
||||
#include "rng_abstract.h"
|
||||
|
||||
class RNG_Qt : public RNG_Abstract {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RNG_Qt(QObject *parent = 0);
|
||||
unsigned int getNumber(unsigned int min, unsigned int max);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,25 +1,136 @@
|
|||
#include "rng_sfmt.h"
|
||||
#include "sfmt/SFMT.h"
|
||||
#include <QDateTime>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <stdexcept>
|
||||
|
||||
// This is from gcc sources, namely from fixincludes/inclhack.def
|
||||
// On C++11 systems, <cstdint> could be included instead.
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX (~(uint64_t)0)
|
||||
#endif
|
||||
|
||||
RNG_SFMT::RNG_SFMT(QObject *parent)
|
||||
: RNG_Abstract(parent)
|
||||
{
|
||||
std::cerr << "Using SFMT random number generator." << std::endl;
|
||||
|
||||
int seed = QDateTime::currentDateTime().toTime_t();
|
||||
init_gen_rand(seed);
|
||||
for (int i = 0; i < 100000; ++i)
|
||||
gen_rand64();
|
||||
// initialize the random number generator with a 32bit integer seed (timestamp)
|
||||
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toTime_t());
|
||||
}
|
||||
|
||||
unsigned int RNG_SFMT::getNumber(unsigned int min, unsigned int max)
|
||||
{
|
||||
mutex.lock();
|
||||
uint64_t r = gen_rand64();
|
||||
mutex.unlock();
|
||||
|
||||
return min + (unsigned int) (((double) (max + 1 - min)) * r / (18446744073709551616.0 + 1.0));
|
||||
/**
|
||||
* This method is the rand() equivalent which calls the cdf with proper bounds.
|
||||
*
|
||||
* It is possible to generate random numbers from [-min, +/-max] though the RNG uses
|
||||
* unsigned numbers only, so this wrapper handles some special cases for min and max.
|
||||
*
|
||||
* It is only necessary that the upper bound is larger or equal to the lower bound - with the exception
|
||||
* that someone wants something like rand() % -foo.
|
||||
*/
|
||||
unsigned int RNG_SFMT::rand(int min, int max) {
|
||||
/* If min is negative, it would be possible to calculate
|
||||
* cdf(0, max - min) + min
|
||||
* There has been no use for negative random numbers with rand() though, so it's treated as error.
|
||||
*/
|
||||
if(min < 0) {
|
||||
throw std::invalid_argument(
|
||||
QString("Invalid bounds for RNG: Got min " +
|
||||
QString::number(min) + " < 0!\n").toStdString());
|
||||
// at this point, the method exits. No return value is needed, because
|
||||
// basically the exception itself is returned.
|
||||
}
|
||||
|
||||
// For complete fairness and equal timing, this should be a roll, but let's skip it anyway
|
||||
if(min == max)
|
||||
return max;
|
||||
|
||||
// This is actually not used in Cockatrice:
|
||||
// Someone wants rand() % -foo, so we compute -rand(0, +foo)
|
||||
// This is the only time where min > max is (sort of) legal.
|
||||
// Not handling this will cause the application to crash.
|
||||
if(min == 0 && max < 0) {
|
||||
return -cdf(0, -max);
|
||||
}
|
||||
|
||||
// No special cases are left, except !(min > max) which is caught in the cdf itself.
|
||||
return cdf(min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Much thought went into this, please read this comment before you modify the code.
|
||||
* Let SFMT() be an alias for sfmt_genrand_uint64() aka SFMT's rand() function.
|
||||
*
|
||||
* SMFT() returns a uniformly distributed pseudorandom number from 0 to UINT64_MAX.
|
||||
* As SFMT() operates on a limited integer range, it is a _discrete_ function.
|
||||
*
|
||||
* We want a random number from a given interval [min, max] though, so we need to
|
||||
* implement the (discrete) cumulative distribution function SFMT(min, max), which
|
||||
* returns a random number X from [min, max].
|
||||
*
|
||||
* This CDF is by formal definition:
|
||||
* SFMT(X; min, max) = (floor(X) - min + 1) / (max - min + 1)
|
||||
*
|
||||
* To get out the random variable, solve for X:
|
||||
* floor(X) = SFMT(X; min, max) * (max - min + 1) + min - 1
|
||||
* So this is, what rand(min, max) should look like.
|
||||
* Problem: SFMT(X; min, max) * (max - min + 1) could produce an integer overflow,
|
||||
* so it is not safe.
|
||||
*
|
||||
* One solution is to divide the universe into buckets of equal size depending on the
|
||||
* range [min, max] and assign X to the bucket that contains the number generated
|
||||
* by SFMT(). This equals to modulo computation and is not satisfying:
|
||||
* If the buckets don't divide the universe equally, because the bucket size is not
|
||||
* a divisor of 2, there will be a range in the universe that is biased because one
|
||||
* bucket is too small thus will be chosen less equally!
|
||||
*
|
||||
* This is solved by rejection sampling:
|
||||
* As SFMT() is assumed to be unbiased, we are allowed to ignore those random numbers
|
||||
* from SFMT() that would force us to have an unequal bucket and generate new random
|
||||
* numbers until one number fits into one of the other buckets.
|
||||
* This can be compared to an ideal six sided die that is rolled until only sides
|
||||
* 1-5 show up, while 6 represents something that you don't want. So you basically roll
|
||||
* a five sided die.
|
||||
*
|
||||
* Note: If you replace the SFMT RNG with some other rand() function in the future,
|
||||
* then you _need_ to change the UINT64_MAX constant to the largest possible random
|
||||
* number which can be created by the new rand() function. This value is often defined
|
||||
* in a RAND_MAX constant.
|
||||
* Otherwise you will probably skew the outcome of the rand() method or worsen the
|
||||
* performance of the application.
|
||||
*/
|
||||
unsigned int RNG_SFMT::cdf(unsigned int min, unsigned int max)
|
||||
{
|
||||
// This all makes no sense if min > max, which should never happen.
|
||||
if(min > max) {
|
||||
throw std::invalid_argument(
|
||||
QString("Invalid bounds for RNG: min > max! Values were: min = " +
|
||||
QString::number(min) + ", max = " +
|
||||
QString::number(max)).toStdString());
|
||||
// at this point, the method exits. No return value is needed, because
|
||||
// basically the exception itself is returned.
|
||||
}
|
||||
|
||||
// First compute the diameter (aka size, length) of the [min, max] interval
|
||||
const unsigned int diameter = max - min + 1;
|
||||
|
||||
// Compute how many buckets (each in size of the diameter) will fit into the
|
||||
// universe.
|
||||
// If the division has a remainder, the result is floored automatically.
|
||||
const uint64_t buckets = UINT64_MAX / diameter;
|
||||
|
||||
// Compute the last valid random number. All numbers beyond have to be ignored.
|
||||
// If there was no remainder in the previous step, limit is equal to UINT64_MAX.
|
||||
const uint64_t limit = diameter * buckets;
|
||||
|
||||
uint64_t rand;
|
||||
// To make the random number generation thread-safe, a mutex is created around
|
||||
// the generation. Outside of the loop of course, to avoid lock/unlock overhead.
|
||||
mutex.lock();
|
||||
do {
|
||||
rand = sfmt_genrand_uint64(&sfmt);
|
||||
} while (rand >= limit);
|
||||
mutex.unlock();
|
||||
|
||||
// Now determine the bucket containing the SFMT() random number and after adding
|
||||
// the lower bound, a random number from [min, max] can be returned.
|
||||
return (unsigned int) (rand / buckets + min);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,40 @@
|
|||
#ifndef RNG_SFMT_H
|
||||
#define RNG_SFMT_H
|
||||
|
||||
#include "rng_abstract.h"
|
||||
#include <climits>
|
||||
#include <QMutex>
|
||||
#include "sfmt/SFMT.h"
|
||||
#include "rng_abstract.h"
|
||||
|
||||
/**
|
||||
* This class encapsulates a state of the art PRNG and can be used
|
||||
* to return uniformly distributed integer random numbers from a range [min, max].
|
||||
* Though technically possible, min must be >= 0 and max should always be > 0.
|
||||
* If max < 0 and min == 0 it is assumed that rand() % -max is wanted and the result will
|
||||
* be -rand(0, -max).
|
||||
* This is the only exception to the rule that !(min > max) and is actually unused in
|
||||
* Cockatrice.
|
||||
*
|
||||
* Technical details:
|
||||
* The RNG uses the SIMD-oriented Fast Mersenne Twister code v1.4.1 from
|
||||
* http://www.math.sci.hiroshima-u.ac.jp/~%20m-mat/MT/SFMT/index.html
|
||||
* The SFMT RNG creates unsigned int 64bit pseudo random numbers.
|
||||
*
|
||||
* These are mapped to values from the interval [min, max] without bias by using Knuth's
|
||||
* "Algorithm S (Selection sampling technique)" from "The Art of Computer Programming 3rd
|
||||
* Edition Volume 2 / Seminumerical Algorithms".
|
||||
*/
|
||||
|
||||
class RNG_SFMT : public RNG_Abstract {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QMutex mutex;
|
||||
sfmt_t sfmt;
|
||||
// The discrete cumulative distribution function for the RNG
|
||||
unsigned int cdf(unsigned int min, unsigned int max);
|
||||
public:
|
||||
RNG_SFMT(QObject *parent = 0);
|
||||
unsigned int getNumber(unsigned int min, unsigned int max);
|
||||
unsigned int rand(int min, int max);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,7 +45,7 @@ void Server_CardZone::shuffle()
|
|||
{
|
||||
QList<Server_Card *> temp;
|
||||
for (int i = cards.size(); i; i--)
|
||||
temp.append(cards.takeAt(rng->getNumber(0, i - 1)));
|
||||
temp.append(cards.takeAt(rng->rand(0, i - 1)));
|
||||
cards = temp;
|
||||
|
||||
playersWithWritePermission.clear();
|
||||
|
|
|
@ -844,7 +844,7 @@ Response::ResponseCode Server_Player::cmdRollDie(const Command_RollDie &cmd, Res
|
|||
|
||||
Event_RollDie event;
|
||||
event.set_sides(cmd.sides());
|
||||
event.set_value(rng->getNumber(1, cmd.sides()));
|
||||
event.set_value(rng->rand(1, cmd.sides()));
|
||||
ges.enqueueGameEvent(event, playerId);
|
||||
|
||||
return Response::RespOk;
|
||||
|
@ -1524,7 +1524,7 @@ Response::ResponseCode Server_Player::cmdRevealCards(const Command_RevealCards &
|
|||
else if (cmd.card_id() == -2) {
|
||||
if (zone->getCards().isEmpty())
|
||||
return Response::RespContextError;
|
||||
cardsToReveal.append(zone->getCards().at(rng->getNumber(0, zone->getCards().size() - 1)));
|
||||
cardsToReveal.append(zone->getCards().at(rng->rand(0, zone->getCards().size() - 1)));
|
||||
} else {
|
||||
Server_Card *card = zone->getCard(cmd.card_id());
|
||||
if (!card)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
University. All rights reserved.
|
||||
University.
|
||||
Copyright (c) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima University
|
||||
and The University of Tokyo.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
@ -11,10 +14,10 @@ met:
|
|||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of the Hiroshima University nor the names of
|
||||
its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission.
|
||||
* Neither the names of Hiroshima University, The University of
|
||||
Tokyo nor the names of its contributors may be used to endorse
|
||||
or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
|
164
common/sfmt/SFMT-common.h
Normal file
164
common/sfmt/SFMT-common.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @file SFMT-common.h
|
||||
*
|
||||
* @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom
|
||||
* number generator with jump function. This file includes common functions
|
||||
* used in random number generation and jump.
|
||||
*
|
||||
* @author Mutsuo Saito (Hiroshima University)
|
||||
* @author Makoto Matsumoto (The University of Tokyo)
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
* University.
|
||||
* Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima
|
||||
* University and The University of Tokyo.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The 3-clause BSD License is applied to this software, see
|
||||
* LICENSE.txt
|
||||
*/
|
||||
#ifndef SFMT_COMMON_H
|
||||
#define SFMT_COMMON_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "SFMT.h"
|
||||
|
||||
inline static void do_recursion(w128_t * r, w128_t * a, w128_t * b,
|
||||
w128_t * c, w128_t * d);
|
||||
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift);
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift);
|
||||
|
||||
/**
|
||||
* This function simulates SIMD 128-bit right shift by the standard C.
|
||||
* The 128-bit integer given in in is shifted by (shift * 8) bits.
|
||||
* This function simulates the LITTLE ENDIAN SIMD.
|
||||
* @param out the output of this function
|
||||
* @param in the 128-bit data to be shifted
|
||||
* @param shift the shift value
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
|
||||
tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
|
||||
|
||||
oh = th >> (shift * 8);
|
||||
ol = tl >> (shift * 8);
|
||||
ol |= th << (64 - shift * 8);
|
||||
out->u[0] = (uint32_t)(ol >> 32);
|
||||
out->u[1] = (uint32_t)ol;
|
||||
out->u[2] = (uint32_t)(oh >> 32);
|
||||
out->u[3] = (uint32_t)oh;
|
||||
}
|
||||
#else
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift)
|
||||
{
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
|
||||
tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
|
||||
|
||||
oh = th >> (shift * 8);
|
||||
ol = tl >> (shift * 8);
|
||||
ol |= th << (64 - shift * 8);
|
||||
out->u[1] = (uint32_t)(ol >> 32);
|
||||
out->u[0] = (uint32_t)ol;
|
||||
out->u[3] = (uint32_t)(oh >> 32);
|
||||
out->u[2] = (uint32_t)oh;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function simulates SIMD 128-bit left shift by the standard C.
|
||||
* The 128-bit integer given in in is shifted by (shift * 8) bits.
|
||||
* This function simulates the LITTLE ENDIAN SIMD.
|
||||
* @param out the output of this function
|
||||
* @param in the 128-bit data to be shifted
|
||||
* @param shift the shift value
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
|
||||
tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
|
||||
|
||||
oh = th << (shift * 8);
|
||||
ol = tl << (shift * 8);
|
||||
oh |= tl >> (64 - shift * 8);
|
||||
out->u[0] = (uint32_t)(ol >> 32);
|
||||
out->u[1] = (uint32_t)ol;
|
||||
out->u[2] = (uint32_t)(oh >> 32);
|
||||
out->u[3] = (uint32_t)oh;
|
||||
}
|
||||
#else
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift)
|
||||
{
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
|
||||
tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
|
||||
|
||||
oh = th << (shift * 8);
|
||||
ol = tl << (shift * 8);
|
||||
oh |= tl >> (64 - shift * 8);
|
||||
out->u[1] = (uint32_t)(ol >> 32);
|
||||
out->u[0] = (uint32_t)ol;
|
||||
out->u[3] = (uint32_t)(oh >> 32);
|
||||
out->u[2] = (uint32_t)oh;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function represents the recursion formula.
|
||||
* @param r output
|
||||
* @param a a 128-bit part of the internal state array
|
||||
* @param b a 128-bit part of the internal state array
|
||||
* @param c a 128-bit part of the internal state array
|
||||
* @param d a 128-bit part of the internal state array
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,
|
||||
w128_t *d) {
|
||||
w128_t x;
|
||||
w128_t y;
|
||||
|
||||
lshift128(&x, a, SFMT_SL2);
|
||||
rshift128(&y, c, SFMT_SR2);
|
||||
r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SFMT_SR1) & SFMT_MSK2) ^ y.u[0]
|
||||
^ (d->u[0] << SFMT_SL1);
|
||||
r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SFMT_SR1) & SFMT_MSK1) ^ y.u[1]
|
||||
^ (d->u[1] << SFMT_SL1);
|
||||
r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SFMT_SR1) & SFMT_MSK4) ^ y.u[2]
|
||||
^ (d->u[2] << SFMT_SL1);
|
||||
r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SFMT_SR1) & SFMT_MSK3) ^ y.u[3]
|
||||
^ (d->u[3] << SFMT_SL1);
|
||||
}
|
||||
#else
|
||||
inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b,
|
||||
w128_t *c, w128_t *d)
|
||||
{
|
||||
w128_t x;
|
||||
w128_t y;
|
||||
|
||||
lshift128(&x, a, SFMT_SL2);
|
||||
rshift128(&y, c, SFMT_SR2);
|
||||
r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SFMT_SR1) & SFMT_MSK1)
|
||||
^ y.u[0] ^ (d->u[0] << SFMT_SL1);
|
||||
r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SFMT_SR1) & SFMT_MSK2)
|
||||
^ y.u[1] ^ (d->u[1] << SFMT_SL1);
|
||||
r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SFMT_SR1) & SFMT_MSK3)
|
||||
^ y.u[2] ^ (d->u[2] << SFMT_SL1);
|
||||
r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SFMT_SR1) & SFMT_MSK4)
|
||||
^ y.u[3] ^ (d->u[3] << SFMT_SL1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -1,95 +1,96 @@
|
|||
#pragma once
|
||||
#ifndef SFMT_PARAMS_H
|
||||
#define SFMT_PARAMS_H
|
||||
|
||||
#if !defined(MEXP)
|
||||
#ifdef __GNUC__
|
||||
#warning "MEXP is not defined. I assume MEXP is 19937."
|
||||
#if !defined(SFMT_MEXP)
|
||||
#if defined(__GNUC__) && !defined(__ICC)
|
||||
#warning "SFMT_MEXP is not defined. I assume MEXP is 19937."
|
||||
#endif
|
||||
#define MEXP 19937
|
||||
#define SFMT_MEXP 19937
|
||||
#endif
|
||||
/*-----------------
|
||||
BASIC DEFINITIONS
|
||||
-----------------*/
|
||||
/** Mersenne Exponent. The period of the sequence
|
||||
/** Mersenne Exponent. The period of the sequence
|
||||
* is a multiple of 2^MEXP-1.
|
||||
* #define MEXP 19937 */
|
||||
* #define SFMT_MEXP 19937 */
|
||||
/** SFMT generator has an internal state array of 128-bit integers,
|
||||
* and N is its size. */
|
||||
#define N (MEXP / 128 + 1)
|
||||
#define SFMT_N (SFMT_MEXP / 128 + 1)
|
||||
/** N32 is the size of internal state array when regarded as an array
|
||||
* of 32-bit integers.*/
|
||||
#define N32 (N * 4)
|
||||
#define SFMT_N32 (SFMT_N * 4)
|
||||
/** N64 is the size of internal state array when regarded as an array
|
||||
* of 64-bit integers.*/
|
||||
#define N64 (N * 2)
|
||||
#define SFMT_N64 (SFMT_N * 2)
|
||||
|
||||
/*----------------------
|
||||
the parameters of SFMT
|
||||
following definitions are in paramsXXXX.h file.
|
||||
----------------------*/
|
||||
/** the pick up position of the array.
|
||||
#define POS1 122
|
||||
#define SFMT_POS1 122
|
||||
*/
|
||||
|
||||
/** the parameter of shift left as four 32-bit registers.
|
||||
#define SL1 18
|
||||
#define SFMT_SL1 18
|
||||
*/
|
||||
|
||||
/** the parameter of shift left as one 128-bit register.
|
||||
* The 128-bit integer is shifted by (SL2 * 8) bits.
|
||||
#define SL2 1
|
||||
/** the parameter of shift left as one 128-bit register.
|
||||
* The 128-bit integer is shifted by (SFMT_SL2 * 8) bits.
|
||||
#define SFMT_SL2 1
|
||||
*/
|
||||
|
||||
/** the parameter of shift right as four 32-bit registers.
|
||||
#define SR1 11
|
||||
#define SFMT_SR1 11
|
||||
*/
|
||||
|
||||
/** the parameter of shift right as one 128-bit register.
|
||||
* The 128-bit integer is shifted by (SL2 * 8) bits.
|
||||
#define SR2 1
|
||||
/** the parameter of shift right as one 128-bit register.
|
||||
* The 128-bit integer is shifted by (SFMT_SL2 * 8) bits.
|
||||
#define SFMT_SR21 1
|
||||
*/
|
||||
|
||||
/** A bitmask, used in the recursion. These parameters are introduced
|
||||
* to break symmetry of SIMD.
|
||||
#define MSK1 0xdfffffefU
|
||||
#define MSK2 0xddfecb7fU
|
||||
#define MSK3 0xbffaffffU
|
||||
#define MSK4 0xbffffff6U
|
||||
#define SFMT_MSK1 0xdfffffefU
|
||||
#define SFMT_MSK2 0xddfecb7fU
|
||||
#define SFMT_MSK3 0xbffaffffU
|
||||
#define SFMT_MSK4 0xbffffff6U
|
||||
*/
|
||||
|
||||
/** These definitions are part of a 128-bit period certification vector.
|
||||
#define PARITY1 0x00000001U
|
||||
#define PARITY2 0x00000000U
|
||||
#define PARITY3 0x00000000U
|
||||
#define PARITY4 0xc98e126aU
|
||||
#define SFMT_PARITY1 0x00000001U
|
||||
#define SFMT_PARITY2 0x00000000U
|
||||
#define SFMT_PARITY3 0x00000000U
|
||||
#define SFMT_PARITY4 0xc98e126aU
|
||||
*/
|
||||
|
||||
#if MEXP == 607
|
||||
#if SFMT_MEXP == 607
|
||||
#include "SFMT-params607.h"
|
||||
#elif MEXP == 1279
|
||||
#elif SFMT_MEXP == 1279
|
||||
#include "SFMT-params1279.h"
|
||||
#elif MEXP == 2281
|
||||
#elif SFMT_MEXP == 2281
|
||||
#include "SFMT-params2281.h"
|
||||
#elif MEXP == 4253
|
||||
#elif SFMT_MEXP == 4253
|
||||
#include "SFMT-params4253.h"
|
||||
#elif MEXP == 11213
|
||||
#elif SFMT_MEXP == 11213
|
||||
#include "SFMT-params11213.h"
|
||||
#elif MEXP == 19937
|
||||
#elif SFMT_MEXP == 19937
|
||||
#include "SFMT-params19937.h"
|
||||
#elif MEXP == 44497
|
||||
#elif SFMT_MEXP == 44497
|
||||
#include "SFMT-params44497.h"
|
||||
#elif MEXP == 86243
|
||||
#elif SFMT_MEXP == 86243
|
||||
#include "SFMT-params86243.h"
|
||||
#elif MEXP == 132049
|
||||
#elif SFMT_MEXP == 132049
|
||||
#include "SFMT-params132049.h"
|
||||
#elif MEXP == 216091
|
||||
#elif SFMT_MEXP == 216091
|
||||
#include "SFMT-params216091.h"
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#error "MEXP is not valid."
|
||||
#undef MEXP
|
||||
#if defined(__GNUC__) && !defined(__ICC)
|
||||
#error "SFMT_MEXP is not valid."
|
||||
#undef SFMT_MEXP
|
||||
#else
|
||||
#undef MEXP
|
||||
#undef SFMT_MEXP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,46 +1,50 @@
|
|||
#pragma once
|
||||
#ifndef SFMT_PARAMS19937_H
|
||||
#define SFMT_PARAMS19937_H
|
||||
|
||||
#define POS1 122
|
||||
#define SL1 18
|
||||
#define SL2 1
|
||||
#define SR1 11
|
||||
#define SR2 1
|
||||
#define MSK1 0xdfffffefU
|
||||
#define MSK2 0xddfecb7fU
|
||||
#define MSK3 0xbffaffffU
|
||||
#define MSK4 0xbffffff6U
|
||||
#define PARITY1 0x00000001U
|
||||
#define PARITY2 0x00000000U
|
||||
#define PARITY3 0x00000000U
|
||||
#define PARITY4 0x13c9e684U
|
||||
#define SFMT_POS1 122
|
||||
#define SFMT_SL1 18
|
||||
#define SFMT_SL2 1
|
||||
#define SFMT_SR1 11
|
||||
#define SFMT_SR2 1
|
||||
#define SFMT_MSK1 0xdfffffefU
|
||||
#define SFMT_MSK2 0xddfecb7fU
|
||||
#define SFMT_MSK3 0xbffaffffU
|
||||
#define SFMT_MSK4 0xbffffff6U
|
||||
#define SFMT_PARITY1 0x00000001U
|
||||
#define SFMT_PARITY2 0x00000000U
|
||||
#define SFMT_PARITY3 0x00000000U
|
||||
#define SFMT_PARITY4 0x13c9e684U
|
||||
|
||||
|
||||
/* PARAMETERS FOR ALTIVEC */
|
||||
#if defined(__APPLE__) /* For OSX */
|
||||
#define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1)
|
||||
#define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1)
|
||||
#define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4)
|
||||
#define ALTI_MSK64 \
|
||||
(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)
|
||||
#define ALTI_SL2_PERM \
|
||||
#define SFMT_ALTI_SL1 \
|
||||
(vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1)
|
||||
#define SFMT_ALTI_SR1 \
|
||||
(vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1)
|
||||
#define SFMT_ALTI_MSK \
|
||||
(vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4)
|
||||
#define SFMT_ALTI_MSK64 \
|
||||
(vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3)
|
||||
#define SFMT_ALTI_SL2_PERM \
|
||||
(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)
|
||||
#define ALTI_SL2_PERM64 \
|
||||
#define SFMT_ALTI_SL2_PERM64 \
|
||||
(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)
|
||||
#define ALTI_SR2_PERM \
|
||||
#define SFMT_ALTI_SR2_PERM \
|
||||
(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)
|
||||
#define ALTI_SR2_PERM64 \
|
||||
#define SFMT_ALTI_SR2_PERM64 \
|
||||
(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)
|
||||
#else /* For OTHER OSs(Linux?) */
|
||||
#define ALTI_SL1 {SL1, SL1, SL1, SL1}
|
||||
#define ALTI_SR1 {SR1, SR1, SR1, SR1}
|
||||
#define ALTI_MSK {MSK1, MSK2, MSK3, MSK4}
|
||||
#define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3}
|
||||
#define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}
|
||||
#define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}
|
||||
#define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}
|
||||
#define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}
|
||||
#define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1}
|
||||
#define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1}
|
||||
#define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4}
|
||||
#define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3}
|
||||
#define SFMT_ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}
|
||||
#define SFMT_ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}
|
||||
#define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}
|
||||
#define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}
|
||||
#endif /* For OSX */
|
||||
#define IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6"
|
||||
#define SFMT_IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6"
|
||||
|
||||
#endif /* SFMT_PARAMS19937_H */
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
/**
|
||||
/**
|
||||
* @file SFMT.c
|
||||
* @brief SIMD oriented Fast Mersenne Twister(SFMT)
|
||||
*
|
||||
* @author Mutsuo Saito (Hiroshima University)
|
||||
* @author Makoto Matsumoto (Hiroshima University)
|
||||
*
|
||||
* Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
* University. All rights reserved.
|
||||
* Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
* University.
|
||||
* Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima
|
||||
* University and The University of Tokyo.
|
||||
* Copyright (C) 2013 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
* University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The new BSD License is applied to this software, see LICENSE.txt
|
||||
* The 3-clause BSD License is applied to this software, see
|
||||
* LICENSE.txt
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "SFMT.h"
|
||||
#include "SFMT-params.h"
|
||||
#include "SFMT-common.h"
|
||||
|
||||
#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)
|
||||
#define BIG_ENDIAN64 1
|
||||
|
@ -27,74 +39,20 @@
|
|||
#endif
|
||||
#undef ONLY64
|
||||
#endif
|
||||
/*------------------------------------------------------
|
||||
128-bit SIMD data type for Altivec, SSE2 or standard C
|
||||
------------------------------------------------------*/
|
||||
#if defined(HAVE_ALTIVEC)
|
||||
#if !defined(__APPLE__)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
vector unsigned int s;
|
||||
uint32_t u[4];
|
||||
};
|
||||
/** 128-bit data type */
|
||||
typedef union W128_T w128_t;
|
||||
|
||||
#elif defined(HAVE_SSE2)
|
||||
#include <emmintrin.h>
|
||||
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
__m128i si;
|
||||
uint32_t u[4];
|
||||
};
|
||||
/** 128-bit data type */
|
||||
typedef union W128_T w128_t;
|
||||
|
||||
#else
|
||||
|
||||
/** 128-bit data structure */
|
||||
struct W128_T {
|
||||
uint32_t u[4];
|
||||
};
|
||||
/** 128-bit data type */
|
||||
typedef struct W128_T w128_t;
|
||||
|
||||
#endif
|
||||
|
||||
/*--------------------------------------
|
||||
FILE GLOBAL VARIABLES
|
||||
internal state, index counter and flag
|
||||
--------------------------------------*/
|
||||
/** the 128-bit internal state array */
|
||||
static w128_t sfmt[N];
|
||||
/** the 32bit integer pointer to the 128-bit internal state array */
|
||||
static uint32_t *psfmt32 = &sfmt[0].u[0];
|
||||
#if !defined(BIG_ENDIAN64) || defined(ONLY64)
|
||||
/** the 64bit integer pointer to the 128-bit internal state array */
|
||||
static uint64_t *psfmt64 = (uint64_t *)&sfmt[0].u[0];
|
||||
#endif
|
||||
/** index counter to the 32-bit internal state array */
|
||||
static int idx;
|
||||
/** a flag: it is 0 if and only if the internal state is not yet
|
||||
* initialized. */
|
||||
static int initialized = 0;
|
||||
/** a parity check vector which certificate the period of 2^{MEXP} */
|
||||
static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};
|
||||
|
||||
/**
|
||||
* parameters used by sse2.
|
||||
*/
|
||||
static const w128_t sse2_param_mask = {{SFMT_MSK1, SFMT_MSK2,
|
||||
SFMT_MSK3, SFMT_MSK4}};
|
||||
/*----------------
|
||||
STATIC FUNCTIONS
|
||||
----------------*/
|
||||
inline static int idxof(int i);
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift);
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift);
|
||||
inline static void gen_rand_all(void);
|
||||
inline static void gen_rand_array(w128_t *array, int size);
|
||||
inline static void gen_rand_array(sfmt_t * sfmt, w128_t *array, int size);
|
||||
inline static uint32_t func1(uint32_t x);
|
||||
inline static uint32_t func2(uint32_t x);
|
||||
static void period_certification(void);
|
||||
static void period_certification(sfmt_t * sfmt);
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
inline static void swap(w128_t *array, int size);
|
||||
#endif
|
||||
|
@ -102,11 +60,15 @@ inline static void swap(w128_t *array, int size);
|
|||
#if defined(HAVE_ALTIVEC)
|
||||
#include "SFMT-alti.h"
|
||||
#elif defined(HAVE_SSE2)
|
||||
#include "SFMT-sse2.h"
|
||||
#if defined(_MSC_VER)
|
||||
#include "SFMT-sse2-msc.h"
|
||||
#else
|
||||
#include "SFMT-sse2.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function simulate a 64-bit index of LITTLE ENDIAN
|
||||
* This function simulate a 64-bit index of LITTLE ENDIAN
|
||||
* in BIG ENDIAN machine.
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
|
@ -118,190 +80,48 @@ inline static int idxof(int i) {
|
|||
return i;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function simulates SIMD 128-bit right shift by the standard C.
|
||||
* The 128-bit integer given in in is shifted by (shift * 8) bits.
|
||||
* This function simulates the LITTLE ENDIAN SIMD.
|
||||
* @param out the output of this function
|
||||
* @param in the 128-bit data to be shifted
|
||||
* @param shift the shift value
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
|
||||
tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
|
||||
|
||||
oh = th >> (shift * 8);
|
||||
ol = tl >> (shift * 8);
|
||||
ol |= th << (64 - shift * 8);
|
||||
out->u[0] = (uint32_t)(ol >> 32);
|
||||
out->u[1] = (uint32_t)ol;
|
||||
out->u[2] = (uint32_t)(oh >> 32);
|
||||
out->u[3] = (uint32_t)oh;
|
||||
}
|
||||
#else
|
||||
inline static void rshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
|
||||
tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
|
||||
|
||||
oh = th >> (shift * 8);
|
||||
ol = tl >> (shift * 8);
|
||||
ol |= th << (64 - shift * 8);
|
||||
out->u[1] = (uint32_t)(ol >> 32);
|
||||
out->u[0] = (uint32_t)ol;
|
||||
out->u[3] = (uint32_t)(oh >> 32);
|
||||
out->u[2] = (uint32_t)oh;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function simulates SIMD 128-bit left shift by the standard C.
|
||||
* The 128-bit integer given in in is shifted by (shift * 8) bits.
|
||||
* This function simulates the LITTLE ENDIAN SIMD.
|
||||
* @param out the output of this function
|
||||
* @param in the 128-bit data to be shifted
|
||||
* @param shift the shift value
|
||||
*/
|
||||
#ifdef ONLY64
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
|
||||
tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
|
||||
|
||||
oh = th << (shift * 8);
|
||||
ol = tl << (shift * 8);
|
||||
oh |= tl >> (64 - shift * 8);
|
||||
out->u[0] = (uint32_t)(ol >> 32);
|
||||
out->u[1] = (uint32_t)ol;
|
||||
out->u[2] = (uint32_t)(oh >> 32);
|
||||
out->u[3] = (uint32_t)oh;
|
||||
}
|
||||
#else
|
||||
inline static void lshift128(w128_t *out, w128_t const *in, int shift) {
|
||||
uint64_t th, tl, oh, ol;
|
||||
|
||||
th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
|
||||
tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
|
||||
|
||||
oh = th << (shift * 8);
|
||||
ol = tl << (shift * 8);
|
||||
oh |= tl >> (64 - shift * 8);
|
||||
out->u[1] = (uint32_t)(ol >> 32);
|
||||
out->u[0] = (uint32_t)ol;
|
||||
out->u[3] = (uint32_t)(oh >> 32);
|
||||
out->u[2] = (uint32_t)oh;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function represents the recursion formula.
|
||||
* @param r output
|
||||
* @param a a 128-bit part of the internal state array
|
||||
* @param b a 128-bit part of the internal state array
|
||||
* @param c a 128-bit part of the internal state array
|
||||
* @param d a 128-bit part of the internal state array
|
||||
*/
|
||||
#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))
|
||||
#ifdef ONLY64
|
||||
inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,
|
||||
w128_t *d) {
|
||||
w128_t x;
|
||||
w128_t y;
|
||||
|
||||
lshift128(&x, a, SL2);
|
||||
rshift128(&y, c, SR2);
|
||||
r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0]
|
||||
^ (d->u[0] << SL1);
|
||||
r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1]
|
||||
^ (d->u[1] << SL1);
|
||||
r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2]
|
||||
^ (d->u[2] << SL1);
|
||||
r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3]
|
||||
^ (d->u[3] << SL1);
|
||||
}
|
||||
#else
|
||||
inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,
|
||||
w128_t *d) {
|
||||
w128_t x;
|
||||
w128_t y;
|
||||
|
||||
lshift128(&x, a, SL2);
|
||||
rshift128(&y, c, SR2);
|
||||
r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0]
|
||||
^ (d->u[0] << SL1);
|
||||
r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1]
|
||||
^ (d->u[1] << SL1);
|
||||
r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2]
|
||||
^ (d->u[2] << SL1);
|
||||
r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3]
|
||||
^ (d->u[3] << SL1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))
|
||||
/**
|
||||
* This function fills the internal state array with pseudorandom
|
||||
* integers.
|
||||
*/
|
||||
inline static void gen_rand_all(void) {
|
||||
int i;
|
||||
w128_t *r1, *r2;
|
||||
|
||||
r1 = &sfmt[N - 2];
|
||||
r2 = &sfmt[N - 1];
|
||||
for (i = 0; i < N - POS1; i++) {
|
||||
do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &sfmt[i];
|
||||
}
|
||||
for (; i < N; i++) {
|
||||
do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1 - N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &sfmt[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function fills the user-specified array with pseudorandom
|
||||
* integers.
|
||||
*
|
||||
* @param array an 128-bit array to be filled by pseudorandom numbers.
|
||||
* @param sfmt SFMT internal state
|
||||
* @param array an 128-bit array to be filled by pseudorandom numbers.
|
||||
* @param size number of 128-bit pseudorandom numbers to be generated.
|
||||
*/
|
||||
inline static void gen_rand_array(w128_t *array, int size) {
|
||||
inline static void gen_rand_array(sfmt_t * sfmt, w128_t *array, int size) {
|
||||
int i, j;
|
||||
w128_t *r1, *r2;
|
||||
|
||||
r1 = &sfmt[N - 2];
|
||||
r2 = &sfmt[N - 1];
|
||||
for (i = 0; i < N - POS1; i++) {
|
||||
do_recursion(&array[i], &sfmt[i], &sfmt[i + POS1], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
r1 = &sfmt->state[SFMT_N - 2];
|
||||
r2 = &sfmt->state[SFMT_N - 1];
|
||||
for (i = 0; i < SFMT_N - SFMT_POS1; i++) {
|
||||
do_recursion(&array[i], &sfmt->state[i], &sfmt->state[i + SFMT_POS1], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
}
|
||||
for (; i < N; i++) {
|
||||
do_recursion(&array[i], &sfmt[i], &array[i + POS1 - N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
for (; i < SFMT_N; i++) {
|
||||
do_recursion(&array[i], &sfmt->state[i],
|
||||
&array[i + SFMT_POS1 - SFMT_N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
}
|
||||
for (; i < size - N; i++) {
|
||||
do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
for (; i < size - SFMT_N; i++) {
|
||||
do_recursion(&array[i], &array[i - SFMT_N],
|
||||
&array[i + SFMT_POS1 - SFMT_N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
}
|
||||
for (j = 0; j < 2 * N - size; j++) {
|
||||
sfmt[j] = array[j + size - N];
|
||||
for (j = 0; j < 2 * SFMT_N - size; j++) {
|
||||
sfmt->state[j] = array[j + size - SFMT_N];
|
||||
}
|
||||
for (; i < size; i++, j++) {
|
||||
do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
sfmt[j] = array[i];
|
||||
do_recursion(&array[i], &array[i - SFMT_N],
|
||||
&array[i + SFMT_POS1 - SFMT_N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &array[i];
|
||||
sfmt->state[j] = array[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -312,12 +132,12 @@ inline static void swap(w128_t *array, int size) {
|
|||
uint32_t x, y;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
x = array[i].u[0];
|
||||
y = array[i].u[2];
|
||||
array[i].u[0] = array[i].u[1];
|
||||
array[i].u[2] = array[i].u[3];
|
||||
array[i].u[1] = x;
|
||||
array[i].u[3] = y;
|
||||
x = array[i].u[0];
|
||||
y = array[i].u[2];
|
||||
array[i].u[0] = array[i].u[1];
|
||||
array[i].u[2] = array[i].u[3];
|
||||
array[i].u[1] = x;
|
||||
array[i].u[3] = y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -343,114 +163,101 @@ static uint32_t func2(uint32_t x) {
|
|||
|
||||
/**
|
||||
* This function certificate the period of 2^{MEXP}
|
||||
* @param sfmt SFMT internal state
|
||||
*/
|
||||
static void period_certification(void) {
|
||||
static void period_certification(sfmt_t * sfmt) {
|
||||
int inner = 0;
|
||||
int i, j;
|
||||
uint32_t work;
|
||||
uint32_t *psfmt32 = &sfmt->state[0].u[0];
|
||||
const uint32_t parity[4] = {SFMT_PARITY1, SFMT_PARITY2,
|
||||
SFMT_PARITY3, SFMT_PARITY4};
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
inner ^= psfmt32[idxof(i)] & parity[i];
|
||||
inner ^= psfmt32[idxof(i)] & parity[i];
|
||||
for (i = 16; i > 0; i >>= 1)
|
||||
inner ^= inner >> i;
|
||||
inner ^= inner >> i;
|
||||
inner &= 1;
|
||||
/* check OK */
|
||||
if (inner == 1) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
/* check NG, and modification */
|
||||
for (i = 0; i < 4; i++) {
|
||||
work = 1;
|
||||
for (j = 0; j < 32; j++) {
|
||||
if ((work & parity[i]) != 0) {
|
||||
psfmt32[idxof(i)] ^= work;
|
||||
return;
|
||||
}
|
||||
work = work << 1;
|
||||
}
|
||||
work = 1;
|
||||
for (j = 0; j < 32; j++) {
|
||||
if ((work & parity[i]) != 0) {
|
||||
psfmt32[idxof(i)] ^= work;
|
||||
return;
|
||||
}
|
||||
work = work << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------
|
||||
PUBLIC FUNCTIONS
|
||||
----------------*/
|
||||
#define UNUSED_VARIABLE(x) (void)(x)
|
||||
/**
|
||||
* This function returns the identification string.
|
||||
* The string shows the word size, the Mersenne exponent,
|
||||
* and all parameters of this generator.
|
||||
* @param sfmt SFMT internal state
|
||||
*/
|
||||
const char *get_idstring(void) {
|
||||
return IDSTR;
|
||||
const char *sfmt_get_idstring(sfmt_t * sfmt) {
|
||||
UNUSED_VARIABLE(sfmt);
|
||||
return SFMT_IDSTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the minimum size of array used for \b
|
||||
* fill_array32() function.
|
||||
* @param sfmt SFMT internal state
|
||||
* @return minimum size of array used for fill_array32() function.
|
||||
*/
|
||||
int get_min_array_size32(void) {
|
||||
return N32;
|
||||
int sfmt_get_min_array_size32(sfmt_t * sfmt) {
|
||||
UNUSED_VARIABLE(sfmt);
|
||||
return SFMT_N32;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the minimum size of array used for \b
|
||||
* fill_array64() function.
|
||||
* @param sfmt SFMT internal state
|
||||
* @return minimum size of array used for fill_array64() function.
|
||||
*/
|
||||
int get_min_array_size64(void) {
|
||||
return N64;
|
||||
int sfmt_get_min_array_size64(sfmt_t * sfmt) {
|
||||
UNUSED_VARIABLE(sfmt);
|
||||
return SFMT_N64;
|
||||
}
|
||||
|
||||
#ifndef ONLY64
|
||||
#if !defined(HAVE_SSE2) && !defined(HAVE_ALTIVEC)
|
||||
/**
|
||||
* This function generates and returns 32-bit pseudorandom number.
|
||||
* init_gen_rand or init_by_array must be called before this function.
|
||||
* @return 32-bit pseudorandom number
|
||||
* This function fills the internal state array with pseudorandom
|
||||
* integers.
|
||||
* @param sfmt SFMT internal state
|
||||
*/
|
||||
uint32_t gen_rand32(void) {
|
||||
uint32_t r;
|
||||
void sfmt_gen_rand_all(sfmt_t * sfmt) {
|
||||
int i;
|
||||
w128_t *r1, *r2;
|
||||
|
||||
assert(initialized);
|
||||
if (idx >= N32) {
|
||||
gen_rand_all();
|
||||
idx = 0;
|
||||
r1 = &sfmt->state[SFMT_N - 2];
|
||||
r2 = &sfmt->state[SFMT_N - 1];
|
||||
for (i = 0; i < SFMT_N - SFMT_POS1; i++) {
|
||||
do_recursion(&sfmt->state[i], &sfmt->state[i],
|
||||
&sfmt->state[i + SFMT_POS1], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &sfmt->state[i];
|
||||
}
|
||||
for (; i < SFMT_N; i++) {
|
||||
do_recursion(&sfmt->state[i], &sfmt->state[i],
|
||||
&sfmt->state[i + SFMT_POS1 - SFMT_N], r1, r2);
|
||||
r1 = r2;
|
||||
r2 = &sfmt->state[i];
|
||||
}
|
||||
r = psfmt32[idx++];
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function generates and returns 64-bit pseudorandom number.
|
||||
* init_gen_rand or init_by_array must be called before this function.
|
||||
* The function gen_rand64 should not be called after gen_rand32,
|
||||
* unless an initialization is again executed.
|
||||
* @return 64-bit pseudorandom number
|
||||
*/
|
||||
uint64_t gen_rand64(void) {
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
uint32_t r1, r2;
|
||||
#else
|
||||
uint64_t r;
|
||||
#endif
|
||||
|
||||
assert(initialized);
|
||||
assert(idx % 2 == 0);
|
||||
|
||||
if (idx >= N32) {
|
||||
gen_rand_all();
|
||||
idx = 0;
|
||||
}
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
r1 = psfmt32[idx];
|
||||
r2 = psfmt32[idx + 1];
|
||||
idx += 2;
|
||||
return ((uint64_t)r2 << 32) | r1;
|
||||
#else
|
||||
r = psfmt64[idx / 2];
|
||||
idx += 2;
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ONLY64
|
||||
/**
|
||||
|
@ -464,6 +271,7 @@ uint64_t gen_rand64(void) {
|
|||
* before the first call of this function. This function can not be
|
||||
* used after calling gen_rand function, without initialization.
|
||||
*
|
||||
* @param sfmt SFMT internal state
|
||||
* @param array an array where pseudorandom 32-bit integers are filled
|
||||
* by this function. The pointer to the array must be \b "aligned"
|
||||
* (namely, must be a multiple of 16) in the SIMD version, since it
|
||||
|
@ -478,14 +286,13 @@ uint64_t gen_rand64(void) {
|
|||
* memory. Mac OSX doesn't have these functions, but \b malloc of OSX
|
||||
* returns the pointer to the aligned memory block.
|
||||
*/
|
||||
void fill_array32(uint32_t *array, int size) {
|
||||
assert(initialized);
|
||||
assert(idx == N32);
|
||||
void sfmt_fill_array32(sfmt_t * sfmt, uint32_t *array, int size) {
|
||||
assert(sfmt->idx == SFMT_N32);
|
||||
assert(size % 4 == 0);
|
||||
assert(size >= N32);
|
||||
assert(size >= SFMT_N32);
|
||||
|
||||
gen_rand_array((w128_t *)array, size / 4);
|
||||
idx = N32;
|
||||
gen_rand_array(sfmt, (w128_t *)array, size / 4);
|
||||
sfmt->idx = SFMT_N32;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -496,6 +303,7 @@ void fill_array32(uint32_t *array, int size) {
|
|||
* multiple of two. The generation by this function is much faster
|
||||
* than the following gen_rand function.
|
||||
*
|
||||
* @param sfmt SFMT internal state
|
||||
* For initialization, init_gen_rand or init_by_array must be called
|
||||
* before the first call of this function. This function can not be
|
||||
* used after calling gen_rand function, without initialization.
|
||||
|
@ -514,14 +322,13 @@ void fill_array32(uint32_t *array, int size) {
|
|||
* memory. Mac OSX doesn't have these functions, but \b malloc of OSX
|
||||
* returns the pointer to the aligned memory block.
|
||||
*/
|
||||
void fill_array64(uint64_t *array, int size) {
|
||||
assert(initialized);
|
||||
assert(idx == N32);
|
||||
void sfmt_fill_array64(sfmt_t * sfmt, uint64_t *array, int size) {
|
||||
assert(sfmt->idx == SFMT_N32);
|
||||
assert(size % 2 == 0);
|
||||
assert(size >= N64);
|
||||
assert(size >= SFMT_N64);
|
||||
|
||||
gen_rand_array((w128_t *)array, size / 2);
|
||||
idx = N32;
|
||||
gen_rand_array(sfmt, (w128_t *)array, size / 2);
|
||||
sfmt->idx = SFMT_N32;
|
||||
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
swap((w128_t *)array, size /2);
|
||||
|
@ -532,54 +339,58 @@ void fill_array64(uint64_t *array, int size) {
|
|||
* This function initializes the internal state array with a 32-bit
|
||||
* integer seed.
|
||||
*
|
||||
* @param sfmt SFMT internal state
|
||||
* @param seed a 32-bit integer used as the seed.
|
||||
*/
|
||||
void init_gen_rand(uint32_t seed) {
|
||||
void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed) {
|
||||
int i;
|
||||
|
||||
uint32_t *psfmt32 = &sfmt->state[0].u[0];
|
||||
|
||||
psfmt32[idxof(0)] = seed;
|
||||
for (i = 1; i < N32; i++) {
|
||||
psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)]
|
||||
^ (psfmt32[idxof(i - 1)] >> 30))
|
||||
+ i;
|
||||
for (i = 1; i < SFMT_N32; i++) {
|
||||
psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)]
|
||||
^ (psfmt32[idxof(i - 1)] >> 30))
|
||||
+ i;
|
||||
}
|
||||
idx = N32;
|
||||
period_certification();
|
||||
initialized = 1;
|
||||
sfmt->idx = SFMT_N32;
|
||||
period_certification(sfmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes the internal state array,
|
||||
* with an array of 32-bit integers used as the seeds
|
||||
* @param sfmt SFMT internal state
|
||||
* @param init_key the array of 32-bit integers, used as a seed.
|
||||
* @param key_length the length of init_key.
|
||||
*/
|
||||
void init_by_array(uint32_t *init_key, int key_length) {
|
||||
void sfmt_init_by_array(sfmt_t * sfmt, uint32_t *init_key, int key_length) {
|
||||
int i, j, count;
|
||||
uint32_t r;
|
||||
int lag;
|
||||
int mid;
|
||||
int size = N * 4;
|
||||
int size = SFMT_N * 4;
|
||||
uint32_t *psfmt32 = &sfmt->state[0].u[0];
|
||||
|
||||
if (size >= 623) {
|
||||
lag = 11;
|
||||
lag = 11;
|
||||
} else if (size >= 68) {
|
||||
lag = 7;
|
||||
lag = 7;
|
||||
} else if (size >= 39) {
|
||||
lag = 5;
|
||||
lag = 5;
|
||||
} else {
|
||||
lag = 3;
|
||||
lag = 3;
|
||||
}
|
||||
mid = (size - lag) / 2;
|
||||
|
||||
memset(sfmt, 0x8b, sizeof(sfmt));
|
||||
if (key_length + 1 > N32) {
|
||||
count = key_length + 1;
|
||||
memset(sfmt, 0x8b, sizeof(sfmt_t));
|
||||
if (key_length + 1 > SFMT_N32) {
|
||||
count = key_length + 1;
|
||||
} else {
|
||||
count = N32;
|
||||
count = SFMT_N32;
|
||||
}
|
||||
r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)]
|
||||
^ psfmt32[idxof(N32 - 1)]);
|
||||
r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)]
|
||||
^ psfmt32[idxof(SFMT_N32 - 1)]);
|
||||
psfmt32[idxof(mid)] += r;
|
||||
r += key_length;
|
||||
psfmt32[idxof(mid + lag)] += r;
|
||||
|
@ -587,34 +398,36 @@ void init_by_array(uint32_t *init_key, int key_length) {
|
|||
|
||||
count--;
|
||||
for (i = 1, j = 0; (j < count) && (j < key_length); j++) {
|
||||
r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)]
|
||||
^ psfmt32[idxof((i + N32 - 1) % N32)]);
|
||||
psfmt32[idxof((i + mid) % N32)] += r;
|
||||
r += init_key[j] + i;
|
||||
psfmt32[idxof((i + mid + lag) % N32)] += r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % N32;
|
||||
r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % SFMT_N32)]
|
||||
^ psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]);
|
||||
psfmt32[idxof((i + mid) % SFMT_N32)] += r;
|
||||
r += init_key[j] + i;
|
||||
psfmt32[idxof((i + mid + lag) % SFMT_N32)] += r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % SFMT_N32;
|
||||
}
|
||||
for (; j < count; j++) {
|
||||
r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)]
|
||||
^ psfmt32[idxof((i + N32 - 1) % N32)]);
|
||||
psfmt32[idxof((i + mid) % N32)] += r;
|
||||
r += i;
|
||||
psfmt32[idxof((i + mid + lag) % N32)] += r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % N32;
|
||||
r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % SFMT_N32)]
|
||||
^ psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]);
|
||||
psfmt32[idxof((i + mid) % SFMT_N32)] += r;
|
||||
r += i;
|
||||
psfmt32[idxof((i + mid + lag) % SFMT_N32)] += r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % SFMT_N32;
|
||||
}
|
||||
for (j = 0; j < N32; j++) {
|
||||
r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)]
|
||||
+ psfmt32[idxof((i + N32 - 1) % N32)]);
|
||||
psfmt32[idxof((i + mid) % N32)] ^= r;
|
||||
r -= i;
|
||||
psfmt32[idxof((i + mid + lag) % N32)] ^= r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % N32;
|
||||
for (j = 0; j < SFMT_N32; j++) {
|
||||
r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % SFMT_N32)]
|
||||
+ psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]);
|
||||
psfmt32[idxof((i + mid) % SFMT_N32)] ^= r;
|
||||
r -= i;
|
||||
psfmt32[idxof((i + mid + lag) % SFMT_N32)] ^= r;
|
||||
psfmt32[idxof(i)] = r;
|
||||
i = (i + 1) % SFMT_N32;
|
||||
}
|
||||
|
||||
idx = N32;
|
||||
period_certification();
|
||||
initialized = 1;
|
||||
sfmt->idx = SFMT_N32;
|
||||
period_certification(sfmt);
|
||||
}
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,24 +1,28 @@
|
|||
/**
|
||||
* @file SFMT.h
|
||||
#pragma once
|
||||
/**
|
||||
* @file SFMT.h
|
||||
*
|
||||
* @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom
|
||||
* number generator
|
||||
* number generator using C structure.
|
||||
*
|
||||
* @author Mutsuo Saito (Hiroshima University)
|
||||
* @author Makoto Matsumoto (Hiroshima University)
|
||||
* @author Makoto Matsumoto (The University of Tokyo)
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
||||
* University. All rights reserved.
|
||||
* University.
|
||||
* Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima
|
||||
* University and The University of Tokyo.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The new BSD License is applied to this software.
|
||||
* see LICENSE.txt
|
||||
* The 3-clause BSD License is applied to this software, see
|
||||
* LICENSE.txt
|
||||
*
|
||||
* @note We assume that your system has inttypes.h. If your system
|
||||
* doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,
|
||||
* and you have to define PRIu64 and PRIx64 in this file as follows:
|
||||
* @verbatim
|
||||
typedef unsigned int uint32_t
|
||||
typedef unsigned long long uint64_t
|
||||
typedef unsigned long long uint64_t
|
||||
#define PRIu64 "llu"
|
||||
#define PRIx64 "llx"
|
||||
@endverbatim
|
||||
|
@ -28,14 +32,14 @@
|
|||
* unsigned int and 64-bit unsigned int in hexadecimal format.
|
||||
*/
|
||||
|
||||
#ifndef SFMT_H
|
||||
#define SFMT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifndef SFMTST_H
|
||||
#define SFMTST_H
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
#include <inttypes.h>
|
||||
|
@ -60,105 +64,232 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define ALWAYSINLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define ALWAYSINLINE
|
||||
#endif
|
||||
#include "SFMT-params.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1200
|
||||
#define PRE_ALWAYS __forceinline
|
||||
#else
|
||||
#define PRE_ALWAYS inline
|
||||
/*------------------------------------------
|
||||
128-bit SIMD like data type for standard C
|
||||
------------------------------------------*/
|
||||
#if defined(HAVE_ALTIVEC)
|
||||
#if !defined(__APPLE__)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
vector unsigned int s;
|
||||
uint32_t u[4];
|
||||
uint64_t u64[2];
|
||||
};
|
||||
#elif defined(HAVE_SSE2)
|
||||
#include <emmintrin.h>
|
||||
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
uint32_t u[4];
|
||||
uint64_t u64[2];
|
||||
__m128i si;
|
||||
};
|
||||
#else
|
||||
#define PRE_ALWAYS inline
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
uint32_t u[4];
|
||||
uint64_t u64[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
uint32_t gen_rand32(void);
|
||||
uint64_t gen_rand64(void);
|
||||
void fill_array32(uint32_t *array, int size);
|
||||
void fill_array64(uint64_t *array, int size);
|
||||
void init_gen_rand(uint32_t seed);
|
||||
void init_by_array(uint32_t *init_key, int key_length);
|
||||
const char *get_idstring(void);
|
||||
int get_min_array_size32(void);
|
||||
int get_min_array_size64(void);
|
||||
/** 128-bit data type */
|
||||
typedef union W128_T w128_t;
|
||||
|
||||
/* These real versions are due to Isaku Wada */
|
||||
/** generates a random number on [0,1]-real-interval */
|
||||
inline static double to_real1(uint32_t v)
|
||||
{
|
||||
return v * (1.0/4294967295.0);
|
||||
/* divided by 2^32-1 */
|
||||
/**
|
||||
* SFMT internal state
|
||||
*/
|
||||
struct SFMT_T {
|
||||
/** the 128-bit internal state array */
|
||||
w128_t state[SFMT_N];
|
||||
/** index counter to the 32-bit internal state array */
|
||||
int idx;
|
||||
};
|
||||
|
||||
typedef struct SFMT_T sfmt_t;
|
||||
|
||||
void sfmt_fill_array32(sfmt_t * sfmt, uint32_t * array, int size);
|
||||
void sfmt_fill_array64(sfmt_t * sfmt, uint64_t * array, int size);
|
||||
void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed);
|
||||
void sfmt_init_by_array(sfmt_t * sfmt, uint32_t * init_key, int key_length);
|
||||
const char * sfmt_get_idstring(sfmt_t * sfmt);
|
||||
int sfmt_get_min_array_size32(sfmt_t * sfmt);
|
||||
int sfmt_get_min_array_size64(sfmt_t * sfmt);
|
||||
void sfmt_gen_rand_all(sfmt_t * sfmt);
|
||||
|
||||
#ifndef ONLY64
|
||||
/**
|
||||
* This function generates and returns 32-bit pseudorandom number.
|
||||
* init_gen_rand or init_by_array must be called before this function.
|
||||
* @param sfmt SFMT internal state
|
||||
* @return 32-bit pseudorandom number
|
||||
*/
|
||||
inline static uint32_t sfmt_genrand_uint32(sfmt_t * sfmt) {
|
||||
uint32_t r;
|
||||
uint32_t * psfmt32 = &sfmt->state[0].u[0];
|
||||
|
||||
if (sfmt->idx >= SFMT_N32) {
|
||||
sfmt_gen_rand_all(sfmt);
|
||||
sfmt->idx = 0;
|
||||
}
|
||||
r = psfmt32[sfmt->idx++];
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* This function generates and returns 64-bit pseudorandom number.
|
||||
* init_gen_rand or init_by_array must be called before this function.
|
||||
* The function gen_rand64 should not be called after gen_rand32,
|
||||
* unless an initialization is again executed.
|
||||
* @param sfmt SFMT internal state
|
||||
* @return 64-bit pseudorandom number
|
||||
*/
|
||||
inline static uint64_t sfmt_genrand_uint64(sfmt_t * sfmt) {
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
uint32_t * psfmt32 = &sfmt->state[0].u[0];
|
||||
uint32_t r1, r2;
|
||||
#else
|
||||
uint64_t r;
|
||||
#endif
|
||||
uint64_t * psfmt64 = &sfmt->state[0].u64[0];
|
||||
assert(sfmt->idx % 2 == 0);
|
||||
|
||||
if (sfmt->idx >= SFMT_N32) {
|
||||
sfmt_gen_rand_all(sfmt);
|
||||
sfmt->idx = 0;
|
||||
}
|
||||
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
||||
r1 = psfmt32[sfmt->idx];
|
||||
r2 = psfmt32[sfmt->idx + 1];
|
||||
sfmt->idx += 2;
|
||||
return ((uint64_t)r2 << 32) | r1;
|
||||
#else
|
||||
r = psfmt64[sfmt->idx / 2];
|
||||
sfmt->idx += 2;
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1]-real-interval */
|
||||
inline static double genrand_real1(void)
|
||||
/* =================================================
|
||||
The following real versions are due to Isaku Wada
|
||||
================================================= */
|
||||
/**
|
||||
* converts an unsigned 32-bit number to a double on [0,1]-real-interval.
|
||||
* @param v 32-bit unsigned integer
|
||||
* @return double on [0,1]-real-interval
|
||||
*/
|
||||
inline static double sfmt_to_real1(uint32_t v)
|
||||
{
|
||||
return to_real1(gen_rand32());
|
||||
return v * (1.0/4294967295.0);
|
||||
/* divided by 2^32-1 */
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1)-real-interval */
|
||||
inline static double to_real2(uint32_t v)
|
||||
/**
|
||||
* generates a random number on [0,1]-real-interval
|
||||
* @param sfmt SFMT internal state
|
||||
* @return double on [0,1]-real-interval
|
||||
*/
|
||||
inline static double sfmt_genrand_real1(sfmt_t * sfmt)
|
||||
{
|
||||
return v * (1.0/4294967296.0);
|
||||
return sfmt_to_real1(sfmt_genrand_uint32(sfmt));
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an unsigned 32-bit integer to a double on [0,1)-real-interval.
|
||||
* @param v 32-bit unsigned integer
|
||||
* @return double on [0,1)-real-interval
|
||||
*/
|
||||
inline static double sfmt_to_real2(uint32_t v)
|
||||
{
|
||||
return v * (1.0/4294967296.0);
|
||||
/* divided by 2^32 */
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1)-real-interval */
|
||||
inline static double genrand_real2(void)
|
||||
/**
|
||||
* generates a random number on [0,1)-real-interval
|
||||
* @param sfmt SFMT internal state
|
||||
* @return double on [0,1)-real-interval
|
||||
*/
|
||||
inline static double sfmt_genrand_real2(sfmt_t * sfmt)
|
||||
{
|
||||
return to_real2(gen_rand32());
|
||||
return sfmt_to_real2(sfmt_genrand_uint32(sfmt));
|
||||
}
|
||||
|
||||
/** generates a random number on (0,1)-real-interval */
|
||||
inline static double to_real3(uint32_t v)
|
||||
/**
|
||||
* converts an unsigned 32-bit integer to a double on (0,1)-real-interval.
|
||||
* @param v 32-bit unsigned integer
|
||||
* @return double on (0,1)-real-interval
|
||||
*/
|
||||
inline static double sfmt_to_real3(uint32_t v)
|
||||
{
|
||||
return (((double)v) + 0.5)*(1.0/4294967296.0);
|
||||
return (((double)v) + 0.5)*(1.0/4294967296.0);
|
||||
/* divided by 2^32 */
|
||||
}
|
||||
|
||||
/** generates a random number on (0,1)-real-interval */
|
||||
inline static double genrand_real3(void)
|
||||
/**
|
||||
* generates a random number on (0,1)-real-interval
|
||||
* @param sfmt SFMT internal state
|
||||
* @return double on (0,1)-real-interval
|
||||
*/
|
||||
inline static double sfmt_genrand_real3(sfmt_t * sfmt)
|
||||
{
|
||||
return to_real3(gen_rand32());
|
||||
}
|
||||
/** These real versions are due to Isaku Wada */
|
||||
|
||||
/** generates a random number on [0,1) with 53-bit resolution*/
|
||||
inline static double to_res53(uint64_t v)
|
||||
{
|
||||
return v * (1.0/18446744073709551616.0L);
|
||||
return sfmt_to_real3(sfmt_genrand_uint32(sfmt));
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1) with 53-bit resolution from two
|
||||
* 32 bit integers */
|
||||
inline static double to_res53_mix(uint32_t x, uint32_t y)
|
||||
{
|
||||
return to_res53(x | ((uint64_t)y << 32));
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1) with 53-bit resolution
|
||||
/**
|
||||
* converts an unsigned 32-bit integer to double on [0,1)
|
||||
* with 53-bit resolution.
|
||||
* @param v 32-bit unsigned integer
|
||||
* @return double on [0,1)-real-interval with 53-bit resolution.
|
||||
*/
|
||||
inline static double genrand_res53(void)
|
||||
{
|
||||
return to_res53(gen_rand64());
|
||||
}
|
||||
inline static double sfmt_to_res53(uint64_t v)
|
||||
{
|
||||
return v * (1.0/18446744073709551616.0);
|
||||
}
|
||||
|
||||
/** generates a random number on [0,1) with 53-bit resolution
|
||||
using 32bit integer.
|
||||
/**
|
||||
* generates a random number on [0,1) with 53-bit resolution
|
||||
* @param sfmt SFMT internal state
|
||||
* @return double on [0,1) with 53-bit resolution
|
||||
*/
|
||||
inline static double genrand_res53_mix(void)
|
||||
{
|
||||
inline static double sfmt_genrand_res53(sfmt_t * sfmt)
|
||||
{
|
||||
return sfmt_to_res53(sfmt_genrand_uint64(sfmt));
|
||||
}
|
||||
|
||||
|
||||
/* =================================================
|
||||
The following function are added by Saito.
|
||||
================================================= */
|
||||
/**
|
||||
* generates a random number on [0,1) with 53-bit resolution from two
|
||||
* 32 bit integers
|
||||
*/
|
||||
inline static double sfmt_to_res53_mix(uint32_t x, uint32_t y)
|
||||
{
|
||||
return sfmt_to_res53(x | ((uint64_t)y << 32));
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a random number on [0,1) with 53-bit resolution
|
||||
* using two 32bit integers.
|
||||
* @param sfmt SFMT internal state
|
||||
* @return double on [0,1) with 53-bit resolution
|
||||
*/
|
||||
inline static double sfmt_genrand_res53_mix(sfmt_t * sfmt)
|
||||
{
|
||||
uint32_t x, y;
|
||||
|
||||
x = gen_rand32();
|
||||
y = gen_rand32();
|
||||
return to_res53_mix(x, y);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
x = sfmt_genrand_uint32(sfmt);
|
||||
y = sfmt_genrand_uint32(sfmt);
|
||||
return sfmt_to_res53_mix(x, y);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -213,12 +213,22 @@ FreeBSD 9.1 until the systems were updated.
|
|||
FreeBSD
|
||||
: `pkg_add -r qt4 qt4-linguist qt4-moc qt4-qmake qt4-rcc qt4-uic git cmake protobuf`
|
||||
|
||||
2. Download the sources from github via\
|
||||
`cd git clone https://github.com/Daenyth/Cockatrice.git`
|
||||
2. Download the sources from github via
|
||||
`git clone https://github.com/Daenyth/Cockatrice.git`
|
||||
|
||||
3. To compile the sources, change into the newly created directory,
|
||||
create a build directory and invoke cmake:\
|
||||
`cd Cockatrice mkdir build cd build cmake .. make`\
|
||||
create a build directory and invoke cmake:
|
||||
|
||||
i. `cd Cockatrice`
|
||||
|
||||
ii. `mkdir build`
|
||||
|
||||
iii. `cd build`
|
||||
|
||||
iv. `cmake ..`
|
||||
|
||||
v. `make`
|
||||
|
||||
If you have some issues with pthread\_ add ’pthread’ to the
|
||||
“target\_link\_libraries” entry in the `CMakeFiles.txt` in
|
||||
`Cockatrice/common`.
|
||||
|
@ -229,7 +239,7 @@ FreeBSD 9.1 until the systems were updated.
|
|||
|
||||
5. Before you start Cockatrice for the first time, run `oracle -dlsets`
|
||||
and download available cards, denn run `cockatrice`. The default
|
||||
paths for decks, pics, cards and tokens are located in\
|
||||
paths for decks, pics, cards and tokens are located in
|
||||
`/home/<user>/.local/share/data/Cockatrice/Cockatrice`.
|
||||
|
||||
#### MacOS X
|
||||
|
@ -244,10 +254,10 @@ Cockatrice is open source you are free to run your own. The compilation
|
|||
works like already written above, but instead of invoking `cmake ..`,
|
||||
you have to do it like this:
|
||||
|
||||
- If you want to build the server, use:\
|
||||
- If you want to build the server, use:
|
||||
`cmake -DWITH_SERVER=1 ..`
|
||||
|
||||
- If you want to build the server, but not the client, use:\
|
||||
- If you want to build the server, but not the client, use:
|
||||
`cmake -DWITH_SERVER=1 -DWITHOUT_CLIENT=1 ..`
|
||||
|
||||
There is more information on compiling and running Servatrice on CentOS
|
||||
|
@ -368,13 +378,14 @@ has come out, you must re-run the Oracle and download set information.
|
|||
except for “Instant” along with “Artifact” and “U”, the Deck editor
|
||||
will only show you all Blue Instant and Artifact cards.
|
||||
|
||||
ll Letter & Card Type\
|
||||
U & Blue\
|
||||
W & White\
|
||||
X & Colorless\
|
||||
G & Green\
|
||||
R & Red\
|
||||
B & Black\
|
||||
|Letter | Card Type |
|
||||
|-------|-----------|
|
||||
| U | Blue |
|
||||
| W | White |
|
||||
| X | Colorless |
|
||||
| G | Green |
|
||||
| R | Red |
|
||||
| B | Black |
|
||||
|
||||
3. Card Data
|
||||
: This section shows the Oracle text for the card that you currently
|
||||
|
@ -736,7 +747,7 @@ players can not add or remove counters to or from your cards.
|
|||
|
||||
#### Pointing at Cards / Arrows
|
||||
|
||||
Pointing at cars is needed for resolving spells, or declaring attackers
|
||||
Pointing at cards is needed for resolving spells, or declaring attackers
|
||||
and blockers. All you need to do is right-click over a card and drag an
|
||||
arrow over to what you are pointing at. Permanents, spells in the stack,
|
||||
and even a players life total can be pointed at. You can point at your
|
||||
|
|
|
@ -487,7 +487,7 @@ Sometimes Counters are needed to be placed on cards that the counters on the sid
|
|||
(One of each counter)
|
||||
|
||||
\subsubsection{Pointing at Cards / Arrows}
|
||||
Pointing at cars is needed for resolving spells, or declaring attackers and blockers. All you need to do is right-click over a card and drag an arrow over to what you are pointing at. Permanents, spells in the stack, and even a players life total can be pointed at. You can point at your opponents cards and life total, and they can point at yours. When your arrows are no loner needed, press Ctrl-R to remove them from the screen.
|
||||
Pointing at cards is needed for resolving spells, or declaring attackers and blockers. All you need to do is right-click over a card and drag an arrow over to what you are pointing at. Permanents, spells in the stack, and even a players life total can be pointed at. You can point at your opponents cards and life total, and they can point at yours. When your arrows are no loner needed, press Ctrl-R to remove them from the screen.
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[scale=0.5]{pics/fetch98fd} \\
|
||||
|
|
Loading…
Reference in a new issue