Annotation of loncom/interface/lonplacementtest.pm, revision 1.1
1.1 ! raeburn 1: # The LearningOnline Network with CAPA
! 2: # Handler to manage dependencies for HTML files uploaded directly
! 3: # to a course.
! 4: #
! 5: # $Id: lonplacementtest.pm,v 1.1 2016/03/31 21:57:13 raeburn Exp $
! 6: #
! 7: # Copyright Michigan State University Board of Trustees
! 8: #
! 9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
! 10: #
! 11: # LON-CAPA is free software; you can redistribute it and/or modify
! 12: # it under the terms of the GNU General Public License as published by
! 13: # the Free Software Foundation; either version 2 of the License, or
! 14: # (at your option) any later version.
! 15: #
! 16: # LON-CAPA is distributed in the hope that it will be useful,
! 17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
! 18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 19: # GNU General Public License for more details.
! 20: #
! 21: # You should have received a copy of the GNU General Public License
! 22: # along with LON-CAPA; if not, write to the Free Software
! 23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
! 24: # /home/httpd/html/adm/gpl.txt
! 25: #
! 26: # http://www.lon-capa.org/
! 27: #
! 28: #
! 29: ###############################################################
! 30: ###############################################################
! 31:
! 32: =pod
! 33:
! 34: =head1 NAME
! 35:
! 36: lonplacementtest - Handler to provide initial screen for student
! 37: after log-in and/or role selection for a Placement Test course container
! 38: which is currently partially completed.
! 39:
! 40: =head1 SYNOPSIS
! 41:
! 42: lonplacementtest provides an interface for the student to choose
! 43: whether to continue with an existing, partially completed test,
! 44: or whether to start a new test. Also provides utility functions
! 45: used to compute/export scores, and increment the course-wide maxtries
! 46: parameter for the user, when an instance of a test is complete.
! 47:
! 48: =head1 DESCRIPTION
! 49:
! 50: This module is used after student log-in and/or role selection
! 51: for a Placement Test course contained, if there is a current,
! 52: partially completed version of the test. The student is prompted
! 53: to choose whether to continue with the current test or start a
! 54: new one.
! 55:
! 56: =head1 INTERNAL SUBROUTINES
! 57:
! 58: =over
! 59:
! 60: =item check_completion()
! 61:
! 62: =back
! 63:
! 64: =cut
! 65:
! 66: package Apache::lonplacementtest;
! 67:
! 68: use strict;
! 69: use Apache::Constants qw(:common :http);
! 70: use Apache::lonnet;
! 71: use Apache::loncommon;
! 72: use Apache::lonhtmlcommon;
! 73: use Apache::lonnavmaps;
! 74: use Apache::lonpageflip;
! 75: use Apache::lonroles;
! 76: use Apache::lonparmset;
! 77: use Apache::lonlocal;
! 78: use LONCAPA qw(:DEFAULT :match);
! 79:
! 80: sub handler {
! 81: my $r=shift;
! 82: if ($r->header_only) {
! 83: &Apache::loncommon::content_type($r,'text/html');
! 84: $r->send_http_header;
! 85: return OK;
! 86: }
! 87: if (!$env{'request.course.fn'}) {
! 88: # Not in a course.
! 89: $env{'user.error.msg'}="/adm/lonplacementtest:bre:0:0:Not in a course";
! 90: return HTTP_NOT_ACCEPTABLE;
! 91: } elsif ($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement') {
! 92: # Not in a Placement Test
! 93: $env{'user.error.msg'}="/adm/lonplacementtest:bre:0:0:Not in a placement test";
! 94: return HTTP_NOT_ACCEPTABLE;
! 95: }
! 96: &Apache::loncommon::content_type($r,'text/html');
! 97: $r->send_http_header;
! 98: my ($totalpoints,$incomplete) = &check_completion(undef,undef,1);
! 99: if (($incomplete) && ($incomplete < 100) && (!$env{'request.role.adv'})) {
! 100: $r->print(&showincomplete($incomplete));
! 101: } else {
! 102: my $furl = &Apache::lonpageflip::first_accessible_resource();
! 103: my $cdesc = $env{'course.'.$env{'request.course.id'}.'.description'};
! 104: my $msg = &mt('Entering [_1] ...',$cdesc);
! 105: &Apache::lonroles::redirect_user($r, &mt('Entering [_1]',$cdesc),$furl, $msg);
! 106: }
! 107: return OK;
! 108: }
! 109:
! 110: sub check_completion {
! 111: my ($makenew,$map,$recursive) = @_;
! 112: my $navmap = Apache::lonnavmaps::navmap->new();
! 113: return unless (ref($navmap));
! 114: my @resources = $navmap->retrieveResources($map,
! 115: sub { $_[0]->is_problem() },$recursive);
! 116: my $currmax = 0;
! 117: my $totalpoints = 0;
! 118: my $totaldone = 0;
! 119: my $totalnotdone = 0;
! 120: my $incomplete;
! 121: if (@resources) {
! 122: my $firstsymb = $resources[0]->symb();
! 123: my %bytitle;
! 124: foreach my $res (@resources) {
! 125: my $currsymb = $res->symb();
! 126: my $title = $res->compTitle;
! 127: unless (exists($bytitle{$title})) {
! 128: $bytitle{$title} = 0;
! 129: }
! 130: my $notdone = 0;
! 131: my $done = 0;
! 132: my %storetries;
! 133: my $points = 0;
! 134: foreach my $part (@{$res->parts()}) {
! 135: my $tries = $res->tries($part);
! 136: my $maxtries = $res->maxtries($part);
! 137: if ($currmax < $maxtries) {
! 138: $currmax = $maxtries;
! 139: }
! 140: if ($tries < $maxtries) {
! 141: $notdone ++;
! 142: my $tries = $res->tries($part);
! 143: my @response_ids = $res->responseIds($part);
! 144: if (@response_ids) {
! 145: foreach my $id (@response_ids) {
! 146: $storetries{"resource.$part.$id.awarded"}=0;
! 147: $storetries{"resource.$part.$id.awarddetail"}='ASSIGNED_SCORE';
! 148: }
! 149: $storetries{"resource.$part.tries"}=$maxtries;
! 150: $storetries{"resource.$part.solved"}='incorrect_by_override';
! 151: $storetries{"resource.$part.award"}='ASSIGNED_SCORE';
! 152: $storetries{"resource.$part.awarded"}=0;
! 153: }
! 154: } else {
! 155: my $awarded = $res->awarded($part);
! 156: my $weight = $res->weight($part);
! 157: $points += $awarded * $weight;
! 158: $done ++;
! 159: }
! 160: }
! 161: if ($notdone) {
! 162: $totalnotdone += $notdone;
! 163: if ($makenew && keys(%storetries)) {
! 164: my $result=&Apache::lonnet::cstore(\%storetries,$currsymb,$env{'request.course.id'},
! 165: $env{'user.domain'},$env{'user.name'});
! 166: }
! 167: }
! 168: if ($done) {
! 169: $totaldone += $done;
! 170: }
! 171: $bytitle{$title} += $points;
! 172: $totalpoints += $points;
! 173: }
! 174: if ($makenew) {
! 175: my $newmax = $currmax + 1;
! 176: my $result =
! 177: &Apache::lonparmset::storeparm_by_symb_inner($firstsymb,'0_maxtries',
! 178: 4,$newmax,'int_pos',
! 179: $env{'user.name'},
! 180: $env{'user.domain'});
! 181: my %grades = (
! 182: uname => $env{'user.name'},
! 183: domain => $env{'user.domain'},
! 184: total => $totalpoints,
! 185: bytitle => \%bytitle,
! 186: );
! 187: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
! 188: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
! 189: if (($cnum ne '') && ($cdom ne '')) {
! 190: &Apache::lonnet::auto_export_grades($cnum,$cdom,\%grades);
! 191: }
! 192: }
! 193: }
! 194: my $totalparts = $totalnotdone + $totaldone;
! 195: if (($totalparts) && ($totalnotdone)) {
! 196: if (!$totaldone) {
! 197: $incomplete = 100;
! 198: } else {
! 199: my $undonepct = (100*$totalnotdone)/$totalparts;
! 200: $incomplete = sprintf("%0d",$undonepct);
! 201: }
! 202: }
! 203: return ($totalpoints,$incomplete);
! 204: }
! 205:
! 206: sub showresult {
! 207: my ($complete) = @_;
! 208: my ($score) = &Apache::lonplacementtest::check_completion(1,undef,1);
! 209: my %aclt = &test_action_text();
! 210: my $brcrum = [{'href' => '/adm/flip?postdata=firstres%3a',
! 211: 'text' => 'Test Status'},];
! 212: my $output = &Apache::loncommon::start_page('Placement Test Completed',
! 213: undef,{bread_crumbs=>$brcrum});
! 214: if ($complete) {
! 215: $output .= '<p class="LC_info">'.&mt('Test is complete').'</p>';
! 216: }
! 217: return $output
! 218: .'<p>'.&mt('You scored [quant,_1,point].',$score).'</p>'
! 219: .&Apache::lonhtmlcommon::actionbox(
! 220: ['<a href="/adm/flip?postdata=firstres%3a">'.$aclt{'newt'}.'</a></li>',
! 221: '<a href="/adm/logout">'.$aclt{'exit'}.'</a></li>',
! 222: ])
! 223: .&Apache::loncommon::end_page();
! 224: }
! 225:
! 226: sub showincomplete {
! 227: my ($incomplete) = @_;
! 228: my %aclt = &test_action_text();
! 229: if ($incomplete == 100) {
! 230: my $brcrum = [{'href' => '/adm/flip?postdata=firstres%3a',
! 231: 'text' => 'Test Status'},];
! 232: return &Apache::loncommon::start_page('Placement Test Unattempted',
! 233: undef,{bread_crumbs=>$brcrum})
! 234: .'<p class="LC_warning">'.&mt('Your Placement Test is incomplete.').'<p></p>'
! 235: .&mt('Currently, you have not submitted any answers for any of the questions.')
! 236: .'</p>'
! 237: .&Apache::lonhtmlcommon::actionbox(
! 238: ['<a href="/adm/flip?postdata=firstres%3a">'.$aclt{'begin'}.'</a></li>',
! 239: '<a href="/adm/logout">'.$aclt{'exit'}.'</a></li>',
! 240: ])
! 241: .&Apache::loncommon::end_page();
! 242: } elsif ($incomplete) {
! 243: my $brcrum = [{'href' => '/adm/flip?postdata=endplacement%3a',
! 244: 'text' => 'Test Status'},];
! 245: return &Apache::loncommon::start_page('Incomplete Placement Test',
! 246: undef,{bread_crumbs=>$brcrum})
! 247: .'<p class="LC_warning">'.&mt('Your Placement Test is incomplete.').'<p></p>'
! 248: .&mt('Currently, you have not provided an answer for [_1]% of the questions.',$incomplete)
! 249: .'</p>'
! 250: .&Apache::lonhtmlcommon::actionbox(
! 251: ['<a href="/adm/flip?postdata=endplacement%3a">'.$aclt{'endt'}.'</a></li>',
! 252: '<a href="/adm/flip?postdata=firstanswerable%3a">'.$aclt{'comp'}.'</a></li>',
! 253: '<a href="/adm/logout">'.$aclt{'exit'}.'</a></li>',
! 254: ])
! 255: .&Apache::loncommon::end_page();
! 256: }
! 257: }
! 258:
! 259: sub test_action_text {
! 260: return &Apache::lonlocal::texthash(
! 261: 'exit' => 'Logout',
! 262: 'newt' => 'Start a new test',
! 263: 'endt' => 'Mark test as completed',
! 264: 'comp' => 'Go to first unanswered question',
! 265: 'begin' => 'Go to start',
! 266: );
! 267: }
! 268:
! 269: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>