Class: JLDrill::Contents

Inherits:
Object
  • Object
show all
Defined in:
lib/jldrill/model/Contents.rb

Overview

Where all the items are stored

Constant Summary collapse

LINE_START_RE =
/^\//

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(quiz) ⇒ Contents

Returns a new instance of Contents.



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/jldrill/model/Contents.rb', line 13

def initialize(quiz)
    @quiz = quiz
    @bins = []
    @res = []
    addBin("Unseen")
    addBin("Poor")
    addBin("Fair")
    addBin("Good")
    addBin("Excellent")
    addBin("Forgotten")
    @binNum = 0
end

Instance Attribute Details

#binsObject (readonly)

Returns the value of attribute bins.



11
12
13
# File 'lib/jldrill/model/Contents.rb', line 11

def bins
  @bins
end

#quizObject (readonly)

Returns the value of attribute quiz.



11
12
13
# File 'lib/jldrill/model/Contents.rb', line 11

def quiz
  @quiz
end

Instance Method Details

#add(vocab, bin) ⇒ Object

Adds a vocab to a specific bin. Returns the item that was added



69
70
71
72
73
74
75
76
# File 'lib/jldrill/model/Contents.rb', line 69

def add(vocab, bin)
    item = nil
    if !vocab.nil? && vocab.valid?
        item = Item.new(vocab)
        addItem(item, bin)
    end
    return item
end

#addBin(name) ⇒ Object

Adds a new bin to the end of the contents



36
37
38
39
# File 'lib/jldrill/model/Contents.rb', line 36

def addBin(name)
    @bins.push(Bin.new(name, @bins.length))
    @res.push(Regexp.new("^#{name}$",nil))
end

#addContents(contents) ⇒ Object

Add the contents from another quiz to this one. Only adds the items that doen’t already exists. Sets the positions of the new items to the end of this contents. Returns the last item that was added, or nil if none were added.



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/jldrill/model/Contents.rb', line 143

def addContents(contents)
    lastItem = nil
    tempArray = getSortedItems
    contents.eachByPosition do |item|
        if !tempArray.binarySearch(item)
            newItem = item.clone
            newItem.position = -1
            self.addItem(newItem, newItem.bin)
            lastItem = newItem
        end
    end
    return lastItem
end

#addItem(item, bin) ⇒ Object

Add an item to a bin



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/jldrill/model/Contents.rb', line 55

def addItem(item, bin)
    item.bin = bin
    item.quiz = @quiz
    item.schedule.score = 0
    if item.position == -1
        item.position = length 
    end
    @bins[bin].push(item)
    item.container = self
    itemAdded(item)
    saveNeeded
end

#addUniquely(item) ⇒ Object

Adds an item to the contents only if it doesn’t already exist. It places it in the bin specified in the item. It also sets it’s position to the end contents.



88
89
90
91
92
93
94
95
96
# File 'lib/jldrill/model/Contents.rb', line 88

def addUniquely(item)
    if !exists?(item.to_o)
        item.position = -1
        addItem(item, item.bin)
        true
    else
        false
    end
end

#allItemsObject

Returns an array of all the items in the bins, sorted by position. Note: this also updates the positions of the items if they are out of whack (i.e. duplicates). This is to combat against some old broken files.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/jldrill/model/Contents.rb', line 188

def allItems
    items = []
    bins.each do |bin|
        items += bin.contents
    end
    items.sort! do |x,y| 
        x.position <=> y.position
    end
    # Renumber the positions in case they are out of whack
    i = 0
    items.each do |item|
        item.position = i
        i += 1
    end
    return items
end

#delete(item) ⇒ Object

Delete the specified item



236
237
238
239
240
241
242
# File 'lib/jldrill/model/Contents.rb', line 236

def delete(item)
    if !item.nil?
        @bins[item.bin].delete(item)
        repositionItems
        saveNeeded
    end
end

#eachByPosition(&block) ⇒ Object

