File:  [LON-CAPA] / loncom / interface / lonplacementtest.pm
Revision 1.1: download - view: text, annotated - select for diffs
Sat Apr 2 04:30:21 2016 UTC (8 years, 2 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- Bug 6808. New course container -- "Placement" for Placement Tests.
  Work in progress.

    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/04/02 04:30:21 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>