Skip to content
Snippets Groups Projects
texamsummary.cpp 8.82 KiB
Newer Older
/***************************************************************************
 *   Copyright (C) 2011-2021 by Tomasz Bojczuk                             *
 *   seelook@gmail.com                                                     *
 *                                                                         *
 *   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 3 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, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/

#include "texamsummary.h"
#include "dialogs/tlevelpreviewitem.h"
#include "texamexecutor.h"
#include "texamview.h"
#include <exam/tattempt.h>
#include <exam/texam.h>
#include <exam/textrans.h>
#include <exam/tlevel.h>
#include <exam/tqaunit.h>
#include <qtr.h>
#if defined(Q_OS_ANDROID)
#include <Android/tandroid.h>
#endif
#include <QtCore/qtimer.h>

#include <QtCore/qdebug.h>

inline QStringList getDelegate(const QString &label, float value, float wTotal)
{
    return QStringList() << label + QLatin1String(": ") << QString(" <b>%1</b> (%2\%)").arg(value).arg(qRound(value * 100.0 / wTotal));
inline QStringList timeDelegate(const QString &label, const QString &time)
{
    return QStringList() << label + QLatin1String(": ") << QString(" <b>%1</b>").arg(time);
TexamSummary::TexamSummary(QQuickItem *parent)
    : QQuickItem(parent)
    m_exam = EXECUTOR->exam();

    m_answersLabel << tr("Number of questions:") << QString(" <b>%1</b>").arg(m_exam->count()) << TexTrans::corrAnswersNrTxt()
                   << QString("<b>%1</b>").arg(m_exam->count() - m_exam->mistakes() - m_exam->halfMistaken()) << TexTrans::mistakesNrTxt() + QLatin1String(":")
                   << QString("<b>%1</b>").arg(m_exam->mistakes()) << TexTrans::halfMistakenTxt() + QLatin1String(":")
                   << QString("<b>%1</b>").arg(m_exam->halfMistaken());

    m_answersModel << m_exam->count() - m_exam->mistakes() - m_exam->halfMistaken();
    m_answersModel << m_exam->halfMistaken();
    m_answersModel << m_exam->mistakes();

    m_timesModel << timeDelegate(TexTrans::totalTimetxt(), TexamView::formatedTotalTime(m_exam->totalTime() * 1000));
    m_timesModel << timeDelegate(tr("Time taken to answer"), TexamView::formatedTotalTime(m_exam->workTime() * 1000));
    m_timesModel << timeDelegate(TexTrans::averAnsverTimeTxt(), QString("%1 s").arg(static_cast<qreal>(m_exam->averageReactonTime()) / 10.0, 0, 'f', 1, '0'));

    if (m_exam->mistakes() || m_exam->halfMistaken()) {
        float wAccid = 0.0f, wKey = 0.0f, wNote = 0.0f, wOctave = 0.0f, wStyle = 0.0f, wPos = 0.0f, wString = 0.0f, wTotal;
        float wInto = 0.0f, wLittle = 0.0f, wPoor = 0.0f, wRtm = 0.0f;
        for (int i = 0; i < m_exam->count(); ++i) {
            if (!m_exam->question(i)->isCorrect()) {
                if (m_exam->question(i)->wrongAccid())
                    wAccid++;
                if (m_exam->question(i)->wrongKey())
                    wKey++;
                if (m_exam->question(i)->wrongNote())
                    wNote++;
                if (m_exam->question(i)->wrongOctave())
                    wOctave++;
                if (m_exam->question(i)->wrongStyle())
                    wStyle++;
                if (m_exam->question(i)->wrongPos())
                    wPos++;
                if (m_exam->question(i)->wrongString())
                    wString++;
                if (m_exam->question(i)->wrongIntonation())
                    wInto++;
                if (m_exam->question(i)->littleNotes())
                    wLittle++;
                if (m_exam->question(i)->poorEffect())
                    wPoor++;
                if (m_exam->question(i)->wrongRhythm())
                    wRtm++;
            }
        }

        wTotal = wAccid + wKey + wNote + wOctave + wStyle + wPos + wString + wInto + wLittle + wPoor + wRtm;
        if (wNote) {
            m_resultsModel << getDelegate(tr("Wrong notes"), wNote, wTotal);
            m_kindOfMistakes << static_cast<int>(wNote);
        }
        if (wAccid) {
            m_resultsModel << getDelegate(tr("Wrong accidentals"), wAccid, wTotal);
            m_kindOfMistakes << static_cast<int>(wAccid);
        }
        if (wKey) {
            m_resultsModel << getDelegate(tr("Wrong key signatures"), wKey, wTotal);
            m_kindOfMistakes << static_cast<int>(wKey);
        }
        if (wOctave) {
            m_resultsModel << getDelegate(tr("Wrong octaves"), wOctave, wTotal);
            m_kindOfMistakes << static_cast<int>(wOctave);
        }
        if (wStyle) {
            m_resultsModel << getDelegate(tr("Wrong note names"), wStyle, wTotal);
            m_kindOfMistakes << static_cast<int>(wStyle);
        }
        if (wPos) {
            m_resultsModel << getDelegate(tr("Wrong positions on guitar"), wPos, wTotal);
            m_kindOfMistakes << static_cast<int>(wPos);
        }
        if (wString) {
            m_resultsModel << getDelegate(tr("Wrong strings"), wString, wTotal);
            m_kindOfMistakes << static_cast<int>(wString);
        }
        if (wInto) {
            m_resultsModel << getDelegate(tr("Out of tune"), wInto, wTotal);
            m_kindOfMistakes << static_cast<int>(wInto);
        }
        if (wRtm) {
            m_resultsModel << getDelegate(qTR("AnswerText", "incorrect rhythm"), wRtm, wTotal);
            m_kindOfMistakes << static_cast<int>(wRtm);
        }
        if (wLittle) {
            m_resultsModel << getDelegate(qTR("AnswerText", "little valid notes"), wLittle, wTotal);
            m_kindOfMistakes << static_cast<int>(wLittle);
        }
        if (wPoor) {
            m_resultsModel << getDelegate(qTR("AnswerText", "poor effectiveness"), wPoor, wTotal);
            m_kindOfMistakes << static_cast<int>(wPoor);
        }
    m_resultHeader = tr("Results:") + QLatin1String("<br>") + TexTrans::effectTxt() + QString(": <b>%1\%</b>").arg(qRound(m_exam->effectiveness()));
QString TexamSummary::title() const
{
    if (m_exam) {
        if (m_exam->isExercise())
            return tr("Progress of exercises");
        else
            return tr("Exam results");
    }
    return QString();
void TexamSummary::setLevelPreview(TlevelPreviewItem *lp)
{
    m_levelPreview = lp;
    m_levelPreview->setLevel(m_exam->level());
QString TexamSummary::student() const
{
    return tr("student:") + QString("<font size=\"5\"><b>  %1</b></font>").arg(m_exam->userName());
bool TexamSummary::isExercise() const
{
    return m_exam && m_exam->isExercise();
void TexamSummary::continueExecutor()
{
    m_accepted = true;
    if (m_exam->isExercise())
        EXECUTOR->continueExercise();
    else
        EXECUTOR->continueInit();
bool TexamSummary::hasQuestions() const
{
    return m_exam && m_exam->count() > 0;
void TexamSummary::exerciseToExam()
{
    m_accepted = true;
    EXECUTOR->restoreExerciseAfterSummary();
    EXECUTOR->exerciseToExam();
void TexamSummary::closeSummary()
{
    if (!m_accepted) {
        if (EXECUTOR->summaryReason() == TexamExecutor::SumFinishExer)
            QTimer::singleShot(10, [=] {
                EXECUTOR->finishExerciseAfterSummary();
            });
        else
            QTimer::singleShot(10, [=] {
                EXECUTOR->closeExecutor();
            });
    }
bool TexamSummary::discardedAtBegin() const
{
    return EXECUTOR->summaryReason() == TexamExecutor::SumContExam && !EXECUTOR->isInitialized();
bool TexamSummary::enableContinue() const
{
    return m_exam->isExercise() || !EXECUTOR->isInitialized();
int TexamSummary::buttColumsCount() const
{
    return (!enableContinue() && isExercise()) || (enableContinue() && !isExercise()) ? 3 : 2;
#if defined(Q_OS_ANDROID)
void TexamSummary::sendExam()
{
    QString space = QStringLiteral(" ");
    QString br = QStringLiteral("\n");
    QString message = qTR("TexamSummary", "student:") + space + m_exam->userName() + br;
    message += qTR("AnalyzeDialog", "level:") + space + m_exam->level()->name + br;
    message += tr("Number of questions:") + space + QString::number(m_exam->count()) + br;
    // Tandroid::sendExam(tr("Send exam file"), message, m_exam->fileName());