File:  [LON-CAPA] / modules / gci / londocsgci.pm
Revision 1.10: download - view: text, annotated - select for diffs
Sat Jan 9 01:07:56 2010 UTC (14 years, 3 months ago) by gci
Branches: MAIN
CVS tags: HEAD
- Customization for GCI_3 to keep IE8 happy.
  - Use ids for form tags for question checkboxes and bin counts.
  - Use document.getElementById(id) to retrieve the form element
     for Javascript operations.

    1: # The LearningOnline Network
    2: # Custom Edit Course Routines for Assembly of Valid Concept Tests from
    3: # Geoscience Concept Inventory. 
    4: #
    5: # $Id: londocsgci.pm,v 1.10 2010/01/09 01:07:56 gci 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: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: # http://www.lon-capa.org/
   28: #
   29: 
   30: 
   31: package Apache::londocsgci;
   32: 
   33: use strict;
   34: 
   35: use Apache::lonnet;
   36: use Apache::loncommon;
   37: use LONCAPA::map();
   38: use Apache::lonindexer;
   39: use Apache::lonlocal;
   40: use LONCAPA qw(:DEFAULT :match);
   41: 
   42: {  #scope variables 
   43:  
   44: my $path;
   45: my $version;
   46: my $reqnum;
   47: my @mandcats;
   48: my @bincats;
   49: my @categories;
   50: my @allprobs;
   51: my %probcat;
   52: my %prereqs;
   53: my %revreqs;
   54: my @defchosen;
   55: my @chosen;
   56: my @mandprobs;
   57: my @bins;
   58: my @optional;
   59: my %mandatory;
   60: my @development;
   61: 
   62: sub setdefaults {
   63:    $path='/res/gci/gci';
   64:    $version='GCIv2-1-1';
   65:    $reqnum=15;
   66:    @allprobs=('01','02','37','2004_73','03','04','05','06','07',
   67:               '08','10',
   68:               '09',
   69:               '11','12','13','14','15','16','17',
   70:               '18','69',
   71:               '19','20',
   72:               '21','22','23','24','25','26','27','28','29','30',
   73:               '31','32','33','34','35','36','38',
   74:               '39A','39B',
   75:               '40',
   76:               '41','42','43','44','45','46','47','48','49','50',
   77:               '51',
   78:               '52','57',
   79:               '53','54','55','56','58',
   80:               '60',
   81:               '61','62','63','64','65','66','67','68','70',
   82:               '71');
   83:     @bins = ( ['03','04','06'],
   84:               ['07','08','09'],
   85:               ['10','12','13','14','15','16','17'],
   86:               ['18','19','20','21','22','23','24','25'],
   87:               ['26','27','28','30'],
   88:               ['32','33','34','35','36'],
   89:               ['38','39A','39B','40','41','42','43','44','45','46'],
   90:               ['47','48','49','50','51','52','53'],
   91:               ['54','55','56','57','58','60','61','62'],
   92:               ['63','64','65'],
   93:               ['66','67','68','69','70','71']);
   94:     @optional = ('05','11','29','31');
   95:     @mandcats = ('M1','M2','M3','M4');
   96:     @bincats = ('A','B','C','D','E','F','G','H','I','J','K');
   97:     @categories=(@mandcats,@bincats);
   98:     %probcat =('01' => 'M1' ,'02' => 'M2' ,'37' => 'M3' ,'2004_73' => 'M4' ,
   99:               '03' => 'A' ,'04' => 'A','05' => ''  ,'06' => 'A' ,'07' => 'B' ,
  100:               '08' => 'B' ,'09' => 'B' ,'10' => 'C' ,'11' => ''  ,'12' => 'C' ,
  101:               '13' => 'C' ,'14' => 'C' ,'15' => 'C' ,'16' => 'C' ,'17' => 'C' ,'18' => 'D' ,'19' => 'D' ,'20' => 'D' ,
  102:               '21' => 'D' ,'22' => 'D' ,'23' => 'D' ,'24' => 'D' ,'25' => 'D' ,'26' => 'E' ,'27' => 'E' ,'28' => 'E' ,'29' => ''  ,'30' => 'E' ,
  103:               '31' => ''  ,'32' => 'F' ,'33' => 'F' ,'34' => 'F' ,'35' => 'F' ,'36' => 'F' ,'38' => 'G' ,
  104:               '39A'=> 'G' ,'39B'=> 'G' ,
  105:               '40' => 'G' ,
  106:               '41' => 'G' ,'42' => 'G' ,'43' => 'G' ,'44' => 'G' ,'45' => 'G' ,'46' => 'G' ,'47' => 'H' ,'48' => 'H' ,'49' => 'H' ,'50' => 'H' ,
  107:               '51' => 'H' ,'52' => 'H' ,'53' => 'H' ,'54' => 'I' ,'55' => 'I' ,'56' => 'I' ,'57' => 'I' ,'58' => 'I' ,
  108:               '60' => 'I' ,
  109:               '61' => 'I' ,'62' => 'I' ,'63' => 'J' ,'64' => 'J' ,'65' => 'J' ,'66' => 'K' ,'67' => 'K' ,'68' => 'K' ,'69' => 'K' ,'70' => 'K' ,
  110:               '71' => 'K');
  111:     %mandatory=('01' => 1 ,'02' => 1,'37' => 1, '2004_73' => 1);
  112:     @mandprobs = ('01','02','37','2004_73');
  113:     %prereqs=('10' => '08', '57' => '52', '69' => '18');
  114:     foreach my $item (keys(%prereqs)) {
  115:         $revreqs{$prereqs{$item}} = $item;
  116:     }
  117:     @defchosen=('01','02','03','07','12','18','26','32','37','38','47','54','63','66','2004_73');
  118:     @development = ('001','002','003','004','005','006','007','008','009','010','011','012','013','014');
  119: }
  120: 
  121: sub checkvalid {
  122:    my %covered=();
  123:    my %chosenproblems=();
  124:    my @errors=();
  125:    my $num=$#chosen+1;
  126:    if ($num<$reqnum) {
  127:       push(@errors,&mt('Test requires at least [_1] items, but has only [_2].',$reqnum,$num)); 
  128:    }
  129:    foreach my $item (@chosen) {
  130:       $chosenproblems{$item}=1;
  131:       $covered{$probcat{$item}}=1;
  132:    }
  133:    foreach my $cat (@categories) {
  134:       unless ($covered{$cat}) {
  135:          push(@errors,&mt('Bin [_1] not covered.',$cat));
  136:       }
  137:    }
  138:    foreach my $item (@chosen) {
  139:        if ($prereqs{$item}) {
  140:           unless ($chosenproblems{$prereqs{$item}}) {
  141:               my $url = &fullurl($item);
  142:               my $title = &Apache::lonnet::metadata($url,'title');
  143:               my $prerequrl = &fullurl($prereqs{$item});
  144:               my $prereqtitle = &Apache::lonnet::metadata($prerequrl,'title');
  145:               push(@errors,&mt('[_1] requires [_2].',"'$title'","'$prereqtitle'"));
  146:           }
  147:        }
  148:    }
  149:    return @errors;
  150: }
  151: 
  152: sub fullurl {
  153:    my ($item,$catname)=@_;
  154:    unless ($item=~/\_/) { $item='_'.$item; }
  155:    if ($catname eq 'development') {
  156:        return $path.'/pilot/pilot'.$item.'.problem';
  157:    }
  158:    return $path.'/'.$version.'/GCI'.$item.'.problem';
  159: }
  160: 
  161: sub item_from_url {
  162:     my ($url)=@_;
  163:     if ($url =~ m{\Q$path\E/\Q$version\E/GCI_?([^.]+)\.problem$}) {
  164:         return $1;
  165:     }
  166: }
  167: 
  168: sub validcheck {
  169:    my ($r)=@_;
  170:    my @errors=&checkvalid();
  171:    if ($#errors>-1) {
  172:       $r->print('<span class="LC_error">'.&mt('Your test is not yet valid.').'</span><p>'.&mt('The following issues must be addressed before you can use the test:').'<ul>');
  173:       foreach my $message (@errors) {
  174:          $r->print('<li>'.$message.'</li>');
  175:       }
  176:       $r->print('</ul></p>');
  177:       return 0;
  178:    }
  179:    return 1;
  180: }
  181: 
  182: sub listresources {
  183:    my ($r,$context,$cdom,$cnum)=@_;
  184:    my $numchosen = scalar(@chosen);
  185:    my $multipart = 0;
  186:    my $composites;
  187:    if ($numchosen > 0) {
  188:        foreach my $key (keys(%prereqs)) {
  189:            if (grep(/^\Q$key\E/,@chosen)) {
  190:                $multipart ++;
  191:                $numchosen --;
  192:            }
  193:        }
  194:        if ($multipart) {
  195:            $composites = &mt(' (of which [quant,_1,is a combination question,are combination questions] in which students select both an answer, and the reasoning used).',$multipart).'<br />';
  196:        } else {
  197:            $composites = '.&nbsp;';
  198:        }
  199:    }
  200:    unless ($numchosen > 0) {
  201:       $r->print('<h3>'.&mt('Create a Concept Test').'</h3>'.
  202:                 '<p>'.&mt('Choose how the test should be built:').'<br />'.
  203:                 '<form name="choices" method="post" action="/adm/coursedocs" onsubmit="javascript:setDocsPhase();">'.
  204:                 '<label><input type="radio" name="concepttest" value="defchosen" />'.&mt('Have a valid test built automatically by the WebCenter.').'</label><br />'.
  205:                 '<label><input type="radio" name="concepttest" value="editmyown" checked="checked" />'.&mt('Make your own selection of questions from the Geoscience Concept Inventory.').'</label><br /><br />'.
  206:                 '<input type="hidden" name="phase" value="" />'.
  207:                 '<input type="submit" name="choosetest" value="'.&mt('Next').'"></p>');
  208:        return;
  209:    }
  210:    if ((!&validcheck($r)) || ($env{'form.concepttest'} eq 'editmyown')) {
  211:       &editor($r,$context,$cdom,$cnum);
  212:    } else {
  213:       my $numsub = &get_submissions_count($cdom,$cnum);
  214:       unless ($env{'form.phase'} eq 'storemap') {
  215:           $r->print('<p>'.&mt('This course contains a valid concept test which includes [quant,_1,question]',$numchosen).$composites.'<a href="/adm/navmaps" target="_coursecontents">'.&mt('Display Contents').'</a><br />');
  216:       }
  217:       if ($numsub > 0) {
  218:           $r->print(&mt('As there are existing student submissions, modification of the [_1]contents[_2] of the Concept Test will result in loss of student performance data, and is [_3]not[_4] permitted.','<i>','</i>','<b>','</b>').'<br />'.&mt('Modification of open and close dates [_1]is[_2] permitted.','<b>','</b>').'</p>');
  219:       } else {
  220:           $r->print('<fieldset><legend>'.&mt('Modify Test').'</legend>'.
  221:                     &mt('Currently no student submissions have been recorded, so you may modify the contents of the Concept Test.').
  222:                     '<br /><form name="changetest" method="post" action="/adm/coursedocs">'.
  223:                     '<input type="hidden" name="concepttest" value="editmyown" />'.
  224:                     '<input type="submit" name="modifytest" value="'.&mt('Edit Concept Test').'" /></form></fieldset></p>');
  225:       }
  226:       my ($crsparms,$ineffect,$parmlev) = &current_parms($cdom,$cnum);
  227:       my $formname = 'datesform';
  228:       my $datebutton = &mt('Save');
  229:       my $startform =
  230:           &Apache::lonhtmlcommon::date_setter($formname,'opendate',
  231:                                               $crsparms->{'opendate'});
  232:       my $endform =
  233:           &Apache::lonhtmlcommon::date_setter($formname,'duedate',
  234:                                                            $crsparms->{'duedate'});
  235:       $r->print('<p><fieldset><legend>'.&mt('Test Availability').'</legend>'.
  236:                 &mt('Open and close dates for test items for the concept test are currently set as follows:').
  237:                 '<br />'.
  238:                 '<form name="'.$formname.'" method="post" '.
  239:                 'action="/adm/coursedocs">'.
  240:                 &Apache::lonhtmlcommon::start_pick_box().
  241:                 &Apache::lonhtmlcommon::row_title(&mt('Open date')).
  242:                 $startform.
  243:                 &Apache::lonhtmlcommon::row_closure(1).
  244:                 &Apache::lonhtmlcommon::row_title(&mt('Close date')).
  245:                 $endform.
  246:                 &Apache::lonhtmlcommon::row_closure(1).
  247:                 &Apache::lonhtmlcommon::end_pick_box().'<br />'. 
  248:                 '<input type="hidden" name="phase" value="storeparms" />'.
  249:                 '<input type="submit" value="'.$datebutton.'" />'.
  250:                 '</form></fieldset></p>');
  251:    }
  252: }
  253: 
  254: sub editor {
  255:     my ($r,$context,$cdom,$cnum)=@_;
  256:     my %chosenitems=();
  257:     my $havedev = 0;
  258:     foreach my $item (@chosen) {
  259:         $chosenitems{$item}=1;
  260:     }
  261:     my @devitems = &get_development_questions($cdom,$cnum);
  262:     &Apache::lonnet::appenv({'request.gcicontext' => 'buildtest'});
  263:     $r->print('<form name="selecteditems" method="post" action="/adm/coursedocs"
  264:               onsubmit="return validTestCheck()">');
  265:     $r->print(&mt('Select test items from the numbered bins below and then press [_1]"Store Problem Selection"[_2] at the bottom of the page.','<i>','</i>').'<br />');
  266:     $r->print('<ul>'.
  267:               '<li>'.&mt('Tests will contain a minimum of [_1] questions from the GCI 2 Inventory.',"<b>$reqnum</b>").'</li>'.
  268:               '<li>'.&mt('Tests must contain [_1]four[_2] mandatory questions and at least one item from each of [_1]eleven[_2] other bins.','<b>','</b>').'</li>'.
  269:               '<li>'.&mt('All tests conclude with [_1]two[_2] questions selected by the system (at random) from a pool of development questions being piloted by the GCI team.','<b>','</b>').'</li>'.
  270:               '</ul>');
  271:     my $mandleg = &mt('Mandatory Questions');
  272:     $r->print(&display_questions(\@mandprobs,'mandatory',$mandleg,\%chosenitems));
  273:     for (my $i=0; $i<@bins; $i++) {
  274:         my $num = $i+1;
  275:         my $legend = &mt('Bin [_1]',$num);
  276:         my $catname = 'bin'.$i;
  277:         $r->print(&display_questions($bins[$i],$catname,$legend,\%chosenitems));
  278:     }
  279:     my $optleg = &mt('Optional Questions');
  280:     $r->print(&display_questions(\@optional,'optional',$optleg,\%chosenitems));
  281:     my $devleg = &mt('Development Questions');
  282:     $r->print(&display_questions(\@devitems,'development',$devleg,\%chosenitems));
  283:     $r->print('<input type="hidden" name="phase" value="storemap" />'.
  284:               '<input type="hidden" name="context" value="'.$context.'" />'.
  285:               '<input type="submit" value="'.&mt('Store Problem Selection').'" />'.
  286:               '</form>');
  287:     &Apache::lonnet::delenv('request.gcicontext');
  288: }
  289: 
  290: sub display_questions {
  291:     my ($questions,$catname,$catlegend,$chosenitems) = @_;
  292:     return unless((ref($questions) eq 'ARRAY') && (ref($chosenitems) eq 'HASH'));
  293:     my $total = 0;
  294:     foreach my $item (@{$questions}) {
  295:         if ($chosenitems->{$item}) {
  296:             $total ++;
  297:         }
  298:     }
  299:     my $fieldid = 'GCI_'.$catname.'_q';
  300:     my $titleid = 'GCI_'.$catname.'_t';
  301:     my $countid = 'GCI_'.$catname.'_count';
  302:     my $output = '<fieldset>';
  303:     my %fixed = (
  304:         mandatory   => 4,
  305:         development => 2, 
  306:     );
  307:     if (($catname eq 'mandatory') || ($catname eq 'development')) {
  308:         $output .= '<legend>'.&mt('[_1] [_2] selected automatically',$catlegend,
  309:                    '<input type="text" name="'.$countid.'" size="1" '.
  310:                    'value="'.$fixed{$catname}.'" readonly="readonly" />').'</legend>';
  311:     } else {
  312:         $output .= '<legend>'.&mt('[_1]: currently [_2] selected',$catlegend,
  313:                    '<input type="text" name="'.$countid.'" id="'.$countid.'" size="1" value="'.
  314:                    $total.'" readonly="readonly" />').'</legend>';
  315:     }
  316:     $output .= '<span id="'.$titleid.'">'.
  317:               '<a href="javascript:showQuestions('."'$fieldid','$titleid'".')">'.
  318:               &mt('Show').'</a> ...</span><br />'.
  319:               '<div id="'.$fieldid.'">'.
  320:               &Apache::loncommon::start_data_table().
  321:               &Apache::loncommon::start_data_table_header_row();
  322:     unless (($catname eq 'development') || ($catname eq 'mandatory')) {
  323:         $output .= '<th>'.&mt('Select').'</th>';
  324:     }
  325:     $output .= '<th>'.&mt('Problem').
  326:                '</th><th>'.&mt('Preview').'</th>'.
  327:                &Apache::loncommon::end_data_table_header_row();
  328:     foreach my $item (@{$questions}) {
  329:         my $url = &fullurl($item,$catname);
  330:         my $title = &Apache::lonnet::metadata($url,'title');
  331:         $output .= &Apache::loncommon::start_data_table_row().'<td>';
  332:         if ($catname eq 'mandatory') {
  333:             $output .= '<input type="hidden" name="item'.$item.'" value="checked" />';
  334:         } elsif ($catname eq 'development') {
  335:             $output .= '<input type="hidden" name="pilot'.$item.'" value="checked" />';
  336:         } else {
  337:             $output .= '<input type="checkbox" name="item'.$item.'" id="item'.$item.'"';
  338:             if ($chosenitems->{$item}) { $output .= ' checked="checked"'; }
  339:             $output .= ' onclick="countChecked('."'$catname'".');';
  340:             my $binname;
  341:             if ($prereqs{$item}) {
  342:                 for (my $i=0; $i<@bincats; $i++) {
  343:                     if ($bincats[$i] eq $probcat{$prereqs{$item}}) {
  344:                         $binname = 'bin'.$i; 
  345:                         last;
  346:                     }
  347:                 }
  348:                 $output .= 'checkPrereqs('."'dep','$item','$prereqs{$item}','$binname'".');';
  349:             } elsif ($revreqs{$item}) {
  350:                 for (my $i=0; $i<@bincats; $i++) {
  351:                     if ($bincats[$i] eq $probcat{$item}) {
  352:                         $binname = 'bin'.$i;
  353:                         last;
  354:                     }
  355:                 }
  356:                 $output .= 'checkPrereqs('."'pre','$revreqs{$item}','$item','$binname'".');';
  357:             }
  358:             $output .= '" />'.
  359:                        '<input type="hidden" name="container'.$item.'" value="'.
  360:                        $catname.'"></td><td>';
  361:         }
  362:         $output .= '<b>'.$title.'</b></td>';
  363:         my $content=&Apache::lonindexer::showpreview($url);
  364:         $output .= '<td> '.($content eq '' ? '&nbsp;':$content).' </td>'."\n".
  365:                    &Apache::loncommon::end_data_table_row();
  366:     }
  367:     $output .= &Apache::loncommon::end_data_table().
  368:                '</div></fieldset><br />';
  369:     return $output;
  370: }
  371: 
  372: sub get_development_questions {
  373:     my ($cdom,$cnum) = @_;
  374:     my $cid = $cdom.'_'.$cnum;
  375:     my %courseenv = &Apache::lonnet::userenvironment($cdom,$cnum,
  376:                         ('internal.courseowner'));
  377:     my $seed = $courseenv{'internal.courseowner'};
  378:     my $rndseed=&Apache::lonnet::rndseed($seed,$cid,$cdom,$cnum);
  379:     &Apache::lonnet::setup_random_from_rndseed($rndseed);
  380:     my @devitems = &Math::Random::random_permutation(@development);
  381:     return ($devitems[0],$devitems[1]); 
  382: }
  383: 
  384: sub evaluate {
  385:    if ($env{'form.phase'} eq 'storemap') {
  386:       @chosen=();
  387:       foreach my $item (@allprobs) {
  388:          if ($env{'form.item'.$item}) {
  389:             push(@chosen,$item);
  390:          }
  391:       }
  392:    }
  393: }
  394: 
  395: sub mapread_gci {
  396:     my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
  397:     my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
  398:     return
  399:       &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/default_1261144274.sequence');
  400: }
  401: 
  402: sub storemap_gci {
  403:     my ($coursedom,$coursenum) = @_;
  404:     if (($coursedom !~ /^$match_domain$/) || ($coursenum !~ /^$match_courseid$/)) { 
  405:         $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
  406:         $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
  407:     }
  408:     return ('unauthorized',2) if (($coursedom eq '') || ($coursedom eq '') ||
  409:                    (!&Apache::lonnet::allowed('mdc',$coursedom.'_'.$coursenum)));
  410:     my ($outtext,$errtext)=
  411:         &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/default_1261144274.sequence',1);
  412:     if ($errtext) { return ($errtext,2); }
  413:     return ($errtext,0);
  414: }
  415: 
  416: sub chosen_to_map {
  417:    my %chosenproblems=();
  418:    foreach my $item (@chosen) {
  419:       $chosenproblems{$item}=1;
  420:    }
  421:    @LONCAPA::map::order=();
  422:    @LONCAPA::map::resources=();
  423:    my $counter = 0;
  424:    my $residx;
  425:    for (my $idx=0;$idx<=$#allprobs;$idx++) {
  426:        $residx=$idx+1;
  427:        if ($chosenproblems{$allprobs[$idx]}) {
  428:           my $url  = &LONCAPA::map::qtunescape(&fullurl($allprobs[$idx]));
  429:           if (($revreqs{$allprobs[$idx]}) && 
  430:               ($chosenproblems{$revreqs{$allprobs[$idx]}})) {
  431:               my $probnum = '_'.$allprobs[$idx].'_'.$revreqs{$allprobs[$idx]};
  432:               $url = &LONCAPA::map::qtunescape(&fullurl($probnum));
  433:           } elsif ($prereqs{$allprobs[$idx]}) {
  434:               next;
  435:           }
  436:           push(@LONCAPA::map::order,$residx);
  437:           $counter ++;
  438: 	  my $name = &LONCAPA::map::qtunescape('Problem '.$counter);
  439: 	  $LONCAPA::map::resources[$residx]=join(':', ($name, $url, 'false', 'normal', 'res'));
  440:        }
  441:     }
  442:     foreach my $devitem (@development) {
  443:         if ($env{'form.pilot'.$devitem}) {
  444:             my $url = &LONCAPA::map::qtunescape(&fullurl($devitem,'development'));
  445:             $residx ++;
  446:             push(@LONCAPA::map::order,$residx);
  447:             $counter ++;
  448:             my $name = &LONCAPA::map::qtunescape('Problem '.$counter);
  449:             $LONCAPA::map::resources[$residx]=join(':', ($name, $url, 'false', 'normal', 'res'));
  450:         }
  451:     }
  452: }
  453: 
  454: sub map_to_chosen {
  455:     @chosen=();
  456:     foreach my $idx (@LONCAPA::map::order) {
  457:        my ($title,$url)=split(':',$LONCAPA::map::resources[$idx]);
  458:        my $item;
  459:        unless ($url eq '') {
  460:            $item = &item_from_url($url);
  461:            if (($item =~ /^(\d+)_(\d+)$/) && ($prereqs{$2} eq $1)) {
  462:                push(@chosen,($1,$2));
  463:            } else {
  464:                push(@chosen,$item);
  465:            }
  466:        }
  467:     }
  468:     if (($env{'form.concepttest'} eq 'defchosen') || 
  469:         ((@chosen == 0) && ($env{'form.concepttest'} eq 'editmyown'))) {
  470:         @chosen = @defchosen;
  471:     }
  472: }
  473: 
  474: sub store {
  475:    my ($caller,$cdom,$cnum)=@_;
  476:    if ($env{'form.concepttest'} eq 'defchosen') {
  477:        @chosen = @defchosen;
  478:    }
  479:    my @errors=&checkvalid();
  480:    if (@errors > 0) {
  481:        if (($caller eq 'requestcrs') && ($env{'form.concepttest'} eq 'defchosen')) {
  482:            return &mt('Invalid concept test.');
  483:        } else {
  484:            my $errormsg = '<span class="LC_warning">'.&mt('Invalid concept test:');
  485:            if (@errors > 1) {
  486:                $errormsg .= '<ul><li>'.join('</li><li>',@errors).'</li></ul>';
  487:            } else {
  488:                $errormsg .= '<br />'.$errors[0];
  489:            }
  490:            $errormsg .= '</span>';
  491:            return $errormsg;
  492:        }
  493:    }
  494:    &chosen_to_map();
  495:    my ($err,$errnum) = &storemap_gci($cdom,$cnum);
  496:    if ($caller eq 'requestcrs') {
  497:        if ($errnum == 0) {
  498:            return; 
  499:        } else {
  500:            return 'An error occurred when storing the concept test';
  501:        }
  502:    }
  503:    if ($env{'form.phase'} eq 'storemap') {
  504:       if ($errnum == 0) {
  505:          &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
  506:          return '<p>'.&mt('You have successfully assembled a valid test.').'</p>'.
  507:                 '<p><a href="/adm/navmaps">'.&mt('Display Table of Contents').
  508:                 '</a>'.('&nbsp;' x4).'<a href="/adm/menu">'.&mt('Return to Main Menu').'</a></p>';
  509:       } else {
  510:           return '<div class="LC_error">'.&mt('An error occurred when storing your concept test: [_1].',$err).'</div>';
  511:       }
  512:    }
  513:    return;
  514: }
  515: 
  516: sub load {
  517:    &mapread_gci();
  518:    &map_to_chosen();
  519:    if (@chosen > 0) {
  520:        my @errors=&checkvalid();
  521:        if ($#errors>1) { @chosen=@defchosen; }
  522:    }
  523: }
  524: 
  525: sub current_parms {
  526:     my ($cdom,$cnum) = @_;
  527:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
  528:     my (%crsparms,%ineffect,%parmlev);
  529:     foreach my $item ('opendate','duedate') {
  530:         $crsparms{$item} = $courseopt->{$env{'request.course.id'}.'.0.'.$item};
  531:         my ($result,@outpar) =
  532:             &Apache::lonparmset::parmval('0.'.$item,'0.0',undef,undef,
  533:                                          $cdom,undef,undef,$courseopt);
  534:         if ($result) {
  535:             $ineffect{$item} = $outpar[$result];
  536:             $parmlev{$item} = $result;
  537:         }
  538:     }
  539:     return (\%crsparms,\%ineffect,\%parmlev);
  540: }
  541: 
  542: sub store_dates_parms {
  543:     my ($cdom,$cnum) = @_;
  544:     my $topsymb = '___0___uploaded/'.$cdom.'/'.$cnum.'/default.sequence';
  545:     my ($opendate,$duedate) = 
  546:         &Apache::lonuserutils::get_dates_from_form('opendate','duedate');
  547:     my %dates = (
  548:                   opendate => {
  549:                                value => $opendate,
  550:                                type  => 'date_start',
  551:                               },
  552:                   duedate => {
  553:                                value => $duedate,
  554:                                type  => 'date_end',
  555:                              },
  556:                 );
  557:     my %parmresult;
  558:     foreach my $date (keys(%dates)) {
  559:         $parmresult{$date} =
  560:             &Apache::lonparmset::storeparm_by_symb($topsymb,
  561:                                    '0_'.$date,14,$dates{$date}{'value'},
  562:                                    $dates{$date}{'type'},undef,$cdom);
  563:     }
  564:     my $output = &mt('Open and Close dates set for test items').'<ul>'.
  565:                  '<li>'.&mt('Concept Test Questions open:').' '.
  566:                         &Apache::lonlocal::locallocaltime($opendate).'</li>'.
  567:                  '<li>'.&mt('Concept Test Questions close:').' '.
  568:                         &Apache::lonlocal::locallocaltime($duedate).'</li>'.
  569:                  '</ul>';
  570:     return $output;
  571: }
  572: 
  573: sub get_submissions_count {
  574:     my ($cdom,$cnum) = @_;
  575:     my $navmap = Apache::lonnavmaps::navmap->new();
  576:     if (!defined($navmap)) {
  577:         my $itemserror = '<span class="LC_warning">'.&mt('An error occurred retrieving information about the course.').'<br />'.&mt('It is recommended that you [_1]re-select the course[_2].','<a href="/adm/roles">','</a>').'</span>';
  578:         return $itemserror;
  579:     }
  580:     my @allres=$navmap->retrieveResources('/uploaded/'.$cdom.'/'.$cnum.'/default_1261144274.sequence',sub {if ($_[0]->is_problem) { $_[0]->parts();} return 1;});
  581:     my (%resourcetracker,$submissioncount);
  582:     my %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',
  583:                                                  $cdom,$cnum);
  584:     foreach my $resource (@allres) {
  585:         my $symb = $resource->symb();
  586:         my @parts = @{$resource->parts()};
  587:         foreach my $part (@parts) {
  588:             if ($resource->handgrade($part) eq 'yes') {
  589:                 next;
  590:             }
  591:             if ($resource->is_survey($part)) {
  592:                 next;
  593:             }
  594:             if (exists($resourcetracker{$symb."\0".$part."\0users"})) {
  595:                 $submissioncount += $resourcetracker{$symb."\0".$part."\0users"};
  596:             }
  597:         }
  598:     }
  599:     return $submissioncount;
  600: }
  601: 
  602: sub builder_javascript {
  603:     my %lt = &Apache::lonlocal::texthash(
  604:                                           show => 'Show',
  605:                                           hide => 'Hide',
  606:                                         );
  607:     my $prereqjs = "
  608: function checkPrereqs(caller,item,prereq,binname) {
  609:     var changedPrereq = 0;
  610:     element = document.getElementById('item'+item);
  611:     if (element.checked == false) {
  612:         return;
  613:     } else {
  614:         prereqelement = document.getElementById('item'+prereq);
  615:         if (!prereqelement.checked) {
  616:             prereqelement.checked = true;
  617:             changedPrereq = 1;
  618:             countChecked(binname);
  619:         }
  620:     }
  621: ";
  622:     
  623:     my ($hasdep,$prereq,$hasdeptitle,$prereqtitle) = ('','','','');
  624:     foreach my $item (sort(keys(%prereqs))) {
  625:         $hasdep .= "'$item',";
  626:         $prereq .= "'$prereqs{$item}',";
  627:         my $url = &fullurl($item);
  628:         $hasdeptitle .= "'".&Apache::lonnet::metadata($url,'title')."',";
  629:         my $purl = &fullurl($prereqs{$item});
  630:         $prereqtitle .= "'".&Apache::lonnet::metadata($purl,'title')."',";
  631:     }
  632:     $hasdep =~ s/,$//;
  633:     $prereq =~ s/,$//;
  634:     $hasdeptitle =~ s/,$//;
  635:     $prereqtitle =~ s/,$//;
  636: 
  637:     $prereqjs .= <<"ENDFN";
  638: 
  639:     var hasDeps = Array($hasdep);
  640:     var preReqs = Array($prereq);
  641:     var hasDepTitles = Array($hasdeptitle);
  642:     var preReqTitles = Array($prereqtitle);
  643:     for (var i=0; i<hasDeps.length; i++) {
  644:         if (hasDeps[i] == item) {
  645:             var msg = hasDepTitles[i]+' question has a prerequisite: '+preReqTitles[i]+'.\\nThe two questions will appear together in a composite question.';
  646:             if (changedPrereq == 1) {
  647:                 msg = msg+'\\n\\nAs the prerequisite was not checked, inclusion of '+hasDepTitles[i]+' has now caused '+preReqTitles[i]+' to also be checked automatically.';
  648:             }
  649:             if (caller == 'pre') {
  650:                 msg = msg +'\\n\\nIf you do not wish to include '+preReqTitles[i]+' you will first need to uncheck '+hasDepTitles[i]+', then uncheck '+preReqTitles[i]+' again.'
  651:             }
  652:             alert(msg);
  653:             break;
  654:         }
  655:     }
  656:     return;
  657: }
  658: 
  659: ENDFN
  660: 
  661:     return <<ENDJS;
  662: function showQuestions(content,title) {
  663:     document.getElementById(content).style.display = "";
  664:     document.getElementById(title).innerHTML='<a href="javascript:hideQuestions('+"'"+content+"','"+title+"'"+');">$lt{'hide'}</a> ...';
  665:     return;
  666: }
  667: 
  668: function hideQuestions(content,title) {
  669:     document.getElementById(content).style.display = "none";
  670:     document.getElementById(title).innerHTML='<a href="javascript:showQuestions('+"'"+content+"','"+title+"'"+')">$lt{'show'}</a> ...';
  671:     return;
  672: }
  673: 
  674: function setInitialVisibility() {
  675:     if (document.getElementById('GCI_mandatory_q') == null) {
  676:         return;
  677:     }
  678:     document.getElementById('GCI_mandatory_q').style.display = "none";
  679:     document.getElementById('GCI_bin0_q').style.display = "none";
  680:     document.getElementById('GCI_bin1_q').style.display = "none";
  681:     document.getElementById('GCI_bin2_q').style.display = "none";
  682:     document.getElementById('GCI_bin3_q').style.display = "none";
  683:     document.getElementById('GCI_bin4_q').style.display = "none";
  684:     document.getElementById('GCI_bin5_q').style.display = "none";
  685:     document.getElementById('GCI_bin6_q').style.display = "none";
  686:     document.getElementById('GCI_bin7_q').style.display = "none";
  687:     document.getElementById('GCI_bin8_q').style.display = "none";
  688:     document.getElementById('GCI_bin9_q').style.display = "none";
  689:     document.getElementById('GCI_bin10_q').style.display = "none";
  690:     document.getElementById('GCI_optional_q').style.display = "none";
  691:     document.getElementById('GCI_development_q').style.display = "none";
  692: }
  693: 
  694: function countChecked(binname) {
  695:     var count = 0;
  696:     for (var i=0; i<document.selecteditems.elements.length; i++) {
  697:         if (document.selecteditems.elements[i].type == "hidden") {
  698:             if (document.selecteditems.elements[i].value == binname) {
  699:                 var itemname = document.selecteditems.elements[i].name;
  700:                 var itemnum = itemname.substr(9);
  701:                 element = document.getElementById('item'+itemnum);
  702:                 if (element.checked) {
  703:                     count ++;
  704:                 }
  705:             }
  706:         }
  707:     }
  708:     countelement = document.getElementById('GCI_'+binname+'_count');
  709:     countelement.value = count;
  710: }
  711: 
  712: function validTestCheck() {
  713:     var empty = '';
  714:     for (var i=0; i<11; i++) {
  715:         var binname = 'GCI_bin'+i+'_count';
  716:         var j = i+1;
  717:         countelement = document.getElementById(binname);        
  718:         if (countelement.value < 1) {
  719:             empty = empty +' '+j;
  720:         }
  721:     }
  722:     if (empty != "") {
  723:         alert("Current test invalid - select at least one item from the following bin(s): "+empty);
  724:         return false;
  725:     }
  726:     return true;
  727: }
  728: 
  729: function setDocsPhase() {
  730:     if (document.choices.concepttest.length) {
  731:         for (var i=0; i<document.choices.concepttest.length; i++) {
  732:             if (document.choices.concepttest[i].checked) {
  733:                 if (document.choices.concepttest[i].value == 'defchosen') {
  734:                     document.choices.phase.value = 'storemap';
  735:                     alert("Setting value for phase to "+document.choices.phase.value);
  736: 
  737:                 }
  738:             }
  739:         }
  740:     }
  741:     return;
  742: }
  743: 
  744: $prereqjs
  745: 
  746: ENDJS
  747: 
  748: }
  749: 
  750: } #end scope variables
  751: 
  752: 1;
  753: __END__
  754: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>