[LON-CAPA-cvs] cvs: loncom /homework optionresponse.pm /interface lonparmset.pm

raeburn raeburn at source.lon-capa.org
Tue Apr 28 09:12:53 EDT 2015


raeburn		Tue Apr 28 13:12:53 2015 EDT

  Modified files:              
    /loncom/interface	lonparmset.pm 
    /loncom/homework	optionresponse.pm 
  Log:
  - Bug 2802
   - Lenient (partial credit) parameter for optionresponse supports relative 
     weights when checkboxes are in use. 
   -  Different numbers of points (either positive or negative) can be specified
      for correct foils (checked or unchecked) and incorrect foils (checked or 
      unchecked).
      - Overview modes for parameter setting include textboxes for each of the
        four types if "weighted" is selected.
  - Overview modes for parameter setting for Client IP/Name Access Control
    also include individual textboxes for each IP or Name, with separate
    boxes for "allow from" and "deny from".
  Work in progress.
  
  
-------------- next part --------------
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.548 loncom/interface/lonparmset.pm:1.549
--- loncom/interface/lonparmset.pm:1.548	Fri Dec 12 02:12:18 2014
+++ loncom/interface/lonparmset.pm	Tue Apr 28 13:12:46 2015
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set parameters for assessments
 #
-# $Id: lonparmset.pm,v 1.548 2014/12/12 02:12:18 raeburn Exp $
+# $Id: lonparmset.pm,v 1.549 2015/04/28 13:12:46 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -932,6 +932,162 @@
 COURSECONTENTSCRIPT
 }
 
