001 /* PAVLOV -- Multiple Choice Study System
002 * Copyright (C) 2000 - 2004 T.J. Willis
003 *
004 * This program is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU General Public License
006 * as published by the Free Software Foundation; either version 2
007 * of the License, or (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program; if not, write to the Free Software
016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
017 *
018 * $Header: /cvsroot/pavlov/net/sourceforge/pavlov/user/ChapterStatistics.java,v 1.5 2004/06/03 03:18:23 tj_willis Exp $
019 */
020 package net.sourceforge.pavlov.user;
021
022 import java.io.*;
023 import org.apache.log4j.*;
024
025 /**
026 * Statistics which describle all quizzes a user has taken in a given
027 * chapter.
028 *
029 * @author <a href="mailto:tj_willis@users.sourceforge.net"> T.J. Willis </a>
030 * @version 1.0
031 */
032 public class ChapterStatistics
033 implements Serializable
034 {
035 // unit coverage in TestQuiz.java
036 /**
037 * Number of questions in the chapter.
038 *
039 */
040 public int nQuestions; // # questions
041 /**
042 * Number of questions in the chapter that have been answered.
043 *
044 */
045 public int nAnswered; // #questions answered at least once
046 /**
047 * Number of questions answered correctly at least once.
048 *
049 */
050 public int nOnceRights; // #questions answered right at least once
051 /**
052 * Number of questions answered only wrong.
053 *
054 */
055 public int nOnlyWrongs; // #questions answered, but never right
056 /**
057 * Total number of answers.
058 *
059 */
060 public int totAnswers; // sum of each questions nrights+nwrongs
061 /**
062 * Total number of right answers.
063 *
064 */
065 public int totRights; // sum of each question's nrights
066
067 /**
068 * Percentage of questions answered right at least once divided by number of questions in chapter.
069 *
070 */
071 public double rightsVersusNumberOfQuestions;
072 /**
073 * Percentage of questions answered at least once, but with no correct answers divided by number of questions in the chapter.
074 *
075 */
076 public double onlyWrongsVersusNumberOfQuestions;
077 /**
078 * Percentage of right answers.
079 *
080 */
081 public double rightsVersusNumberOfAnswers;
082 /**
083 * Percentage of questions that have been answered.
084 *
085 */
086 public double frequency; // nanswered vs. nquestions
087
088 //public long duration; time in mS from first question answered to now
089 /**
090 * Creates a new <code>ChapterStatistics</code> instance.
091 *
092 */
093 public ChapterStatistics() {
094 nQuestions = 0;
095 nAnswered = 0;
096
097 nOnceRights = 0;
098 nOnlyWrongs = 0;
099
100 totRights = 0;
101
102 rightsVersusNumberOfQuestions = 0.0;
103 rightsVersusNumberOfAnswers = 0.0;
104
105 frequency = 0.0;
106 }
107 /**
108 * Creates a new <code>ChapterStatistics</code> instance.
109 *
110 * @param nQs Number of questions.
111 * @param totAs Total number of answers.
112 * @param nAns Number of questions answered at least once.
113 * @param c Number of questions answered correctly at least once.
114 * @param d Total number of correct answers.
115 * @param e Number of questions answered only incorrectly.
116 */
117 public ChapterStatistics(int nQs, int totAs, int nAns, int c, int d, int e) {
118 nQuestions = nQs; // # questions
119 totAnswers = totAs;
120 nAnswered = nAns;
121 nOnceRights = c; //# of questions answered right at least onc
122 totRights = d; // sum of each question's nrights
123 nOnlyWrongs = e;
124 recalc();
125 }
126
127 /**
128 * Number of right answers as percentage of number of total answers.
129 *
130 * @return a <code>double</code> value
131 */
132 public double getPercentageOfRightAnswers() {
133 return (1.0 * totRights) / (1.0 * totAnswers);
134 }
135
136 /**
137 * Number of wrong answers as percentage of number of total answers.
138 *
139 * @return a <code>double</code> value
140 */
141 public double getPercentageOfWrongAnswers() {
142 return (1.0 * (totAnswers - totRights)) / (1.0 * totAnswers);
143 }
144
145 /**
146 * Percentage of questions in the chapter that have been answered at least once.
147 *
148 * @return a <code>double</code> value
149 */
150 public double getPercentOfQuestionsAnsweredAtLeastOnce() {
151 return (1.0 * nAnswered) / (1.0 * nQuestions);
152 }
153
154 /**
155 * Number of wrong answers over all quizzes for this user on this chapter.
156 *
157 * @return an <code>int</code> value
158 */
159 public int getTotalNumberOfWrongAnswers() {
160 return totAnswers - totRights;
161 }
162
163 /**
164 * Percentage of questions that have been answered correctly at least once.
165 *
166 * @return a <code>double</code> value
167 */
168 public double getPercentOfQuestionsAnsweredRightAtLeastOnce() {
169 return ((1.0 * nOnceRights) / (1.0 * nQuestions));
170 }
171
172 /**
173 * Percentage of questions that have been answered at least once, but never correctly.
174 *
175 * @return a <code>double</code> value
176 */
177 public double getPercentOfQuestionsOnlyAnsweredWrong() {
178 return ((1.0 * nOnlyWrongs) / (1.0 * nQuestions));
179 }
180
181 /**
182 * Number of questions in the chapter that the user has never answered.
183 *
184 * @return an <code>int</code> value
185 */
186 public int getNumberNeverAnswered() {
187 return nQuestions - nOnceRights - nOnlyWrongs;
188 }
189
190 /**
191 * Percentage of questions in the chapter that the user has never answered.
192 *
193 * @return a <code>double</code> value
194 */
195 public double getPercentNeverAnswered() {
196 return (1.0 * getNumberNeverAnswered()) / (1.0 * nQuestions);
197 }
198
199
200 /**
201 * Recalculares derived statistics from basic statistics.
202 *
203 */
204 public void recalc() {
205 frequency = (1.0) * nAnswered / (1.0) * nQuestions;
206 rightsVersusNumberOfAnswers = (1.0) * totRights / (1.0) * nAnswered;
207 rightsVersusNumberOfQuestions = (1.0) * nOnceRights / (1.0) * nQuestions;
208 onlyWrongsVersusNumberOfQuestions = (1.0) * nOnlyWrongs / (1.0) * nQuestions;
209 }
210
211 /**
212 * Uses a nifty trick from "Design Patterns in Java" to make a
213 * completely independent copy of this chapter. Useful in chapter
214 * editors.
215 *
216 * @return a <code>ChapterStatistics</code> value
217 */
218 public ChapterStatistics deepCopy()
219 {
220 try {
221 ByteArrayOutputStream b = new ByteArrayOutputStream();
222 ObjectOutputStream out = new ObjectOutputStream(b);
223 out.writeObject(this);
224 ByteArrayInputStream bIn = new ByteArrayInputStream(b.toByteArray());
225 ObjectInputStream oi = new ObjectInputStream(bIn);
226 return ( (ChapterStatistics)oi.readObject());
227 } catch (IOException e) {
228 System.out.println("exception: " + e);
229 return null;
230 } catch (ClassNotFoundException e1){
231 System.out.println("exception: " + e1);
232 return null;
233 }
234 }
235
236
237 /**
238 * Call when the question has been answered correctly.
239 *
240 * @param q a <code>QuestionData</code> value
241 */
242 public void addRight(QuestionData q) {
243 totAnswers++; // 4 dec 02
244 if (q.getRight() + q.getWrong() == 1)
245 nAnswered++;
246
247 if (q.getRight() == 1) {
248 nOnceRights++;
249 if(q.getWrong()>0) nOnlyWrongs--; // 26 jan 04
250 }
251 totRights++;
252 recalc();
253 }
254
255 /**
256 * Call when the question has been answered incorrectly.
257 *
258 * @param q a <code>QuestionData</code> value
259 */
260 public void addWrong(QuestionData q) {
261 totAnswers++; // 4 dec 02
262 if (q.getRight() + q.getWrong() == 1)
263 nAnswered++;
264 if ( (q.getRight() < 1) && (q.getWrong() ==1) ) {
265 nOnlyWrongs++;
266 }
267 recalc();
268 }
269
270 // will break if you add qd for the same question multiple times
271 /**
272 * Add a question to the ChapterStatistics. Only add a question once!
273 *
274 * @param qd a <code>QuestionData</code> value
275 */
276 public void addQuestionData(QuestionData qd) {
277 nQuestions++;
278 if (qd.getRight() + qd.getWrong() > 0)nAnswered++;
279 if (qd.getRight() > 0) nOnceRights++;
280 else if (qd.getWrong() > 0)nOnlyWrongs++;
281 totAnswers += qd.getRight() + qd.getWrong();
282 totRights += qd.getRight();
283 }
284
285 }