|
|
|
/*
|
|
|
|
This file is part of the KDE games library
|
|
|
|
Copyright (C) 2001-2003 Nicolas Hadacek (hadacek@kde.org)
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kexthighscore_item.h"
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include "khighscore.h"
|
|
|
|
#include "kexthighscore_internal.h"
|
|
|
|
#include "kexthighscore_gui.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace KExtHighscore
|
|
|
|
{
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
Item::Item(const TQVariant &def, const TQString &label, int alignment)
|
|
|
|
: _default(def), _label(label), _alignment(alignment),
|
|
|
|
_format(NoFormat), _special(NoSpecial)
|
|
|
|
{}
|
|
|
|
|
|
|
|
Item::~Item()
|
|
|
|
{}
|
|
|
|
|
|
|
|
TQVariant Item::read(uint, const TQVariant &value) const
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Item::setPrettyFormat(Format format)
|
|
|
|
{
|
|
|
|
bool buint = ( _default.type()==TQVariant::UInt );
|
|
|
|
bool bdouble = ( _default.type()==TQVariant::Double );
|
|
|
|
bool bnum = ( buint || bdouble || _default.type()==TQVariant::Int );
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case OneDecimal:
|
|
|
|
case Percentage:
|
|
|
|
Q_ASSERT(bdouble);
|
|
|
|
break;
|
|
|
|
case MinuteTime:
|
|
|
|
Q_ASSERT(bnum);
|
|
|
|
break;
|
|
|
|
case DateTime:
|
|
|
|
Q_ASSERT( _default.type()==TQVariant::DateTime );
|
|
|
|
break;
|
|
|
|
case NoFormat:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_format = format;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Item::setPrettySpecial(Special special)
|
|
|
|
{
|
|
|
|
bool buint = ( _default.type()==TQVariant::UInt );
|
|
|
|
bool bnum = ( buint || _default.type()==TQVariant::Double
|
|
|
|
|| _default.type()==TQVariant::Int );
|
|
|
|
|
|
|
|
switch (special) {
|
|
|
|
case ZeroNotDefined:
|
|
|
|
Q_ASSERT(bnum);
|
|
|
|
break;
|
|
|
|
case NegativeNotDefined:
|
|
|
|
Q_ASSERT(bnum && !buint);
|
|
|
|
break;
|
|
|
|
case DefaultNotDefined:
|
|
|
|
break;
|
|
|
|
case Anonymous:
|
|
|
|
Q_ASSERT( _default.type()==TQVariant::String );
|
|
|
|
break;
|
|
|
|
case NoSpecial:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_special = special;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Item::timeFormat(uint n)
|
|
|
|
{
|
|
|
|
Q_ASSERT( n<=3600 && n!=0 );
|
|
|
|
n = 3600 - n;
|
|
|
|
return TQString::number(n / 60).rightJustify(2, '0') + ':'
|
|
|
|
+ TQString::number(n % 60).rightJustify(2, '0');
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Item::pretty(uint, const TQVariant &value) const
|
|
|
|
{
|
|
|
|
switch (_special) {
|
|
|
|
case ZeroNotDefined:
|
|
|
|
if ( value.toUInt()==0 ) return "--";
|
|
|
|
break;
|
|
|
|
case NegativeNotDefined:
|
|
|
|
if ( value.toInt()<0 ) return "--";
|
|
|
|
break;
|
|
|
|
case DefaultNotDefined:
|
|
|
|
if ( value==_default ) return "--";
|
|
|
|
break;
|
|
|
|
case Anonymous:
|
|
|
|
if ( value.toString()==ItemContainer::ANONYMOUS )
|
|
|
|
return i18n(ItemContainer::ANONYMOUS_LABEL);
|
|
|
|
break;
|
|
|
|
case NoFormat:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (_format) {
|
|
|
|
case OneDecimal:
|
|
|
|
return TQString::number(value.toDouble(), 'f', 1);
|
|
|
|
case Percentage:
|
|
|
|
return TQString::number(value.toDouble(), 'f', 1) + "%";
|
|
|
|
case MinuteTime:
|
|
|
|
return timeFormat(value.toUInt());
|
|
|
|
case DateTime:
|
|
|
|
if ( value.toDateTime().isNull() ) return "--";
|
|
|
|
return KGlobal::locale()->formatDateTime(value.toDateTime());
|
|
|
|
case NoSpecial:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
Score::Score(ScoreType type)
|
|
|
|
: _type(type)
|
|
|
|
{
|
|
|
|
const ItemArray &items = internal->scoreInfos();
|
|
|
|
for (uint i=0; i<items.size(); i++)
|
|
|
|
_data[items[i]->name()] = items[i]->item()->defaultValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
Score::~Score()
|
|
|
|
{}
|
|
|
|
|
|
|
|
const TQVariant &Score::data(const TQString &name) const
|
|
|
|
{
|
|
|
|
Q_ASSERT( _data.contains(name) );
|
|
|
|
return _data[name];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Score::setData(const TQString &name, const TQVariant &value)
|
|
|
|
{
|
|
|
|
Q_ASSERT( _data.contains(name) );
|
|
|
|
Q_ASSERT( _data[name].type()==value.type() );
|
|
|
|
_data[name] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Score::isTheWorst() const
|
|
|
|
{
|
|
|
|
Score s;
|
|
|
|
return score()==s.score();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Score::operator <(const Score &score)
|
|
|
|
{
|
|
|
|
return internal->manager.isStrictlyLess(*this, score);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &operator <<(TQDataStream &s, const Score &score)
|
|
|
|
{
|
|
|
|
s << (TQ_UINT8)score.type();
|
|
|
|
s << score._data;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &operator >>(TQDataStream &s, Score &score)
|
|
|
|
{
|
|
|
|
TQ_UINT8 type;
|
|
|
|
s >> type;
|
|
|
|
score._type = (ScoreType)type;
|
|
|
|
s >> score._data;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
MultiplayerScores::MultiplayerScores()
|
|
|
|
{}
|
|
|
|
|
|
|
|
MultiplayerScores::~MultiplayerScores()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void MultiplayerScores::clear()
|
|
|
|
{
|
|
|
|
Score score;
|
|
|
|
for (uint i=0; i<_scores.size(); i++) {
|
|
|
|
_nbGames[i] = 0;
|
|
|
|
TQVariant name = _scores[i].data("name");
|
|
|
|
_scores[i] = score;
|
|
|
|
_scores[i].setData("name", name);
|
|
|
|
_scores[i]._data["mean score"] = double(0);
|
|
|
|
_scores[i]._data["nb won games"] = uint(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplayerScores::setPlayerCount(uint nb)
|
|
|
|
{
|
|
|
|
_nbGames.resize(nb);
|
|
|
|
_scores.resize(nb);
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplayerScores::setName(uint i, const TQString &name)
|
|
|
|
{
|
|
|
|
_scores[i].setData("name", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplayerScores::addScore(uint i, const Score &score)
|
|
|
|
{
|
|
|
|
TQVariant name = _scores[i].data("name");
|
|
|
|
double mean = _scores[i].data("mean score").toDouble();
|
|
|
|
uint won = _scores[i].data("nb won games").toUInt();
|
|
|
|
_scores[i] = score;
|
|
|
|
_scores[i].setData("name", name);
|
|
|
|
_nbGames[i]++;
|
|
|
|
mean += (double(score.score()) - mean) / _nbGames[i];
|
|
|
|
_scores[i]._data["mean score"] = mean;
|
|
|
|
if ( score.type()==Won ) won++;
|
|
|
|
_scores[i]._data["nb won games"] = won;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplayerScores::show(TQWidget *parent)
|
|
|
|
{
|
|
|
|
// check consistency
|
|
|
|
if ( _nbGames.size()<2 ) kdWarning(11002) << "less than 2 players" << endl;
|
|
|
|
else {
|
|
|
|
bool ok = true;
|
|
|
|
uint nb = _nbGames[0];
|
|
|
|
for (uint i=1; i<_nbGames.size(); i++)
|
|
|
|
if ( _nbGames[i]!=nb ) ok = false;
|
|
|
|
if (!ok)
|
|
|
|
kdWarning(11002) << "players have not same number of games" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// order the players according to the number of won games
|
|
|
|
TQValueVector<Score> ordered;
|
|
|
|
for (uint i=0; i<_scores.size(); i++) {
|
|
|
|
uint won = _scores[i].data("nb won games").toUInt();
|
|
|
|
double mean = _scores[i].data("mean score").toDouble();
|
|
|
|
TQValueVector<Score>::iterator it;
|
|
|
|
for(it = ordered.begin(); it!=ordered.end(); ++it) {
|
|
|
|
uint cwon = (*it).data("nb won games").toUInt();
|
|
|
|
double cmean = (*it).data("mean score").toDouble();
|
|
|
|
if ( won<cwon || (won==cwon && mean<cmean) ) {
|
|
|
|
ordered.insert(it, _scores[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( it==ordered.end() ) ordered.push_back(_scores[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// show the scores
|
|
|
|
KDialogBase dialog(KDialogBase::Plain, i18n("Multiplayers Scores"),
|
|
|
|
KDialogBase::Close, KDialogBase::Close,
|
|
|
|
parent, "show_multiplayers_score", true, true);
|
|
|
|
TQHBoxLayout *hbox = new TQHBoxLayout(dialog.plainPage(),
|
|
|
|
KDialog::marginHint(), KDialog::spacingHint());
|
|
|
|
|
|
|
|
TQVBox *vbox = new TQVBox(dialog.plainPage());
|
|
|
|
hbox->addWidget(vbox);
|
|
|
|
if ( _nbGames[0]==0 ) (void)new TQLabel(i18n("No game played."), vbox);
|
|
|
|
else {
|
|
|
|
(void)new TQLabel(i18n("Scores for last game:"), vbox);
|
|
|
|
(void)new LastMultipleScoresList(ordered, vbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _nbGames[0]>1 ) {
|
|
|
|
vbox = new TQVBox(dialog.plainPage());
|
|
|
|
hbox->addWidget(vbox);
|
|
|
|
(void)new TQLabel(i18n("Scores for the last %1 games:")
|
|
|
|
.arg(_nbGames[0]), vbox);
|
|
|
|
(void)new TotalMultipleScoresList(ordered, vbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
dialog.enableButtonSeparator(false);
|
|
|
|
dialog.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &operator <<(TQDataStream &s, const MultiplayerScores &score)
|
|
|
|
{
|
|
|
|
s << score._scores;
|
|
|
|
s << score._nbGames;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &operator >>(TQDataStream &s, MultiplayerScores &score)
|
|
|
|
{
|
|
|
|
s >> score._scores;
|
|
|
|
s >> score._nbGames;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|