+sub toggleparmtextbox_js {
+    return <<"ENDSCRIPT";
+
+if (!document.getElementsByClassName) {
+    function getElementsByClassName(node, classname) {
+        var a = [];
+        var re = new RegExp('(^| )'+classname+'( |$)');
+        var els = node.getElementsByTagName("*");
+        for(var i=0,j=els.length; i<j; i++)
+            if(re.test(els[i].className))a.push(els[i]);
+        return a;
+    }
+}
+
+function showHideLenient() {
+    var lenients;
+    var setRegExp = /^set_/;
+    if (document.getElementsByClassName) {
+        lenients = document.getElementsByClassName('LC_lenient_radio');
+    } else {
+        lenients = getElementsByClassName(document.body,'LC_lenient_radio');
+    }
+    if (lenients != 'undefined') {
+        for (var i=0; i<lenients.length; i++) {
+            if (lenients[i].checked) {
+                if (lenients[i].value == 'weighted') {
+                    if (setRegExp.test(lenients[i].name)) {
+                        var identifier = lenients[i].name.replace(setRegExp,'');
+                        toggleParmTextbox(document.parmform,identifier);
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+function toggleParmTextbox(form,key) {
+    var divfortext = document.getElementById('LC_parmtext_'+key);
+    if (divfortext) {
+        var caller = form.elements['set_'+key];
+        if (caller.length) {
+            for (i=0; i<caller.length; i++) {
+                if (caller[i].checked) {
+                    if (caller[i].value == 'weighted') {
+                        divfortext.style.display = 'inline';
+                    } else {
+                        divfortext.style.display = 'none';
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+ENDSCRIPT
+}
+
+sub validateparms_js {
+    return <<'ENDSCRIPT';
+
+function validateParms() {
+    var textRegExp = /^settext_/;
+    var tailLenient = /\.lenient$/;
+    var patternRelWeight = /^\-?[\d.]+$/;
+    var patternLenientStd = /^(yes|no|default)$/;
+    var ipallowRegExp = /^setipallow_/;
+    var ipdenyRegExp = /^setipdeny_/; 
+    var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
+    if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
+        if (document.parmform.elements.length) {
+            for (i=0; i<document.parmform.elements.length; i++) {
+                var name=document.parmform.elements[i].name;
+                if (textRegExp.test(name)) { 
+                    var identifier = name.replace(textRegExp,'');
+                    if (tailLenient.test(identifier)) {
+                        if (document.parmform.elements['set_'+identifier].length) {
+                            for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
+                                if (document.parmform.elements['set_'+identifier][j].checked) {
+                                    if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
+                                        var relweight = document.parmform.elements[i].value;
+                                        relweight = relweight.replace(/^\s+|\s+$/g,'');
+                                        if (!patternRelWeight.test(relweight)) {
+                                            relweight = '0.0';
+                                        }
+                                        if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
+                                            document.parmform.elements['set_'+identifier][j].value = relweight;
+                                        } else {
+                                            document.parmform.elements['set_'+identifier][j].value += ','+relweight;
+                                        }
+                                    }
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    if (ipallowRegExp.test(name)) {
+                        var identifier = name.replace(ipallowRegExp,'');
+                        var possallow = document.parmform.elements[i].value;
+                        possallow = possallow.replace(/^\s+|\s+$/g,'');
+                        if (patternIP.test(possallow)) {
+                            if (document.parmform.elements['set_'+identifier].value) {
+                                possallow = ','+possallow;
+                            }
+                            document.parmform.elements['set_'+identifier].value += possallow; 
+                        }
+                    } else {
+                        if (ipdenyRegExp.test(name)) {
+                            var identifier = name.replace(ipdenyRegExp,'');
+                            var possdeny = document.parmform.elements[i].value;
+                            possdeny = possdeny.replace(/^\s+|\s+$/g,'');
+                            if (patternIP.test(possdeny)) {
+                                possdeny = '!'+possdeny;
+                                if (document.parmform.elements['set_'+identifier].value) {
+                                    possdeny = ','+possdeny;
+                                }
+                                document.parmform.elements['set_'+identifier].value += possdeny;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return true;
+}
+
+ENDSCRIPT
+}
+
+sub ipacc_boxes_js  {
+    my $remove = &mt('Remove');
+    return <<"END";
+\$(document).ready(function() {
+    var wrapper         = \$(".LC_string_ipacc_wrap");
+    var add_button      = \$(".LC_add_ipacc_button");
+    var ipaccRegExp     = /^LC_string_ipacc_/;
+
+    \$(add_button).click(function(e){
+        e.preventDefault();
+        var identifier = \$(this).closest("div").attr("id");
+        identifier = identifier.replace(ipaccRegExp,'');
+        \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'"/><a href="#" class="LC_remove_ipacc">$remove</a></div>');
+    });
+
+    \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
+        e.preventDefault(); \$(this).closest("div").remove();
+    })
+});
+
+
+END
+}
+
 sub startpage {
     my ($r,$psymb,$crstype) = @_;
 
@@ -2165,7 +2321,6 @@
         my ($got_chostname,$chostname,$cmajor,$cminor);
         my $totalstored = 0;
         my $now = time;
-
         for (my $i=0;$i<=$#markers;$i++) {
             my ($needsrelease,$needsnewer,$name);
             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3)$/) {
@@ -2198,9 +2353,10 @@
                         }
                     }
                 }
-            } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate)\&\d+$/) {
+            } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc)\&\d+$/) {
                 $name = $1;
                 my $val = $values[$i];
+                my $valmatch = '';
                 if ($name eq 'examcode') {
                     if (&Apache::lonnet::validCODE($values[$i])) {
                         $val = 'valid';
@@ -2217,15 +2373,32 @@
                             $val = 'past';
                         }
                     }
+                } elsif (($name eq 'lenient') || ($name eq 'acc')) {
+                    my $stringtype = &get_stringtype($name);
+                    my $stringmatch = &standard_string_matches($stringtype);
+                    if (ref($stringmatch) eq 'ARRAY') {
+                        foreach my $item (@{$stringmatch}) {
+                            if (ref($item) eq 'ARRAY') {
+                                my ($regexpname,$pattern) = @{$item};
+                                if ($pattern ne '') {
+                                    if ($val =~ /$pattern/) {
+                                        $valmatch = $regexpname;
+                                        $val = '';
+                                        last;
+                                    }
+                                }
+                            }
+                        }
+                    }
                 }
                 $needsrelease =
-                    $Apache::lonnet::needsrelease{"parameter:$name:$val"};
+                    $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch"};
                 if ($needsrelease) {
                     unless ($got_chostname) {
                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                         $got_chostname = 1;
                     } 
-                    $needsnewer = &parameter_releasecheck($name,$val,
+                    $needsnewer = &parameter_releasecheck($name,$val,$valmatch,
                                                           $needsrelease,
                                                           $cmajor,$cminor);
                 }
@@ -2847,15 +3020,17 @@
     if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
         my $cmd=$1;
         my $thiskey=$2;
+        next if ($cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny');
         my ($tuname,$tudom)=&extractuser($thiskey);
         my $tkey=$thiskey;
             if ($tuname) {
         $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
         }
         if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
-        my ($data, $typeof, $text, $name, $valchk);
+        my ($data, $typeof, $text, $name, $valchk, $valmatch);
         if ($cmd eq 'set') {
             $data=$env{$key};
+            $valmatch = '';
             $valchk = $data;
             $typeof=$env{'form.typeof_'.$thiskey};
             $text = &mt('Saved modified parameter for');
@@ -2863,6 +3038,21 @@
                 $name = 'type';
             } elsif ($typeof eq 'string_lenient') {
                 $name = 'lenient';
+                my $stringmatch = &standard_string_matches($typeof);
+                if (ref($stringmatch) eq 'ARRAY') {
+                    foreach my $item (@{$stringmatch}) {
+                        if (ref($item) eq 'ARRAY') {
+                            my ($regexpname,$pattern) = @{$item};
+                            if ($pattern ne '') {
+                                if ($data =~ /$pattern/) {
+                                    $valmatch = $regexpname;
+                                    $valchk = '';
+                                    last;
+                                }
+                            }
+                        }
+                    }
+                }
             } elsif ($typeof eq 'string_discussvote') {
                 $name = 'discussvote';
             } elsif ($typeof eq 'string_examcode') {
@@ -2901,13 +3091,13 @@
         }
         if ($name ne '') {
             my ($needsrelease,$needsnewer);
-            $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk"};
+            $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch"};
             if ($needsrelease) {
                 unless ($got_chostname) {
                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                     $got_chostname = 1;
                 }
-                $needsnewer = &parameter_releasecheck($name,$valchk,
+                $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,
                                                       $needsrelease,
                                                       $cmajor,$cminor);
                 if ($needsnewer) {
@@ -3194,6 +3384,62 @@
     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'" />';
 }
 
+sub string_ip_selector {
+    my ($thiskey, $showval) = @_;
+    my %access = (
+                   allow => [],
+                   deny  => [],
+                 );
+    if ($showval ne '') {
+        my @current;
+        if ($showval =~ /,/) {
+            @current = split(/,/,$showval);
+        } else {
+            @current = ($showval);
+        }
+        foreach my $item (@current) {
+            if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
+                push(@{$access{'deny'}},$1);
+            } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
+                push(@{$access{'allow'}},$item);
+            }
+        }
+    }
+    if (!@{$access{'allow'}}) {
+        @{$access{'allow'}} = ('');
+    }
+    if (!@{$access{'deny'}}) {
+        @{$access{'deny'}} = ('');
+    }
+    my $output = '<input type="hidden" name="set_'.$thiskey.'" />
+<table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
+    foreach my $acctype ('allow','deny') {
+        $output .= '
+<td valign="top">
+<div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
+  <div class="LC_string_ipacc_inner">'."\n";
+        my $num = 0;
+        foreach my $curr (@{$access{$acctype}}) {
+            $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'">';
+            if ($num > 0) {
+                $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
+            }
+            $output .= '</div>'."\n";
+            $num ++;
+        }
+        $output .= '
+  </div>
+<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>
+</div>
+</td>';
+   }
+   $output .= '
+</tr>
+</table>'."\n";
+    return $output;
+}
+
+{
 my %strings =
     (
      'string_yesno'
@@ -3216,13 +3462,34 @@
      'string_lenient'
              => [['yes', 'Yes' ],
                  [ 'no', 'No' ],
-                 [ 'default', 'Default - only bubblesheet grading is lenient' ]],
+                 [ 'default', 'Default - only bubblesheet grading is lenient' ],
+                 [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
      'string_discussvote'
              => [['yes','Yes'],
                  ['notended','Yes, unless discussion ended'],
                  ['no','No']],
+     'string_ip'
+             => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
+                 ['_denyfrom_',], 'Hostname(s) or IP(s) from which access is disallowed'], 
      );
 
+my %stringmatches = (
+         'string_lenient'
+              => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
+         'string_ip'
+              => [['_allowfrom_','[^\!]+'],
+                  ['_denyfrom_','\!']],
+    );
+
+my %stringtypes = (
+                    type         => 'string_questiontype',
+                    lenient      => 'string_lenient',
+                    retrypartial => 'string_yesno',
+                    discussvote  => 'string_discussvote',
+                    examcode     => 'string_examcode',
+                    acc          => 'string_ip',
+                  );
+
 sub standard_string_options {
     my ($string_type) = @_;
     if (ref($strings{$string_type}) eq 'ARRAY') {
@@ -3231,37 +3498,73 @@
     return;
 }
 
+sub standard_string_matches {
+    my ($string_type) = @_;
+    if (ref($stringmatches{$string_type}) eq 'ARRAY') {
+        return $stringmatches{$string_type};
+    }
+    return;
+}
+
+sub get_stringtype {
+    my ($name) = @_;
+    if (exists($stringtypes{$name})) {
+        return $stringtypes{$name};
+    }
+    return;
+}
+
 sub string_selector {
     my ($thistype, $thiskey, $showval, $name) = @_;
 
     if (!exists($strings{$thistype})) {
-    return &default_selector($thiskey,$showval);
+        return &default_selector($thiskey,$showval);
     }
 
     my %skiptype;
     if (($thistype eq 'string_questiontype') || 
         ($thistype eq 'string_lenient') ||
         ($thistype eq 'string_discussvote') ||
+        ($thistype eq 'string_ip') ||
         ($name eq 'retrypartial')) {
         my ($got_chostname,$chostname,$cmajor,$cminor); 
         foreach my $possibilities (@{ $strings{$thistype} }) {
             next unless (ref($possibilities) eq 'ARRAY');
             my ($parmval, $description) = @{ $possibilities };
-            my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval"};
+            my $parmmatch;
+            if (ref($stringmatches{$thistype}) eq 'ARRAY') {
+                foreach my $item (@{$stringmatches{$thistype}}) {
+                    if (ref($item) eq 'ARRAY') {
+                        if ($parmval eq $item->[0]) {
+                            $parmmatch = $parmval;
+                            $parmval = '';
+                            last;
+                        }
+                    }
+                }
+            }
+            my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
             if ($needsrelease) {
                 unless ($got_chostname) {
                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                     $got_chostname = 1;
                 }
-                my $needsnewer=&parameter_releasecheck($name,$parmval,$needsrelease,
-                                                       $cmajor,$cminor);
+                my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,
+                                                       $needsrelease,$cmajor,$cminor);
                 if ($needsnewer) {
-                    $skiptype{$parmval} = 1;
+                    if ($parmmatch ne '') {
+                        $skiptype{$parmmatch} = 1;
+                    } elsif ($parmval ne '') {
+                        $skiptype{$parmval} = 1;
+                    }
                 }
             }
         }
     }
-    
+
+    if ($thistype eq 'string_ip') {
+        return &string_ip_selector($thiskey,$showval); 
+    }
 
     my $result;
     my $numinrow = 3;
@@ -3278,7 +3581,7 @@
         foreach my $possibilities (@{ $strings{$thistype} }) {
             next unless (ref($possibilities) eq 'ARRAY');
             my ($name, $description) = @{ $possibilities };
-            next if ($skiptype{$name}); 
+            next if ($skiptype{$name});
             $rem = $i%($numinrow);
             if ($rem == 0) {
                 if ($i > 0) {
@@ -3286,24 +3589,66 @@
                 }
                 $result .= '<tr>';
             }
-            $result .= '<td class="LC_left_item">'.
+            my $colspan;
+            if ($i == @{ $strings{$thistype} }-1) {
+                $rem = @{ $strings{$thistype} }%($numinrow);
+                if ($rem) {
+                    my $colsleft = $numinrow - $rem;
+                    if ($colsleft) {
+                        $colspan = $colsleft+1;
+                        $colspan = ' colspan="'.$colspan.'"';
+                    }
+                }
+            }
+            my ($add,$onchange,$css_class);
+            if ($thistype eq 'string_lenient') {
+                if ($name eq 'weighted') {
+                    my $display;
+                    my %relatives = &Apache::lonlocal::texthash(
+                                        corrchkd     => 'Correct (checked)',
+                                        corrunchkd   => 'Correct (unchecked)',
+                                        incorrchkd   => 'Incorrect (checked)',
+                                        incorrunchkd => 'Incorrect (unchecked)',
+                    );
+                    my %textval = (
+                                    corrchkd     => '1.0',
+                                    corrunchkd   => '1.0',
+                                    incorrchkd   => '0.0',
+                                    incorrunchkd => '0.0',
+                    );
+                    if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
+                        $textval{'corrchkd'} = $1;
+                        $textval{'corrunchkd'} = $2;
+                        $textval{'incorrchkd'} = $3;
+                        $textval{'incorrunchkd'} = $4;
+                        $display = 'inline';
+                        $showval = $name;
+                    } else {
+                        $display = 'none';
+                    }
+                    $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
+                           '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
+                    foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
+                        $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
+                                '<td><input type="text" name="settext_'.$thiskey.'"'.
+                                ' value="'.$textval{$reltype}.'" size="3" />'.
+                                '</td></tr>';
+                    }
+                    $add .= '</table></div>'."\n";
+                }
+                $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
+                $css_class = ' class="LC_lenient_radio"';
+            }
+            $result .= '<td class="LC_left_item"'.$colspan.'>'.
                        '<span class="LC_nobreak"><label>'.
                        '<input type="radio" name="set_'.$thiskey.
-                       '" value="'.$name.'"';
+                       '" value="'.$name.'"'.$onchange.$css_class;
             if ($showval eq $name) {
                 $result .= ' checked="checked"';
             }
-            $result .= ' />'.&mt($description).'</label></span></td>';
+            $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
             $i++;
         }
-        $rem = @{ $strings{$thistype} }%($numinrow);
-        my $colsleft = $numinrow - $rem;
-        if ($colsleft > 1 ) {
-            $result .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
-                       ' </td>';
-        } elsif ($colsleft == 1) {
-            $result .= '<td class="LC_left_item"> </td>';
-        }
         $result .= '</tr>';
     }
     if ($result) {
@@ -3312,6 +3657,64 @@
     return $result;
 }
 
+sub oldversion_warning {
+    my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
+    my $desc;
+    my $stringtype = &get_stringtype($name);
+    if ($stringtype ne '') {
+        if ($name eq 'examcode') {
+            $desc = $value;
+        } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
+            foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
+                next unless (ref($possibilities) eq 'ARRAY');
+                my ($parmval, $description) = @{ $possibilities };
+                my $parmmatch;
+                if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
+                    foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
+                        if (ref($item) eq 'ARRAY') {
+                            my ($regexpname,$pattern) = @{$item};
+                            if ($parmval eq $regexpname) {
+                                if ($value =~ /$pattern/) {
+                                    $desc = $description; 
+                                    $parmmatch = 1;
+                                    last;
+                                }
+                            }
+                        }
+                    }
+                    last if ($parmmatch);
+                } elsif ($parmval eq $value) {
+                    $desc = $description;
+                    last;
+                }
+            }
+        }
+    } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
+        my $now = time;
+        if ($value =~ /^\d+$/) {
+            if ($name eq 'printstartdate') {
+                if ($value > $now) {
+                    $desc = &Apache::lonlocal::locallocaltime($value);
+                }
+            } elsif ($name eq 'printenddate') {
+                if ($value < $now) {
+                    $desc = &Apache::lonlocal::locallocaltime($value);
+                }
+            }
+        }
+    }
+    my $standard_name = &standard_parameter_names($name);
+    return '<p class="LC_warning">'.
+           &mt('[_1] was [_2]not[_3] set to [_4].',
+               $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
+           &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
+           $cmajor.'.'.$cminor,$chostname,
+           $needsrelease).
+           '</p>';
+}
+
+}
+
 #
 # Shift all start and end dates by $shift
 #
@@ -3357,7 +3760,7 @@
         text=>"Overview Mode"});
 
     my %loaditems = (
-                      'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1');",
+                      'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
                     );
     my $js = '
 <script type="text/javascript">
@@ -3365,16 +3768,21 @@
 '.
             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
             &showhide_js()."\n".
+            &toggleparmtextbox_js()."\n".
+            &validateparms_js()."\n".
+            &ipacc_boxes_js()."\n".
 '// ]]>
 </script>
 ';
+
+#FIXME need onload
     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                                                     {'add_entries' => \%loaditems,});
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
     $r->print($start_page.$breadcrumbs);
     &startSettingsScreen($r,'parmset',$crstype);
     $r->print(<<ENDOVER);
