/***************************************************************************
 *   Copyright (C) 2007 by Arnold Kraschinski                              *
 *   arnold.kra67@gmx.de                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
 ***************************************************************************/

#ifndef VERBDATA_H_
#define VERBDATA_H_

#include <QString>
#include <QVector>
#include <QList>
#include <QStringList>

/** If a Spanish verb is completely conjugated there are 63 forms
  * of the verb. The classes in this file store the forms in a QVector.
  * The order of the forms in the vector is the following, the 
  * numbers are the indexes in the vector.
  *
  * For one time, e. g. presente the order of the personal forms is
  * as follows: yo, tu, (él, ella, usted), nosotros, vosotros, (ellos, ustedes)
  *
  *  0.. 5: Presente
  *  6..11: Indefinido
  * 12..17: Futuro
  * 18..23: Imperfecto
  * 24..29: Condicional
  * 30..35: Subjuntivo Presente
  * 36..41: Subjuntivo Imperfecto 1. version
  * 42..47: Subjuntivo Imperfecto 2. version
  * 48..53: Subjuntivo Futuro
  * 54..59: Imperativo
  * 60    : Gerundium
  * 61    : Participio 1. version
  * 62    : Participio 2. version
  */
#define NUMBER_OF_VERB_FORMS         63

#define LEVEL_ARRAY_SIZE             8
#define MAXLEVELS                    LEVEL_ARRAY_SIZE - 1


/** A struct to store irregular forms of a verb.
  * 
  * index - is the position of the form in the vector of forms
  * offset - is the number of characters that have to be cut off from the infinitive
  * ending - is the new ending that has to be added to the remaining part of the infinitive
  *
  * @short A struct to store irregular forms of a verb.
  * @author Kraschinski Arnold <arnold.kra67@gmx.de>
  * @version 2.00.00
  */
struct IrregularPattern
{
    int index;
    int offset;
    QString ending;
};


