Logo Search packages:      
Sourcecode: kalcul version File versions  Download package

kalculview.cpp

/***************************************************************************
 *   Copyright (C) 2005 by Anne-Marie Mahfouf   *
 *   annemarie.mahfouf@free.fr   *
 *                                                                         *
 *   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 Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/


#include "kalculview.h"
#include "settings.h"
#include "results.h"

#include <qdatetime.h>
#include <qdir.h>
#include <qfile.h>
#include <qlabel.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qpushbutton.h>
#include <qtimer.h>
#include <qvalidator.h>

#include <klineedit.h>
#include <klocale.h>
#include <kprogress.h>
#include <kurl.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include <kclock.h>
#include <kdebug.h>

00046 KalculView::KalculView(QWidget *parent)
    : kalculview_base(parent)
{
    mode = Settings::operation();
    paused = false;
    total = 0;
    correct = 0;
    firstNum = 0;
    secondNum = 0;
    kProgress1->setFormat("%v");
    kProgress2->setFormat("%v");
    kProgress1->setTotalSteps(Settings::numOp());
    kProgress2->setTotalSteps(Settings::numOp());
    clock = new KClock(clockFrame);

    resultLabel->setText( i18n("Click on the Start button") );
    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else
        clock->setTimeLeft(0);
    //TODO: make sure the upper limit is appropriate for the maximum possible value.
    //If you use multiply and limits of e.g. 50 and 50, it could be higher than 999
    intValidator = new QIntValidator(0, 999, this);
    answerLine->setValidator(intValidator);

    connect(startButton, SIGNAL(clicked()), this, SLOT(slotStart()));
    connect(answerLine, SIGNAL(returnPressed()), this, SLOT(slotCheck()));
    connect(pauseButton, SIGNAL(clicked()), this, SLOT(slotPause()));
    connect(clock, SIGNAL(signalTimeout()), this, SLOT(timerDone()));
}

00077 KalculView::~KalculView()
{

}

00082 void KalculView::setLevel(const QString& level)
{
    mode = Level;
    levelQuestionsList.clear();

    int tmpCurrent = 0;
    int tmpPosition;
    QStringList tmpList = QStringList::split("\n", level);
    for (QStringList::Iterator it = tmpList.begin(); it != tmpList.end();
         ++it, ++tmpCurrent) {
        tmpPosition = (*it).find("=");
        levelQuestionsList.append((*it).left(tmpPosition));
        correctAnswer[tmpCurrent] = (*it).mid(tmpPosition + 2).toInt();
    }
    levelNumberOfQuestions = tmpCurrent;
    
    reset();
}

00101 void KalculView::setPracticeMode(int practiceMode)
{
    mode = practiceMode;
    reset();
}

00107 void KalculView::settingsChanged()
{
    mode = Settings::operation();
    reset();

    //update user name
    emit signalChangeStatusbar(i18n("User: %1").arg(Settings::nameLine())); 
}

00116 void KalculView::displayOperation()
{
    //TODO: Optimize calculation(replace the clumsy while loops)

    //make sure the numbers are >0 for division
    if (mode == Practice_Division) {
        firstNum = random.getLong(Settings::maxFirst() - 1) + 1;
        secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
    }
    else {
        firstNum = random.getLong(Settings::maxFirst());
        secondNum = random.getLong(Settings::maxSecond());
    }

    // + operation
    if (mode == Practice_Addition ) {
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum + secondNum;
            kdDebug() << correctAnswer[total] << endl;
            kdDebug() << Settings::max() << endl;
            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst());
                secondNum = random.getLong(Settings::maxSecond()); 
                correctAnswer[total] = firstNum + secondNum;        
            }
        }
        else
            correctAnswer[total] = firstNum + secondNum;
    }
    
    // - operation
    else if (mode == Practice_Subtraction) {
        //make sure the first number is bigger than the second one
        while (firstNum < secondNum)
        {
            firstNum = random.getLong(Settings::maxFirst());
            secondNum = random.getLong(Settings::maxSecond());
        }
        correctAnswer[total] = firstNum - secondNum;
    }

    // * operation
    else if (mode == Practice_Multiplication) {
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum * secondNum;
            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst());
                secondNum = random.getLong(Settings::maxSecond());
                correctAnswer[total] = firstNum * secondNum;
            }
        }
        else
            correctAnswer[total] = firstNum * secondNum;
    }

    // / operation
    else if (mode == Practice_Division ) {
        // make sure the first number is bigger than the second one
        // operations like 4 / 9 might be a little too hard except for preset levels
        while (firstNum < secondNum || (firstNum % secondNum) != 0)
        {
            firstNum = random.getLong(Settings::maxFirst() - 1) + 1;
            secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
        }
           
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum / secondNum;

            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst() - 1 ) + 1;
                secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
                correctAnswer[total] = firstNum / secondNum;
            }
        }
        else
            correctAnswer[total] = firstNum / secondNum;
    } 
                
    if (mode == Practice_Addition) //case?
        questionString[total] = i18n("%1 + %2").arg(QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Subtraction)
        questionString[total] = i18n("%1 - %2").arg(QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Multiplication)
        questionString[total] = i18n("%1 * %2").arg(QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Division)
        questionString[total] = i18n("%1 / %2").arg(QString::number(firstNum), QString::number(secondNum));
    else if (mode == Level) 
        questionString[total] = i18n(levelQuestionsList[total]);

    questionLabel->setText(questionString[total]);
}

void KalculView::slotCheck()
{
    if (answerLine->text().isEmpty())
        return;
    answerNum[total] = answerLine->text().toInt();
    if (correctAnswer[total] != answerNum[total]) 
    {   //TODO: save in config
        QString text = "<qt>";
        text += "<font color=\"red\">" + i18n("Wrong answer.") + "</font><br>";
        text += i18n("Correct Answer:");
        text += "<br>";
        text += questionString[total] + " = " + QString::number(correctAnswer[total]);
        text += "</qt>";
        resultLabel->setText(text);
    }
    else
    {
        correct++;
        kProgress2->setValue(kProgress2->progress()+1);
        resultLabel->setText(i18n("Correct!"));
    }
    total++;
    
    emit signalChangeStatusbar(i18n("User: %1").arg(Settings::nameLine()) + ",  " +
                               i18n("Correct: %1").arg(QString::number(correct)) +
                               i18n(" Total: %1").arg(QString::number(total)));
                               
    kProgress1->setProgress(total);

    int complete;
    (mode == Level) ? complete = levelNumberOfQuestions : complete = Settings::numOp();
    
    if (total == complete) // if correct == number of questions set
    {
        clock->stop();
        // write statistics in config
        saveResults();
        
        // display result dialog
        displayResultDialog();
        
        // reset everything
        reset();
        emit signalChangeStatusbar(i18n("User: %1").arg(Settings::nameLine())); 
        return;
    }
    
    answerLine->clear();
    displayOperation();
}

void KalculView::timerDone()
{
    displayResultDialog();
    reset();
}

void KalculView::slotStart()
{
    pauseButton->setEnabled(true);
    answerLine->setEnabled(true);
    answerLine->setFocus();
    questionLabel->setEnabled(true);
    startButton->setText(i18n("Stop"));
    resultLabel->setText(i18n("Ready"));
    disconnect( startButton, SIGNAL( clicked() ), this, SLOT( slotStart() ) );
    connect( startButton, SIGNAL( clicked() ), this, SLOT( slotStop() ) );
    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else
        clock->setTimeLeft(0);
    clock->start();
    displayOperation();
    update();
}

void KalculView::slotPause()
{
    if (paused) {
        pauseButton->setText(i18n("Pause"));
        clock->setPaused(false);
        answerLine->setEnabled(true);
        answerLine->setFocus();
        paused = false;
    } else {
        pauseButton->setText(i18n("Continue"));
        clock->setPaused(true);
        answerLine->setEnabled(false);
        paused = true;
    }
}

void KalculView::saveResults()
{
    KURL url;
    //save data in .kde/share/kalcul/userName.txt
    QString myString=QString("kalcul/%1.txt").arg(Settings::nameLine());
    QFile myFile;
    myFile.setName(locateLocal("data", myString));
    if (myFile.open(IO_WriteOnly | IO_Append))  {
        QTextStream textStream(&myFile);
        textStream << Settings::nameLine()<<",";
        //save date and time of the day
        textStream << QDate::currentDate().toString() << ",";
        textStream << QTime::currentTime().toString() << endl;
        //save test time, correct answers, total answers
        if (Settings::timerBool())  {
            int trueTime = Settings::time()*60-clock->timeLeft();
            textStream << trueTime << ","; 
        }
        else
            textStream << clock->timeLeft() << ","; //test duration in seconds
        textStream << correct << "," << total << endl;
        for (int i=0; i<Settings::numOp(); i++)
        {
            textStream<<questionString[i]<<",";
            textStream<< QString::number(correctAnswer[i])<<",";
            textStream<< QString::number(answerNum[i])<<endl;
        }
    myFile.close();
    }
}

void KalculView::slotStop()
{
    //stop the test
    reset();
    disconnect(startButton, SIGNAL(clicked()), this, SLOT(slotStop()));
}

00341 void KalculView::reset()
{
    clock->stop();

    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else 
        clock->setTimeLeft(0);
    total = 0;
    if (mode == Level) {
        kProgress1->setTotalSteps(levelNumberOfQuestions);
        kProgress2->setTotalSteps(levelNumberOfQuestions);
        kProgress1->setProgress(total);
        kProgress2->setProgress(total);
    } else {
        kProgress1->setTotalSteps(Settings::numOp());
        kProgress2->setTotalSteps(Settings::numOp());
        kProgress1->setProgress(total);
        kProgress2->setProgress(total);
    }
    correct = 0;
    questionLabel->setText(QString::null);
    resultLabel->setText(QString::null);
    startButton->setText(i18n("Start"));
    connect(startButton, SIGNAL(clicked()), this, SLOT(slotStart()));
    pauseButton->setEnabled(false);
    answerLine->clear();
    answerLine->setEnabled(false);
    emit signalChangeStatusbar(i18n("User: %1").arg(Settings::nameLine()) + ",  " +
                               i18n("Correct: %1").arg(QString::number(correct)) +
                               i18n(" Total: %1").arg(QString::number(total)));
}

00374 void KalculView::displayResultDialog()
{
    //TODO result dialog - SUCKS BIG TIME -  should be replaced with kdeedu own result dialog
    results *resultsDialog = new results(this);
    resultsDialog->resultsLabel->setText(i18n("You have %1 answers right out of %2").arg(correct).arg(total));
    for (int i=0; i < total; i++) {
        resultsDialog->questionLabel->setText(resultsDialog->questionLabel->text() + questionString[i] + " =  \n");
        resultsDialog->correctAnswerLabel->setText(resultsDialog->correctAnswerLabel->text() + QString::number(correctAnswer[i]) + "\n");
        resultsDialog->yourAnswerLabel->setText(resultsDialog->yourAnswerLabel->text() + i18n("Your answer: ") + QString::number(answerNum[i]) + "\n");
    }
    resultsDialog->adjustSize();
    resultsDialog->show();
}

#include "kalculview.moc"


Generated by  Doxygen 1.6.0   Back to index