-<form method="post" action="/adm/parmset?action=newoverview" name="parmform">
+<form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
 ENDOVER
     my @ids=();
     my %typep=();
@@ -3495,6 +3903,7 @@
 
         &listdata($r,$resourcedata,$listdata,$sortorder);
     }
+#FIXME
     $r->print(&tableend().
          ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'').
           '</form>');
@@ -3542,14 +3951,24 @@
     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
-
+    my $js = '<script type="text/javascript">'."\n".
+             '// <![CDATA['."\n".
+             &toggleparmtextbox_js()."\n".
+             &validateparms_js()."\n".
+             &ipacc_boxes_js()."\n".
+             '// ]]>'."\n".
+             '</script>'."\n";
     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
     text=>"Overview Mode"});
-    my $start_page=&Apache::loncommon::start_page('Modify Parameters');
+    my %loaditems = (
+                      'onload'   => "showHideLenient();",
+                    );
+
+    my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
     $r->print($start_page.$breadcrumbs);
     &startSettingsScreen($r,'parmset',$crstype);
-    $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform">');
+    $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
 
 # Store modified
 
@@ -3567,7 +3986,7 @@
 # List data
 
     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder);
-
+#FIXME
     $r->print(&tableend().'<p>'.
     ($foundkeys?'<input type="submit" value="'.&mt('Save').'" />':'<span class="LC_info">'.&mt('There are no parameters.').'</span>').'</p></form>'.
           &Apache::loncommon::end_page());
