File indexing completed on 2023-10-03 03:29:21

0001 /*
0002     SPDX-FileCopyrightText: 2001-2004 Nicolas Hadacek <hadacek@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #ifndef KEXTHIGHSCORE_H
0008 #define KEXTHIGHSCORE_H
0009 
0010 #include "kexthighscore_item.h"
0011 
0012 #include <libkdegames_export.h>
0013 
0014 #include <QLoggingCategory>
0015 #include <QVector>
0016 #include <QUrl>
0017 
0018 namespace KExtHighscore
0019 {
0020 
0021 class Score;
0022 class Item;
0023 
0024 class ManagerPrivate;
0025 extern ManagerPrivate *internal;
0026 
0027 /**
0028  * Get the current game type.
0029  */
0030  uint gameType();
0031 
0032 /**
0033  * Set the current game type.
0034  */
0035  void setGameType(uint gameType);
0036 
0037 /**
0038  * Configure the highscores.
0039  * @return true if the configuration has been modified and saved
0040  */
0041  bool configure(QWidget *parent);
0042 
0043 /**
0044  * Show the highscores lists.
0045  */
0046  void show(QWidget *parent);
0047 
0048 /**
0049  * Submit a score. See @ref Manager for usage example.
0050  *
0051  * @param score the players score
0052  * @param widget a widget used as parent for error message box.
0053  */
0054  void submitScore(const Score &score, QWidget *widget);
0055 
0056 /**
0057  * @return the last score in the local list of highscores. The worst possible
0058  * score if there are less items than the maximum number.
0059  */
0060  Score lastScore();
0061 
0062 /**
0063  * @return the first score in the local list of highscores (the worst possible
0064  * score if there is no entry).
0065  */
0066  Score firstScore();
0067 
0068 /**
0069  * This class manages highscores and players entries (several players can
0070  * share the same highscores list if the libkdegame library is built to
0071  * support a common highscores file; NOTE that to correctly implement such
0072  * feature we probably need a locking mechanism in @ref KHighscore).
0073  *
0074  * You need one instance of this class during the application lifetime; in
0075  * main() just insert 
0076  * \code
0077  *   KExtHighscore::Manager highscoresManager;
0078  * \endcode
0079  * with the needed arguments. Use the derived class if you need to
0080  * reimplement some of the default methods.
0081  *
0082  * This class has three functions:
0083  * <ul>
0084  * <li> Update the highscores list when new entries are submitted </li>
0085  * <li> Display the highscores list and the players list </li>
0086  * <li> Send query to an optional web server to support world-wide
0087  *      highscores </li>
0088  * </ul>
0089  *
0090  * The highscores and the players lists contain several items described by
0091  * the @ref Item class.
0092  *
0093  * The highscores list contains by default:
0094  * <ul>
0095  * <li> the player name (automatically set from the config value)</li>
0096  * <li> the score value </li>
0097  * <li> the time and date of the highscore (automatically set) </li>
0098  * </ul>
0099  * You can replace the score item (for e.g. displaying it differently) with
0100  * setScoreItem or add an item with addScoreItem.
0101  *
0102  * The players list contains:
0103  * <ul>
0104  * <li> the player name (as defined by the user in the configuration
0105  *      dialog) </li>
0106  * <li> the number of games played </li>
0107  * <li> the mean score </li>
0108  * <li> the best score </li>
0109  * <li> the best score time and date </li>
0110  * <li> the player comment (as defined by the user in the
0111  *      configuration dialog) </li>
0112  * </ul>
0113  * You can replace the best score and the mean score items
0114  * by calling setPlayerItem.
0115  *
0116  * To submit a new score at game end, just construct a Score, set the
0117  * score data and then call submitScore().
0118  * \code
0119  *     KExtHighscore::Score score(KExtHighscore::Won);
0120  *     score.setScore(myScore);
0121  *     KExtHighscore::submitScore(score, widget);
0122  * \endcode
0123  * You only need to set the score value with Score::setScore()
0124  * and the value of the items that you have optionally added
0125  * with Score::setData() player name and date are set automatically.
0126  */
0127 class  Manager
0128 {
0129  public:
0130     /**
0131      * Constructor
0132      *
0133      * @param nbGameTypes the number of different game types (usually one).
0134      *        For example KMines has easy, normal and expert levels.
0135      * @param maxNbEntries the maximum numbers of highscores entries (by game
0136      *        types)
0137      */
0138     explicit Manager(uint nbGameTypes = 1, uint maxNbEntries = 10);
0139     virtual ~Manager();
0140     
0141     /**
0142      * Set the world-wide highscores.
0143      * By default there is no world-wide highscores.
0144      *
0145      * Note: should be called at construction time.
0146      *
0147      * @param url the web server url
0148      * @param version the game version which is sent to the web server (it can
0149      * be useful for backward compatibility on the server side).
0150      */
0151     void setWWHighscores(const QUrl &url, const QString &version);
0152 
0153     /**
0154      * Set if the number of lost games should be track for the world-wide
0155      * highscores statistics. By default, there is no tracking.
0156      * False by default.
0157      *
0158      * Note: should be called at construction time.
0159      */
0160     void setTrackLostGames(bool track);
0161     
0162     /**
0163      * Set if the number of "draw" games should be track for the world-wide
0164      * highscores statistics. By default, there is no tracking.
0165      * False by default.
0166      *
0167      * Note: should be called at construction time.
0168      */
0169     void setTrackDrawGames(bool track);
0170 
0171     /**
0172      * Set if the statistics tab should be shown in the highscores dialog.
0173      * You only want to show this tab if it makes sense to lose or to win the
0174      * game (for e.g. it makes no sense for a tetris game but it does for a
0175      * minesweeper game).
0176      * False by default.
0177      *
0178      * Note: should be called at construction time.
0179      */
0180     void setShowStatistics(bool show);
0181     
0182     /**
0183      * Set if draw games statistics should be shown (enable this if
0184      * draws are possible in your game).
0185      * False by default.
0186      */
0187     void setShowDrawGamesStatistic(bool show);
0188 
0189     enum ScoreTypeBound { ScoreNotBound, ScoreBound };
0190     /**
0191      * Set the ranges for the score histogram.
0192      *
0193      * Note: should be called at construction time.
0194      */
0195     void setScoreHistogram(const QVector<uint> &scores, ScoreTypeBound type);
0196 
0197     /** 
0198     * Enumerate different conditions under which to show the
0199     * high score dialog.
0200     */
0201     enum ShowMode { AlwaysShow,          ///< Always show the dialog
0202                     NeverShow,           ///< Never show the dialog
0203                     ShowForHigherScore,  ///< Show if score has improved
0204                     ShowForHighestScore  ///< Only for the top spot
0205                   };
0206     /**
0207      * Set how the highscores dialog is shown at game end.
0208      * By default, the mode is ShowForHigherScore.
0209      *
0210      * Note: should be called at construction time.
0211      */
0212     void setShowMode(ShowMode mode);
0213 
0214     /**
0215      * Score type (@see setScoreType).
0216      * @p Normal default score (unsigned integer without upper bound)
0217      * @p MinuteTime score by time bound at 3599 seconds (for e.g. kmines)
0218      */
0219     enum ScoreType { Normal, MinuteTime };
0220     /**
0221      * Set score type. Helper method to quickly set the type of score.
0222      * By default the type is Normal.
0223      *
0224      * Note: should be called at construction time.
0225      */
0226     void setScoreType(ScoreType type);
0227 
0228     /**
0229      * Some predefined item types.
0230      * @p ScoreDefault default item for the score in the highscores list.
0231      * @p MeanScoreDefault default item for the mean score (only show one decimal and
0232      * 0 is shown as "--".
0233      * @p BestScoreDefault default item for the best score (0 is shown as "--").
0234      * @p ElapsedTime optional item for elapsed time (maximum value is 3599 seconds).
0235      */
0236     enum ItemType { ScoreDefault, MeanScoreDefault, BestScoreDefault,
0237                     ElapsedTime };
0238     /**
0239      * Create a predefined item.
0240      */
0241     static Item *createItem(ItemType type);
0242 
0243     /**
0244      * Replace the default score item in the highscores list by the given one.
0245      * @p worstScore is the worst possible score. By default it is 0.
0246      *
0247      * Note: This method should be called at construction time.
0248      */
0249     void setScoreItem(uint worstScore, Item *item);
0250 
0251     /**
0252      * Add an item in the highscores list (it will add a column to this list).
0253      *
0254      * Note: This method should be called at construction time.
0255      */
0256     void addScoreItem(const QString &name, Item *item);
0257 
0258     enum PlayerItemType { MeanScore, BestScore };
0259     /**
0260      * Replace an item in the players list.
0261      *
0262      * Note: This method should be called at construction time.
0263      */
0264     void setPlayerItem(PlayerItemType type, Item *item);
0265 
0266     /**
0267      * @return true if the first score is strictly worse than the second one.
0268      * By default return <pre>s1.score()<s2.score()</pre>. You can reimplement
0269      * this method if additional items added to @ref Score can further
0270      * differentiate the scores (for e.g. the time spent).
0271      *
0272      * Note that you do not need to use directly this method, simply write
0273      * <pre>s1<s2</pre> since the operator calls this method.
0274      */
0275     virtual bool isStrictlyLess(const Score &s1, const Score &s2) const;
0276 
0277     /**
0278      * Possible type of label (@see gameTypeLabel).
0279      * @p Standard label used in config file.
0280      * @p I18N label used to display the game type.
0281      * @p WW label used when contacting the world-wide highscores server.
0282      * @p Icon label used to load the icon corresponding to the game type.
0283      */
0284     enum LabelType { Standard, I18N, WW, Icon };
0285 
0286     /**
0287      * @return the label corresponding to the game type. The default
0288      * implementation works only for one game type: you need to reimplement
0289      * this method if the number of game types is more than one.
0290      */
0291     virtual QString gameTypeLabel(uint gameType, LabelType type) const;
0292 
0293  protected:
0294     /**
0295      * This method is called once for each player (ie for each user). You
0296      * can reimplement it to convert old style highscores to the new mechanism
0297      * (@see submitLegacyScore). By default this method does nothing.
0298      *
0299      * @param gameType the game type
0300      */
0301     virtual void convertLegacy(uint gameType) { Q_UNUSED(gameType); }
0302 
0303     /**
0304      * This method should be called from @ref convertLegacy. It is used
0305      * to submit an old highscore (it will not be sent over the network).
0306      * For each score do something like:
0307      * \code
0308      * Score score(Won);
0309      * score.setScore(oldScore);
0310      * score.setData("name", name);
0311      * submitLegacyScore(score);
0312      * \endcode
0313      * Note that here you can set the player "name" and the highscore "date"
0314      * if they are known.
0315      */
0316     void submitLegacyScore(const Score &score) const;
0317 
0318     /**
0319      * This method is called before submitting a score to the world-wide
0320      * highscores server. You can reimplement this method to add an entry
0321      * with @ref addToQueryURL. By default this method does nothing.
0322      *
0323      * @param url the URL to query
0324      * @param score the score to be submitted.
0325      */
0326     virtual void additionalQueryItems(QUrl &url, const Score &score) const
0327         { Q_UNUSED(url); Q_UNUSED(score); }
0328 
0329     /**
0330      * Add an entry to the url to be submitted (@see additionalQueryItems).
0331      *
0332      * @param url the URL to query
0333      * @param item the item name
0334      * @param content the item content
0335      */
0336     static void addToQueryURL(QUrl &url, const QString &item,
0337                               const QString &content);
0338 
0339     friend class ManagerPrivate;
0340 
0341  private:
0342     Manager(const Manager &);
0343     Manager &operator =(const Manager &);
0344 };
0345 
0346 } // namespace
0347 
0348 Q_DECLARE_LOGGING_CATEGORY(GAMES_EXTHIGHSCORE)
0349 
0350 #endif