Annotation of loncom/interface/spreadsheet/studentcalc.pm, revision 1.21
1.1 matthew 1: #
1.21 ! matthew 2: # $Id: studentcalc.pm,v 1.20 2003/09/12 19:00:54 matthew Exp $
1.1 matthew 3: #
4: # Copyright Michigan State University Board of Trustees
5: #
6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
7: #
8: # LON-CAPA is free software; you can redistribute it and/or modify
9: # it under the terms of the GNU General Public License as published by
10: # the Free Software Foundation; either version 2 of the License, or
11: # (at your option) any later version.
12: #
13: # LON-CAPA is distributed in the hope that it will be useful,
14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: # GNU General Public License for more details.
17: #
18: # You should have received a copy of the GNU General Public License
19: # along with LON-CAPA; if not, write to the Free Software
20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21: #
22: # /home/httpd/html/adm/gpl.txt
23: #
24: # http://www.lon-capa.org/
25: #
26: # The LearningOnline Network with CAPA
27: # Spreadsheet/Grades Display Handler
28: #
29: # POD required stuff:
30:
31: =head1 NAME
32:
33: studentcalc
34:
35: =head1 SYNOPSIS
36:
37: =head1 DESCRIPTION
38:
39: =over 4
40:
41: =cut
42:
43: ###################################################
44: ### StudentSheet ###
45: ###################################################
46: package Apache::studentcalc;
47:
1.17 matthew 48: use warnings FATAL=>'all';
49: no warnings 'uninitialized';
50:
1.1 matthew 51: use strict;
52: use Apache::Constants qw(:common :http);
53: use Apache::lonnet;
1.3 matthew 54: use Apache::loncommon();
55: use Apache::loncoursedata();
1.1 matthew 56: use Apache::lonnavmaps;
1.3 matthew 57: use Apache::Spreadsheet();
58: use Apache::assesscalc();
1.1 matthew 59: use HTML::Entities();
60: use Spreadsheet::WriteExcel;
61: use Time::HiRes;
62:
63: @Apache::studentcalc::ISA = ('Apache::Spreadsheet');
64:
65: my @Sequences = ();
66: my %Exportrows = ();
67:
68: my $current_course;
69:
1.8 matthew 70: sub initialize {
1.11 matthew 71: &Apache::assesscalc::initialize();
1.8 matthew 72: &initialize_sequence_cache();
73: }
74:
1.1 matthew 75: sub initialize_package {
76: $current_course = $ENV{'request.course.id'};
77: &initialize_sequence_cache();
78: &load_cached_export_rows();
1.8 matthew 79: }
80:
81: sub ensure_correct_sequence_data {
82: if ($current_course ne $ENV{'request.course.id'}) {
83: &initialize_sequence_cache();
84: $current_course = $ENV{'request.course.id'};
85: }
86: return;
1.1 matthew 87: }
88:
89: sub initialize_sequence_cache {
90: #
91: # Set up the sequences and assessments
92: @Sequences = ();
93: my ($top,$sequences,$assessments) =
94: &Apache::loncoursedata::get_sequence_assessment_data();
95: if (! defined($top) || ! ref($top)) {
96: # There has been an error, better report it
1.2 matthew 97: &Apache::lonnet::logthis('top is undefined (studentcalc.pm)');
1.1 matthew 98: return;
99: }
100: @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');
101: }
102:
103: sub clear_package {
1.17 matthew 104: undef(@Sequences);
105: undef(%Exportrows);
1.18 matthew 106: &Apache::assesscalc::clear_package();
1.1 matthew 107: }
108:
109: sub get_title {
110: my $self = shift;
1.6 matthew 111: my @title = ();
112: #
113: # Determine the students name
1.3 matthew 114: my %userenv = &Apache::loncoursedata::GetUserName($self->{'name'},
115: $self->{'domain'});
1.6 matthew 116: my $name = join(' ',
117: @userenv{'firstname','middlename','lastname','generation'});
1.3 matthew 118: $name =~ s/\s+$//;
1.6 matthew 119:
120: push (@title,$name);
121: push (@title,$self->{'coursedesc'});
122: push (@title,scalar(localtime(time)));
123: return @title;
124: }
125:
126: sub get_html_title {
127: my $self = shift;
128: my ($name,$desc,$time) = $self->get_title();
129: my $title = '<h1>'.$name;
1.3 matthew 130: if ($ENV{'user.name'} ne $self->{'name'} &&
131: $ENV{'user.domain'} ne $self->{'domain'}) {
1.19 matthew 132: $title .= ' '.&Apache::loncommon::aboutmewrapper
1.3 matthew 133: ($self->{'name'}.'@'.$self->{'domain'},
134: $self->{'name'},$self->{'domain'});
135: }
136: $title .= "</h1>\n";
1.6 matthew 137: $title .= '<h2>'.$desc."</h2>\n";
138: $title .= '<h3>'.$time.'</h3>';
1.1 matthew 139: return $title;
140: }
141:
142: sub parent_link {
143: my $self = shift;
1.21 ! matthew 144: return '<p><a href="/adm/classcalc">Course level sheet</a></p>'."\n";
1.1 matthew 145: }
146:
1.14 matthew 147: sub convenience_links {
148: my $self = shift;
149: my ($resource) = @_;
150: my $symb = &Apache::lonnet::escape($resource->{'symb'});
151: my $result = <<"END";
152: <a href="/adm/grades?symb=$symb&command=submission" target="LONcatInfo">
153: <img src="/adm/lonMisc/subm_button.gif" border=0 />
154: </a>
155: <a href="/adm/grades?symb=$symb&command=gradingmenu" target="LONcatInfo">
156: <img src="/adm/lonMisc/pgrd_button.gif" border=0 />
157: </a>
158: <a href="/adm/parmset?symb=$symb" target="LONcatInfo">
159: <img src="/adm/lonMisc/pprm_button.gif" border=0 />
160: </a>
161: END
162: return $result;
163: }
164:
1.1 matthew 165: sub outsheet_html {
166: my $self = shift;
167: my ($r) = @_;
1.13 matthew 168: my $importcolor = '#FFFFAA';
1.12 matthew 169: my $exportcolor = '#88FF88';
1.1 matthew 170: ####################################
171: # Get the list of assessment files #
172: ####################################
173: my @AssessFileNames = $self->othersheets('assesscalc');
1.2 matthew 174: my $editing_is_allowed = &Apache::lonnet::allowed('mgr',
175: $ENV{'request.course.id'});
1.1 matthew 176: ####################################
177: # Determine table structure #
178: ####################################
179: my $num_uneditable = 26;
180: my $num_left = 52-$num_uneditable;
181: my $tableheader =<<"END";
1.2 matthew 182: <p>
1.1 matthew 183: <table border="2">
184: <tr>
185: <th colspan="2" rowspan="2"><font size="+2">Student</font></th>
1.12 matthew 186: <td bgcolor="$importcolor" colspan="$num_uneditable">
1.1 matthew 187: <b><font size="+1">Import</font></b></td>
188: <td colspan="$num_left">
189: <b><font size="+1">Calculations</font></b></td>
190: </tr><tr>
191: END
192: my $label_num = 0;
193: foreach (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')){
194: if ($label_num<$num_uneditable) {
1.12 matthew 195: $tableheader .='<td bgcolor="'.$importcolor.'">';
1.1 matthew 196: } else {
197: $tableheader .='<td>';
198: }
199: $tableheader .="<b><font size=+1>$_</font></b></td>";
200: $label_num++;
201: }
202: $tableheader .="</tr>\n";
1.4 matthew 203: if ($self->blackout()) {
204: $r->print('<font color="red" size="+2"><p>'.
205: 'Some computations are not available at this time.<br />'.
206: 'There are problems whose status you are allowed to view.'.
207: '</font></p>'."\n");
208: } else {
209: $r->print($tableheader);
210: #
211: # Print out template row
212: if (exists($ENV{'request.role.adv'}) && $ENV{'request.role.adv'}) {
213: $r->print('<tr><td>Template</td><td> </td>'.
1.12 matthew 214: $self->html_template_row($num_uneditable,
215: $importcolor)."</tr>\n");
1.4 matthew 216: }
217: #
218: # Print out summary/export row
219: $r->print('<tr><td>Summary</td><td>0</td>'.
1.12 matthew 220: $self->html_export_row($exportcolor)."</tr>\n");
1.4 matthew 221: }
1.1 matthew 222: $r->print("</table>\n");
223: #
224: # Prepare to output rows
1.4 matthew 225: if (exists($ENV{'request.role.adv'}) && $ENV{'request.role.adv'}) {
226: $tableheader =<<"END";
1.2 matthew 227: </p><p>
1.1 matthew 228: <table border="2">
1.14 matthew 229: <tr><th>Row</th><th> </th><th>Assessment</th>
1.1 matthew 230: END
1.4 matthew 231: } else {
232: $tableheader =<<"END";
233: </p><p>
234: <table border="2">
235: <tr><th> </th><th>Assessment</th>
236: END
237: }
1.1 matthew 238: foreach (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')){
239: if ($label_num<$num_uneditable) {
240: $tableheader.='<td bgcolor="#FFDDDD">';
241: } else {
242: $tableheader.='<td>';
243: }
244: $tableheader.="<b><font size=+1>$_</font></b></td>";
245: }
246: $tableheader.="\n";
247: #
248: my $num_output = 1;
249: if (scalar(@Sequences)< 1) {
250: &initialize_sequence_cache();
251: }
252: foreach my $Sequence (@Sequences) {
253: next if ($Sequence->{'num_assess'} < 1);
254: $r->print("<h3>".$Sequence->{'title'}."</h3>\n");
255: $r->print($tableheader);
256: foreach my $resource (@{$Sequence->{'contents'}}) {
257: next if ($resource->{'type'} ne 'assessment');
258: my $rownum = $self->get_row_number_from_key($resource->{'symb'});
259: my $assess_filename = $self->{'row_source'}->{$rownum};
1.2 matthew 260: my $row_output = '<tr>';
261: if ($editing_is_allowed) {
262: $row_output .= '<td>'.$rownum.'</td>';
1.14 matthew 263: $row_output .= '<td>'.$self->convenience_links($resource).'</td>';
1.2 matthew 264: $row_output .= '<td>'.
265: '<a href="/adm/assesscalc?sname='.$self->{'name'}.
266: '&sdomain='.$self->{'domain'}.
267: '&filename='.$assess_filename.
1.4 matthew 268: '&usymb='.&Apache::lonnet::escape($resource->{'symb'}).
269: '">'.$resource->{'title'}.'</a><br />';
1.2 matthew 270: $row_output .= &assess_file_selector($rownum,
271: $assess_filename,
272: \@AssessFileNames).
273: '</td>';
274: } else {
275: $row_output .= '<td><a href="'.$resource->{'src'}.'?symb='.
1.4 matthew 276: &Apache::lonnet::escape($resource->{'symb'}).
277: '">Go To</a>';
1.2 matthew 278: $row_output .= '</td><td>'.$resource->{'title'}.'</td>';
279: }
1.4 matthew 280: if ($self->blackout() && $self->{'blackout_rows'}->{$rownum}>0) {
281: $row_output .=
282: '<td colspan="52">Unavailable at this time</td></tr>'."\n";
283: } else {
1.12 matthew 284: $row_output .= $self->html_row($num_uneditable,$rownum,
285: $exportcolor,$importcolor).
1.4 matthew 286: "</tr>\n";
287: }
1.1 matthew 288: $r->print($row_output);
289: }
290: $r->print("</table>\n");
291: }
1.2 matthew 292: $r->print("</p>\n");
1.1 matthew 293: return;
294: }
295:
296: ########################################################
297: ########################################################
298:
299: =pod
300:
301: =item &assess_file_selector()
302:
303: =cut
304:
305: ########################################################
306: ########################################################
307: sub assess_file_selector {
308: my ($row,$default,$AssessFiles)=@_;
1.2 matthew 309: if (!defined($AssessFiles) || ! @$AssessFiles) {
310: return '';
311: }
1.1 matthew 312: return '' if (! &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}));
313: my $element_name = 'FileSelect_'.$row;
314: my $load_dialog = '<select size="1" name="'.$element_name.'" '.
315: 'onchange="'.
316: "document.sheet.cell.value='source_$row';".
317: "document.sheet.newformula.value=document.sheet.$element_name\.value;".
318: 'document.sheet.submit()" '.'>'."\n";
319: foreach my $file (@{$AssessFiles}) {
320: $load_dialog .= ' <option name="'.$file.'"';
321: $load_dialog .= ' selected' if ($default eq $file);
322: $load_dialog .= '>'.$file."</option>\n";
323: }
324: $load_dialog .= "</select>\n";
325: return $load_dialog;
326: }
327:
328: sub modify_cell {
329: my $self = shift;
330: my ($cell,$formula) = @_;
331: if ($cell =~ /^source_(\d+)$/) {
332: # Need to make sure $formula is a valid filename....
333: my $row = $1;
334: $cell = 'A'.$row;
335: $self->{'row_source'}->{$row} = $formula;
336: my $original_source = $self->formula($cell);
337: if ($original_source =~ /__&&&__/) {
338: ($original_source,undef) = split('__&&&__',$original_source);
339: }
340: $formula = $original_source.'__&&&__'.$formula;
341: } elsif ($cell =~ /([A-z])\-/) {
342: $cell = 'template_'.$1;
343: } elsif ($cell !~ /^([A-z](\d+)|template_[A-z])$/) {
344: return;
345: }
346: $self->set_formula($cell,$formula);
347: $self->rebuild_stats();
348: return;
349: }
350:
1.7 matthew 351: sub csv_rows {
352: # writes the meat of the spreadsheet to an excel worksheet. Called
353: # by Spreadsheet::outsheet_excel;
1.1 matthew 354: my $self = shift;
1.7 matthew 355: my ($filehandle) = @_;
356: #
357: # Write a header row
358: $self->csv_output_row($filehandle,undef,
1.10 matthew 359: ('Sequence or Folder','Assessment title'));
1.7 matthew 360: #
361: # Write each assessments row
362: if (scalar(@Sequences)< 1) {
363: &initialize_sequence_cache();
364: }
365: foreach my $Sequence (@Sequences) {
366: next if ($Sequence->{'num_assess'} < 1);
367: foreach my $resource (@{$Sequence->{'contents'}}) {
368: my $rownum = $self->get_row_number_from_key($resource->{'symb'});
369: my @assessdata = ($Sequence->{'title'},
370: $resource->{'title'});
371: $self->csv_output_row($filehandle,$rownum,@assessdata);
372: }
373: }
374: return;
1.1 matthew 375: }
1.6 matthew 376:
377: sub excel_rows {
378: # writes the meat of the spreadsheet to an excel worksheet. Called
379: # by Spreadsheet::outsheet_excel;
1.1 matthew 380: my $self = shift;
1.6 matthew 381: my ($worksheet,$cols_output,$rows_output) = @_;
382: #
383: # Write a header row
384: $cols_output = 0;
385: foreach my $value ('Container','Assessment title') {
386: $worksheet->write($rows_output,$cols_output++,$value);
387: }
388: $rows_output++;
389: #
390: # Write each assessments row
391: if (scalar(@Sequences)< 1) {
392: &initialize_sequence_cache();
393: }
394: foreach my $Sequence (@Sequences) {
395: next if ($Sequence->{'num_assess'} < 1);
396: foreach my $resource (@{$Sequence->{'contents'}}) {
397: my $rownum = $self->get_row_number_from_key($resource->{'symb'});
398: my @assessdata = ($Sequence->{'title'},
399: $resource->{'title'});
400: $self->excel_output_row($worksheet,$rownum,$rows_output++,
401: @assessdata);
402: }
403: }
404: return;
1.1 matthew 405: }
1.6 matthew 406:
1.1 matthew 407: sub outsheet_recursive_excel {
408: my $self = shift;
409: my ($r) = @_;
410: }
411:
412: sub compute {
413: my $self = shift;
1.18 matthew 414: my ($r) = @_;
415: my $connection = $r->connection();
416: if ($connection->aborted()) { $self->cleanup; return; }
1.1 matthew 417: if (! defined($current_course) ||
418: $current_course ne $ENV{'request.course.id'}) {
419: $current_course = $ENV{'request.course.id'};
420: &clear_package();
421: &initialize_sequence_cache();
422: }
423: $self->initialize_safe_space();
424: my @sequences = @Sequences;
425: if (@sequences < 1) {
426: my ($top,$sequences,$assessments) =
427: &Apache::loncoursedata::get_sequence_assessment_data();
428: if (! defined($top) || ! ref($top)) {
429: &Apache::lonnet::logthis('top is undefined');
430: return;
431: }
432: @sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');
433: }
434: &Apache::assesscalc::initialize_package($self->{'name'},$self->{'domain'});
435: my %f = $self->formulas();
436: #
437: # Process the formulas list -
438: # the formula for the A column of a row is symb__&&__filename
439: my %c = $self->constants();
440: foreach my $seq (@sequences) {
441: next if ($seq->{'num_assess'}<1);
442: foreach my $resource (@{$seq->{'contents'}}) {
1.18 matthew 443: if ($connection->aborted()) { $self->cleanup(); return; }
1.1 matthew 444: next if ($resource->{'type'} ne 'assessment');
445: my $rownum = $self->get_row_number_from_key($resource->{'symb'});
446: my $cell = 'A'.$rownum;
447: my $assess_filename = 'Default';
448: if (exists($self->{'row_source'}->{$rownum})) {
449: $assess_filename = $self->{'row_source'}->{$rownum};
450: } else {
451: $self->{'row_source'}->{$rownum} = $assess_filename;
452: }
453: $f{$cell} = $resource->{'symb'}.'__&&&__'.$assess_filename;
1.18 matthew 454: if ($connection->aborted()) { $self->cleanup(); return; }
1.1 matthew 455: my $assessSheet = Apache::assesscalc->new($self->{'name'},
456: $self->{'domain'},
457: $assess_filename,
458: $resource->{'symb'});
1.18 matthew 459: my @exportdata = $assessSheet->export_data($r);
460: if ($connection->aborted()) { $self->cleanup(); return; }
1.4 matthew 461: if ($assessSheet->blackout()) {
462: $self->blackout(1);
463: $self->{'blackout_rows'}->{$rownum} = 1;
464: }
1.1 matthew 465: #
466: # Be sure not to disturb the formulas in the 'A' column
467: my $data = shift(@exportdata);
468: $c{$cell} = $data if (defined($data));
469: #
470: # Deal with the remaining columns
471: my $i=0;
472: foreach (split(//,'BCDEFGHIJKLMNOPQRSTUVWXYZ')) {
473: my $cell = $_.$rownum;
474: my $data = shift(@exportdata);
475: if (defined($data)) {
476: $f{$cell} = 'import';
477: $c{$cell} = $data;
478: }
479: $i++;
480: }
481: }
482: }
483: $self->constants(\%c);
484: $self->formulas(\%f);
485: $self->calcsheet();
486: #
487: # Store export row in cache
488: my @exportarray=$self->exportrow();
489: my $student = $self->{'name'}.':'.$self->{'domain'};
490: $Exportrows{$student}->{'time'} = time;
491: $Exportrows{$student}->{'data'} = \@exportarray;
492: # save export row
493: $self->save_export_data();
1.9 matthew 494: #
495: $self->save() if ($self->need_to_save());
496: return;
497: }
498:
499: sub set_row_sources {
500: my $self = shift;
501: while (my ($cell,$value) = each(%{$self->{'formulas'}})) {
1.17 matthew 502: next if ($cell !~ /^A(\d+)$/ || $1 < 1);
1.9 matthew 503: my $row = $1;
504: (undef,$value) = split('__&&&__',$value);
505: $value = 'Default' if (! defined($value));
506: $self->{'row_source'}->{$row} = $value;
507: }
1.1 matthew 508: return;
509: }
510:
511: sub set_row_numbers {
512: my $self = shift;
513: while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {
514: next if ($cell !~ /^A(\d+)/);
515: my $row = $1;
516: next if ($row == 0);
517: my ($symb,undef) = split('__&&&__',$formula);
518: $self->{'row_numbers'}->{$symb} = $row;
1.17 matthew 519: $self->{'maxrow'} = $row if ($row > $self->{'maxrow'});
1.1 matthew 520: }
521: }
522:
523: sub get_row_number_from_symb {
524: my $self = shift;
525: my ($key) = @_;
526: ($key,undef) = split('__&&&__',$key) if ($key =~ /__&&&__/);
527: return $self->get_row_number_from_key($key);
528: }
529:
530: #############################################
531: #############################################
532:
533: =pod
534:
535: =item &load_cached_export_rows
536:
537: Retrieves and parsers the export rows of the student spreadsheets.
538: These rows are saved in the courses directory in the format:
539:
540: sname:sdom:studentcalc:.time => time
541:
542: sname:sdom:studentcalc => ___=___Adata___;___Bdata___;___Cdata___;___ .....
543:
544: =cut
545:
546: #############################################
547: #############################################
548: sub load_cached_export_rows {
1.17 matthew 549: undef(%Exportrows);
1.1 matthew 550: my @tmp = &Apache::lonnet::dump('nohist_calculatedsheets',
551: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
552: $ENV{'course.'.$ENV{'request.course.id'}.'.num'},undef);
553: my %Selected_Assess_Sheet;
554: if ($tmp[0] =~ /^error/) {
555: &Apache::lonnet::logthis('unable to read cached student export rows '.
556: 'for course '.$ENV{'request.course.id'});
557: return;
558: }
559: my %tmp = @tmp;
560: while (my ($key,$sheetdata) = each(%tmp)) {
561: my ($sname,$sdom,$sheettype,$remainder) = split(':',$key);
562: my $student = $sname.':'.$sdom;
563: if ($remainder =~ /\.time/) {
564: $Exportrows{$student}->{'time'} = $sheetdata;
565: } else {
566: $sheetdata =~ s/^___=___//;
567: my @Data = split('___;___',$sheetdata);
568: $Exportrows{$student}->{'data'} = \@Data;
569: }
570: }
571: }
572:
573: #############################################
574: #############################################
575:
576: =pod
577:
578: =item &save_export_data()
579:
580: Writes the export data for this student to the course cache.
581:
582: =cut
583:
584: #############################################
585: #############################################
586: sub save_export_data {
587: my $self = shift;
1.20 matthew 588: &Apache::assesscalc::save_cached_export_rows($self->{'name'},
589: $self->{'domain'});
1.5 matthew 590: return if ($self->temporary());
1.1 matthew 591: my $student = $self->{'name'}.':'.$self->{'domain'};
592: return if (! exists($Exportrows{$student}));
593: return if (! $self->is_default());
594: my $key = join(':',($self->{'name'},$self->{'domain'},'studentcalc')).':';
595: my $timekey = $key.'.time';
596: my $newstore = join('___;___',
597: @{$Exportrows{$student}->{'data'}});
598: $newstore = '___=___'.$newstore;
1.16 matthew 599: my $result= &Apache::lonnet::put('nohist_calculatedsheets',
1.1 matthew 600: { $key => $newstore,
601: $timekey => $Exportrows{$student}->{'time'} },
602: $self->{'cdom'},
603: $self->{'cnum'});
604: return;
605: }
606:
607: #############################################
608: #############################################
609:
610: =pod
611:
612: =item &export_data()
613:
614: Returns the export data associated with the spreadsheet. Computes the
615: spreadsheet only if necessary.
616:
617: =cut
618:
619: #############################################
620: #############################################
621: sub export_data {
622: my $self = shift;
1.18 matthew 623: my ($r) = @_;
624: my $connection = $r->connection();
1.1 matthew 625: my $student = $self->{'name'}.':'.$self->{'domain'};
626: if (! exists($Exportrows{$student}) ||
1.15 matthew 627: ! defined($Exportrows{$student}) ||
1.16 matthew 628: ! exists($Exportrows{$student}->{'data'}) ||
1.15 matthew 629: ! defined($Exportrows{$student}->{'data'}) ||
1.16 matthew 630: ! exists($Exportrows{$student}->{'time'}) ||
631: ! defined($Exportrows{$student}->{'time'}) ||
1.1 matthew 632: ! $self->check_expiration_time($Exportrows{$student}->{'time'})) {
1.18 matthew 633: $self->compute($r);
1.1 matthew 634: }
1.18 matthew 635: if ($connection->aborted()) { $self->cleanup(); return; }
1.1 matthew 636: my @Data = @{$Exportrows{$student}->{'data'}};
637: for (my $i=0; $i<=$#Data;$i++) {
638: $Data[$i]="'".$Data[$i]."'" if ($Data[$i]=~/\D/ && defined($Data[$i]));
639: }
640: return @Data;
641: }
642:
643: 1;
644:
645: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>