Goes through each of the items in the contents by position. This is going to be very slow, so don’t use it unless you really have to.



101
102
103
104
# File 'lib/jldrill/model/Contents.rb', line 101

def eachByPosition(&block)
    tempArray = allItems
    tempArray.each(&block)
end

#empty?Boolean

Returns true if all of the bins are empty

Returns:

  • (Boolean)


273
274
275
276
277
278
# File 'lib/jldrill/model/Contents.rb', line 273

def empty?
    retVal = @bins.all? do |bin|
        bin.empty?
    end
    retVal
end

#exists?(vocab) ⇒ Boolean

Returns true if the vocabulary exists already in the contents

Returns:

  • (Boolean)


79
80
81
82
83
# File 'lib/jldrill/model/Contents.rb', line 79

def exists?(vocab)
    return @bins.any? do |bin|
        bin.contain?(vocab)
    end
end

#findAll(&block) ⇒ Object

Returns a list of items for which block returns true



245
246
247
248
249
250
251
# File 'lib/jldrill/model/Contents.rb', line 245

def findAll(&block)
    retVal = []
    @bins.each do |bin|
        retVal += bin.findAll(&block)
    end
    return retVal
end

#findUnseen(n, range) ⇒ Object

Returns the nth unseen item in the range of contents, or nil if there aren’t any unseen items



296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/jldrill/model/Contents.rb', line 296

def findUnseen(n, range)
    total = numUnseen(range)
    if n > total || !includesRange?(range)
        return nil
    end
    
    i = range.end
    prev = total
    while (prev = (prev - @bins[i].numUnseen)) > n
        i -= 1 
    end
    
    @bins[i].findUnseen(n - prev)
end

#getSortedItemsObject

Get an array of all the items sorted by hash. The array includes a binary search algorithm for finding items.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/jldrill/model/Contents.rb', line 109

def getSortedItems
    items = []
    bins.each do |bin|
        items += bin.contents
    end
    items = allItems.sort! do |x, y|
        x.hash <=> y.hash
    end
    def items.binarySearch(item, spos=nil, epos=nil)
        if spos == nil
            spos = 0
        end
        if epos == nil
            epos = self.size - 1
        end
        if spos > epos
            return false
        end
        pos = ((epos - spos) / 2) + spos
        if self[pos].hash < item.hash
            return self.binarySearch(item, pos + 1, epos)
        elsif self[pos].hash > item.hash
            return self.binarySearch(item, spos, pos - 1)
        else
            return self[pos].eql?(item)
        end
    end
    return items
end

#includesRange?(range) ⇒ Boolean

returns true if there are bins in the specified range

Returns:

  • (Boolean)


290
291
292
# File 'lib/jldrill/model/Contents.rb', line 290

def includesRange?(range)
    !(range.begin < 0 || range.end > 5)
end

#itemAdded(item) ⇒ Object



31
32
33
# File 'lib/jldrill/model/Contents.rb', line 31

def itemAdded(item)
    @quiz.updateItemAdded(item)
end

#lengthObject

Returns the number items in all the bins



42
43
44
45
46
47
48
# File 'lib/jldrill/model/Contents.rb', line 42

def length
    total = 0
    @bins.each do |bin|
        total += bin.length
    end
    total
end

#moveToBin(item, bin) ⇒ Object

Move the specified item to the specified bin



219
220
221
222
223
224
225
# File 'lib/jldrill/model/Contents.rb', line 219

def moveToBin(item, bin)
    if !item.nil?
        @bins[item.bin].delete(item)
        @bins[bin].push(item)
        saveNeeded
    end
end

#numUnseen(range) ⇒ Object

Returns the number of unseen items in the range of bins



281
282
283
284
285
286
287
# File 'lib/jldrill/model/Contents.rb', line 281

def numUnseen(range)
    total = 0
    range.each do |i|
        total += @bins[i].numUnseen
    end
    total
end

#parseItem(line, bin) ⇒ Object

