File indexing completed on 2024-04-28 07:51:50

0001 /***************************************************************************
0002  *   Copyright (C) 2005, 2008 by Albert Astals Cid <aacid@kde.org>         *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  ***************************************************************************/
0009 
0010 #include "scores.h"
0011 
0012 #include <QFont>
0013 #include <QPainter>
0014 #include <QPalette>
0015 
0016 #include <KIconLoader>
0017 #include <KLocalizedString>
0018 
0019 #include "settings.h"
0020 
0021 scores::scores()
0022 {
0023     player p;
0024     for (int i = 1; i <= kirikiSettings::numberOfPlayers(); i++)
0025     {
0026         if (i == 1)
0027         {
0028             p.setName(kirikiSettings::player1Name());
0029             p.setHuman(kirikiSettings::player1IsHuman());
0030         }
0031         else if (i == 2)
0032         {
0033             p.setName(kirikiSettings::player2Name());
0034             p.setHuman(kirikiSettings::player2IsHuman());
0035         }
0036         else if (i == 3)
0037         {
0038             p.setName(kirikiSettings::player3Name());
0039             p.setHuman(kirikiSettings::player3IsHuman());
0040         }
0041         else if (i == 4)
0042         {
0043             p.setName(kirikiSettings::player4Name());
0044             p.setHuman(kirikiSettings::player4IsHuman());
0045         }
0046         else if (i == 5)
0047         {
0048             p.setName(kirikiSettings::player5Name());
0049             p.setHuman(kirikiSettings::player5IsHuman());
0050         }
0051         else if (i == 6)
0052         {
0053             p.setName(kirikiSettings::player6Name());
0054             p.setHuman(kirikiSettings::player6IsHuman());
0055         }
0056         
0057         m_players.append(p);
0058     }
0059     
0060     m_currentPlayer = 0;
0061     
0062     m_rows.append(Row(Row::NamesRow));
0063     m_rows.append(Row(Row::ScoreRow, i18n("1s"), 0));
0064     m_rows.append(Row(Row::ScoreRow, i18n("2s"), 1));
0065     m_rows.append(Row(Row::ScoreRow, i18n("3s"), 2));
0066     m_rows.append(Row(Row::ScoreRow, i18n("4s"), 3));
0067     m_rows.append(Row(Row::ScoreRow, i18n("5s"), 4));
0068     m_rows.append(Row(Row::ScoreRow, i18n("6s"), 5));
0069     m_rows.append(Row(Row::BonusRow, i18n("Bonus if > 62"), -1, Row::BoldFontFlag));
0070     m_rows.append(Row(Row::UpperTotalRow, i18n("Upper total"), -1, Row::BoldFontFlag));
0071     m_rows.append(Row(Row::EmptyRow));
0072     m_rows.append(Row(Row::ScoreRow, i18n("3 of a Kind"), 6));
0073     m_rows.append(Row(Row::ScoreRow, i18n("4 of a Kind"), 7));
0074     m_rows.append(Row(Row::ScoreRow, i18n("Full House"), 8));
0075     m_rows.append(Row(Row::ScoreRow, i18n("Small Straight"), 9));
0076     m_rows.append(Row(Row::ScoreRow, i18n("Large Straight"), 10));
0077     m_rows.append(Row(Row::ScoreRow, i18n("Kiriki"), 11));
0078     m_rows.append(Row(Row::ScoreRow, i18n("Chance"), 12));
0079     m_rows.append(Row(Row::LowerTotalRow, i18n("Lower Total"), -1, Row::BoldFontFlag));
0080     m_rows.append(Row(Row::EmptyRow));
0081     m_rows.append(Row(Row::GrandTotalRow, i18n("Grand Total"), -1, Row::BoldFontFlag | Row::BiggerFontFlag));
0082 }
0083 
0084 bool scores::allScores() const
0085 {
0086     bool all;
0087     all = true;
0088     for (int i = 0; i < m_players.count(); i++) all = all && m_players.at(i).allScores();
0089     return all;
0090 }
0091 
0092 void scores::nextPlayer()
0093 {
0094     m_currentPlayer++;
0095     m_currentPlayer = m_currentPlayer % m_players.count();
0096 }
0097 
0098 const player &scores::currentPlayer() const
0099 {
0100     return m_players.at(m_currentPlayer);
0101 }
0102 
0103 int scores::currentPlayerNumber() const
0104 {
0105     return m_currentPlayer;
0106 }
0107 
0108 const player &scores::winner() const
0109 {
0110     int best = 0;
0111     for (int i = 1; i < m_players.count(); i++)
0112     {
0113         if (m_players.at(best).grandTotal() < m_players.at(i).grandTotal()) best = i;
0114     }
0115     return m_players.at(best);
0116 }
0117 
0118 Row scores::row(int row) const
0119 {
0120     return m_rows.at(row);
0121 }
0122 
0123 int scores::rowForScoreRow(int scoreRow) const
0124 {
0125     for (int i = 0; i < m_rows.count(); ++i)
0126     {
0127         if (m_rows.at(i).scoreRow() == scoreRow) return i;
0128     }
0129     return -1;
0130 }
0131 
0132 int scores::rowCount(const QModelIndex &/*index*/) const
0133 {
0134     return m_rows.count();
0135 }
0136 
0137 int scores::columnCount(const QModelIndex &/*index*/) const
0138 {
0139     return m_players.size() + 1;
0140 }
0141 
0142 QVariant scores::data(const QModelIndex &index, int role) const
0143 {
0144     if (!index.isValid()) return QVariant();
0145     
0146     int column = index.column();
0147     const Row row = m_rows.at(index.row());
0148     
0149     if (row.type() == Row::NamesRow)
0150     {
0151         if (column > 0)
0152         {
0153             const player &p = m_players.at(column - 1);
0154             if (role == Qt::DecorationRole)
0155             {
0156                 QString icon;
0157                 if (p.isHuman()) icon = QStringLiteral("user-identity");
0158                 else icon = QStringLiteral("cpu");
0159                 return KIconLoader::global()->loadIcon(icon, KIconLoader::NoGroup, KIconLoader::SizeMedium);
0160             }
0161             else if (role == Qt::DisplayRole)
0162             {
0163                 return p.name();
0164             }
0165             else if (role == Qt::BackgroundRole)
0166             {
0167                 if (column - 1 == m_currentPlayer)
0168                 {
0169                     QPalette pal;
0170                     return pal.alternateBase().color().darker(110);
0171                 }
0172             }
0173             else if (role == Qt::FontRole)
0174             {
0175                 QFont f;
0176                 f.setPointSize(kirikiSettings::fontSize());
0177                 if (column - 1 == m_currentPlayer)
0178                 {
0179                     f.setBold(true);
0180                 }
0181                 return f;
0182             }
0183         }
0184         return QVariant();
0185     }
0186     
0187     if (role == Qt::FontRole)
0188     {
0189         QFont f;
0190         f.setPointSize(kirikiSettings::fontSize());
0191         if (row.flags() & Row::BoldFontFlag) f.setBold(true);
0192         if (row.flags() & Row::BiggerFontFlag) f.setPointSize(f.pointSize() + 5);
0193         return f;
0194     }
0195     else if (role == Qt::BackgroundRole)
0196     {
0197         QPalette p;
0198         QColor c;
0199         if (column % 2 == 0)
0200         {
0201             c = p.alternateBase().color();
0202             if (index.row() % 2) c = c.darker(105);
0203         }
0204         else
0205         {
0206             if (index.row() % 2 == 0) c = p.base().color();
0207             else c = p.alternateBase().color();
0208         }
0209         
0210         if (row.type() == Row::GrandTotalRow) c = p.highlight().color().lighter();
0211         
0212         if (column - 1 == m_currentPlayer) c = c.darker(110);
0213         
0214         return c;
0215     }
0216     else if (role == Qt::TextAlignmentRole)
0217     {
0218         if (column != 0) return Qt::AlignCenter;
0219     }
0220     
0221     if (row.type() == Row::EmptyRow) return QVariant();
0222 
0223     if (role != Qt::DisplayRole) return QVariant();
0224     
0225     if (column == 0) return row.text();
0226 
0227     const player &p = m_players.at(column - 1);
0228     int score = -1;
0229     
0230     if (row.type() == Row::ScoreRow) score = p.score(row.scoreRow());
0231     else if (row.type() == Row::BonusRow) score = p.bonus();
0232     else if (row.type() == Row::UpperTotalRow) score = p.upperTotalWithBonus();
0233     else if (row.type() == Row::LowerTotalRow) score = p.lowerTotal();
0234     else if (row.type() == Row::GrandTotalRow) score = p.grandTotal();
0235     
0236     if (score < 0) return QVariant();
0237     else return QString::number(score);
0238 }
0239 
0240 void scores::askForRedraw()
0241 {
0242     Q_EMIT dataChanged(index(0, 0), index(m_rows.count() - 1, m_players.count() - 1));
0243 }
0244 
0245 bool scores::setData(const QModelIndex &mi, const QVariant &value, int role)
0246 {
0247     if (role != Qt::EditRole) return false;
0248     
0249     const Row row = m_rows.at(mi.row());
0250     if (row.type() != Row::ScoreRow) return false;
0251     
0252     if (row.scoreRow() == 11)
0253     {
0254         // Kiriki can be acumulated
0255         if (m_players[m_currentPlayer].score(11) > 0 && value.toInt() > 0)
0256         {
0257             m_players[m_currentPlayer].setScore(11, m_players[m_currentPlayer].score(11) + value.toInt());
0258         }
0259         else if (m_players[m_currentPlayer].score(11) < 0)
0260         {
0261             m_players[m_currentPlayer].setScore(11, value.toInt());
0262         }
0263         else return false;
0264     }
0265     else
0266     {
0267         if (m_players[m_currentPlayer].score(row.scoreRow()) >= 0) return false;
0268         m_players[m_currentPlayer].setScore(row.scoreRow(), value.toInt());
0269     }
0270     
0271     Q_EMIT dataChanged(mi, mi);
0272     
0273     for (int i = 0; i < m_rows.count(); ++i)
0274     {
0275         const Row::Type t = m_rows.at(i).type();
0276         if (t == Row::BonusRow || t == Row::UpperTotalRow || t == Row::LowerTotalRow || t == Row::GrandTotalRow)
0277             Q_EMIT dataChanged(index(m_currentPlayer + 1, i), index(m_currentPlayer + 1, i));
0278     }
0279     
0280     return true;
0281 }
0282 
0283 void scores::print(QPainter &painter, double width, double height) const
0284 {
0285     QFont f;
0286     QFontMetrics fm(f);
0287     double margin = width * 0.1;
0288     double widthToUse = width - 2.0 * margin;
0289     double fontHeight;
0290     double heightToUse;
0291     bool continueFindingFont = true;
0292     while (continueFindingFont)
0293     {
0294         fontHeight = fm.height();
0295         heightToUse = 40.0 * fontHeight;
0296         if ( heightToUse < height - 2.0 * margin )
0297         {
0298             continueFindingFont = false;
0299         }
0300         else
0301         {
0302             f.setPointSize(f.pointSize() - 1);
0303             fm = QFontMetrics(f);
0304         }
0305     }
0306     
0307     double cellWidth = widthToUse / (double)(m_players.count() + 1);
0308     double cellHeight = fontHeight * 2.0;
0309     
0310     painter.drawRect( QRectF( margin, margin, widthToUse, heightToUse ) );
0311     for (int i = 1; i <= 20; ++i)
0312     {
0313         painter.drawLine( QPointF(margin, margin + i * cellHeight), QPointF(margin + widthToUse, margin + i * cellHeight) );
0314     }
0315         
0316     for (int i = 1; i <= m_players.count() + 1; ++i)
0317     {
0318         painter.drawLine( QPointF(margin + i * cellWidth, margin), QPointF(margin + i * cellWidth, margin + heightToUse) );
0319     }
0320     
0321     // write the names
0322     for (int i = 1; i <= m_players.count(); ++i)
0323     {
0324         QRectF cell(margin + i * cellWidth, margin, cellWidth, cellHeight);
0325         painter.drawText( cell, Qt::AlignCenter, m_players[i-1].name() );
0326     }
0327     
0328     // write the plays
0329     for (int i = 1; i <= 20; ++i)
0330     {
0331         QRectF cell(margin, margin + i * cellHeight, cellWidth, cellHeight);
0332         painter.drawText( cell, Qt::AlignCenter, data( index(i, 0), Qt::DisplayRole ).toString() );
0333     }
0334     
0335     // write the scores
0336     for (int i = 1; i <= m_players.count(); ++i)
0337     {
0338         for (int j = 1; j <= 20; ++j)
0339         {
0340             QRectF cell(margin + i * cellWidth, margin + j * cellHeight, cellWidth, cellHeight);
0341             painter.drawText( cell, Qt::AlignCenter, data( index(j, i), Qt::DisplayRole ).toString() );
0342         }
0343     }
0344 }