@@ -4722,65 +5141,20 @@
 }
 
 sub parameter_releasecheck {
-    my ($name,$value,$needsrelease,$cmajor,$cminor) = @_;
+    my ($name,$value,$valmatch,$needsrelease,$cmajor,$cminor) = @_;
     my $needsnewer;
     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
     if (($cmajor < $needsmajor) || 
         ($cmajor == $needsmajor && $cminor < $needsminor)) {
         $needsnewer = 1;
-    } else {
-        &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value});
+    } elsif ($valmatch) {
+        &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch});
+    } elsif ($value) { 
+        &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.':'});
     }
     return $needsnewer;
 }
 
-sub oldversion_warning {
-    my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
-    my $desc;
-    my %stringtypes = (
-                        type         => 'string_questiontype',
-                        lenient      => 'string_lenient',
-                        retrypartial => 'string_yesno',
-                        discussvote  => 'string_discussvote',
-                        examcode     => 'string_examcode',
-                      );
-    if (exists($stringtypes{$name})) {
-        if ($name eq 'examcode') {
-            $desc = $value;
-        } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
-            foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
-                next unless (ref($possibilities) eq 'ARRAY');
-                my ($parmval, $description) = @{ $possibilities };
-                if ($parmval eq $value) {
-                    $desc = $description;
-                    last;
-                }
-            }
-        }
-    } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
-        my $now = time;
-        if ($value =~ /^\d+$/) {
-            if ($name eq 'printstartdate') {
-                if ($value > $now) { 
-                    $desc = &Apache::lonlocal::locallocaltime($value);
-                }
-            } elsif ($name eq 'printenddate') {
-                if ($value < $now) {
-                    $desc = &Apache::lonlocal::locallocaltime($value);
-                }
-            }
-        }
-    }
-    my $standard_name = &standard_parameter_names($name);
-    return '<p class="LC_warning">'.
-           &mt('[_1] was [_2]not[_3] set to [_4].',
-               $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
-           &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
-           $cmajor.'.'.$cminor,$chostname,
-           $needsrelease).
-           '</p>';
-}
-
 sub handler {
     my $r=shift;
 
Index: loncom/homework/optionresponse.pm
diff -u loncom/homework/optionresponse.pm:1.199 loncom/homework/optionresponse.pm:1.200
--- loncom/homework/optionresponse.pm:1.199	Tue Apr 21 12:28:05 2015
+++ loncom/homework/optionresponse.pm	Tue Apr 28 13:12:52 2015
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: optionresponse.pm,v 1.199 2015/04/21 12:28:05 raeburn Exp $
+# $Id: optionresponse.pm,v 1.200 2015/04/28 13:12:52 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -300,6 +300,10 @@
 	my $wrong=0;
 	my $ignored=0;
         my $checked=0;
+        my $corrchkd=0;
+        my $corrunchkd=0;
+        my $incorrchkd=0;
+        my $incorrunchkd=0;
         my ($numrows,$bubbles_per_row);
         if ($Apache::lonhomework::scantronmode) {
             my $numitems = scalar(@opt);
@@ -329,6 +333,10 @@
                 }
             }
         }
