File indexing completed on 2022-12-06 19:27:14

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