301 lines
8.2 KiB
C++
301 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ü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ü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ü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üfung leider nicht bestanden."));
|
|
}
|
|
else
|
|
{
|
|
bPassed = true;
|
|
labResult->setText(tr("<font color='green'>Bestanden</font>"));
|
|
QMessageBox::information(this, tr("Ergebnis"), tr("<b>Herzlichen Glückwunsch!</b><p>Sie haben die Prüfung bestanden!"));
|
|
}
|
|
|
|
if (bSaveStat)
|
|
{ // Prü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);
|
|
}
|
|
}
|