Parse the line for an item.

Add it to the contents in the specified bin. Return the item that was added.



160
161
162
163
# File 'lib/jldrill/model/Contents.rb', line 160

def parseItem(line, bin)
    item = Item.create(line)
    return addItem(item, bin)
end

#parseLine(line) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/jldrill/model/Contents.rb', line 165

def parseLine(line)
    parsed = false
    # Line items are the most common, so they are checked first
    if line =~ LINE_START_RE
            parseItem(line, @binNum)
            parsed = true
    else
        # Bin names are less common so they are checked after
        @bins.each do |bin|
            re = @res[bin.number]
            if line =~ re
                @binNum = bin.number
                parsed = true
            end
        end
    end
    parsed
end

#rangeAllSeen?(range) ⇒ Boolean

Returns false if any of the bins in the range have unseen items in them

Returns:

  • (Boolean)


313
314
315
316
317
318
319
# File 'lib/jldrill/model/Contents.rb', line 313

def rangeAllSeen?(range)
    a = range.to_a
    seen = a.all? do |bin|
        @bins[bin].allSeen?
    end
    seen
end

#rangeEmpty?(range) ⇒ Boolean

Returns false if any of the bins in the range have items in them

Returns:

  • (Boolean)


323
324
325
326
327
328
329
# File 'lib/jldrill/model/Contents.rb', line 323

def rangeEmpty?(range)
    a = range.to_a
    hasItems = a.any? do |bin|
        !@bins[bin].empty?
    end
    !hasItems
end

#removeDuplicatesObject

Removes all duplicate items. Keeps the version in the highest bin



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/jldrill/model/Contents.rb', line 255

def removeDuplicates
    @bins.reverse_each do |bin|
        bin.reverse_each do |item|
            obj = item.to_o
            print "#{item.position}: #{item.to_o.reading}..."
            duplicates = self.findAll do |candidate|
                ((item != candidate) && (obj == candidate.to_o))
            end
            duplicates.each do |dup|
                print "   #{dup.position}"
                self.delete(dup)
            end
            print "\n"
        end
    end
end

#repositionItemsObject

Renumber the positions of the items



228
229
230
231
232
233
# File 'lib/jldrill/model/Contents.rb', line 228

def repositionItems
    # allItems renumbers the positions as a side-effect.
    # Perhaps I should duplicate the code here.  I'm of
    # two minds...
    allItems
end

#resetObject

Reset the contents back to their original order and schedule



206
207
208
209
210
211
212
213
214
215
216
# File 'lib/jldrill/model/Contents.rb', line 206

def reset
    @bins[0].contents = allItems
    1.upto(@bins.length - 1) do |i|
        @bins[i].contents = []
    end
    @bins[0].each do |item|
        item.schedule.reset
        item.itemStats.reset
    end
    saveNeeded
end

#saveNeededObject

Returns true if the contents have been changed but not saved



27
28
29
# File 'lib/jldrill/model/Contents.rb', line 27

def saveNeeded
    @quiz.setNeedsSave(true)
end

#sizeObject



50
51
52
# File 'lib/jldrill/model/Contents.rb', line 50

def size
    length
end

#statusObject

Return a string containing the length of all the bins



332
333
334
335
336
337
338
339
340
341
342
# File 'lib/jldrill/model/Contents.rb', line 332

def status
    retVal = "New: #{@bins[0].length} "
    if (quiz.options.forgettingThresh != 0.0)
        retVal += "Forgotten: #{@bins[5].length} "
    end
    retVal += "Review: #{@bins[4].length} "
    retVal += "Working: #{@bins[1].length}, "
    retVal += "#{@bins[2].length}, "
    retVal += "#{@bins[3].length}"
    retVal
end

#to_sObject



344
345
346
347
348
349
350
# File 'lib/jldrill/model/Contents.rb', line 344

def to_s
    retVal = ""
    @bins.each do |bin|
        retVal += bin.to_s
    end
    retVal
end