File indexing completed on 2024-04-14 04:01:05

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