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    }