/** Abstract base class for all verb classes.
 *
 * @short Abstract base class for all verb classes.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class Verb
{
public:
    Verb();
    Verb(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~Verb();

    /** @return the infinitive of the verb
      */
    QString infinitive() const { return m_infinitive; };

    /** @return the number of the verb-family
      */
    int family() const { return m_family; };

    /** @return the informatin if the verb is reflexive
      */
    bool reflexive() const { return m_reflexive; };

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false) = 0;
    
    /** The endings for the different tenses and the offsets to shorten the infinitives 
      * are already collected in arrays. In this function the infinitives are combined with
      * the information in the arrays. The resulting set of forms is returned in a vector.
      * If html is true a html tag to help displaying the ending is added.
      *
      * @param offset[] the information which part of the infinitive has to be cut
      * @param ending[] the endings that have to be added to the rest of the infinitive
      * @param html true, the forms contain a html tag; false the forms come without the tag
      * @return a QVector with the created forms.
      */
    QVector<QString> buildForms(int offset[], QString ending[], bool html = false);

    /** @return if the verb is regular or not
      */
    virtual bool isRegular() = 0;

    /** Look at the ending of the verb and find the number for the ending. The values are
      * ENDING_AR, ENDING_ER, ENDING_IR or ENDING_IR2 or -1 if the ending hasn't been found.
      *
      * @return an integer number that stands for the ending, -1 indicates that the ending hasn't been found.
      */
    int endingNumber();

    /** Look at the ending of the given infinitive and find the number for the ending. The values are
      * ENDING_AR, ENDING_ER, ENDING_IR or ENDING_IR2 or -1 if the ending hasn't been found.
      *
      * @param infinitive the infinitive to be tested
      * @return an integer number that stands for the ending, -1 indicates that the ending hasn't been found.
      */
    static int endingNumber(QString infinitive);
    
    /** <TODO> Later on it should be possible to store translations of verbs using KVTML-Files.
      * Then a parameter which indicates the language would be necessary.
      *
      * @return true if the verb is translated, false if not
      */
    bool translated() { return false; };

    /** return the information if the verb is among the selected verbs.
      *
      * @return true if the verb is selected, false if the verb isn't selected
      */
    bool selected() { return m_selected; };

    /** Add the verb to the set of selected verbs. The function puts the verb
      * into the level m_level = 0 and sets the m_lastDay = 0.
      *
      * @param bool set if the verb is among the selected verbs.
      */
    void setSelected(bool selected);

    /** @return the current learning level in which the verb is at the moment
      */
    int level() const { return m_level; };

    /** A call to this function puts the verb if it is selected into the level 
      * given as parameter. The function calculates the day as a julian day until
      * the verb will stay in this level and stores it in m_lastDay. If the verb
      * isn't selected the level can't be set and m_level and m_lastDay will be
      * resetted to 0.
      *
      * @param level the number of the level where the verb has to be placed
      */
    void setLevel(int level);
    
    /** Brings the verb to the next higher level. If it is already in the highest level
      * it remains there but the m_lastDay is set to a new date.
      */
    void levelUp();
    
    /** Brings the verb to the next lower level. If it is already in the lowest level 0
      * it remains there and the m_lastDay is set to 0.
      */
    void levelDown();

    /** @return the date as a Julian day until the verb remains in the current level.
      */
    int lastDay() const { return m_lastDay; };
    
    /** Sets the status of a verb, this means the three members m_selected, m_level, m_lastDay
      * according to the parameters. The default values set the verb to the status
      * not selected.
      *
      * @param bool true if the verb is selected, false if it should be not selected
      * @param int the level the verb should get
      * @param int the julian day until the verb remains in the level
      */
    void setStatus( bool selected = false, int level = 0, int lastDay = 0);
    
    /** When a verb reaches a higher level it is blocked for some time. Call this 
      * function to find out if the verb is blocked at the moment. The verb is never
      * blocked in level 0.
      *
      * @return true if the verb is blocked an shouldn't be trained, false if it can be trained
      */
    bool blocked();
    
    /** If a verb is in a level higher than level 0 it is in that level for a fixed time.
      * After that time the verb expires and is send to the next lower level. Verbs in
      * level 0 don't expire.
      *
      * @return true if the verb has expired and should be brought to a lower level
      */
    bool expired();

    /** Compare a verb object with a QString. The criteria to compare a verb object with a string
      * is the infinitive.
      *
      * @param infinitive the infinitive that should be compared with the verb object
      * @return if the this object is smaller than the argument object
      */
    bool isSmallerThan(QString v) const;

    /** To use the QtAlgorithms qSort function it is necessary to implement operator<()  The
      * criteria to sort verb objects is the order of the infinitives.
      *
      * @param v the verb object which should be compared
      * @return if the this object is smaller than the argument object
      */
    bool operator<(const Verb& v) const;

protected:
    QString     m_infinitive;
    bool        m_reflexive;
    int         m_family;
    QString     m_comment;
    QString     m_option;
    
    /** The verbs in the list can be have the status selected or not. This can
     *  be used by learning software to identify the verbs the user wants to train.
     */
    bool        m_selected;
    
    /** The verbs can be in several different levels. The maximum of levels is
     *  set in MAXLEVELS
     */
    int         m_level;
    
    /** The day as a Julian date until the verb remains in the current level
     */
    int         m_lastDay;

    static QString          ENDING[4];
public:
    /** The reflexiv pronouns */
    static const QString    REFLEXIV_PRONOUNS[6];
    
    static const int        ENDING_AR;
    static const int        ENDING_ER;
    static const int        ENDING_IR;
    static const int        ENDING_IR2;
    
    /** The endings for regular -ar verbs.       */
    static int              AMAR_OFFSET[NUMBER_OF_VERB_FORMS];
    static QString          AMAR_ENDING[NUMBER_OF_VERB_FORMS];
    
    /** The endings for regular -er verbs.      */
    static int              TEMER_OFFSET[NUMBER_OF_VERB_FORMS];
    static QString          TEMER_ENDING[NUMBER_OF_VERB_FORMS];
    
    /** The endings for regular -ir verbs.      */
    static int              PARTIR_OFFSET[NUMBER_OF_VERB_FORMS];
    static QString          PARTIR_ENDING[NUMBER_OF_VERB_FORMS];
    static const int        NUMBER_OF_FORMS;

    /** Names for the different levels      */
    static const QString    LEVELNAMES[LEVEL_ARRAY_SIZE];
    
    /** The number of days a verb is blocked when it reaches the level      */
    static int              LEVEL_BLOCK_DAYS[LEVEL_ARRAY_SIZE];
    
    /** The number of days after which a verb is send back to the next
      * lower level.
      */
    static int              LEVEL_EXPIRE_DAYS[LEVEL_ARRAY_SIZE];
    
    static const int        MAXLEVEL;
    static const int        UNTRAINED;
    static const int        TRAINED;
    static const int        WELLKNOWN;
    static const int        VERYWELLKNOWN;
    static const int        SECUREDKNOWLEDGE;
    static const int        FOREVER;
};


