afutrainer/dlglearnstatistic.cpp

418 lines
15 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 "dlglearnstatistic.h"
#include "chapter.h"
#include "tools.h"
#include "plotwidget.h"
#include <qdatetime.h>
CDlgLearnStatistic::CDlgLearnStatistic(QWidget *pParent) : QDialog(pParent)
{
m_pChapter = 0;
setupUi(this);
cbPeriod->addItem(tr("2 Wochen"), 14);
cbPeriod->addItem(tr("1 Monat"), 30);
cbPeriod->addItem(tr("3 Monate"), 90);
cbPeriod->addItem(tr("6 Monate"), 30*6);
cbPeriod->addItem(tr("1 Jahr"), 365);
cbPeriod->setCurrentIndex(0);
m_pPlotLevel = new CPlotWidget(groupLevel);
m_pPlotLevel->setFrameShape(QFrame::Panel);
m_pPlotLevel->setFrameShadow(QFrame::Sunken);
groupLevel->layout()->addWidget(m_pPlotLevel);
m_pPlotLevel->setBorderDistance(25, 5, 5, 25);
m_pPlotLevel->setLimitY(0.0, 5.5);
m_pPlotLevel->setBorderPen(QPen(Qt::black));
m_pPlotLevel->setBorder(CPlotWidget::BorderLeft | CPlotWidget::BorderBottom);
m_pPlotLevel->setTicY(1.0);
QList<CPlotWidgetTic> listTics;
for (int i=0; i<=LEVEL_MAX; i++)
{
CPlotWidgetTic tic (i, QPixmap(CQuestion::levelIconName(i)));
listTics.append(tic);
}
m_pPlotLevel->setTicListY(listTics);
m_pPlotClicked = new CPlotWidget(groupClicked);
m_pPlotClicked->setFrameShape(QFrame::Panel);
m_pPlotClicked->setFrameShadow(QFrame::Sunken);
groupClicked->layout()->addWidget(m_pPlotClicked);
m_pPlotClicked->setType(CPlotWidget::PlotBarsSum);
m_pPlotClicked->setBarOffset(-0.5);
m_pPlotClicked->setBorderDistance(25, 5, 5, 25);
// Zeitaufwand
cbPeriod2->addItem(tr("2 Wochen"), 14);
cbPeriod2->addItem(tr("1 Monat"), 30);
cbPeriod2->addItem(tr("3 Monate"), 90);
cbPeriod2->addItem(tr("6 Monate"), 30*6);
cbPeriod2->addItem(tr("1 Jahr"), 365);
cbPeriod2->setCurrentIndex(0);
m_pPlotTime = new CPlotWidget(groupTimeExpediture);
m_pPlotTime->setFrameShape(QFrame::Panel);
m_pPlotTime->setFrameShadow(QFrame::Sunken);
groupTimeExpediture->layout()->addWidget(m_pPlotTime);
m_pPlotTime->setType(CPlotWidget::PlotBarsSum);
m_pPlotTime->setBarOffset(-0.5);
m_pPlotTime->setBorderDistance(25, 5, 5, 25);
/*
m_pPlotTimePerQuestion = new CPlotWidget(groupTimeExpediturePerQuestion);
m_pPlotTimePerQuestion->setFrameShape(QFrame::Panel);
m_pPlotTimePerQuestion->setFrameShadow(QFrame::Sunken);
groupTimeExpediturePerQuestion->layout()->addWidget(m_pPlotTimePerQuestion);
m_pPlotTimePerQuestion->setType(CPlotWidget::PlotLines);
m_pPlotTimePerQuestion->setBorderDistance(25, 5, 5, 25);
*/
}
void CDlgLearnStatistic::go(CChapter *pChapter)
{
m_pChapter = pChapter;
updateTable();
updateHistory();
updateTimeExpediture();
exec();
}
void CDlgLearnStatistic::updateTable()
{
const int w=60, h=16;
QList<CQuestion*> listQuestion = m_pChapter->questionPool();
CDayStatistic ds;
// CHAPTER STATISTICS
labChapter->setText (m_pChapter->text());
labChapterCount->setText(QString("%1").arg(listQuestion.size()));
labChapterVeryOften->setText(QString("%1").arg(m_pChapter->countQuestion(0)));
labChapterOften->setText(QString("%1").arg(m_pChapter->countQuestion(1)));
labChapterNormal->setText(QString("%1").arg(m_pChapter->countQuestion(2)));
labChapterRare->setText(QString("%1").arg(m_pChapter->countQuestion(3)));
labChapterVeryRare->setText(QString("%1").arg(m_pChapter->countQuestion(4)));
labChapterExtremeRare->setText(QString("%1").arg(m_pChapter->countQuestion(5)));
labChapterAvgText->setText(m_pChapter->levelAvgText());
labChapterAvgIcon->setPixmap(m_pChapter->levelAvgPixmap());
labChapterAvgIcon->setToolTip(QString("Kennzahl: %1").arg(m_pChapter->levelAvg(), 4, 'g', 2));
double dQuestionCount = listQuestion.size(), dPercent=0.0;
dPercent = (double)m_pChapter->countQuestion(0)/dQuestionCount;
labChapterVeryOftenBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterVeryOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
dPercent = (double)m_pChapter->countQuestion(1)/dQuestionCount;
labChapterOftenBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
dPercent = (double)m_pChapter->countQuestion(2)/dQuestionCount;
labChapterNormalBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterNormalBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
dPercent = (double)m_pChapter->countQuestion(3)/dQuestionCount;
labChapterRareBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
dPercent = (double)m_pChapter->countQuestion(4)/dQuestionCount;
labChapterVeryRareBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterVeryRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
dPercent = (double)m_pChapter->countQuestion(5)/dQuestionCount;
labChapterExtremeRareBar->setPixmap(createProgressBar(w, h, dPercent));
labChapterExtremeRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
ds = m_pChapter->dayStatistic(QDate());
labClickCount->setText(QString::number(ds.clickedCount()));
labClickCorrect->setText(QString::number(ds.clickedCorrect()));
labClickWrong->setText(QString::number(ds.clickedWrong()));
labClickCorrectP->setText(ds.clickedCount() != 0 ? QString("%1 %").arg(100.0 * ds.clickedCorrect() / ds.clickedCount(), 0, 'f', 1) : "--");
labClickWrongP->setText(ds.clickedCount() != 0 ? QString("%1 %").arg(100.0 * ds.clickedWrong() / ds.clickedCount(), 0, 'f', 1) : "--");
labTimeExpediture->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpediture() / 3600000).arg(ds.timeExpediture() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpediture()/1000 % 60, 2, 10, QChar('0')));
labTimeExpeditureCorrect->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpeditureCorrect() / 3600000).arg(ds.timeExpeditureCorrect() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpeditureCorrect()/1000 % 60, 2, 10, QChar('0')));
labTimeExpeditureWrong->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpeditureWrong() / 3600000).arg(ds.timeExpeditureWrong() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpeditureWrong()/1000 % 60, 2, 10, QChar('0')));
labTimeExpeditureCorrectP->setText(ds.timeExpediture() != 0 ? QString("%1 %").arg(100.0 * ds.timeExpeditureCorrect() / ds.timeExpediture(), 0, 'f', 1) : "--");
labTimeExpeditureWrongP->setText(ds.timeExpediture() != 0 ? QString("%1 %").arg(100.0 * ds.timeExpeditureWrong() / ds.timeExpediture(), 0, 'f', 1) : "--");
labTimePerQuestion->setText(ds.clickedCount() != 0 ? QString("%2 m %3 s").arg(ds.timeExpediture() / ds.clickedCount() / 60000).arg(ds.timeExpediture() / 1000 / ds.clickedCount() % 60, 2, 10, QChar('0')) : "--");
labTimePerQuestionCorrect->setText(ds.clickedCorrect() != 0 ? QString("%2 m %3 s").arg(ds.timeExpeditureCorrect() / ds.clickedCorrect() / 60000).arg(ds.timeExpeditureCorrect() / 1000 / ds.clickedCorrect() % 60, 2, 10, QChar('0')) : "--");
labTimePerQuestionWrong->setText(ds.clickedWrong() != 0 ? QString("%2 m %3 s").arg(ds.timeExpeditureWrong() / ds.clickedWrong() / 60000).arg(ds.timeExpeditureWrong() / 1000 / ds.clickedWrong() % 60, 2, 10, QChar('0')) : "--");
}
void CDlgLearnStatistic::on_cbPeriod_currentIndexChanged(int index)
{
Q_UNUSED(index);
updateHistory();
}
void CDlgLearnStatistic::updateHistory()
{
int iDays = cbPeriod->itemData(cbPeriod->currentIndex()).toInt(), idx=0;
CPlotWidgetCurve curveLevel, curveClickedCorrect, curveClickedWrong;
QDate date = QDate::currentDate();
CDayStatistic ds;
QList<CPlotWidgetTic> listTics;
CPlotWidgetTic tic;
bool bAddTic=false;
unsigned uMaxClicked=0;
if (m_pChapter == 0) return;
setCursor(Qt::WaitCursor);
date = date.addDays(-iDays);
tic.setLineType(CPlotWidgetTic::LineNone);
tic.setFillType(CPlotWidgetTic::FillAll);
tic.setPen(QPen(Qt::darkGray));
while (date <= QDate::currentDate())
{
if (bAddTic)
{
bAddTic=false;
tic.setPos(idx-1);
if (listTics.size() % 2)
tic.setBrush(QBrush(Qt::white));
else
tic.setBrush(QBrush(QColor(232,232,232)));
listTics.append(tic);
}
ds = m_pChapter->dayStatistic(date);
curveLevel.append(CPlotWidgetPoint(idx, ds.level()));
curveClickedCorrect.append(CPlotWidgetPoint((double)idx, ds.clickedCorrect()));
curveClickedWrong.append(CPlotWidgetPoint((double)idx, ds.clickedWrong()));
if (ds.clickedCount() > uMaxClicked) uMaxClicked = ds.clickedCount();
date = date.addDays(1);
// X-Tics
if (iDays <= 14)
{ // daily tics
tic.setText(date.toString("ddd"));
tic.setWidth(1);
if (date.dayOfWeek() == Qt::Monday)
tic.setLineType(CPlotWidgetTic::LinePlot);
else
tic.setLineType(CPlotWidgetTic::LineNone);
bAddTic=true;
}
else if (iDays <= 90 && date.dayOfWeek() == Qt::Monday)
{
tic.setText(QString("KW %1").arg(date.weekNumber()));
tic.setWidth(7);
bAddTic=true;
}
else if (iDays > 90 && date.day() == 1)
{
tic.setText(date.toString("MMM"));
tic.setWidth(date.daysInMonth());
if (date.month() == 1)
tic.setLineType(CPlotWidgetTic::LinePlot);
else
tic.setLineType(CPlotWidgetTic::LineNone);
bAddTic=true;
}
idx++;
}
m_pPlotLevel->setTicListX(listTics);
m_pPlotClicked->setTicListX(listTics);
curveLevel.setPen(QPen(Qt::darkBlue));
curveClickedCorrect.setPen(QPen(Qt::green));
curveClickedCorrect.setBrush(QBrush(Qt::green));
curveClickedWrong.setPen(QPen(Qt::red));
curveClickedWrong.setBrush(QBrush(Qt::red));
m_pPlotLevel->clearCurves();
m_pPlotLevel->appendCurve(curveLevel);
m_pPlotLevel->update();
m_pPlotClicked->clearCurves();
m_pPlotClicked->appendCurve(curveClickedCorrect);
m_pPlotClicked->appendCurve(curveClickedWrong);
m_pPlotClicked->update();
unsigned uDiffBase[] = {1, 2, 5, 10}, uDiffMulti=1, uDiff=0, uDiffCount=0;
idx = 0;
do
{
if (idx == 4) { idx = 0; uDiffMulti*=10; }
uDiff = uDiffBase[idx] * uDiffMulti;
uDiffCount = (uMaxClicked / uDiff) + 1;
idx++;
}
while (uDiffCount > 9);
m_pPlotClicked->setLimitY(0, uDiffCount * uDiff + uDiff/2);
listTics.clear();
tic.clear();
tic.setTextFlags(Qt::AlignRight | Qt::AlignVCenter);
for (unsigned u=0; u<=uDiffCount * uDiff; u+=uDiff)
{
tic.setPos(u);
tic.setText(QString("%1").arg(u));
listTics.append(tic);
}
m_pPlotClicked->setTicListY(listTics);
setCursor(Qt::ArrowCursor);
}
void CDlgLearnStatistic::on_cbPeriod2_currentIndexChanged(int index)
{
Q_UNUSED(index);
updateTimeExpediture();
}
void CDlgLearnStatistic::updateTimeExpediture()
{
int iDays = cbPeriod2->itemData(cbPeriod2->currentIndex()).toInt(), idx=0;
CPlotWidgetCurve curveTimeWrong, curveTimeCorrect,curveTimePQWrong, curveTimePQCorrect; // PQ=per question
QDate date = QDate::currentDate();
CDayStatistic ds;
QList<CPlotWidgetTic> listTics;
CPlotWidgetTic tic;
bool bAddTic=false;
unsigned uMaxTime=0;
if (m_pChapter == 0) return;
setCursor(Qt::WaitCursor);
date = date.addDays(-iDays);
tic.setLineType(CPlotWidgetTic::LineNone);
tic.setFillType(CPlotWidgetTic::FillAll);
tic.setPen(QPen(Qt::darkGray));
while (date <= QDate::currentDate())
{
if (bAddTic)
{
bAddTic=false;
tic.setPos(idx-1);
if (listTics.size() % 2)
tic.setBrush(QBrush(Qt::white));
else
tic.setBrush(QBrush(QColor(232,232,232)));
listTics.append(tic);
}
ds = m_pChapter->dayStatistic(date);
curveTimeWrong.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureWrong()/1000.0/60.0));
curveTimeCorrect.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureCorrect()/1000.0/60.0));
/* if (ds.clickedWrong() > 0)
curveTimePQWrong.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureWrong()/1000.0/60.0/(double)ds.clickedWrong()));
else
curveTimePQWrong.append(CPlotWidgetPoint(idx, 0));
if (ds.clickedCorrect() > 0)
curveTimePQCorrect.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureCorrect()/1000.0/60.0/(double)ds.clickedCorrect()));
else
curveTimePQWrong.append(CPlotWidgetPoint(idx, 0));*/
if (ds.timeExpediture()/1000/60 > uMaxTime) uMaxTime = ds.timeExpediture()/1000/60;
date = date.addDays(1);
// X-Tics
if (iDays <= 14)
{ // daily tics
tic.setText(date.toString("ddd"));
tic.setWidth(1);
if (date.dayOfWeek() == Qt::Monday)
tic.setLineType(CPlotWidgetTic::LinePlot);
else
tic.setLineType(CPlotWidgetTic::LineNone);
bAddTic=true;
}
else if (iDays <= 90 && date.dayOfWeek() == Qt::Monday)
{
tic.setText(QString("KW %1").arg(date.weekNumber()));
tic.setWidth(7);
bAddTic=true;
}
else if (iDays > 90 && date.day() == 1)
{
tic.setText(date.toString("MMM"));
tic.setWidth(date.daysInMonth());
if (date.month() == 1)
tic.setLineType(CPlotWidgetTic::LinePlot);
else
tic.setLineType(CPlotWidgetTic::LineNone);
bAddTic=true;
}
idx++;
}
m_pPlotTime->setTicListX(listTics);
//m_pPlotTimePerQuestion->setTicListX(listTics);
curveTimeCorrect.setPen(QPen(Qt::green));
curveTimeCorrect.setBrush(QBrush(Qt::green));
curveTimeWrong.setPen(QPen(Qt::red));
curveTimeWrong.setBrush(QBrush(Qt::red));
m_pPlotTime->clearCurves();
m_pPlotTime->appendCurve(curveTimeCorrect);
m_pPlotTime->appendCurve(curveTimeWrong);
m_pPlotTime->update();
/*
m_pPlotTimePerQuestion->clearCurves();
m_pPlotTimePerQuestion->appendCurve(curveTimePQCorrect);
m_pPlotTimePerQuestion->appendCurve(curveTimePQWrong);
m_pPlotTimePerQuestion->setAutoLimitRoundY(0.1);
m_pPlotTimePerQuestion->update();
*/
unsigned uDiffBase[] = {1, 2, 5, 10}, uDiffMulti=1, uDiff=0, uDiffCount=0;
idx = 0;
do
{
if (idx == 4) { idx = 0; uDiffMulti*=10; }
uDiff = uDiffBase[idx] * uDiffMulti;
uDiffCount = (uMaxTime / uDiff) + 1;
idx++;
}
while (uDiffCount > 9);
m_pPlotTime->setLimitY(0, uDiffCount * uDiff + uDiff/2);
listTics.clear();
tic.clear();
tic.setTextFlags(Qt::AlignRight | Qt::AlignVCenter);
for (unsigned u=0; u<=uDiffCount * uDiff; u+=uDiff)
{
tic.setPos(u);
tic.setText(QString("%1").arg(u));
listTics.append(tic);
}
m_pPlotTime->setTicListY(listTics);
setCursor(Qt::ArrowCursor);
}