Class: JLDrill::Strategy
- Inherits:
-
Object
- Object
- JLDrill::Strategy
- Defined in:
- lib/jldrill/model/Quiz/Strategy.rb
Overview
Strategy for choosing, promoting and demoting items in the quiz.
Instance Attribute Summary collapse
-
#forgottenStats ⇒ Object
readonly
Returns the value of attribute forgottenStats.
-
#reviewStats ⇒ Object
readonly
Returns the value of attribute reviewStats.
Class Method Summary collapse
Instance Method Summary collapse
-
#contents ⇒ Object
Returns the contents for the quiz.
-
#correct(item) ⇒ Object
Mark the item as having been reviewed correctly.
-
#createProblem(item) ⇒ Object
Create a problem for the given item at the correct level.
-
#demote(item) ⇒ Object
Demote the item.
-
#findUnseen(binNum) ⇒ Object
Return the index of the first item in the bin that hasn’t been seen yet.
- #forgottenSet ⇒ Object
- #forgottenSetSize ⇒ Object
- #getForgottenItem ⇒ Object
-
#getItem ⇒ Object
Get an item to quiz.
-
#getNewItem ⇒ Object
Get an item from the New Set.
-
#getReviewItem ⇒ Object
Get an item from the Review Set.
-
#getWorkingItem ⇒ Object
Get an item from the Working Set.
-
#incorrect(item) ⇒ Object
Mark the item as having been reviewed incorrectly.
-
#initialize(quiz) ⇒ Strategy
constructor
A new instance of Strategy.
-
#learn(item) ⇒ Object
Promote the item from the working set into the review set without any further training.
- #newSet ⇒ Object
-
#options ⇒ Object
Returns the options for the quiz.
-
#promote(item) ⇒ Object
Promote the item to the next level/bin.
-
#randomUnseen(range) ⇒ Object
Returns a random unseen item.
-
#reschedule ⇒ Object
Sort the items according to their schedule.
- #reviewSet ⇒ Object
-
#reviewSetKnown? ⇒ Boolean
Returns true if the review set has been reviewed enough that it is considered to be known.
-
#reviewSetSize ⇒ Object
Returns the number of items in the review set.
-
#shouldReview? ⇒ Boolean
Returns true if at least one working set full of items have been promoted to the review set, and the review set is not known to the required level.
-
#status ⇒ Object
Returns a string showing the status of the quiz with this strategy.
- #workingSetEmpty? ⇒ Boolean
-
#workingSetFull? ⇒ Boolean
Returns true if the working set is not full.
-
#workingSetSize ⇒ Object
Returns the number of items in the working set.
Constructor Details
#initialize(quiz) ⇒ Strategy
Returns a new instance of Strategy.
12 13 14 15 16 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 12 def initialize(quiz) @quiz = quiz @reviewStats = Statistics.new(quiz, 4) @forgottenStats = Statistics.new(quiz, 5) end |
Instance Attribute Details
#forgottenStats ⇒ Object (readonly)
Returns the value of attribute forgottenStats.
10 11 12 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 10 def forgottenStats @forgottenStats end |
#reviewStats ⇒ Object (readonly)
Returns the value of attribute reviewStats.
10 11 12 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 10 def reviewStats @reviewStats end |
Class Method Details
.forgottenSetBin ⇒ Object
30 31 32 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 30 def Strategy.forgottenSetBin return 5 end |
.newSetBin ⇒ Object
18 19 20 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 18 def Strategy.newSetBin return 0 end |
.reviewSetBin ⇒ Object
26 27 28 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 26 def Strategy.reviewSetBin return 4 end |
.workingSetBins ⇒ Object
22 23 24 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 22 def Strategy.workingSetBins return 1..3 end |
Instance Method Details
#contents ⇒ Object
Returns the contents for the quiz
50 51 52 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 50 def contents @quiz.contents end |
#correct(item) ⇒ Object
Mark the item as having been reviewed correctly
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 300 def correct(item) @reviewStats.correct(item) @forgottenStats.correct(item) item.itemStats.correct if ((item.bin == Strategy.reviewSetBin) || (item.bin == Strategy.forgottenSetBin)) item.schedule.correct promote(item) else item.allCorrect if(item.schedule.score >= .promoteThresh) promote(item) end end end |
#createProblem(item) ⇒ Object
Create a problem for the given item at the correct level
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 247 def createProblem(item) item.itemStats.createProblem @reviewStats.startTimer(item.bin == Strategy.reviewSetBin) @forgottenStats.startTimer(item.bin == Strategy.forgottenSetBin) # Drill at the scheduled level in the review and forgotten sets if (item.bin == Strategy.reviewSetBin) || (item.bin == Strategy.forgottenSetBin) problem = item.problem else # Otherwise drill for the specific bin level = item.bin - 1 problem = ProblemFactory.create(level, item) end return problem end |
#demote(item) ⇒ Object
Demote the item
286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 286 def demote(item) if !item.nil? item.demoteAll if (item.bin != 0) contents.moveToBin(item, 1) else # Demoting bin 0 items is non-sensical, but it should do # something sensible anyway. contents.moveToBin(item, 0) end end end |
#findUnseen(binNum) ⇒ Object
Return the index of the first item in the bin that hasn’t been seen yet. If they have all been seen, reset the bin
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 161 def findUnseen(binNum) bin = contents.bins[binNum] if bin.empty? return -1 end if bin.allSeen? bin.setUnseen end bin.firstUnseen end |
#forgottenSet ⇒ Object
86 87 88 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 86 def forgottenSet @quiz.contents.bins[Strategy.forgottenSetBin] end |
#forgottenSetSize ⇒ Object
90 91 92 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 90 def forgottenSetSize forgottenSet.length end |
#getForgottenItem ⇒ Object
213 214 215 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 213 def getForgottenItem forgottenSet[0] end |
#getItem ⇒ Object
Get an item to quiz
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 223 def getItem item = nil if contents.empty? return nil end if !workingSetFull? if shouldReview? item = getReviewItem elsif !forgottenSet.empty? item = getForgottenItem elsif !newSet.empty? item = getNewItem end end # Usually we get a working item if the above is not true item = getWorkingItem if item.nil? item.allSeen(true) return item end |
#getNewItem ⇒ Object
Get an item from the New Set
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 190 def getNewItem if .randomOrder index = rand(newSet.length) else index = findUnseen(Strategy.newSetBin) end if !(index == -1) item = newSet[index] # Resetting the schedule to make up for the consequences # of an old bug where reset drills weren't reset properly. item.resetSchedules promote(item) item else nil end end |
#getReviewItem ⇒ Object
Get an item from the Review Set
209 210 211 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 209 def getReviewItem reviewSet[0] end |
#getWorkingItem ⇒ Object
Get an item from the Working Set
218 219 220 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 218 def getWorkingItem randomUnseen(Strategy.workingSetBins) end |
#incorrect(item) ⇒ Object
Mark the item as having been reviewed incorrectly
317 318 319 320 321 322 323 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 317 def incorrect(item) @reviewStats.incorrect(item) @forgottenStats.incorrect(item) item.allIncorrect item.itemStats.incorrect demote(item) end |
#learn(item) ⇒ Object
Promote the item from the working set into the review set without any further training. If it is already in the review set, simply mark it correct.
328 329 330 331 332 333 334 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 328 def learn(item) if item.bin <= 3 item.setScores(.promoteThresh) contents.moveToBin(item, 3) end correct(item) end |
#newSet ⇒ Object
59 60 61 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 59 def newSet @quiz.contents.bins[Strategy.newSetBin] end |
#options ⇒ Object
Returns the options for the quiz
55 56 57 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 55 def @quiz. end |
#promote(item) ⇒ Object
Promote the item to the next level/bin
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 264 def promote(item) if !item.nil? item.setScores(0) if item.bin < 3 item.setLevels(item.bin) contents.moveToBin(item, item.bin + 1) else if item.bin == 3 # Newly promoted items item.itemStats.consecutive = 1 @reviewStats.learned += 1 @forgottenStats.learned += 1 item.scheduleAll end # Put the item at the back of the bin contents.bins[item.bin].delete(item) reviewSet.push(item) end end end |
#randomUnseen(range) ⇒ Object
Returns a random unseen item. Return nil if the range is empty. Resets the seen status if all the items are already seen.
175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 175 def randomUnseen(range) if contents.rangeEmpty?(range) return nil end if contents.rangeAllSeen?(range) range.to_a.each do |bin| contents.bins[bin].setUnseen end end index = rand(contents.numUnseen(range)) item = contents.findUnseen(index, range) item end |
#reschedule ⇒ Object
Sort the items according to their schedule
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 95 def reschedule # Check for legacy files that may have Kanji # problems schedules but no kanji reviewSet.each do |x| x.removeInvalidKanjiProblems end # Sort the review set reviewSet.sort! do |x,y| x.schedule.reviewLoad <=> y.schedule.reviewLoad end # Move old items to the forgotten set while ((.forgettingThresh != 0.0) && (!reviewSet.empty?) && (reviewSet[0].schedule.reviewRate >= .forgettingThresh.to_f)) contents.moveToBin(reviewSet[0], Strategy.forgottenSetBin) end # Sort the forgotten set forgottenSet.sort! do |x,y| x.schedule.reviewLoad <=> y.schedule.reviewLoad end # If the user changes the settings then we may have to # unforget some items while ((!forgottenSet.empty?) && ((.forgettingThresh == 0.0) || (forgottenSet.last.schedule.reviewRate < .forgettingThresh.to_f))) contents.moveToBin(forgottenSet.last, Strategy.reviewSetBin) end # Sort the review set again reviewSet.sort! do |x,y| x.schedule.reviewLoad <=> y.schedule.reviewLoad end end |
#reviewSet ⇒ Object
77 78 79 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 77 def reviewSet @quiz.contents.bins[Strategy.reviewSetBin] end |
#reviewSetKnown? ⇒ Boolean
Returns true if the review set has been reviewed enough that it is considered to be known. This happens when we have reviewed ten items while in the target zone. The target zone occurs when in the last 10 items, we have a 90% success rate or when we have a 90% confidence that the the items have a 90% chance of success.
138 139 140 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 138 def reviewSetKnown? !(10 - @reviewStats.timesInTargetZone > 0) end |
#reviewSetSize ⇒ Object
Returns the number of items in the review set
82 83 84 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 82 def reviewSetSize reviewSet.length end |
#shouldReview? ⇒ Boolean
Returns true if at least one working set full of items have been promoted to the review set, and the review set is not known to the required level. Note: if the new set and the working set are both empty, this will always return true.
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 148 def shouldReview? # if we only have review set items, or we are in review mode # then return true if (newSet.empty? && workingSetEmpty?) || (.reviewMode) return true end !reviewSetKnown? && (reviewSetSize >= .introThresh) && !(reviewSet.allSeen?) end |
#status ⇒ Object
Returns a string showing the status of the quiz with this strategy
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 35 def status if shouldReview? retVal = " #{@reviewStats.recentAccuracy}%" if @reviewStats.inTargetZone? retVal += " - #{(10 - @reviewStats.timesInTargetZone)}" end elsif !forgottenSet.empty? retVal = " Forgotten Items" else retVal = " New Items" end retVal end |
#workingSetEmpty? ⇒ Boolean
63 64 65 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 63 def workingSetEmpty? contents.rangeEmpty?(Strategy.workingSetBins) end |
#workingSetFull? ⇒ Boolean
Returns true if the working set is not full
73 74 75 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 73 def workingSetFull? workingSetSize >= .introThresh end |
#workingSetSize ⇒ Object
Returns the number of items in the working set
68 69 70 |
# File 'lib/jldrill/model/Quiz/Strategy.rb', line 68 def workingSetSize contents.bins[1].length + contents.bins[2].length + contents.bins[3].length end |