File indexing completed on 2024-04-21 04:03:59

0001 /*
0002     SPDX-FileCopyrightText: 2001-2003 Nicolas Hadacek <hadacek@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "kexthighscore_item.h"
0008 
0009 #include <QApplication>
0010 #include <QHBoxLayout>
0011 #include <QLabel>
0012 #include <QLocale>
0013 #include <QWidget>
0014 
0015 #include <KPageDialog>
0016 
0017 #include <KGameHighscore>
0018 
0019 #include "kexthighscore_internal.h"
0020 #include "kexthighscore_gui.h"
0021 
0022 
0023 namespace KExtHighscore
0024 {
0025 
0026 //-----------------------------------------------------------------------------
0027 Item::Item(const QVariant &def, const QString &label, Qt::AlignmentFlag alignment)
0028     : _default(def), _label(label), _alignment(alignment),
0029       _format(NoFormat), _special(NoSpecial)
0030 {}
0031 
0032 Item::~Item()
0033 {}
0034 
0035 QVariant Item::read(uint, const QVariant &value) const
0036 {
0037     return value;
0038 }
0039 
0040 void Item::setPrettyFormat(Format format)
0041 {
0042     bool buint = (_default.metaType().id() == QMetaType::UInt);
0043     bool bdouble = (_default.metaType().id() == QMetaType::Double);
0044     bool bnum = (buint || bdouble || _default.metaType().id() == QMetaType::Int);
0045 
0046     switch (format) {
0047     case OneDecimal:
0048     case Percentage:
0049         Q_ASSERT(bdouble);
0050         break;
0051     case MinuteTime:
0052         Q_ASSERT(bnum);
0053         break;
0054     case DateTime:
0055         Q_ASSERT(_default.metaType().id() == QMetaType::QDateTime);
0056     break;
0057     case NoFormat:
0058         break;
0059     }
0060 
0061     _format = format;
0062 }
0063 
0064 void Item::setPrettySpecial(Special special)
0065 {
0066     bool buint = (_default.metaType().id() == QMetaType::UInt);
0067     bool bnum = (buint || _default.metaType().id() == QMetaType::Double
0068                  || _default.metaType().id() == QMetaType::Int);
0069 
0070     switch (special) {
0071     case ZeroNotDefined:
0072         Q_ASSERT(bnum);
0073         break;
0074     case NegativeNotDefined:
0075         Q_ASSERT(bnum && !buint);
0076         break;
0077     case DefaultNotDefined:
0078         break;
0079     case Anonymous:
0080         Q_ASSERT(_default.metaType().id() == QMetaType::QString);
0081         break;
0082     case NoSpecial:
0083         break;
0084     }
0085 
0086      _special = special;
0087 }
0088 
0089 QString Item::timeFormat(uint n)
0090 {
0091     Q_ASSERT( n<=3600 && n!=0 );
0092     n = 3600 - n;
0093     return QString::number(n / 60).rightJustified(2, QLatin1Char( '0' )) + QLatin1Char( ':' )
0094         + QString::number(n % 60).rightJustified(2, QLatin1Char( '0' ));
0095 }
0096 
0097 QString Item::pretty(uint, const QVariant &value) const
0098 {
0099     switch (_special) {
0100     case ZeroNotDefined:
0101         if ( value.toUInt()==0 ) return QStringLiteral( "--" );
0102         break;
0103     case NegativeNotDefined:
0104         if ( value.toInt()<0 ) return QStringLiteral( "--" );
0105         break;
0106     case DefaultNotDefined:
0107         if ( value==_default ) return QStringLiteral( "--" );
0108         break;
0109     case Anonymous:
0110         if ( value.toString()==QLatin1String( ItemContainer::ANONYMOUS ) )
0111             return ItemContainer::ANONYMOUS_LABEL.toString();
0112         break;
0113     case NoSpecial:
0114         break;
0115     }
0116 
0117     switch (_format) {
0118     case OneDecimal:
0119         return QString::number(value.toDouble(), 'f', 1);
0120     case Percentage:
0121         return QString::number(value.toDouble(), 'f', 1) + QLatin1Char( '%' );
0122     case MinuteTime:
0123         return timeFormat(value.toUInt());
0124     case DateTime:
0125         if ( value.toDateTime().isNull() ) return QStringLiteral( "--" );
0126         return QLocale().toString(value.toDateTime());
0127     case NoFormat:
0128         break;
0129     }
0130 
0131     return value.toString();
0132 }
0133 
0134 //-----------------------------------------------------------------------------
0135 Score::Score(ScoreType type)
0136     : _type(type)
0137 {
0138     const ItemArray &items = internal->scoreInfos();
0139     for (int i=0; i<items.size(); i++)
0140         _data[items[i]->name()] = items[i]->item()->defaultValue();
0141 }
0142 
0143 Score::~Score()
0144 {}
0145 
0146 QVariant Score::data(const QString &name) const
0147 {
0148     Q_ASSERT( _data.contains(name) );
0149     return _data[name];
0150 }
0151 
0152 void Score::setData(const QString &name, const QVariant &value)
0153 {
0154     Q_ASSERT( _data.contains(name) );
0155     Q_ASSERT(_data[name].metaType() == value.metaType());
0156     _data[name] = value;
0157 }
0158 
0159 bool Score::isTheWorst() const
0160 {
0161     Score s;
0162     return score()==s.score();
0163 }
0164 
0165 bool Score::operator <(const Score &score) const
0166 {
0167     return internal->manager.isStrictlyLess(*this, score);
0168 }
0169 
0170 QDataStream &operator <<(QDataStream &s, const Score &score)
0171 {
0172     s << (quint8)score.type();
0173     s << score._data;
0174     return s;
0175 }
0176 
0177 QDataStream &operator >>(QDataStream &s, Score &score)
0178 {
0179     quint8 type;
0180     s >> type;
0181     score._type = (ScoreType)type;
0182     s >> score._data;
0183     return s;
0184 }
0185 
0186 //-----------------------------------------------------------------------------
0187 MultiplayerScores::MultiplayerScores()
0188 {}
0189 
0190 MultiplayerScores::~MultiplayerScores()
0191 {}
0192 
0193 void MultiplayerScores::clear()
0194 {
0195     Score score;
0196     for (int i=0; i<_scores.size(); i++) {
0197         _nbGames[i] = 0;
0198         QVariant name = _scores[i].data(QStringLiteral( "name" ));
0199         _scores[i] = score;
0200         _scores[i].setData(QStringLiteral( "name" ), name);
0201         _scores[i]._data[QStringLiteral( "mean score" )] = double(0);
0202         _scores[i]._data[QStringLiteral( "nb won games" )] = uint(0);
0203     }
0204 }
0205 
0206 void MultiplayerScores::setPlayerCount(uint nb)
0207 {
0208     _nbGames.resize(nb);
0209     _scores.resize(nb);
0210     clear();
0211 }
0212 
0213 void MultiplayerScores::setName(uint i, const QString &name)
0214 {
0215     _scores[i].setData(QStringLiteral( "name" ), name);
0216 }
0217 
0218 void MultiplayerScores::addScore(uint i, const Score &score)
0219 {
0220     QVariant name = _scores[i].data(QStringLiteral( "name" ));
0221     double mean = _scores[i].data(QStringLiteral( "mean score" )).toDouble();
0222     uint won = _scores[i].data(QStringLiteral( "nb won games" )).toUInt();
0223     _scores[i] = score;
0224     _scores[i].setData(QStringLiteral( "name" ), name);
0225     _nbGames[i]++;
0226     mean += (double(score.score()) - mean) / _nbGames[i];
0227     _scores[i]._data[QStringLiteral( "mean score" )] = mean;
0228     if ( score.type()==Won ) won++;
0229     _scores[i]._data[QStringLiteral( "nb won games" )] = won;
0230 }
0231 
0232 void MultiplayerScores::show(QWidget *parent)
0233 {
0234     QLoggingCategory::setFilterRules(QStringLiteral("games.highscore.debug = true"));
0235     
0236     // check consistency
0237     if ( _nbGames.size()<2 ) 
0238     qCWarning(GAMES_EXTHIGHSCORE) << "less than 2 players";
0239     
0240     else {
0241         bool ok = true;
0242         uint nb = _nbGames[0];
0243         for (int i=1; i<_nbGames.size(); i++)
0244             if ( _nbGames[i]!=nb ) ok = false;
0245         if (!ok)
0246            qCWarning(GAMES_EXTHIGHSCORE) << "players have not same number of games";
0247     }
0248 
0249     // order the players according to the number of won games
0250     QList<Score> ordered;
0251     for (int i=0; i<_scores.size(); i++) {
0252         uint won = _scores[i].data(QStringLiteral( "nb won games" )).toUInt();
0253         double mean = _scores[i].data(QStringLiteral( "mean score" )).toDouble();
0254         QList<Score>::iterator it;
0255         for(it = ordered.begin(); it!=ordered.end(); ++it) {
0256             uint cwon = (*it).data(QStringLiteral( "nb won games" )).toUInt();
0257             double cmean = (*it).data(QStringLiteral( "mean score" )).toDouble();
0258             if ( won<cwon || (won==cwon && mean<cmean) ) {
0259                 ordered.insert(it, _scores[i]);
0260                 break;
0261             }
0262         }
0263         if ( it==ordered.end() ) ordered.push_back(_scores[i]);
0264     }
0265 
0266     // show the scores
0267     KPageDialog dialog(parent);
0268     dialog.setWindowTitle(i18nc("@title:window", "Multiplayers Scores"));
0269 // TODO    dialog.setButtons(KDialog::Close);
0270     dialog.setModal(true);
0271     dialog.setFaceType(KPageDialog::Plain);
0272     KPageWidgetItem *page = new KPageWidgetItem( new QLabel(QLatin1String( "" )), QLatin1String( "" ) );
0273     QHBoxLayout *hbox = new QHBoxLayout(page->widget());
0274     //hbox->setMargin(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
0275     //hbox->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
0276 
0277     QWidget *vbox = new QWidget(page->widget());
0278     hbox->addWidget(vbox);
0279     if ( _nbGames[0]==0 ) (void)new QLabel(i18n("No game played."), vbox);
0280     else {
0281         (void)new QLabel(i18n("Scores for last game:"), vbox);
0282         (void)new LastMultipleScoresList(ordered, vbox);
0283     }
0284 
0285     if ( _nbGames[0]>1 ) {
0286         vbox = new QWidget(page->widget());
0287         hbox->addWidget(vbox);
0288         (void)new QLabel(i18n("Scores for the last %1 games:",
0289                           _nbGames[0]), vbox);
0290         (void)new TotalMultipleScoresList(ordered, vbox);
0291     }
0292 
0293     //dialog.showButtonSeparator(false);
0294     dialog.addPage(page);
0295     dialog.exec();
0296 }
0297 
0298 QDataStream &operator <<(QDataStream &s, const MultiplayerScores &score)
0299 {
0300     s << score._scores;
0301     s << score._nbGames;
0302     return s;
0303 }
0304 
0305 QDataStream &operator >>(QDataStream &s, MultiplayerScores &score)
0306 {
0307 
0308 
0309     s >> score._scores;
0310     s >> score._nbGames;
0311     return s;
0312 }
0313 
0314 } // namespace