1 /***************************************************************************
2 * ktouchstatistics.cpp *
3 * -------------------- *
4 * Copyright (C) 2000 by Håvard Frøiland, 2004 by Andreas Nicolai *
5 * ghorwin@users.sourceforge.net *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 ***************************************************************************/
13 #include "ktouchstatistics.h"
14 #include "ktouchstatistics.moc"
16 #include <qlcdnumber.h>
19 #include <qprogressbar.h>
20 #include <qradiobutton.h>
21 #include <qbuttongroup.h>
24 #include <kpushbutton.h>
25 #include <kmessagebox.h>
29 #include <utility> // for std::min and std::max
31 #include "ktouchtrainer.h"
32 #include "ktouchchartwidget.h"
36 KTouchStatistics::KTouchStatistics(QWidget
*parent
, KTouchTrainer
* trainer
)
37 : KTouchStatisticsLayout(parent
), m_trainer(trainer
)
39 sessionCountSlider
->setMaxValue(m_trainer
->m_sessionHistory
.count());
40 sessionCountSlider
->setValue(m_trainer
->m_sessionHistory
.count());
41 chartWidget
->m_trainer
= trainer
;
42 chartWidget
->setChartType( KTouchChartWidget::CharsPerMinute
);
43 connect(closeButton
, SIGNAL(clicked()), this, SLOT(accept()) );
44 connect(clearButton
, SIGNAL(clicked()), this, SLOT(clearHistory()) );
45 connect(sessionCountSlider
, SIGNAL(valueChanged(int)), this, SLOT(updateAverageTab()) );
46 connect(chartTypeButtonGroup
, SIGNAL(clicked(int)), this, SLOT(updateChartTab()) );
49 KTouchStatistics::~KTouchStatistics() {
52 void KTouchStatistics::showEvent(QShowEvent
*) {
53 // adjust slider range in case some sessions have been added
54 sessionCountSlider
->setMaxValue(m_trainer
->m_sessionHistory
.count());
61 void KTouchStatistics::updateCurrentTab() {
62 // general stats group
63 elapsedTimeLCD
->display(static_cast<int>(m_trainer
->m_session
.m_elapsedTime
/1000));
64 totalCharsLCD
->display(static_cast<int>(m_trainer
->m_session
.m_totalChars
) );
65 wrongCharsLCD
->display(static_cast<int>(m_trainer
->m_session
.m_totalChars
-m_trainer
->m_session
.m_correctChars
) );
66 wordsLCD
->display(static_cast<int>(m_trainer
->m_session
.m_words
) );
68 charSpeedLCD
->display(static_cast<int>(m_trainer
->m_session
.charSpeed()) );
69 wordSpeedLCD
->display(static_cast<int>(m_trainer
->m_session
.wordSpeed()) );
71 correctnessBar
->setProgress(static_cast<int>(m_trainer
->m_session
.correctness()*100) );
72 // worst miss/hit ratio group
73 std::list
<KTouchCharStats
> charList( m_trainer
->m_session
.sortedCharStats() );
74 std::list
<KTouchCharStats
>::const_iterator it
=charList
.begin();
76 for (; i
<8 && it
!=charList
.end(); ++i
, ++it
) {
77 if (it
->hitMissRatio()==0)
78 break; // stop listing keys when their hit-miss-ration is zero
80 case 0 : charLabel1
->setText( it
->m_char
); charProgress1
->setEnabled(true);
81 charProgress1
->setProgress( it
->hitMissRatio() ); break;
82 case 1 : charLabel2
->setText( it
->m_char
); charProgress2
->setEnabled(true);
83 charProgress2
->setProgress( it
->hitMissRatio() ); break;
84 case 2 : charLabel3
->setText( it
->m_char
); charProgress3
->setEnabled(true);
85 charProgress3
->setProgress( it
->hitMissRatio() ); break;
86 case 3 : charLabel4
->setText( it
->m_char
); charProgress4
->setEnabled(true);
87 charProgress4
->setProgress( it
->hitMissRatio() ); break;
88 case 4 : charLabel5
->setText( it
->m_char
); charProgress5
->setEnabled(true);
89 charProgress5
->setProgress( it
->hitMissRatio() ); break;
90 case 5 : charLabel6
->setText( it
->m_char
); charProgress6
->setEnabled(true);
91 charProgress6
->setProgress( it
->hitMissRatio() ); break;
92 case 6 : charLabel7
->setText( it
->m_char
); charProgress7
->setEnabled(true);
93 charProgress7
->setProgress( it
->hitMissRatio() ); break;
94 case 7 : charLabel8
->setText( it
->m_char
); charProgress8
->setEnabled(true);
95 charProgress8
->setProgress( it
->hitMissRatio() ); break;
100 case 0 : charLabel1
->setText(" "); charProgress1
->setProgress(0); charProgress1
->setEnabled(false); break;
101 case 1 : charLabel2
->setText(" "); charProgress2
->setProgress(0); charProgress2
->setEnabled(false); break;
102 case 2 : charLabel3
->setText(" "); charProgress3
->setProgress(0); charProgress3
->setEnabled(false); break;
103 case 3 : charLabel4
->setText(" "); charProgress4
->setProgress(0); charProgress4
->setEnabled(false); break;
104 case 4 : charLabel5
->setText(" "); charProgress5
->setProgress(0); charProgress5
->setEnabled(false); break;
105 case 5 : charLabel6
->setText(" "); charProgress6
->setProgress(0); charProgress6
->setEnabled(false); break;
106 case 6 : charLabel7
->setText(" "); charProgress7
->setProgress(0); charProgress7
->setEnabled(false); break;
107 case 7 : charLabel8
->setText(" "); charProgress8
->setProgress(0); charProgress8
->setEnabled(false); break;
112 void KTouchStatistics::updateChartTab() {
113 if (m_trainer
->m_sessionHistory
.size()<2) {
114 chartTypeButtonGroup
->setEnabled(false);
115 chartWidget
->setEraseColor( Qt::gray
);
118 chartTypeButtonGroup
->setEnabled(true);
119 chartWidget
->setEraseColor( Qt::white
);
121 if (charSpeedButton
->isChecked())
122 chartWidget
->setChartType( KTouchChartWidget::CharsPerMinute
);
123 else if (wordSpeedButton
->isChecked())
124 chartWidget
->setChartType( KTouchChartWidget::WordsPerMinute
);
125 else if (accuracyButton
->isChecked())
126 chartWidget
->setChartType( KTouchChartWidget::Accuracy
);
127 else if (timeButton
->isChecked())
128 chartWidget
->setChartType( KTouchChartWidget::ElapsedTime
);
131 void KTouchStatistics::clearHistory() {
132 if (KMessageBox::questionYesNo(0, i18n("Do you really want to clear the session history?"))==KMessageBox::Yes
) {
133 sessionCountSlider
->setValue(0);
134 sessionCountSlider
->setMaxValue(0);
135 m_trainer
->m_sessionHistory
.clear();
141 void KTouchStatistics::updateAverageTab() {
142 if (sessionCountSlider
->value()==0)
143 sessionCountLabel
->setText( i18n("training session.") );
145 sessionCountLabel
->setText( i18n("%1 training sessions.").arg(sessionCountSlider
->value()+1));
146 KTouchTrainingSession sessionSum
=m_trainer
->m_session
;
147 KTouchTrainingSession sessionMin
=m_trainer
->m_session
;
148 KTouchTrainingSession sessionMax
=m_trainer
->m_session
;
149 double charSpeedSum
, charSpeedMin
, charSpeedMax
;
150 charSpeedSum
=charSpeedMin
=charSpeedMax
=m_trainer
->m_session
.charSpeed();
151 double wordSpeedSum
, wordSpeedMin
, wordSpeedMax
;
152 wordSpeedSum
=wordSpeedMin
=wordSpeedMax
=m_trainer
->m_session
.wordSpeed();
153 double correctnessSum
, correctnessMin
, correctnessMax
;
154 correctnessSum
=correctnessMin
=correctnessMax
=m_trainer
->m_session
.correctness();
155 std::set
<KTouchCharStats
> charStatsSum
= m_trainer
->m_session
.m_charStats
;
156 unsigned int lastSession
=m_trainer
->m_sessionHistory
.size()-1;
157 for (int i
=0; i
<sessionCountSlider
->value(); ++i
) {
158 const KTouchTrainingSession
&session
= m_trainer
->m_sessionHistory
[lastSession
-i
];
159 unsigned int elapsedTime
= session
.m_elapsedTime
;
160 unsigned int totalChars
= session
.m_totalChars
;
161 unsigned int correctChars
= session
.m_correctChars
;
162 unsigned int words
= session
.m_words
;
163 double charSpeed
= session
.charSpeed();
164 double wordSpeed
= session
.wordSpeed();
165 double correctness
= session
.correctness();
166 sessionSum
.m_elapsedTime
+= elapsedTime
;
167 sessionMin
.m_elapsedTime
= std::min(elapsedTime
, sessionMin
.m_elapsedTime
);
168 sessionMax
.m_elapsedTime
= std::max(elapsedTime
, sessionMax
.m_elapsedTime
);
169 sessionSum
.m_totalChars
+= totalChars
;
170 sessionMin
.m_totalChars
= std::min(totalChars
, sessionMin
.m_totalChars
);
171 sessionMax
.m_totalChars
= std::max(totalChars
, sessionMax
.m_totalChars
);
172 sessionSum
.m_correctChars
+= correctChars
;
173 sessionMin
.m_correctChars
= std::min(correctChars
, sessionMin
.m_correctChars
);
174 sessionMax
.m_correctChars
= std::max(correctChars
, sessionMax
.m_correctChars
);
175 sessionSum
.m_words
+= words
;
176 sessionMin
.m_words
= std::min(words
, sessionMin
.m_words
);
177 sessionMax
.m_words
= std::max(words
, sessionMax
.m_words
);
178 // sum up and store min/max of calculated stats
179 charSpeedSum
+= charSpeed
;
180 charSpeedMin
= std::min(charSpeed
, charSpeedMin
);
181 charSpeedMax
= std::max(charSpeed
, charSpeedMax
);
182 wordSpeedSum
+= wordSpeed
;
183 wordSpeedMin
= std::min(wordSpeed
, wordSpeedMin
);
184 wordSpeedMax
= std::max(wordSpeed
, wordSpeedMax
);
185 correctnessSum
+= correctness
;
186 correctnessMin
= std::min(correctness
, correctnessMin
);
187 correctnessMax
= std::max(correctness
, correctnessMax
);
188 // store character stats
189 for (set
<KTouchCharStats
>::iterator srcIt
= session
.m_charStats
.begin(); srcIt
!= session
.m_charStats
.end(); ++srcIt
) {
190 set
<KTouchCharStats
>::iterator it
= charStatsSum
.find( KTouchCharStats(srcIt
->m_char
,0,0) );
191 if (it
==charStatsSum
.end())
192 charStatsSum
.insert( *srcIt
);
194 const_cast<KTouchCharStats
&>(*it
).m_correctCount
+= srcIt
->m_correctCount
;
195 const_cast<KTouchCharStats
&>(*it
).m_wrongCount
+= srcIt
->m_wrongCount
;
199 // calculate averaged values
200 if (sessionCountSlider
->value() > 0) {
201 unsigned int sessionCount
= sessionCountSlider
->value()+1;
202 // now calculate the average numbers
203 sessionSum
.m_elapsedTime
/= sessionCount
;
204 sessionSum
.m_totalChars
/= sessionCount
;
205 sessionSum
.m_correctChars
/= sessionCount
;
206 sessionSum
.m_words
/= sessionCount
;
207 charSpeedSum
/= sessionCount
;
208 wordSpeedSum
/= sessionCount
;
209 correctnessSum
/= sessionCount
;
211 // sort char stats (worst hit-miss-ratio first in list)
212 list
<KTouchCharStats
> charStatsList(charStatsSum
.begin(), charStatsSum
.end());
213 charStatsList
.sort( greaterHitMissRatio
);
216 charSpeedAverageLCD
->display(static_cast<int>(charSpeedSum
) );
217 charSpeedMinLCD
->display(static_cast<int>(charSpeedMin
) );
218 charSpeedMaxLCD
->display(static_cast<int>(charSpeedMax
) );
219 wordSpeedAverageLCD
->display(static_cast<int>(wordSpeedSum
) );
220 wordSpeedMinLCD
->display(static_cast<int>(wordSpeedMin
) );
221 wordSpeedMaxLCD
->display(static_cast<int>(wordSpeedMax
) );
222 correctnessAverageBar
->setProgress(static_cast<int>(correctnessSum
*100) );
223 correctnessMinLCD
->display(static_cast<int>(correctnessMin
*100) );
224 correctnessMaxLCD
->display(static_cast<int>(correctnessMax
*100) );
225 // update the focus characters
226 list
<KTouchCharStats
>::const_iterator it
=charStatsList
.begin();
228 for (; i
<6 && it
!=charStatsList
.end(); ++i
, ++it
) {
229 if (it
->hitMissRatio()==0)
230 break; // stop listing keys when their hit-miss-ration is zero
232 case 0 : charLabel1_2
->setText( it
->m_char
); charProgress1_2
->setEnabled(true);
233 charProgress1_2
->setProgress( it
->hitMissRatio() ); break;
234 case 1 : charLabel2_2
->setText( it
->m_char
); charProgress2_2
->setEnabled(true);
235 charProgress2_2
->setProgress( it
->hitMissRatio() ); break;
236 case 2 : charLabel3_2
->setText( it
->m_char
); charProgress3_2
->setEnabled(true);
237 charProgress3_2
->setProgress( it
->hitMissRatio() ); break;
238 case 3 : charLabel4_2
->setText( it
->m_char
); charProgress4_2
->setEnabled(true);
239 charProgress4_2
->setProgress( it
->hitMissRatio() ); break;
240 case 4 : charLabel5_2
->setText( it
->m_char
); charProgress5_2
->setEnabled(true);
241 charProgress5_2
->setProgress( it
->hitMissRatio() ); break;
242 case 5 : charLabel6_2
->setText( it
->m_char
); charProgress6_2
->setEnabled(true);
243 charProgress6_2
->setProgress( it
->hitMissRatio() ); break;
248 case 0 : charLabel1_2
->setText(" "); charProgress1_2
->setProgress(0); charProgress1_2
->setEnabled(false); break;
249 case 1 : charLabel2_2
->setText(" "); charProgress2_2
->setProgress(0); charProgress2_2
->setEnabled(false); break;
250 case 2 : charLabel3_2
->setText(" "); charProgress3_2
->setProgress(0); charProgress3_2
->setEnabled(false); break;
251 case 3 : charLabel4_2
->setText(" "); charProgress4_2
->setProgress(0); charProgress4_2
->setEnabled(false); break;
252 case 4 : charLabel5_2
->setText(" "); charProgress5_2
->setProgress(0); charProgress5_2
->setEnabled(false); break;
253 case 5 : charLabel6_2
->setText(" "); charProgress6_2
->setProgress(0); charProgress6_2
->setEnabled(false); break;