+        my $part=$Apache::inputtags::part;
+        my $id = $Apache::inputtags::response['-1'];
+        my @relweights;
+        my $nonlenient=&grading_is_nonlenient($part,$id,\@relweights);
 	foreach $name (@whichopt) {
 	  my $response;
           if ($env{'form.submitted'} eq 'scantron') {
@@ -369,15 +377,23 @@
             if ($checkboxopt) {
                 if ($response eq $checkboxopt) {
                     $checked++;
+                    if ($grade{$name}) {
+                        $corrchkd ++;
+                    } else {
+                        $incorrchkd ++;
+                    }
+                } else {
+                    if ($grade{$name}) {
+                        $corrunchkd ++;
+                    } else {
+                        $incorrunchkd ++;
+                    }
                 }
-            } 
+            }
 	  } else {
 	    $ignored++;
 	  }
 	}
-	my $part=$Apache::inputtags::part;
-        my $id = $Apache::inputtags::response['-1'];
-        my $nonlenient=&grading_is_nonlenient($part,$id);
 	my $responsestr=&Apache::lonnet::hash2str(%responsehash);
 	my $gradestr   =&Apache::lonnet::hash2str(%grade);
 	my %previous=&Apache::response::check_for_previous($responsestr,
@@ -453,8 +469,22 @@
 		    $ad='ASSIGNED_SCORE';
 	        }
 	        $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
