Class: JLDrill::Statistics
- Inherits:
-
Object
- Object
- JLDrill::Statistics
- Defined in:
- lib/jldrill/model/Quiz/Statistics.rb
Overview
Statistics for a quiz session
Constant Summary collapse
- MINIMUM_CONFIDENCE =
0.009
- SECONDS_PER_DAY =
60 * 60 * 24
Instance Attribute Summary collapse
-
#confidence ⇒ Object
readonly
Returns the value of attribute confidence.
-
#estimate ⇒ Object
readonly
Returns the value of attribute estimate.
-
#lastTen ⇒ Object
readonly
Returns the value of attribute lastTen.
-
#learned ⇒ Object
Returns the value of attribute learned.
-
#levels ⇒ Object
readonly
Returns the value of attribute levels.
-
#reviewed ⇒ Object
Returns the value of attribute reviewed.
-
#timesInTargetZone ⇒ Object
readonly
Returns the value of attribute timesInTargetZone.
Instance Method Summary collapse
-
#accuracy ⇒ Object
Returns the actual % accuracy of the quiz in an integer.
- #averageReviewRate ⇒ Object
-
#calculateConfidence(wasCorrect) ⇒ Object
Calculates a Bayesian estimate (I think!) of the confidence that the items seen to this point were known to an accuracy of at least 90%.
- #correct(item) ⇒ Object
- #correct=(value) ⇒ Object
- #currentReviewRate ⇒ Object
-
#getLevel(item) ⇒ Object
Get the appropriate LevelStat object for this item.
- #incorrect(item) ⇒ Object
- #incorrect=(value) ⇒ Object
-
#initialize(quiz, binNumber) ⇒ Statistics
constructor
A new instance of Statistics.
- #inTargetZone? ⇒ Boolean
- #learnPace ⇒ Object
- #learnTime ⇒ Object
- #learnTimePercent ⇒ Object
- #recentAccuracy ⇒ Object
-
#record(bool) ⇒ Object
Record a result.
- #recordReviewRate(item) ⇒ Object
-
#reEstimate ⇒ Object
Generates an estimate of the % accuracy in an integer.
- #resetConfidence ⇒ Object
- #reviewBin ⇒ Object
- #reviewPace ⇒ Object
- #reviewTime ⇒ Object
- #roundToOneDecimal(value) ⇒ Object
- #size ⇒ Object
- #startTimer(isReview) ⇒ Object
- #statsTable ⇒ Object
- #total ⇒ Object
Constructor Details
#initialize(quiz, binNumber) ⇒ Statistics
Returns a new instance of Statistics.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 21 def initialize(quiz, binNumber) @quiz = quiz @binNumber = binNumber @estimate = 0 @correct = 0 @incorrect = 0 @lastTen = [] @inTargetZone = false @timesInTargetZone = 0 @levels = [] 1.upto(8) do @levels.push(LevelStats.new) end @learned = 0 @reviewed = 0 @reviewRateSum = 0 @reviewTimer = Timer.new @learnTimer = Timer.new @currentTimer = nil resetConfidence end |
Instance Attribute Details
#confidence ⇒ Object (readonly)
Returns the value of attribute confidence.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def confidence @confidence end |
#estimate ⇒ Object (readonly)
Returns the value of attribute estimate.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def estimate @estimate end |
#lastTen ⇒ Object (readonly)
Returns the value of attribute lastTen.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def lastTen @lastTen end |
#learned ⇒ Object
Returns the value of attribute learned.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def learned @learned end |
#levels ⇒ Object (readonly)
Returns the value of attribute levels.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def levels @levels end |
#reviewed ⇒ Object
Returns the value of attribute reviewed.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def reviewed @reviewed end |
#timesInTargetZone ⇒ Object (readonly)
Returns the value of attribute timesInTargetZone.
13 14 15 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 13 def timesInTargetZone @timesInTargetZone end |
Instance Method Details
#accuracy ⇒ Object
Returns the actual % accuracy of the quiz in an integer
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 174 def accuracy retVal = 0 if @incorrect == 0 if @correct != 0 retVal = 100 end else retVal = ((@correct * 100) / total).to_i end retVal end |
#averageReviewRate ⇒ Object
105 106 107 108 109 110 111 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 105 def averageReviewRate retVal = 1.0 if @reviewed != 0 retVal = ((@reviewRateSum * 10).round / @reviewed).to_f / 10 end return retVal end |
#calculateConfidence(wasCorrect) ⇒ Object
Calculates a Bayesian estimate (I think!) of the confidence that the items seen to this point were known to an accuracy of at least 90%.
How this is calculated:
According to Bayes law, P(H|E) = P(E|H) * P(H) / P(E)
Where:
P(H|E) is the probability that the hypothesis is correct
given the evidence.
P(E|H) is the probability that the evididence would be
shown if the hypothesis were correct.
P(H) is the probability that the hypothesis is correct
given any evidence.
P(E) is the probability that the evidence would be seen
in all cases.
This value is calculated incrementally in the following fashion:
P[n] = P(E|H) * P[n-1] / P(E)
i.e., the nth value of P is dependent on the n-1th value of P
In our case, I will assume that the distribution of the
probabilities is uniform (probably wrong!) and say that
if we got the question right
P(E|H) = 0.95
that is, our probability of getting it right is
somewhere between 90 and 100%. I assume uniform
distribution, therefore the average is in the middle.
or if we got the question wrong
P(E|H) = 0.05
obviously, the probability of getting it wrong given
the hypothesis is 1 minus the probability of getting
it right.
P(E) = sum(probabilities for all the hypotheses)
= P(chance < 90) + P(chance is 90+%)
P(chance < 90) = 0.45(1 - P[n-1])
that is, it's equal to 1/2 the range between 0 and 90
times the probability that hypothesis is wrong.
P(chance > 90) = 0.95P[n-1]
that is, it's equal to 1/2 the range between 90 and 100
times the probability that the hypothesis is right.
So...
P(E) = 0.45(1 - P[n-1]) + 0.95P[n-1]
Giving a final answer of
P[n] = P(E|H) * P[n-1] / (0.45(1 - P[n-1]) + 0.95P[n-1])
I fully expect this is completely wrong due to my lack of
ability in math and statistics. But on the other hand, I won't
care much as long as appears from the user's point of view to
be working.
249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 249 def calculateConfidence(wasCorrect) if wasCorrect pEH = 0.95 else pEH = 0.05 end pE = (0.45 * (1.0 - @confidence)) + (0.95 * @confidence) @confidence = (pEH * @confidence) / pE if @confidence < MINIMUM_CONFIDENCE @confidence = MINIMUM_CONFIDENCE end end |
#correct(item) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 131 def correct(item) if item.bin != @binNumber return end @correct += 1 @reviewed += 1 recordReviewRate(item) level = getLevel(item) if !level.nil? level.correct end record(true) reEstimate calculateConfidence(true) end |
#correct=(value) ⇒ Object
163 164 165 166 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 163 def correct=(value) @correct = value reEstimate end |
#currentReviewRate ⇒ Object
113 114 115 116 117 118 119 120 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 113 def currentReviewRate retVal = 1.0 if size > 0 rate = reviewBin[0].schedule.reviewRate retVal = ((rate * 100).round).to_f / 100 end retVal end |
#getLevel(item) ⇒ Object
Get the appropriate LevelStat object for this item
89 90 91 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 89 def getLevel(item) return @levels[Counter.getLevel(item)] end |
#incorrect(item) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 147 def incorrect(item) if item.bin != @binNumber return end @incorrect += 1 @reviewed += 1 recordReviewRate(item) level = getLevel(item) if !level.nil? level.incorrect end record(false) reEstimate calculateConfidence(false) end |
#incorrect=(value) ⇒ Object
168 169 170 171 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 168 def incorrect=(value) @incorrect = value reEstimate end |
#inTargetZone? ⇒ Boolean
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 70 def inTargetZone? # Don't start the countdown until we have reviewed # at least 10 item. if @reviewed <= 10 return false end if !@inTargetZone if recentAccuracy >= 90 @inTargetZone = true end else if (recentAccuracy < 90) && (@confidence < 90) @inTargetZone = false end end return @inTargetZone end |
#learnPace ⇒ Object
293 294 295 296 297 298 299 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 293 def learnPace if @learned > 0 roundToOneDecimal(learnTime / @learned) else 0.0 end end |
#learnTime ⇒ Object
278 279 280 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 278 def learnTime @learnTimer.total end |
#learnTimePercent ⇒ Object
309 310 311 312 313 314 315 316 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 309 def learnTimePercent total = learnPace + reviewPace if total > 0 ((learnPace * 100) / total).to_i else 0 end end |
#recentAccuracy ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 57 def recentAccuracy retVal = 0 if @lastTen.size > 0 0.upto(@lastTen.size) do |i| if @lastTen[i] retVal += 1 end end retVal = (retVal * 100 / @lastTen.size).to_i end retVal end |
#record(bool) ⇒ Object
Record a result. True means that the item was guessed correctly, false means it was incorrect.
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 45 def record(bool) @lastTen.push(bool) while @lastTen.size > 10 @lastTen.delete_at(0) end if inTargetZone? @timesInTargetZone += 1 else @timesInTargetZone = 0 end end |
#recordReviewRate(item) ⇒ Object
93 94 95 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 93 def recordReviewRate(item) @reviewRateSum += item.schedule.reviewRate end |
#reEstimate ⇒ Object
Generates an estimate of the % accuracy in an integer
191 192 193 194 195 196 197 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 191 def reEstimate hop = ((recentAccuracy - @estimate) * 0.3).to_i retVal = @estimate + hop if (retVal > 100) then retVal = 100 end if (retVal < 0) then retVal = 0 end @estimate = retVal end |
#resetConfidence ⇒ Object
262 263 264 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 262 def resetConfidence @confidence = MINIMUM_CONFIDENCE end |
#reviewBin ⇒ Object
97 98 99 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 97 def reviewBin return @quiz.contents.bins[@binNumber] end |
#reviewPace ⇒ Object
301 302 303 304 305 306 307 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 301 def reviewPace if @reviewed > 0 roundToOneDecimal(reviewTime / @reviewed) else 0.0 end end |
#reviewTime ⇒ Object
282 283 284 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 282 def reviewTime @reviewTimer.total end |
#roundToOneDecimal(value) ⇒ Object
286 287 288 289 290 291 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 286 def roundToOneDecimal(value) value = value * 10.0 value = value.round value = value.to_f / 10.0 value end |
#size ⇒ Object
101 102 103 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 101 def size return reviewBin.length end |
#startTimer(isReview) ⇒ Object
266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 266 def startTimer(isReview) if !@currentTimer.nil? @currentTimer.stop end if isReview @currentTimer = @reviewTimer else @currentTimer = @learnTimer end @currentTimer.start end |
#statsTable ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 122 def statsTable dCounter = DurationCounter.new reviewBin.each do |item| dCounter.count(item) end return dCounter end |
#total ⇒ Object
186 187 188 |
# File 'lib/jldrill/model/Quiz/Statistics.rb', line 186 def total @correct + @incorrect end |