[$i]->[2] =~ s/(\'$|^\')//g;
}
+ return $dataset;
}
+ return undef; # error occurred
+}
- my $heading = 'Process Course Data';
- my $title = 'LON-CAPA Statistics';
- my $studentCount = scalar(@students);
- if($status eq 'true') {
- &Apache::lonhtmlcommon::Create_PrgWin($r, $title, $heading);
+sub RT_student_id { return 0; }
+sub RT_awarded { return 1; }
+sub RT_tries { return 2; }
+sub RT_timestamp { return 3; }
+
+sub get_response_time_data {
+ my ($sections,$groups,$enrollment,$symb,$part,$courseid) = @_;
+ return undef if (! defined($symb) ||
+ ! defined($part));
+ $courseid = $env{'request.course.id'} if (! defined($courseid));
+ #
+ &setup_table_names($courseid);
+ my $symb_id = &get_symb_id($symb);
+ if (! defined($symb_id)) {
+ &Apache::lonnet::logthis('Unable to find symb for '.$symb.' in '.$courseid);
+ return undef;
+ }
+ my $part_id = &get_part_id($part);
+ if (! defined($part_id)) {
+ &Apache::lonnet::logthis('Unable to find id for '.$part.' in '.$courseid);
+ return undef;
+ }
+ #
+ my $dbh = &Apache::lonmysql::get_dbh();
+ return undef if (! defined($dbh));
+ my ($student_requirements,$enrollment_requirements) =
+ &limit_by_section_and_status($sections,$enrollment,'d');
+ my ($groups_join,$group_limits) = &limit_by_group($groups,'d','e','f');
+ my $request = 'SELECT '.
+ 'a.student_id, a.awarded, a.tries, b.timestamp '.
+ 'FROM '.$fulldump_part_table.' AS a '.
+ 'LEFT JOIN '.$fulldump_timestamp_table.' AS b '.
+ 'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '.
+ 'a.transaction = b.transaction '.
+ 'LEFT JOIN '.$student_table.' as d '.
+ 'ON a.student_id=d.student_id '.
+ $groups_join;
+ my $limit = ' WHERE '.
+ 'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
+ if (defined($student_requirements)) {
+ $limit .= ' AND '.$student_requirements;
+ }
+ if (defined($enrollment_requirements)) {
+ $limit .= ' AND '.$enrollment_requirements;
+ }
+ if (defined($group_limits)) {
+ $limit .= ' AND '.$group_limits;
+ }
+ $request .= $limit.' ORDER BY b.timestamp';
+# &Apache::lonnet::logthis("request =\n".$request);
+ my $sth = $dbh->prepare($request);
+ $sth->execute();
+ if ($dbh->err) {
+ &Apache::lonnet::logthis('error 5 = '.$dbh->errstr());
+ &Apache::lonnet::logthis('prepared then executed '.$/.$request);
+ return undef;
+ }
+ my $dataset = $sth->fetchall_arrayref();
+ if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
+ return $dataset;
}
- my $count=1;
- foreach my $name (@students) {
- last if($c->aborted());
+}
- if($status eq 'true') {
- my $displayString = $count.'/'.$studentCount.': '.$name;
- &Apache::lonhtmlcommon::Update_PrgWin($displayString, $r);
- }
+################################################
+################################################
- if($extract eq 'true') {
- &ExtractStudentData(\%downloadData, \%cache, \%cache, $name);
- } else {
- &ProcessStudentData(\%cache, \%downloadData, $name);
- }
- $count++;
- }
+=pod
- if($status eq 'true') { &Apache::lonhtmlcommon::Close_PrgWin($r); }
+=item &get_student_scores($Sections,$Groups,$Symbs,$enrollment,$courseid)
- untie(%cache);
- untie(%downloadData);
+=cut
- if(!$c->aborted()) {
- my @files = ($residualFile);
- unlink(@files);
+################################################
+################################################
+sub get_student_scores {
+ my ($sections,$groups,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;
+ $courseid = $env{'request.course.id'} if (! defined($courseid));
+ &setup_table_names($courseid);
+ my $dbh = &Apache::lonmysql::get_dbh();
+ return (undef) if (! defined($dbh));
+ my $tmptable = $courseid.'_temp_'.time;
+ my $request = 'DROP TABLE IF EXISTS '.$tmptable;
+# &Apache::lonnet::logthis('request = '.$/.$request);
+ $dbh->do($request);
+ #
+ my $symb_requirements;
+ if (defined($Symbs) && @$Symbs) {
+ $symb_requirements = '('.
+ join(' OR ', map{ "(a.symb_id='".&get_symb_id($_->{'symb'}).
+ "' AND a.part_id='".&get_part_id($_->{'part'}).
+ "')"
+ } @$Symbs).')';
+ }
+ #
+ my ($student_requirements,$enrollment_requirements) =
+ &limit_by_section_and_status($sections,$enrollment,'b');
+ #
+ my ($groups_join,$group_limits) = &limit_by_group($groups,'b','d','e');
+ my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');
+ ##
+ $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
+ ' SELECT a.student_id,SUM(a.awarded*c.weight) AS score FROM '.
+ $performance_table.' AS a ';
+ $request .= "LEFT JOIN ".$weight_table.' AS c ON a.symb_id=c.symb_id AND a.part_id=c.part_id ';
+ if (defined($student_requirements) || defined($enrollment_requirements)) {
+ $request .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id ';
+ }
+ if (defined($groups_join)) {
+ $request .= $groups_join;
+ }
+ if (defined($symb_requirements) ||
+ defined($student_requirements) ||
+ defined($enrollment_requirements) ||
+ defined($group_limits) ) {
+ $request .= ' WHERE ';
+ }
+ if (defined($symb_requirements)) {
+ $request .= $symb_requirements.' AND ';
+ }
+ if (defined($student_requirements)) {
+ $request .= $student_requirements.' AND ';
+ }
+ if (defined($enrollment_requirements)) {
+ $request .= $enrollment_requirements.' AND ';
+ }
+ if (defined($time_requirements)) {
+ $request .= $time_requirements.' AND ';
+ }
+ $request =~ s/ AND $//; # Strip of the trailing ' AND '.
+ $request .= ' GROUP BY a.student_id';
+# &Apache::lonnet::logthis("request = \n".$request);
+ my $sth = $dbh->prepare($request);
+ $sth->execute();
+ if ($dbh->err) {
+ &Apache::lonnet::logthis('error 6 = '.$dbh->errstr());
+ &Apache::lonnet::logthis('prepared then executed '.$/.$request);
+ return undef;
+ }
+ $request = 'SELECT score,COUNT(*) FROM '.$tmptable.' GROUP BY score';
+# &Apache::lonnet::logthis("request = \n".$request);
+ $sth = $dbh->prepare($request);
+ $sth->execute();
+ if ($dbh->err) {
+ &Apache::lonnet::logthis('error 7 = '.$dbh->errstr());
+ &Apache::lonnet::logthis('prepared then executed '.$/.$request);
+ return undef;
}
+ my $dataset = $sth->fetchall_arrayref();
+ return $dataset;
+}
+
+################################################
+################################################
+
+=pod
+
+=item &setup_table_names()
+
+input: course id
+
+output: none
+
+Cleans up the package variables for local caching.
+
+=cut
+
+################################################
+################################################
+sub setup_table_names {
+ my ($courseid) = @_;
+ if (! defined($courseid)) {
+ $courseid = $env{'request.course.id'};
+ }
+ #
+ if (! defined($current_course) || $current_course ne $courseid) {
+ # Clear out variables
+ $have_read_part_table = 0;
+ undef(%ids_by_part);
+ undef(%parts_by_id);
+ $have_read_symb_table = 0;
+ undef(%ids_by_symb);
+ undef(%symbs_by_id);
+ $have_read_student_table = 0;
+ undef(%ids_by_student);
+ undef(%students_by_id);
+ $have_read_groupnames_table = 0;
+ undef(%ids_by_groupname);
+ #
+ $current_course = $courseid;
+ }
+ #
+ # Set up database names
+ my $base_id = $courseid;
+ $symb_table = $base_id.'_'.'symb';
+ $part_table = $base_id.'_'.'part';
+ $student_table = $base_id.'_'.'student';
+ $groupnames_table = $base_id.'_'.'groupnames';
+ $students_groups_table = $base_id.'_'.'studentgroups';
+ $performance_table = $base_id.'_'.'performance';
+ $parameters_table = $base_id.'_'.'parameters';
+ $fulldump_part_table = $base_id.'_'.'partdata';
+ $fulldump_response_table = $base_id.'_'.'responsedata';
+ $fulldump_timestamp_table = $base_id.'_'.'timestampdata';
+ $weight_table = $base_id.'_'.'weight';
+ #
+ @Tables = (
+ $symb_table,
+ $part_table,
+ $student_table,
+ $groupnames_table,
+ $students_groups_table,
+ $performance_table,
+ $parameters_table,
+ $fulldump_part_table,
+ $fulldump_response_table,
+ $fulldump_timestamp_table,
+ $weight_table,
+ );
+ return;
+}
+
+################################################
+################################################
+
+=pod
+
+=back
+
+=item End of Local Data Caching Subroutines
+
+=cut
+
+################################################
+################################################
+
+} # End scope of table identifiers
- return 'OK';
+################################################
+################################################
+
+=pod
+
+=head3 Classlist Subroutines
+
+=item &get_classlist();
+
+Retrieve the classist of a given class or of the current class. Student
+information is returned from the classlist.db file and, if needed,
+from the students environment.
+
+Optional arguments are $cdom, and $cnum (course domain,
+and course number, respectively). If either is ommitted the course
+will be taken from the current environment ($env{'request.course.id'},
+$env{'course.'.$cid.'.domain'}, and $env{'course.'.$cid.'.num'}).
+
+Returns a reference to a hash which contains:
+ keys '$sname:$sdom'
+ values [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype]
+
+The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used
+as indices into the returned list to future-proof clients against
+changes in the list order.
+
+=cut
+
+################################################
+################################################
+
+sub CL_SDOM { return 0; }
+sub CL_SNAME { return 1; }
+sub CL_END { return 2; }
+sub CL_START { return 3; }
+sub CL_ID { return 4; }
+sub CL_SECTION { return 5; }
+sub CL_FULLNAME { return 6; }
+sub CL_STATUS { return 7; }
+sub CL_TYPE { return 8; }
+sub CL_LOCKEDTYPE { return 9; }
+
+sub get_classlist {
+ my ($cdom,$cnum) = @_;
+ my $cid = $cdom.'_'.$cnum;
+ if (!defined($cdom) || !defined($cnum)) {
+ $cid = $env{'request.course.id'};
+ $cdom = $env{'course.'.$cid.'.domain'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ }
+ my $now = time;
+ #
+ my %classlist=&Apache::lonnet::dump('classlist',$cdom,$cnum);
+ while (my ($student,$info) = each(%classlist)) {
+ if ($student =~ /^(con_lost|error|no_such_host)/i) {
+ &Apache::lonnet::logthis('get_classlist error for '.$cid.':'.$student);
+ return undef;
+ }
+ my ($sname,$sdom) = split(/:/,$student);
+ my @Values = split(/:/,$info);
+ my ($end,$start,$id,$section,$fullname,$type,$lockedtype);
+ if (@Values > 2) {
+ ($end,$start,$id,$section,$fullname,$type,$lockedtype) = @Values;
+ } else { # We have to get the data ourselves
+ ($end,$start) = @Values;
+ $section = &Apache::lonnet::getsection($sdom,$sname,$cid);
+ my %info=&Apache::lonnet::get('environment',
+ ['firstname','middlename',
+ 'lastname','generation','id'],
+ $sdom, $sname);
+ my ($tmp) = keys(%info);
+ if ($tmp =~/^(con_lost|error|no_such_host)/i) {
+ $fullname = 'not available';
+ $id = 'not available';
+ &Apache::lonnet::logthis('unable to retrieve environment '.
+ 'for '.$sname.':'.$sdom);
+ } else {
+ $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
+ $id = $info{'id'};
+ }
+ # Update the classlist with this students information
+ if ($fullname ne 'not available') {
+ my $enrolldata = join(':',$end,$start,$id,$section,$fullname);
+ my $reply=&Apache::lonnet::cput('classlist',
+ {$student => $enrolldata},
+ $cdom,$cnum);
+ if ($reply !~ /^(ok|delayed)/) {
+ &Apache::lonnet::logthis('Unable to update classlist for '.
+ 'student '.$sname.':'.$sdom.
+ ' error:'.$reply);
+ }
+ }
+ }
+ my $status='Expired';
+ if(((!$end) || $now < $end) && ((!$start) || ($now > $start))) {
+ $status='Active';
+ }
+ $classlist{$student} =
+ [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype];
+ }
+ if (wantarray()) {
+ return (\%classlist,['domain','username','end','start','id',
+ 'section','fullname','status','type','lockedtype']);
+ } else {
+ return \%classlist;
+ }
}
-sub GetFileTimestamp {
- my ($studentDomain,$studentName,$filename,$root)=@_;
- $studentDomain=~s/\W//g;
- $studentName=~s/\W//g;
- my $subdir=$studentName.'__';
- $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
- my $proname="$studentDomain/$subdir/$studentName";
- $proname .= '/'.$filename;
- my @dir = &Apache::lonnet::dirlist($proname, $studentDomain, $studentName,
- $root);
- my $fileStat = $dir[0];
- my @stats = split('&', $fileStat);
- if($stats[0] ne 'empty' && $stats[0] ne 'no_such_dir') {
- return $stats[9];
+sub get_group_memberships {
+ my ($classlist,$keylist,$cdom,$cnum) = @_;
+
+ return ({},{}) if (!ref($classlist) || !ref($keylist));
+
+ my $cid = $cdom.'_'.$cnum;
+ if (!defined($cdom) || !defined($cnum)) {
+ $cid = $env{'request.course.id'};
+ $cdom = $env{'course.'.$cid.'.domain'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ }
+ my (%classgroups,%studentgroups);
+ my $now = time;
+ my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};
+ my %curr_groups =&Apache::longroup::coursegroups($cdom,$cnum);
+ if (%curr_groups) {
+ my $grpindex = scalar(@{$keylist});
+ my %groupmemberhash =
+ &Apache::lonnet::get_group_membership($cdom,$cnum);
+ foreach my $student (keys(%{$classlist})) {
+ %{$classgroups{$student}} = ();
+ my $hasgroup = 0;
+ foreach my $status ('previous','future','active','aftercourse') {
+ %{$classgroups{$student}{$status}} = ();
+ }
+ foreach my $group (keys(%curr_groups)) {
+ if (defined($groupmemberhash{$group.':'.$student})) {
+ my ($end,$start) = split(/:/,$groupmemberhash{$group.':'.
+ $student});
+ if ($start == -1) {
+ next;
+ } else {
+ $studentgroups{$group} ++;
+ $hasgroup = 1;
+ if ($end && $end < $now) {
+ $classgroups{$student}{'previous'}{$group} =
+ $groupmemberhash{$group.':'.$student};
+ if ($classlist->{$student}[&CL_STATUS()] eq 'Expired') {
+ if ($access_end && $access_end < $now) {
+ if ($access_end - $end < 86400) {
+ $classgroups{$student}{'aftercourse'}{$group} = $groupmemberhash{$group.':'.$student};
+ }
+ }
+ }
+ } elsif ($now > $start) {
+ if (!$end || $end > $now) {
+ $classgroups{$student}{'active'}{$group} =
+ $groupmemberhash{$group.':'.$student};
+ }
+ } else {
+ $classgroups{$student}{'future'}{$group} =
+ $groupmemberhash{$group.':'.$student};
+ }
+ }
+ }
+ }
+ if (!$hasgroup) {
+ $studentgroups{'none'} ++;
+ } else {
+ $classlist->{$student}->[$grpindex] = join(',',
+ sort(keys(%{$classgroups{$student}{'active'}})));
+ }
+ }
+ }
+ return (\%classgroups,\%studentgroups);
+}
+
+sub get_students_groups {
+ my ($student,$enrollment_status,$classgroups) = @_;
+ my @studentsgroups = ();
+ if (ref($$classgroups{$student}{'active'}) eq 'HASH') {
+ push(@studentsgroups,keys(%{$$classgroups{$student}{'active'}}));
+ }
+ if ($enrollment_status eq 'Any') {
+ foreach my $status ('previous','future') {
+ if (ref($$classgroups{$student}{$status}) eq 'HASH') {
+ push(@studentsgroups,keys(%{$$classgroups{$student}{$status}}));
+ }
+ }
} else {
- return -1;
+ if (ref($$classgroups{$student}{'aftercourse'}) eq 'HASH') {
+ push(@studentsgroups,keys(%{$$classgroups{$student}{'aftercourse'}}));
+ }
}
+ return @studentsgroups;
}
+
# ----- END HELPER FUNCTIONS --------------------------------------------
1;
__END__
+
500 Internal Server Error
Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete
your request.
Please contact the server administrator at
root@localhost to inform them of the time this error occurred,
and the actions you performed just before this error.
More information about this error may be available
in the server error log.