/** Base class for all regular verb classes.
 *
 * @short Base class for all regular verb classes.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbRegular : public Verb
{
public:
    VerbRegular();
    VerbRegular(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbRegular();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false) = 0;
    
    /** @return if the verb is regular or not
      */
    virtual bool isRegular() { return true; };
};


/** Class for all regular verbs with ending on -ar.
 *  The regular conjugation is always done like this: 
 *  Cut off some characters from the invinitive. The number is given by
 *  the AMAR_OFFSET. Add the new ending from AMAR_ENDING to the remaining
 *  part.
 *
 * @short Class for all regular -ar-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbRegularAR  : public VerbRegular
{
public:
    VerbRegularAR();
    VerbRegularAR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbRegularAR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


/** Class for all regular verbs with ending on -er.
 *  The regular conjugation is always done like this: 
 *  Cut off some characters from the invinitive. The number is given by
 *  the TEMER_OFFSET. Add the new ending from TEMER_OFFSET to the remaining
 *  part.
 *
 * @short Class for all regular -er-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbRegularER  : public VerbRegular
{
public:
    VerbRegularER();
    VerbRegularER(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbRegularER();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


/** Class for all regular verbs with ending on -ir.
 *  The regular conjugation is always done like this: 
 *  Cut off some characters from the invinitive. The number is given by
 *  the PARTIR_OFFSET. Add the new ending from PARTIR_OFFSET to the remaining
 *  part.
 *
 * @short Class for all regular -ir-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbRegularIR  : public VerbRegular
{
public:
    VerbRegularIR();
    VerbRegularIR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbRegularIR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


/** Base class for all irregular verb classes.
 *
 * @short Base class for all irregular verb classes.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregular : public Verb
{
public:
    VerbIrregular();
    VerbIrregular(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregular();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false) = 0;
    
    /** @return if the verb is regular or not
      */
    virtual bool isRegular() { return false; };
    
    /** Adds a irregular form to the vector m_irregularForm.
      */
    void addIrregularForm(int index, int offset, QString ending);
protected:
    QList<IrregularPattern>       m_irregularForm;
};



