Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/jldrill/model/Item.rb | 280 | 197 | 88.57%
|
86.80%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 require 'jldrill/model/items/ItemFactory' |
2 require 'jldrill/model/ItemStatus' |
3 require 'jldrill/model/ProblemStatus' |
4 require 'jldrill/model/Quiz/ItemStats' |
5 |
6 module JLDrill |
7 |
8 # Holds an item for the quiz. For memory and performance purposes |
9 # these items are stored as: |
10 # |
11 # o The class of the underlying object |
12 # o A string containing the object |
13 # o The ItemStatus of the object |
14 # |
15 # The string representation of the object can be obtain through to_s(). |
16 # The object representation of the object can be obtained through to_o(). |
17 # |
18 # Item also holds position information of the item in the drill |
19 # * position is the original ordinal position of the item in the quiz |
20 # * bin is the number of the bin |
21 # |
22 # Items stored here must implement the following: |
23 # o to_s() -- returns a string representation of the object |
24 # o create() -- accepts a string and creates the object |
25 class Item |
26 |
27 POSITION_RE = /^Position: (.*)/ |
28 |
29 attr_reader :itemType, :contents, :position, :bin, :status, |
30 :hash, :container, :quiz |
31 attr_writer :position, :bin, :container, :quiz |
32 |
33 def initialize(item=nil) |
34 @quiz = nil |
35 if item.nil? |
36 @itemType = nil |
37 @contents = "" |
38 @hash = "".hash |
39 else |
40 @itemType = item.itemType |
41 @contents = item.to_s |
42 @hash = item.hash |
43 end |
44 @position = -1 |
45 @bin = 0 |
46 @container = nil |
47 @status = ItemStatus.new(self) |
48 @status.add(ProblemStatus.new(self)) |
49 @status.add(ItemStats.new(self)) |
50 @cache = nil |
51 end |
52 |
53 # Create an item using the save string |
54 # Note: We are passing bin to this method, since we no |
55 # longer read it in. Due to legacy issues, the item status |
56 # needs to know what bin it is in when parsing. |
57 def Item.create(string) |
58 item = Item.new |
59 item.parse(string) |
60 return item |
61 end |
62 |
63 def parsePart(part) |
64 parsed = true |
65 |
66 case part |
67 when POSITION_RE |
68 @position = $1.to_i |
69 else # Not something we understand |
70 parsed = false |
71 end |
72 |
73 return parsed |
74 end |
75 |
76 # Parse a whole line which includes status information |
77 def parseLine(line) |
78 line.split("/").each do |part| |
79 if !parsePart(part) |
80 @status.parse(part) |
81 end |
82 end |
83 end |
84 |
85 # Set the value of the item by parsing the string |
86 def parse(string) |
87 @itemType = ItemFactory::find(Vocabulary) |
88 @contents = string |
89 parseLine(@contents) |
90 @hash = self.to_o.hash |
91 end |
92 |
93 # Create a copy of this item |
94 def clone |
95 item = Item.new |
96 item.assign(self) |
97 return item |
98 end |
99 |
100 def removeInvalidKanjiProblems |
101 problemStatus = @status.select("ProblemStatus") |
102 problemStatus.removeInvalidKanjiProblems |
103 end |
104 |
105 # Return the schedule for the Spaced Repetition Drill |
106 def schedule |
107 problemStatus = @status.select("ProblemStatus") |
108 return problemStatus.firstSchedule |
109 end |
110 |
111 # UpdateAll the schedules |
112 def scheduleAll |
113 problemStatus = @status.select("ProblemStatus") |
114 problemStatus.scheduleAll |
115 end |
116 |
117 # Demote all the schedules |
118 def demoteAll |
119 problemStatus = @status.select("ProblemStatus") |
120 problemStatus.demoteAll |
121 end |
122 |
123 def resetSchedules |
124 problemStatus = @status.select("ProblemStatus") |
125 problemStatus.resetAll |
126 end |
127 |
128 def allSeen(value) |
129 problemStatus = @status.select("ProblemStatus") |
130 problemStatus.allSeen(value) |
131 end |
132 |
133 def setScores(value) |
134 problemStatus = @status.select("ProblemStatus") |
135 problemStatus.setScores(value) |
136 end |
137 |
138 def setLevels(value) |
139 problemStatus = @status.select("ProblemStatus") |
140 problemStatus.setLevels(value) |
141 end |
142 |
143 def allCorrect |
144 problemStatus = @status.select("ProblemStatus") |
145 problemStatus.allCorrect |
146 end |
147 |
148 def allIncorrect |
149 problemStatus = @status.select("ProblemStatus") |
150 problemStatus.allIncorrect |
151 end |
152 |
153 def problem |
154 problemStatus = @status.select("ProblemStatus") |
155 return problemStatus.firstProblem |
156 end |
157 |
158 def itemStats |
159 return @status.select("ItemStats") |
160 end |
161 |
162 # Assign the contents of item to this item |
163 def assign(item) |
164 setType(item.itemType) |
165 setContents(item.contents) |
166 @position = item.position |
167 @bin = item.bin |
168 @status.assign(item.status) |
169 @hash = item.hash |
170 @cache = nil |
171 end |
172 |
173 # Set the type of the item |
174 def setType(aType) |
175 @itemType = aType |
176 end |
177 |
178 # set the ItemStatus |
179 def setStatus(status) |
180 parseLine(status.to_s) |
181 end |
182 |
183 # set the contents of the item |
184 def setContents(contents) |
185 @contents = contents |
186 @hash = to_o.hash |
187 end |
188 |
189 # swap the positions between two items |
190 def swapWith(item) |
191 temp = @position |
192 @position = item.position |
193 item.position = temp |
194 |
195 if !@quiz.nil? |
196 if (@bin == 0) && (item.bin == 0) |
197 @quiz.contents.bins[@bin].moveBeforeItem(self, item) |
198 end |
199 @quiz.setNeedsSave(true) |
200 end |
201 end |
202 |
203 def insertBefore(item) |
204 target = item.position |
205 # This is clearly slow. It can be made slightly |
206 # faster by only iterating over the relevant |
207 # items, but I don't know if it's worth the effort |
208 # since the majority of the cost is in creating the |
209 # sorted array in the first place. |
210 @container.eachByPosition do |i| |
211 if (i.position >= target) && |
212 (i.position < @position) |
213 i.position += 1 |
214 end |
215 end |
216 @position = target |
217 |
218 if !@quiz.nil? |
219 if (@bin == 0) && (item.bin == 0) |
220 @quiz.contents.bins[@bin].moveBeforeItem(self, item) |
221 end |
222 @quiz.setNeedsSave(true) |
223 end |
224 end |
225 |
226 # Return the save format of the item |
227 def to_s |
228 retVal = to_o.to_s |
229 retVal += "/Position: #{@position}" |
230 retVal += @status.to_s |
231 retVal += "/\n" |
232 return retVal |
233 end |
234 |
235 # Create the object in the item and return it |
236 def to_o |
237 if !@contents.empty? |
238 if @cache.nil? |
239 @cache = @itemType.create(@contents) |
240 end |
241 else |
242 @cache = nil |
243 end |
244 return @cache |
245 end |
246 |
247 def hasKanji? |
248 v = to_o |
249 return !v.kanji.nil? |
250 end |
251 |
252 # Returns true if the items contain the same object. |
253 # Note: Does *not* compare the status |
254 def eql?(item) |
255 if item.hash == @hash |
256 self.to_o.eql?(item.to_o) |
257 else |
258 false |
259 end |
260 end |
261 |
262 # Returns true if the item contains the object. |
263 def contain?(object) |
264 if object.hash == @hash |
265 self.to_o.eql?(object) |
266 else |
267 false |
268 end |
269 end |
270 |
271 # Indicate to the quiz that the problem has been modified |
272 # This will be called by the problem itself whenever it |
273 # has been modified. |
274 def problemModified(problem) |
275 if !@quiz.nil? |
276 @quiz.problemModified(problem) |
277 end |
278 end |
279 end |
280 end |
Generated on Mon May 23 16:17:46 +0900 2011 with rcov 0.9.8