kexthighscore.h 11.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
    This file is part of the KDE games library
    Copyright (C) 2001-2004 Nicolas Hadacek (hadacek@kde.org)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#ifndef KEXTHIGHSCORE_H
#define KEXTHIGHSCORE_H

#include "kexthighscore_item.h"

#include <libkdegames_export.h>

#include <QLoggingCategory>
28 29
#include <QVector>
#include <QUrl>
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

namespace KExtHighscore
{

class Score;
class Item;

class ManagerPrivate;
extern ManagerPrivate *internal;

/**
 * Get the current game type.
 */
KDEGAMES_EXPORT uint gameType();

/**
 * Set the current game type.
 */
KDEGAMES_EXPORT void setGameType(uint gameType);

/**
 * Configure the highscores.
 * @return true if the configuration has been modified and saved
 */
KDEGAMES_EXPORT bool configure(QWidget *parent);

/**
 * Show the highscores lists.
 */
KDEGAMES_EXPORT void show(QWidget *parent);

/**
 * Submit a score. See @ref Manager for usage example.
 *
 * @param score the players score
 * @param widget a widget used as parent for error message box.
 */
KDEGAMES_EXPORT void submitScore(const Score &score, QWidget *widget);

/**
 * @return the last score in the local list of highscores. The worst possible
 * score if there are less items than the maximum number.
 */
KDEGAMES_EXPORT Score lastScore();

/**
 * @return the first score in the local list of highscores (the worst possible
 * score if there is no entry).
 */
KDEGAMES_EXPORT Score firstScore();

/**
 * This class manages highscores and players entries (several players can
 * share the same highscores list if the libkdegame library is built to
 * support a common highscores file; NOTE that to correctly implement such
 * feature we probably need a locking mechanism in @ref KHighscore).
 *
 * You need one instance of this class during the application lifetime; in
 * main() just insert 
 * \code
 *   KExtHighscore::Manager highscoresManager;
 * \endcode
 * with the needed arguments. Use the derived class if you need to
 * reimplement some of the default methods.
 *
 * This class has three functions:
 * <ul>
 * <li> Update the highscores list when new entries are submitted </li>
 * <li> Display the highscores list and the players list </li>
 * <li> Send query to an optional web server to support world-wide
 *      highscores </li>
 * </ul>
 *
 * The highscores and the players lists contain several items described by
 * the @ref Item class.
 *
 * The highscores list contains by default:
 * <ul>
 * <li> the player name (automatically set from the config value)</li>
 * <li> the score value </li>
 * <li> the time and date of the highscore (automatically set) </li>
 * </ul>
 * You can replace the score item (for e.g. displaying it differently) with
 * setScoreItem or add an item with addScoreItem.
 *
 * The players list contains:
 * <ul>
 * <li> the player name (as defined by the user in the configuration
 *      dialog) </li>
 * <li> the number of games played </li>
 * <li> the mean score </li>
 * <li> the best score </li>
 * <li> the best score time and date </li>
 * <li> the player comment (as defined by the user in the
 *      configuration dialog) </li>
 * </ul>
 * You can replace the best score and the mean score items
 * by calling setPlayerItem.
 *
 * To submit a new score at game end, just construct a Score, set the
 * score data and then call submitScore().
 * \code
 *     KExtHighscore::Score score(KExtHighscore::Won);
 *     score.setScore(myScore);
 *     KExtHighscore::submitScore(score, widget);
 * \endcode
 * You only need to set the score value with Score::setScore()
 * and the value of the items that you have optionally added
 * with Score::setData() player name and date are set automatically.
 */
class KDEGAMES_EXPORT Manager
{
 public:
    /**
     * Constructor
     *
     * @param nbGameTypes the number of different game types (usually one).
     *        For example KMines has easy, normal and expert levels.
     * @param maxNbEntries the maximum numbers of highscores entries (by game
     *        types)
     */
    explicit Manager(uint nbGameTypes = 1, uint maxNbEntries = 10);
    virtual ~Manager();
    
    /**
     * Set the world-wide highscores.
     * By default there is no world-wide highscores.
     *
     * Note: should be called at construction time.
     *
     * @param url the web server url
     * @param version the game version which is sent to the web server (it can
     * be useful for backward compatibility on the server side).
     */
    void setWWHighscores(const QUrl &url, const QString &version);

    /**
     * Set if the number of lost games should be track for the world-wide
     * highscores statistics. By default, there is no tracking.
     * False by default.
     *
     * Note: should be called at construction time.
     */
    void setTrackLostGames(bool track);
    
    /**
     * Set if the number of "draw" games should be track for the world-wide
     * highscores statistics. By default, there is no tracking.
     * False by default.
     *
     * Note: should be called at construction time.
     */
    void setTrackDrawGames(bool track);

    /**
     * Set if the statistics tab should be shown in the highscores dialog.
     * You only want to show this tab if it makes sense to lose or to win the
     * game (for e.g. it makes no sense for a tetris game but it does for a
     * minesweeper game).
     * False by default.
     *
     * Note: should be called at construction time.
     */
    void setShowStatistics(bool show);
    