/** Class for irregular verbs ending on -ar.
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed.
 *
 * @short Class for all irregular -ar-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularAR  : public VerbIrregular
{
public:
    VerbIrregularAR();
    VerbIrregularAR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularAR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


/** Class for irregular verbs ending on -ar that belong to the -car familiy (71)
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed. Finally the changes for -car verbs are made.
 *
 * @short Class for all irregular -car-verbs. (family 71)
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularCAR  : public VerbIrregularAR
{
public:
    VerbIrregularCAR();
    VerbIrregularCAR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularCAR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
private:
    static int              CAR_INDEX[10];
    static QString          CAR_ENDING[10];
public:
};


/** Class for irregular verbs ending on -ar that belong to the -gar familiy (72)
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed. Finally the changes for -gar verbs are made.
 *
 * @short Class for all irregular -gar-verbs. (family 72)
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularGAR  : public VerbIrregularAR
{
public:
    VerbIrregularGAR();
    VerbIrregularGAR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularGAR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
private:
    static int              GAR_INDEX[10];
    static QString          GAR_ENDING[10];
public:
};


/** Class for irregular verbs ending on -ar that belong to the -zar familiy (73)
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed. Finally the changes for -zar verbs are made.
 *
 * @short Class for all irregular -zar-verbs. (family 73)
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularZAR  : public VerbIrregularAR
{
public:
    VerbIrregularZAR();
    VerbIrregularZAR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularZAR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
private:
    static int              ZAR_INDEX[10];
    static QString          ZAR_ENDING[10];
public:
};


/** Class for irregular verbs ending on -er.
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed.
 *
 * @short Class for all irregular -er-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularER  : public VerbIrregular
{
public:
    VerbIrregularER();
    VerbIrregularER(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularER();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


/** Class for irregular verbs ending on -ir.
 *  First the verb is conjugated like a regular verb. After that
 *  the irregular forms are changed.
 *
 * @short Class for all irregular -ir-verbs.
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class VerbIrregularIR  : public VerbIrregular
{
public:
    VerbIrregularIR();
    VerbIrregularIR(QString infinitive, bool reflexive, int family, QString comment = "", QString option = "");
    virtual ~VerbIrregularIR();

    /** Builds the forms of the verbs and returns them in a QVector. According to
      * the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param bool true, the forms contain a html tag; false the forms come without the tag
      * @return the forms of a verb in a QVector
      */
    virtual QVector<QString> conjugate(bool html = false);
};


#define GROUPCOUNT   16
#define FAMILIES_COUNT   91
#define TRAINING_TENSES_SIMPLE      9
#define TRAINING_TENSES_COMPOSED    8
#define TRAINING_TENSES_GERUNDIUM   5
#define TRAINING_TENSES             TRAINING_TENSES_SIMPLE + TRAINING_TENSES_COMPOSED + TRAINING_TENSES_GERUNDIUM 
// = 22

/**
 * The class reads the verbdata.xml file. This file contains the information
 * about all the verbs, verbfamilies and irregular forms. The class provides
 * the information about the verbs known by the program.
 * There are member functions to obtain the conjugation of a verb.
 *
 * @short reads and provides the information about verbs for the program
 * @author Kraschinski Arnold <arnold.kra67@gmx.de>
 * @version 2.00.00
 */
class Verbdata
{
public:
    Verbdata();
    ~Verbdata();
    /** @return The number of verbs in the verblist.
     */
    static int count();

    /** Retrieve a pointer to the list of verbs
      *
      * @return a pointer to the list of verbs
      */
    static QList<Verb*>* getVerblist();

    /** Get a list of the infinitives of all verbs.
      *
      * @return a QStringList with all infinitves
      */
    static QStringList getInfinitiveList();
    
    /** Get a list of pointers to verbs. According to the parameter
      * only the selected verbs or all verbs. The default value
      * is true.
      *
      * @param bool if true the selected verbs, if flase all verbs
      * @return a list with pointers to all the selected verbs
      */
    static QList<Verb*> verbPointers( bool selection = true );

    /** Pass the infinitive of a verb to the funciton and receive all the forms of the verb.
      * According to the parameter html the forms can contain a <span></span> tag to help displaying
      * the ending in an html-output. If html is false the tags aren't included.
      * If the html is true the froms lool like this example: habl<span id="ending">o</span>
      *
      * @param infinitive Pass the infinitive of a verb to the function.
      * @param html true, the forms contain a html tag; false the forms come without the tag
      * @return A QVector with all the forms of the verb.
      */
    static QVector<QString> conjugate(QString infinitive, bool html = false);

    /** Find a verbObject if the infinitive is known. The function uses binary search.
      * So it is necessary that the verbs are already ordered. If the verb is in the list
      * the function returns a pointer to the verb object otherwise it returns 0
      *
      * @param infinitive the infinitive of the verb you will search
      * @return a pointer to the verb Object or 0 if the verb isn't in the list
      */
    static Verb* find(const QString infinitive);

    /** Take the verbSelection from the KVerbosSettings and set all Verbs in
      * the verblist according to the selection status. Adapt the level for
      * expired verbs.
      */
    static void readSettings();
    