+                my $awarded;
+                my $totalfoils = $#{ $Apache::response::foilgroup{'names'} }+1;
+                if (($checkboxopt) && ($max >= $totalfoils) && (@relweights > 0)) {
+                    if ($right == scalar(@whichopt)) {
+                        $awarded = 1;
+                    } else {
+                        $awarded = ($corrchkd*$relweights[0] + $corrunchkd*$relweights[1] +
+                                    $incorrchkd*$relweights[2] + $incorrunchkd*$relweights[3])/(scalar(@whichopt));
+                        $awarded = 1 if ($awarded > 1);
+                        $awarded = 0 if ($awarded < 0);
+                    }
+                } else {
+                    $awarded = $right/(scalar(@whichopt));
+                }
 	        $Apache::lonhomework::results{"resource.$part.$id.awarded"}=
-		    $right/(scalar(@whichopt));
+		    $awarded;
 	        $Apache::lonhomework::results{"resource.$part.$id.numfoils"}=
 		    scalar(@whichopt);
 	     }
@@ -492,7 +522,7 @@
 }
 
 sub grading_is_nonlenient {
-    my ($part,$id) = @_;
+    my ($part,$id,$relweights) = @_;
 # Web mode: we are non-lenient unless told otherwise
     my $defaultparm = 'off';
     my $nonlenient = 1;
@@ -511,9 +541,14 @@
     if ($lenientparm eq 'default') {
         $lenientparm = $defaultparm;
     }
-    if ($lenientparm=~/^0|off|no$/i) {
+    if ($lenientparm=~/^(?:0|off|no)$/i) {
         $nonlenient = 1;
-    } elsif ($lenientparm=~/^1|on|yes$/i) {
+    } elsif ($lenientparm=~/^(?:1|on|yes)$/i) {
+        $nonlenient = 0;
+    } elsif ($lenientparm =~ /^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$/) {
+        if (ref($relweights) eq 'ARRAY') {
+            @{$relweights} = split(/,/,$lenientparm);
+        }
         $nonlenient = 0;
     }
     if (!$nonlenient) {


More information about the LON-CAPA-cvs mailing list