    /**
     * Set if draw games statistics should be shown (enable this if
     * draws are possible in your game).
     * False by default.
     */
    void setShowDrawGamesStatistic(bool show);

    enum ScoreTypeBound { ScoreNotBound, ScoreBound };
    /**
     * Set the ranges for the score histogram.
     *
     * Note: should be called at construction time.
     */
    void setScoreHistogram(const QVector<uint> &scores, ScoreTypeBound type);

    /** 
    * Enumerate different conditions under which to show the
    * high score dialog.
    */
    enum ShowMode { AlwaysShow,          ///< Always show the dialog
                    NeverShow,           ///< Never show the dialog
                    ShowForHigherScore,  ///< Show if score has improved
                    ShowForHighestScore  ///< Only for the top spot
                  };
    /**
     * Set how the highscores dialog is shown at game end.
     * By default, the mode is ShowForHigherScore.
     *
     * Note: should be called at construction time.
     */
    void setShowMode(ShowMode mode);

    /**
     * Score type (@see setScoreType).
     * @p Normal default score (unsigned integer without upper bound)
     * @p MinuteTime score by time bound at 3599 seconds (for e.g. kmines)
     */
    enum ScoreType { Normal, MinuteTime };
    /**
     * Set score type. Helper method to quickly set the type of score.
     * By default the type is Normal.
     *
     * Note: should be called at construction time.
     */
    void setScoreType(ScoreType type);

    /**
     * Some predefined item types.
     * @p ScoreDefault default item for the score in the highscores list.
     * @p MeanScoreDefault default item for the mean score (only show one decimal and
     * 0 is shown as "--".
     * @p BestScoreDefault default item for the best score (0 is shown as "--").
     * @p ElapsedTime optional item for elapsed time (maximum value is 3599 seconds).
     */
    enum ItemType { ScoreDefault, MeanScoreDefault, BestScoreDefault,
                    ElapsedTime };
    /**
     * Create a predefined item.
     */
    static Item *createItem(ItemType type);

    /**
     * Replace the default score item in the highscores list by the given one.
     * @p worstScore is the worst possible score. By default it is 0.
     *
     * Note: This method should be called at construction time.
     */
    void setScoreItem(uint worstScore, Item *item);

    /**
     * Add an item in the highscores list (it will add a column to this list).
     *
     * Note: This method should be called at construction time.
     */
    void addScoreItem(const QString &name, Item *item);

    enum PlayerItemType { MeanScore, BestScore };
    /**
     * Replace an item in the players list.
     *
     * Note: This method should be called at construction time.
     */
    void setPlayerItem(PlayerItemType type, Item *item);

    /**
     * @return true if the first score is strictly worse than the second one.
     * By default return <pre>s1.score()<s2.score()</pre>. You can reimplement
     * this method if additional items added to @ref Score can further
     * differentiate the scores (for e.g. the time spent).
     *
     * Note that you do not need to use directly this method, simply write
     * <pre>s1<s2</pre> since the operator calls this method.
     */
    virtual bool isStrictlyLess(const Score &s1, const Score &s2) const;

    /**
     * Possible type of label (@see gameTypeLabel).
     * @p Standard label used in config file.
     * @p I18N label used to display the game type.
     * @p WW label used when contacting the world-wide highscores server.
     * @p Icon label used to load the icon corresponding to the game type.
     */
    enum LabelType { Standard, I18N, WW, Icon };

    /**
     * @return the label corresponding to the game type. The default
     * implementation works only for one game type: you need to reimplement
     * this method if the number of game types is more than one.
     */
    virtual QString gameTypeLabel(uint gameType, LabelType type) const;

 protected:
    /**
     * This method is called once for each player (ie for each user). You
     * can reimplement it to convert old style highscores to the new mechanism
     * (@see submitLegacyScore). By default this method does nothing.
     *
     * @param gameType the game type
     */
    virtual void convertLegacy(uint gameType) { Q_UNUSED(gameType); }

    /**
     * This method should be called from @ref convertLegacy. It is used
     * to submit an old highscore (it will not be sent over the network).
     * For each score do something like:
     * \code
     * Score score(Won);
     * score.setScore(oldScore);
     * score.setData("name", name);
     * submitLegacyScore(score);
     * \endcode
     * Note that here you can set the player "name" and the highscore "date"
     * if they are known.
     */
    void submitLegacyScore(const Score &score) const;

    /**
     * This method is called before submitting a score to the world-wide
     * highscores server. You can reimplement this method to add an entry
     * with @ref addToQueryURL. By default this method does nothing.
     *
     * @param url the URL to query
     * @param score the score to be submitted.
     */
    virtual void additionalQueryItems(QUrl &url, const Score &score) const
        { Q_UNUSED(url); Q_UNUSED(score); }

    /**
     * Add an entry to the url to be submitted (@see additionalQueryItems).
     *
     * @param url the URL to query
     * @param item the item name
     * @param content the item content
     */
    static void addToQueryURL(QUrl &url, const QString &item,
                              const QString &content);

    friend class ManagerPrivate;

 private:
    Manager(const Manager &);
    Manager &operator =(const Manager &);
};

} // namespace

Q_DECLARE_LOGGING_CATEGORY(GAMES_EXTHIGHSCORE)

#endif