    /** Take the selected verbs from verbdata and write it to the KVerbosSettings and
      * write the settings to the config file.
      */
    static void writeSettings();

    /** Report to the Verbdata that a verb has been trained and if the user
      * answered the task correctly or not and if the answer could change
      * the level of the verb.
      *
      * @param verb a pointer to the verb that has been trained.
      * @param correct set true if the user gave the correct answer otherwise false
      * @param apply decides if the answer can change the level of the verb
      */
    static void reportTraining(Verb* verb, bool correct, bool apply = true);

    /** Report to the Verbdata that a verb has been trained and if the user
      * answered the task correctly or not and if the answer could change
      * the level of the verb.
      *
      * @param infinitive the infinitive of the verb that has been trained.
      * @param correct set true if the user gave the correct answer otherwise false
      * @param apply decides if the answer can change the level of the verb
      */
    static void reportTraining(QString infinitive, bool correct, bool apply = true);

private:
    /** Opens the verbdata.xml file and reads the verb information
     *
     *  @return returns true if the file has been loaded otherwise false.
     */
    static bool readVerbdataFile();

    /** The list with pointers to all the known verbs
     */
    static QList<Verb*>*     m_verbdata;

public:
    /** The number of different grammatical groups of Spanish verbs.
     *  The names are used according to the dicctionary: PONS Standardwörterbuch;
     *  Klett-Verlag, Stuttgart - Dresden 1994, 2. Auflage; 
     */
    static const int GROUPS;

    /** The names for the different grammatical groups of Spanish verbs.
     *  The names are used according to the dicctionary: PONS Standardwörterbuch;
     *  Klett-Verlag, Stuttgart - Dresden 1994, 2. Auflage; 
     */
    static const QString GROUPNAMES[GROUPCOUNT];

    /** The number of different verb families in the database
     */
    static const int FAMILIES;

    /** The numbers in this array map the verb family numbers of the 
     *  verbdata to the group names of my diccionary.
     */
    static const int GROUPMATCH[FAMILIES_COUNT];
    
    /** The tenses that can be trained with the program. The position numbers
      * of the tenses in this array are stored in the QKVerbosPartSettings class
      * to select the tenses the user wants to train.
      *
      * The first number indicates the type of tense: 
      * - 0 = a simple tense with only one form of the verb
      * - 1 = a composed tense with a form of haber and the partizipio
      * - 2 = a continuous tense with a form of estar and the gerundio
      *
      * The second number is necessary to find the forms for the tense in the set
      * of all forms generated by the QKonjugierer class:
      *
      * - The simple tenses
      *         -  0 - Presente:                      0       0
      *         -  1 - Imperfecto                     0       3
      *         -  2 - Indefinido                     0       1
      *         -  3 - Futuro                         0       2
      *         -  4 - Conditional presente           0       4
      *         -  5 - Subjuntivo presente            0       5
      *         -  6 - Subjuntivo imperfecto          0       6       2 versions!  Number: 6
      *         -  7 - Subjuntivo futuro              0       8
      *         -  8 - Imperativo                     0       9
      * 
      * - Tenses: form of 'haber' + partizipio
      *         -  9 - Perfecto                       1       0
      *         - 10 - Pluscuamperfecto               1       3
      *         - 11 - Pretérito anterior             1       1
      *         - 12 - Futuro anterior                1       2
      *         - 13 - Conditional perfecto           1       4
      *         - 14 - Subjuntivo perfecto            1       5
      *         - 15 - Subjuntivo pluscuamperfecto    1       6       2 versions! Number: 15
      *         - 16 - Subjuntivo futuro anterior     1       8
      * 
      * -  Tenses: form of 'estar' + gerundio
      *         - 17 - Gerundio presente              2       0
      *         - 18 - Gerundio imperfecto            2       3
      *         - 19 - Gerundio pretérito             2       1
      *         - 20 - Gerundio futuro                2       2
      *         - 21 - Gerundio conditional           2       4
      */
    static const int     TENSES;
    static const int     IMPERATIVO;
    static const QString TENSEINFO[TRAINING_TENSES][3];
};



#endif // VERBDATA_H_
