300 lines
8.2 KiB
C++
300 lines
8.2 KiB
C++
/***************************************************************************
|
||
* Copyright (C) 2003-2007 by Oliver Saal *
|
||
* osaal@gmx.de *
|
||
* http://www.oliver-saal.de/software/afutrainer/ *
|
||
* *
|
||
* 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., *
|
||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
***************************************************************************/
|
||
|
||
#include "dlgexam.h"
|
||
#include "question.h"
|
||
#include "error.h"
|
||
#include "catalog.h"
|
||
|
||
#include <qmessagebox.h>
|
||
|
||
CDlgExam::CDlgExam (CCatalog *pCatalog, QWidget *pParent) : QDialog (pParent, Qt::WindowMaximizeButtonHint)
|
||
{
|
||
m_pCatalog = pCatalog;
|
||
m_iCurrentQuestion = -1;
|
||
m_bIsFinished = false;
|
||
m_bTimeout = false;
|
||
setupUi(this);
|
||
connect (&m_timer, SIGNAL(timeout()), this, SLOT(onTimer()));
|
||
}
|
||
|
||
CDlgExam::~CDlgExam ()
|
||
{
|
||
}
|
||
|
||
bool CDlgExam::setup (const CExam& exam)
|
||
{
|
||
m_exam = exam;
|
||
labHeader->setText(exam.name());
|
||
|
||
try
|
||
{
|
||
m_listQuestion = exam.createQuestionPool(m_pCatalog->questionPool());
|
||
}
|
||
catch (CError e)
|
||
{
|
||
QMessageBox::critical(this, tr("Fehler"), e.toHtml());
|
||
return false;
|
||
}
|
||
|
||
m_listAnswerMask.clear();
|
||
while (m_listAnswerMask.size() < m_listQuestion.size())
|
||
m_listAnswerMask.append(0);
|
||
|
||
// Antworten bei Bedarf durchmischen
|
||
if (m_pCatalog->useMixedAnswers())
|
||
{
|
||
for (int i=0; i<m_listQuestion.size(); i++)
|
||
m_listQuestion.at(i)->mixAnswers();
|
||
}
|
||
init();
|
||
return true;
|
||
}
|
||
|
||
void CDlgExam::init()
|
||
{
|
||
// Zeitbalken & Zeit<69>berwachung
|
||
m_timer.setInterval(1000);
|
||
m_timer.start();
|
||
m_dtStart = QDateTime::currentDateTime();
|
||
pgTime->setMaximum (m_exam.duration() * 60);
|
||
|
||
// Sonstiges
|
||
pgQuestions->setMaximum (m_listQuestion.size());
|
||
m_bIsFinished = false;
|
||
m_bTimeout = false;
|
||
labMaxWrong->setText(QString("%1").arg(m_exam.maxErrorPoints()));
|
||
|
||
// Navigation
|
||
spinBox->setRange (1, m_listQuestion.size());
|
||
spinBox->setValue(1);
|
||
m_iCurrentQuestion = 1;
|
||
|
||
// Alles updaten
|
||
updateNavi();
|
||
showQuestion();
|
||
updateProgressTimer();
|
||
updateProgressQuestion();
|
||
}
|
||
|
||
void CDlgExam::onTimer()
|
||
{
|
||
updateProgressTimer();
|
||
}
|
||
|
||
void CDlgExam::updateNavi()
|
||
{
|
||
pbFirst->setEnabled (spinBox->value() > spinBox->minimum());
|
||
pbPrev->setEnabled (spinBox->value() > spinBox->minimum());
|
||
pbNext->setEnabled (spinBox->value() < spinBox->maximum());
|
||
pbLast->setEnabled (spinBox->value() < spinBox->maximum());
|
||
}
|
||
|
||
unsigned CDlgExam::answeredQuestionCount()
|
||
{
|
||
unsigned u=0;
|
||
for (int i=0; i<m_listAnswerMask.size(); i++)
|
||
{
|
||
if (m_listAnswerMask.at(i) != 0) u++;
|
||
}
|
||
return u;
|
||
}
|
||
|
||
void CDlgExam::updateProgressQuestion()
|
||
{
|
||
unsigned uAnswered = answeredQuestionCount();
|
||
labProgressQuestions->setText(tr("%1 von %2").arg(uAnswered).arg(m_listAnswerMask.size()));
|
||
pgQuestions->setValue(uAnswered);
|
||
}
|
||
|
||
void CDlgExam::updateProgressTimer()
|
||
{
|
||
QDateTime dt = QDateTime::currentDateTime();
|
||
unsigned uSecs = m_dtStart.secsTo(dt);
|
||
|
||
labProgessTime->setText(tr("Abgelaufene Zeit: %1:%2 min von %3:00 min")
|
||
.arg(uSecs / 60)
|
||
.arg(uSecs % 60, 2, 10, QChar('0'))
|
||
.arg(m_exam.duration()));
|
||
|
||
pgTime->setValue (uSecs);
|
||
|
||
if (uSecs > m_exam.duration()*60)
|
||
{
|
||
m_bTimeout = true;
|
||
m_timer.stop();
|
||
QMessageBox::information(this, tr("Information"), tr("Die Zeit ist abgelaufen.\nDie Pr<50>fung wird deswegen beendet."));
|
||
on_pbFinish_clicked();
|
||
}
|
||
}
|
||
|
||
void CDlgExam::on_pbFirst_clicked()
|
||
{
|
||
spinBox->setValue(1);
|
||
}
|
||
|
||
void CDlgExam::on_pbPrev_clicked()
|
||
{
|
||
int iNew = spinBox->value() - 1;
|
||
if (iNew < 1) iNew = 1;
|
||
spinBox->setValue(iNew);
|
||
}
|
||
|
||
void CDlgExam::on_pbNext_clicked()
|
||
{
|
||
int iNew = spinBox->value() + 1;
|
||
if (iNew > m_listQuestion.size()) iNew = m_listQuestion.size();
|
||
spinBox->setValue(iNew);
|
||
}
|
||
|
||
void CDlgExam::on_pbLast_clicked()
|
||
{
|
||
spinBox->setValue(m_listQuestion.size());
|
||
}
|
||
|
||
void CDlgExam::on_spinBox_valueChanged(int i)
|
||
{
|
||
Q_UNUSED(i);
|
||
onQuestionChanged();
|
||
}
|
||
|
||
void CDlgExam::saveCurrentAnswer()
|
||
{
|
||
unsigned uAnswerMask=0;
|
||
if (m_iCurrentQuestion >= 0)
|
||
{ // Antwort zur aktuellen Frage abspeichern
|
||
if (rbA->isChecked()) uAnswerMask |= 1;
|
||
if (rbB->isChecked()) uAnswerMask |= 2;
|
||
if (rbC->isChecked()) uAnswerMask |= 4;
|
||
if (rbD->isChecked()) uAnswerMask |= 8;
|
||
m_listAnswerMask[m_iCurrentQuestion] = uAnswerMask;
|
||
}
|
||
}
|
||
|
||
void CDlgExam::onQuestionChanged()
|
||
{
|
||
saveCurrentAnswer();
|
||
updateNavi();
|
||
updateProgressQuestion();
|
||
showQuestion(); // neue Frage anzeigen
|
||
}
|
||
|
||
void CDlgExam::showQuestion()
|
||
{
|
||
CQuestion *q=0;
|
||
unsigned uAnswerMask;
|
||
QString str;
|
||
|
||
m_iCurrentQuestion = spinBox->value()-1;
|
||
q = m_listQuestion.at(m_iCurrentQuestion);
|
||
uAnswerMask = m_listAnswerMask.at(m_iCurrentQuestion);
|
||
str = q->learnText(m_pCatalog, m_bIsFinished, false);
|
||
if (m_bIsFinished)
|
||
{
|
||
str += "<hr><p><b>";
|
||
if (!q->isCorrectAnswer(uAnswerMask))
|
||
str += "<font color='red'>";
|
||
else
|
||
str += "<font color='green'>";
|
||
|
||
str += q->correctionText(uAnswerMask) + "</font></p>";
|
||
}
|
||
textBrowser->setHtml(str);
|
||
|
||
rbA->setChecked(uAnswerMask & 1);
|
||
rbB->setChecked(uAnswerMask & 2);
|
||
rbC->setChecked(uAnswerMask & 4);
|
||
rbD->setChecked(uAnswerMask & 8);
|
||
rbNoIdea->setChecked(uAnswerMask == 0);
|
||
}
|
||
|
||
void CDlgExam::on_pbFinish_clicked()
|
||
{
|
||
unsigned uCorrect=0, uWrong=0, uAnsweredCount = answeredQuestionCount(), uErrorPoints=0;
|
||
bool bSaveStat=true, bPassed=false;
|
||
QDateTime dt = QDateTime::currentDateTime();
|
||
unsigned uSecs = m_dtStart.secsTo(dt);
|
||
|
||
saveCurrentAnswer();
|
||
if (uAnsweredCount < (unsigned)m_listQuestion.size() && !m_bTimeout)
|
||
{
|
||
if (QMessageBox::question (this,
|
||
tr("Sicherheitsabfrage"),
|
||
tr("Sie haben noch nicht alle Fragen beantwortet.\nWirklich abgeben?"),
|
||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) return;
|
||
}
|
||
|
||
m_timer.stop();
|
||
pbFinish->setEnabled(false);
|
||
rbA->setEnabled(false);
|
||
rbB->setEnabled(false);
|
||
rbC->setEnabled(false);
|
||
rbD->setEnabled(false);
|
||
rbNoIdea->setEnabled(false);
|
||
pbCancel->setText(tr("Beenden"));
|
||
m_bIsFinished = true;
|
||
showQuestion();
|
||
|
||
for (int i=0; i<m_listQuestion.size(); i++)
|
||
{
|
||
CQuestion *q = m_listQuestion.at(i);
|
||
unsigned uAnswerMask = m_listAnswerMask.at(i);
|
||
if (q->isCorrectAnswer(uAnswerMask))
|
||
uCorrect++;
|
||
else
|
||
{
|
||
uWrong++;
|
||
uErrorPoints+=q->errorPoints();
|
||
}
|
||
}
|
||
labCorrect->setText(QString("%1").arg(uCorrect));
|
||
labWrong->setText(QString("%1").arg(uWrong));
|
||
|
||
if (uAnsweredCount < (unsigned)m_listQuestion.size()/2)
|
||
{
|
||
bPassed = false;
|
||
bSaveStat = false;
|
||
labResult->setText(tr("Ohne Wertung\n(Nicht bestanden)"));
|
||
QMessageBox::information(this, tr("Information"), tr("Sie haben weniger als die H<>lfte aller Fragen beantwortet.\nDiese Pr<50>fung wird deswegen nicht gewertet."));
|
||
}
|
||
else if (uErrorPoints > m_exam.maxErrorPoints())
|
||
{
|
||
bPassed = false;
|
||
labResult->setText(tr("<font color='red'>Nicht bestanden</font>"));
|
||
QMessageBox::information(this, tr("Ergebnis"), tr("Sie haben die Pr<50>fung leider nicht bestanden."));
|
||
}
|
||
else
|
||
{
|
||
bPassed = true;
|
||
labResult->setText(tr("<font color='green'>Bestanden</font>"));
|
||
QMessageBox::information(this, tr("Ergebnis"), tr("<b>Herzlichen Gl<47>ckwunsch!</b><p>Sie haben die Pr<50>fung bestanden!"));
|
||
}
|
||
|
||
if (bSaveStat)
|
||
{ // Pr<50>fungsstatistik speichern
|
||
CExamStat es(m_exam);
|
||
es.setSecs(uSecs);
|
||
es.setQuestions(m_listQuestion, m_listAnswerMask);
|
||
es.setResult(uCorrect, uWrong, uErrorPoints, bPassed);
|
||
m_pCatalog->appendExamStat(es);
|
||
m_pCatalog->saveStatistic(this);
|
||
}
|
||
}
|