| … | |
… | |
| 5 | |
5 | |
| 6 | package WeBWorK::DB::WW; |
6 | package WeBWorK::DB::WW; |
| 7 | |
7 | |
| 8 | use strict; |
8 | use strict; |
| 9 | use warnings; |
9 | use warnings; |
|
|
10 | use Carp; |
| 10 | use WeBWorK::Set; |
11 | use WeBWorK::Set; |
| 11 | use WeBWorK::Problem; |
12 | use WeBWorK::Problem; |
| 12 | |
13 | |
| 13 | use constant LOGIN_PREFIX => "login<>"; |
14 | use constant LOGIN_PREFIX => "login<>"; |
| 14 | use constant SET_PREFIX => "set<>"; |
15 | use constant SET_PREFIX => "set<>"; |
|
|
16 | use constant MAX_PSVN_GENERATION_ATTEMPTS => 200; |
| 15 | |
17 | |
| 16 | # there should be a `use' line for each database type |
18 | # there should be a `use' line for each database type |
| 17 | use WeBWorK::DB::GDBM; |
19 | use WeBWorK::DB::GDBM; |
| 18 | |
20 | |
| 19 | # new($invocant, $courseEnv) |
21 | # new($invocant, $courseEnv) |
| … | |
… | |
| 24 | my $class = ref($invocant) || $invocant; |
26 | my $class = ref($invocant) || $invocant; |
| 25 | my $courseEnv = shift; |
27 | my $courseEnv = shift; |
| 26 | my $dbModule = fullyQualifiedPackageName($courseEnv->{dbInfo}->{wwdb_type}); |
28 | my $dbModule = fullyQualifiedPackageName($courseEnv->{dbInfo}->{wwdb_type}); |
| 27 | my $self = { |
29 | my $self = { |
| 28 | webwork_file => $courseEnv->{dbInfo}->{wwdb_file}, |
30 | webwork_file => $courseEnv->{dbInfo}->{wwdb_file}, |
|
|
31 | psvn_digits => $courseEnv->{dbInfo}->{psvn_digits}, |
| 29 | }; |
32 | }; |
| 30 | $self->{webwork_db} = $dbModule->new($self->{webwork_file}); |
33 | $self->{webwork_db} = $dbModule->new($self->{webwork_file}); |
| 31 | bless $self, $class; |
34 | bless $self, $class; |
| 32 | return $self; |
35 | return $self; |
| 33 | } |
36 | } |
| … | |
… | |
| 39 | return $package; |
42 | return $package; |
| 40 | } |
43 | } |
| 41 | |
44 | |
| 42 | # ----- |
45 | # ----- |
| 43 | |
46 | |
|
|
47 | sub fixMyMistakes($) { # *** |
|
|
48 | my $self = shift; |
|
|
49 | my $userID = "practice1"; |
|
|
50 | my $setID = "dummy"; |
|
|
51 | my $PSVN = 95540; |
|
|
52 | $self->{webwork_db}->connect("rw"); |
|
|
53 | delete $self->{webwork_db}->hashRef->{$PSVN}; |
|
|
54 | my $setsForUser = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
|
|
55 | my $usersForSet = $self->{webwork_db}->hashRef->{SET_PREFIX.$setID}; |
|
|
56 | my %sets = decode($setsForUser); # sets built for user $userID |
|
|
57 | my %users = decode($usersForSet); # users for which set $setID has been built |
|
|
58 | delete $sets{$setID}; |
|
|
59 | delete $users{$userID}; |
|
|
60 | $setsForUser = encode(%sets); |
|
|
61 | $usersForSet = encode(%users); |
|
|
62 | $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID} = $setsForUser; |
|
|
63 | $self->{webwork_db}->hashRef->{SET_PREFIX.$setID} = $usersForSet; |
|
|
64 | $self->{webwork_db}->disconnect; |
|
|
65 | } |
|
|
66 | |
|
|
67 | # ----- |
|
|
68 | |
| 44 | # getSets($userID) - returns a list of sets in the current database for the |
69 | # getSets($userID) - returns a list of sets in the current database for the |
| 45 | # specified user |
70 | # specified user |
| 46 | # $userID - the user ID (a.k.a. login name) of the user to get sets for |
71 | # $userID - the user ID (a.k.a. login name) of the user to get sets for |
| 47 | sub getSets($$) { |
72 | sub getSets($$) { |
| 48 | my $self = shift; |
73 | my $self = shift; |
| 49 | my $userID = shift; |
74 | my $userID = shift; |
| 50 | return unless $self->{webwork_db}->connect("ro"); |
75 | return unless $self->{webwork_db}->connect("ro"); |
| 51 | my $result = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
76 | my $result = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
| 52 | $self->{webwork_db}->disconnect; |
77 | $self->{webwork_db}->disconnect; |
| 53 | return unless defined $result; |
78 | return unless defined $result; |
| 54 | return keys %{decode($result)}; |
79 | my %record = decode($result); |
|
|
80 | return keys %record; |
| 55 | } |
81 | } |
| 56 | |
82 | |
| 57 | # ----- |
83 | # ----- |
| 58 | |
84 | |
| 59 | # getSet($userID, $setID) - returns a WeBWorK::Set object containing data |
85 | # getSet($userID, $setID) - returns a WeBWorK::Set object containing data |
| … | |
… | |
| 62 | # $setID - the ID (a.k.a. name) of the set to retrieve |
88 | # $setID - the ID (a.k.a. name) of the set to retrieve |
| 63 | sub getSet($$$) { |
89 | sub getSet($$$) { |
| 64 | my $self = shift; |
90 | my $self = shift; |
| 65 | my $userID = shift; |
91 | my $userID = shift; |
| 66 | my $setID = shift; |
92 | my $setID = shift; |
| 67 | my $PSVN = getPSVN($userID, $setID); |
93 | my $PSVN = $self->getPSVN($userID, $setID); |
| 68 | return unless $PSVN; |
94 | return unless $PSVN; |
| 69 | return hash2set($self->fetchRcord($PSVN)); |
95 | return hash2set($self->fetchRecord($PSVN)); |
| 70 | } |
96 | } |
| 71 | |
97 | |
| 72 | # setSet($set) - if a set with the same ID for the specified user |
98 | # setSet($set) - if a set with the same ID for the specified user |
| 73 | # exists, it is replaced. If not, a new set is added. |
99 | # exists, it is replaced. If not, a new set is added. |
| 74 | # returns true on success, undef on failure. |
100 | # returns true on success, undef on failure. |
| 75 | # $set - a WeBWorK::Set object containing the set data |
101 | # $set - a WeBWorK::Set object containing the set data |
| 76 | sub setSet($$) { |
102 | sub setSet($$) { |
| 77 | my $self = shift; |
103 | my $self = shift; |
| 78 | my $set = shift; |
104 | my $set = shift; |
| 79 | my $PSVN = getPSVN($set->login_id, $set->id); |
105 | my $PSVN = $self->getPSVN($set->login_id, $set->id); |
| 80 | my %record = ( |
106 | my %record = ( |
| 81 | $PSVN ? $self->fetchRecord($PSVN) : (), |
107 | $PSVN ? $self->fetchRecord($PSVN) : (), |
| 82 | set2hash($set), |
108 | set2hash($set), |
| 83 | ); |
109 | ); |
|
|
110 | $PSVN = $self->setPSVN($set->login_id, $set->id) unless ($PSVN); |
| 84 | return $self->storeRecord($PSVN, %record); |
111 | return $self->storeRecord($PSVN, %record); |
| 85 | } |
112 | } |
| 86 | |
113 | |
| 87 | # deleteSet($userID, $setID) - removes the set with the specified userID and |
114 | # deleteSet($userID, $setID) - removes the set with the specified userID and |
|
|
115 | # setID. Also removes all problems in set. |
| 88 | # setID. Returns true on success, undef on failure. |
116 | # Returns true on success, undef on failure. |
| 89 | # $userID - the user ID (a.k.a. login name) of the set to delete |
117 | # $userID - the user ID (a.k.a. login name) of the set to delete |
| 90 | # $setID - the ID (a.k.a. name) of the set to delete |
118 | # $setID - the ID (a.k.a. name) of the set to delete |
| 91 | sub deleteSet($$$) { |
119 | sub deleteSet($$$) { |
| 92 | my $self = shift; |
120 | my $self = shift; |
| 93 | my $userID = shift; |
121 | my $userID = shift; |
| 94 | my $setID = shift; |
122 | my $setID = shift; |
| 95 | my $PSVN = getPSVN($userID, $setID); |
123 | my $PSVN = $self->getPSVN($userID, $setID); |
| 96 | $self->{classlist_db}->connect("rw"); |
124 | $self->{webwork_db}->connect("rw"); |
| 97 | delete $self->{classlist_db}->hashRef->{$userID}; |
125 | delete $self->{webwork_db}->hashRef->{$PSVN}; |
| 98 | $self->{classlist_db}->disconnect; |
126 | $self->{webwork_db}->disconnect; |
|
|
127 | $self->deletePSVN($userID, $setID); |
| 99 | return 1; |
128 | return 1; |
| 100 | } |
129 | } |
| 101 | |
130 | |
| 102 | # ----- |
131 | # ----- |
| 103 | |
132 | |
| … | |
… | |
| 119 | # $setID - the set ID to get problems from |
148 | # $setID - the set ID to get problems from |
| 120 | sub getProblems($$$) { |
149 | sub getProblems($$$) { |
| 121 | my $self = shift; |
150 | my $self = shift; |
| 122 | my $userID = shift; |
151 | my $userID = shift; |
| 123 | my $setID = shift; |
152 | my $setID = shift; |
| 124 | my $PSVN = getPSVN($userID, $setID); |
153 | my $PSVN = $self->getPSVN($userID, $setID); |
| 125 | my %record = $self->fetchRecord($PSVN); |
154 | my %record = $self->fetchRecord($PSVN); |
|
|
155 | return unless %record; |
| 126 | my @result; |
156 | my @result; |
| 127 | my $i = 1; |
157 | my $i = 1; |
| 128 | while (exists $record{"pse".$i}) { |
158 | while (exists $record{"pse".$i}) { |
| 129 | push @result, $i++; |
159 | push @result, $i++; |
| 130 | } |
160 | } |
| … | |
… | |
| 142 | sub getProblem($$$$) { |
172 | sub getProblem($$$$) { |
| 143 | my $self = shift; |
173 | my $self = shift; |
| 144 | my $userID = shift; |
174 | my $userID = shift; |
| 145 | my $setID = shift; |
175 | my $setID = shift; |
| 146 | my $problemNumber = shift; |
176 | my $problemNumber = shift; |
| 147 | my $PSVN = getPSVN($userID, $setID); |
177 | my $PSVN = $self->getPSVN($userID, $setID); |
| 148 | return unless $PSVN; |
178 | return unless $PSVN; |
| 149 | return hash2problem($problemNumber, fetchRecord($PSVN)); |
179 | return hash2problem($problemNumber, $self->fetchRecord($PSVN)); |
| 150 | } |
180 | } |
| 151 | |
181 | |
| 152 | # setProblem($problem) - if a problem with the same ID for the specified user |
182 | # setProblem($problem) - if a problem with the same ID for the specified user |
| 153 | # exists, it is replaced. If not, a new problem is added. |
183 | # exists, it is replaced. If not, a new problem is added. |
| 154 | # returns true on success, undef on failure. |
184 | # returns true on success, undef on failure. |
| 155 | # $problem - a WeBWorK::Problem object containing the object data |
185 | # $problem - a WeBWorK::Problem object containing the object data |
| 156 | sub setProblem($$) { |
186 | sub setProblem($$) { |
| 157 | my $self = shift; |
187 | my $self = shift; |
| 158 | my $problem = shift; |
188 | my $problem = shift; |
| 159 | my $PSVN = getPSVN($problem->login_id, $problem->set_id); |
189 | my $PSVN = $self->getPSVN($problem->login_id, $problem->set_id); |
|
|
190 | die "failed to add problem: set ", $problem->set_id, " does not exist." |
|
|
191 | unless $PSVN; |
| 160 | my %record = ( |
192 | my %record = ( |
| 161 | $PSVN ? $self->fetchRecord($PSVN) : (), |
193 | $self->fetchRecord($PSVN), |
| 162 | problem2hash($problem), |
194 | problem2hash($problem), |
| 163 | ); |
195 | ); |
| 164 | return $self->storeRecord($PSVN, %record); |
196 | return $self->storeRecord($PSVN, %record); |
| 165 | } |
197 | } |
| 166 | |
198 | |
| … | |
… | |
| 172 | sub deleteProblem($$$$) { |
204 | sub deleteProblem($$$$) { |
| 173 | my $self = shift; |
205 | my $self = shift; |
| 174 | my $userID = shift; |
206 | my $userID = shift; |
| 175 | my $setID = shift; |
207 | my $setID = shift; |
| 176 | my $n = shift; |
208 | my $n = shift; |
| 177 | my $PSVN = getPSVN($userID, $setID); |
209 | my $PSVN = $self->getPSVN($userID, $setID); |
| 178 | my %record = $self->fetchRecord($PSVN); |
210 | my %record = $self->fetchRecord($PSVN); |
| 179 | return unless %record; |
211 | return unless %record; |
| 180 | delete $record{"pfn$n"} if exists $record{"pfn$n"}; |
212 | delete $record{"pfn$n"} if exists $record{"pfn$n"}; |
| 181 | delete $record{"pva$n"} if exists $record{"pva$n"}; |
213 | delete $record{"pva$n"} if exists $record{"pva$n"}; |
| 182 | delete $record{"pmia$n"} if exists $record{"pmia$n"}; |
214 | delete $record{"pmia$n"} if exists $record{"pmia$n"}; |
| … | |
… | |
| 207 | # $setID - the set ID of the problem defaults to delete |
239 | # $setID - the set ID of the problem defaults to delete |
| 208 | # $problemNumber - the problem number of the problem defaults to delete |
240 | # $problemNumber - the problem number of the problem defaults to delete |
| 209 | |
241 | |
| 210 | # ----- |
242 | # ----- |
| 211 | |
243 | |
|
|
244 | # getPSVNs($userID) - get a list of PSVNs for a user |
|
|
245 | # $userID - the user |
|
|
246 | sub getPSVNs($$) { |
|
|
247 | my $self = shift; |
|
|
248 | my $userID = shift; |
|
|
249 | return unless $self->{webwork_db}->connect("ro"); |
|
|
250 | my $setsForUser = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
|
|
251 | $self->{webwork_db}->disconnect; |
|
|
252 | return unless defined $setsForUser; |
|
|
253 | my %sets = decode($setsForUser); |
|
|
254 | return values %sets; |
|
|
255 | } |
|
|
256 | |
|
|
257 | # ----- |
|
|
258 | |
| 212 | # getPSVN($userID, $setID) - look up a PSVN given a user ID and set ID (PSVN |
259 | # getPSVN($userID, $setID) - look up a PSVN given a user ID and set ID (PSVN |
| 213 | # stands for Problem Set Version Number and |
260 | # stands for Problem Set Version Number and |
| 214 | # uniquely identifies a user's version of a set.) |
261 | # uniquely identifies a user's version of a set.) |
| 215 | # $userID - the user ID to lookup |
262 | # $userID - the user ID to lookup |
| 216 | # $serID - the set ID to lookup |
263 | # $serID - the set ID to lookup |
| 217 | sub getPSVN($$$) { |
264 | sub getPSVN($$$) { |
| 218 | my $self = shift; |
265 | my $self = shift; |
| 219 | my $userID = shift; |
266 | my $userID = shift; |
| 220 | my $setID = shift; |
267 | my $setID = shift; |
| 221 | return unless $self->{webwork_db}->connect("ro"); |
268 | return unless $self->{webwork_db}->connect("ro"); |
| 222 | my $result = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
269 | my $setsForUser = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
|
|
270 | my $usersForSet = $self->{webwork_db}->hashRef->{SET_PREFIX.$setID}; |
| 223 | $self->{webwork_db}->disconnect; |
271 | $self->{webwork_db}->disconnect; |
| 224 | return unless $result; |
272 | # * if setsForUser is non-empty, then there are sets built for |
|
|
273 | # this user. |
|
|
274 | # * if usersForSet is non-empty, then this set has been built for |
|
|
275 | # at least one user. |
|
|
276 | # * if either are empty, it is guaranteed that this set has not |
|
|
277 | # been built for this user. |
|
|
278 | return unless defined $setsForUser and defined $usersForSet; |
|
|
279 | return unless $setsForUser and $usersForSet; |
| 225 | my %sets = decode($result); |
280 | my %sets = decode($setsForUser); |
|
|
281 | my %users = decode($usersForSet); |
|
|
282 | # more sanity checks: the following should never happen. |
|
|
283 | # if they do, run screaming for the hills. |
|
|
284 | if (defined $sets{$setID} and not defined $users{$userID}) { |
|
|
285 | die "PSVN indexes inconsistent: set exists in user index ", |
|
|
286 | "but user does not exist in set index."; |
|
|
287 | } elsif (not defined $sets{$setID} and defined $users{$userID}) { |
|
|
288 | die "PSVN indexes inconsistent: user exists in set index ", |
|
|
289 | "but set does not exist in user index."; |
|
|
290 | } elsif ($sets{$setID} != $users{$userID}) { |
|
|
291 | die "PSVN indexes inconsistent: user index and set index ", |
|
|
292 | "gave different PSVN values."; |
|
|
293 | } |
| 226 | return $sets{$setID}; |
294 | return $sets{$setID}; |
|
|
295 | } |
|
|
296 | |
|
|
297 | # setPSVN($userID, $setID) - adds a new PSVN to the PSVN indexesfor the given |
|
|
298 | # user ID and set ID, if it doesn't exist. Returns |
|
|
299 | # the PSVN. |
|
|
300 | # $userID - the user ID to use |
|
|
301 | # $serID - the set ID to use |
|
|
302 | sub setPSVN($$$) { |
|
|
303 | my $self = shift; |
|
|
304 | my $userID = shift; |
|
|
305 | my $setID = shift; |
|
|
306 | my $PSVN = $self->getPSVN($userID, $setID); |
|
|
307 | unless ($PSVN) { |
|
|
308 | # yeah, create a new PSVN here |
|
|
309 | my $min_psvn = 10**($self->{psvn_digits} - 1); |
|
|
310 | my $max_psvn = 10**$self->{psvn_digits} - 1; |
|
|
311 | my $attempts = 0; |
|
|
312 | do { |
|
|
313 | if (++$attempts > MAX_PSVN_GENERATION_ATTEMPTS) { |
|
|
314 | die "failed to find an unused PSVN."; |
|
|
315 | } |
|
|
316 | $PSVN = int(rand($max_psvn-$min_psvn+1)) + $min_psvn; |
|
|
317 | } while ($self->fetchRecord($PSVN)); |
|
|
318 | $self->{webwork_db}->connect("rw"); # open "rw" to lock |
|
|
319 | # get current PSVN indexes |
|
|
320 | my $setsForUser = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
|
|
321 | my $usersForSet = $self->{webwork_db}->hashRef->{SET_PREFIX.$setID}; |
|
|
322 | my %sets = decode($setsForUser); # sets built for user $userID |
|
|
323 | my %users = decode($usersForSet); # users for which set $setID has been built |
|
|
324 | # insert new PSVN into each hash |
|
|
325 | $sets{$setID} = $PSVN; |
|
|
326 | $users{$userID} = $PSVN; |
|
|
327 | # re-encode the hashes |
|
|
328 | $setsForUser = encode(%sets); |
|
|
329 | $usersForSet = encode(%users); |
|
|
330 | # store 'em in the database |
|
|
331 | $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID} = $setsForUser; |
|
|
332 | $self->{webwork_db}->hashRef->{SET_PREFIX.$setID} = $usersForSet; |
|
|
333 | $self->{webwork_db}->disconnect; |
|
|
334 | }; |
|
|
335 | return $PSVN; |
|
|
336 | } |
|
|
337 | |
|
|
338 | # deletePSVN($userID, $setID) - remove an entry from the PSVN indexes. |
|
|
339 | # $userID - the user to remove |
|
|
340 | # $setID - the set to remove |
|
|
341 | sub deletePSVN($$) { |
|
|
342 | my $self = shift; |
|
|
343 | my $userID = shift; |
|
|
344 | my $setID = shift; |
|
|
345 | my $PSVN = $self->getPSVN($userID, $setID); |
|
|
346 | return unless $PSVN; |
|
|
347 | $self->{webwork_db}->connect("rw"); # open "rw" to lock |
|
|
348 | my $setsForUser = $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID}; |
|
|
349 | my $usersForSet = $self->{webwork_db}->hashRef->{SET_PREFIX.$setID}; |
|
|
350 | my %sets = decode($setsForUser); # sets built for user $userID |
|
|
351 | my %users = decode($usersForSet); # users for which set $setID has been built |
|
|
352 | delete $sets{$setID}; |
|
|
353 | delete $users{$userID}; |
|
|
354 | $setsForUser = encode(%sets); |
|
|
355 | $usersForSet = encode(%users); |
|
|
356 | $self->{webwork_db}->hashRef->{LOGIN_PREFIX.$userID} = $setsForUser; |
|
|
357 | $self->{webwork_db}->hashRef->{SET_PREFIX.$setID} = $usersForSet; |
|
|
358 | $self->{webwork_db}->disconnect; |
|
|
359 | return 1; |
| 227 | } |
360 | } |
| 228 | |
361 | |
| 229 | # ----- |
362 | # ----- |
| 230 | |
363 | |
| 231 | # fetchRecord($PSVN) - retrieve the record associated with the given PSVN |
364 | # fetchRecord($PSVN) - retrieve the record associated with the given PSVN |
| … | |
… | |
| 271 | # %hash - hash to encode |
404 | # %hash - hash to encode |
| 272 | sub encode(%) { |
405 | sub encode(%) { |
| 273 | my %hash = @_; |
406 | my %hash = @_; |
| 274 | my $string; |
407 | my $string; |
| 275 | foreach (keys %hash) { |
408 | foreach (keys %hash) { |
|
|
409 | $hash{$_} = "" unless defined $hash{$_}; # promote undef to "" |
| 276 | $hash{$_} =~ s/(=|&)/\\$1/; # escape & and = |
410 | $hash{$_} =~ s/(=|&)/\\$1/; # escape & and = |
| 277 | $string .= "$_=$hash{$_}&"; |
411 | $string .= "$_=$hash{$_}&"; |
| 278 | } |
412 | } |
| 279 | chop $string; # remove final '&' from string for old code :p |
413 | chop $string if $string; # remove final '&' from string for old code :p |
| 280 | return $string; |
414 | return $string; |
| 281 | } |
415 | } |
| 282 | |
416 | |
| 283 | # ----- |
417 | # ----- |
| 284 | |
418 | |
| … | |
… | |
| 301 | # set2hash($set) - unpacks a WeBWorK::Set object and returns PART of a hash |
435 | # set2hash($set) - unpacks a WeBWorK::Set object and returns PART of a hash |
| 302 | # suitable for storage in the webwork database. |
436 | # suitable for storage in the webwork database. |
| 303 | # $set - a WeBWorK::Set object. |
437 | # $set - a WeBWorK::Set object. |
| 304 | sub set2hash($) { |
438 | sub set2hash($) { |
| 305 | my $set = shift; |
439 | my $set = shift; |
| 306 | my %hash; |
440 | return ( |
| 307 | $hash{stnm} = $set->id if defined $set->id; |
441 | stnm => $set->id, |
| 308 | $hash{stlg} = $set->login_id if defined $set->login_id; |
442 | stlg => $set->login_id, |
| 309 | $hash{shfn} = $set->set_header if defined $set->set_header; |
443 | shfn => $set->set_header, |
| 310 | $hash{phfn} = $set->problem_header if defined $set->problem_header; |
444 | phfn => $set->problem_header, |
| 311 | $hash{opdt} = $set->open_date if defined $set->open_date; |
445 | opdt => $set->open_date, |
| 312 | $hash{dudt} = $set->due_date if defined $set->due_date; |
446 | dudt => $set->due_date, |
| 313 | $hash{andt} = $set->answer_date if defined $set->answer_date; |
447 | andt => $set->answer_date, |
|
|
448 | ); |
| 314 | } |
449 | } |
| 315 | |
450 | |
| 316 | # hash@problem($n, %hash) - places selected fields from a webwork |
451 | # hash@problem($n, %hash) - places selected fields from a webwork |
| 317 | # database record in a WeBWorK::Problem |
452 | # database record in a WeBWorK::Problem |
| 318 | # object, which is then returned. |
453 | # object, which is then returned. |
| … | |
… | |
| 331 | $problem->status ( $hash{"pst$n"} ) if defined $hash{"pst$n"}; |
466 | $problem->status ( $hash{"pst$n"} ) if defined $hash{"pst$n"}; |
| 332 | $problem->attempted ( $hash{"pat$n"} ) if defined $hash{"pat$n"}; |
467 | $problem->attempted ( $hash{"pat$n"} ) if defined $hash{"pat$n"}; |
| 333 | $problem->last_answer ( $hash{"pan$n"} ) if defined $hash{"pan$n"}; |
468 | $problem->last_answer ( $hash{"pan$n"} ) if defined $hash{"pan$n"}; |
| 334 | $problem->num_correct ( $hash{"pca$n"} ) if defined $hash{"pca$n"}; |
469 | $problem->num_correct ( $hash{"pca$n"} ) if defined $hash{"pca$n"}; |
| 335 | $problem->num_incorrect ( $hash{"pia$n"} ) if defined $hash{"pia$n"}; |
470 | $problem->num_incorrect ( $hash{"pia$n"} ) if defined $hash{"pia$n"}; |
| 336 | |
471 | return $problem; |
| 337 | } |
472 | } |
| 338 | |
473 | |
| 339 | # problem2hash($problem) - unpacks a WeBWorK::Problem object and returns PART |
474 | # problem2hash($problem) - unpacks a WeBWorK::Problem object and returns PART |
| 340 | # of a hash suitable for storage in the webwork |
475 | # of a hash suitable for storage in the webwork |
| 341 | # database. |
476 | # database. |
| 342 | # $problem - a WeBWorK::Problem object |
477 | # $problem - a WeBWorK::Problem object |
| 343 | sub problem2hash($) { |
478 | sub problem2hash($) { |
| 344 | my $problem = shift; |
479 | my $problem = shift; |
| 345 | my $n = $problem->id; |
480 | my $n = $problem->id; |
| 346 | my %hash; |
481 | # my %hash; |
| 347 | $hash{stnm} = $problem->set_id if defined $problem->set_id; |
482 | # $hash{stnm} = $problem->set_id if defined $problem->set_id; |
| 348 | $hash{stlg} = $problem->login_id if defined $problem->login_id; |
483 | # $hash{stlg} = $problem->login_id if defined $problem->login_id; |
| 349 | $hash{"pfn$n"} = $problem->source_file if defined $problem->source_file; |
484 | # $hash{"pfn$n"} = $problem->source_file if defined $problem->source_file; |
| 350 | $hash{"pva$n"} = $problem->value if defined $problem->value; |
485 | # $hash{"pva$n"} = $problem->value if defined $problem->value; |
| 351 | $hash{"pmia$n"}= $problem->max_attempts if defined $problem->max_attempts; |
486 | # $hash{"pmia$n"}= $problem->max_attempts if defined $problem->max_attempts; |
| 352 | $hash{"pse$n"} = $problem->problem_seed if defined $problem->problem_seed; |
487 | # $hash{"pse$n"} = $problem->problem_seed if defined $problem->problem_seed; |
| 353 | $hash{"pst$n"} = $problem->status if defined $problem->status; |
488 | # $hash{"pst$n"} = $problem->status if defined $problem->status; |
| 354 | $hash{"pat$n"} = $problem->attempted if defined $problem->attempted; |
489 | # $hash{"pat$n"} = $problem->attempted if defined $problem->attempted; |
| 355 | $hash{"pan$n"} = $problem->last_answer if defined $problem->last_answer; |
490 | # $hash{"pan$n"} = $problem->last_answer if defined $problem->last_answer; |
| 356 | $hash{"pca$n"} = $problem->num_correct if defined $problem->num_correct; |
491 | # $hash{"pca$n"} = $problem->num_correct if defined $problem->num_correct; |
| 357 | $hash{"pia$n"} = $problem->num_incorrect if defined $problem->num_incorrect; |
492 | # $hash{"pia$n"} = $problem->num_incorrect if defined $problem->num_incorrect; |
| 358 | return %hash; |
493 | # return %hash; |
|
|
494 | return ( |
|
|
495 | stnm => $problem->set_id, |
|
|
496 | stlg => $problem->login_id, |
|
|
497 | "pfn$n" => $problem->source_file, |
|
|
498 | "pva$n" => $problem->value, |
|
|
499 | "pmia$n" => $problem->max_attempts, |
|
|
500 | "pse$n" => $problem->problem_seed, |
|
|
501 | "pst$n" => $problem->status, |
|
|
502 | "pat$n" => $problem->attempted, |
|
|
503 | "pan$n" => $problem->last_answer, |
|
|
504 | "pca$n" => $problem->num_correct, |
|
|
505 | "pia$n" => $problem->num_incorrect, |
|
|
506 | |
|
|
507 | ); |
| 359 | } |
508 | } |
| 360 | |
509 | |
| 361 | 1; |
510 | 1; |