--- loncom/interface/lonparmset.pm 2003/08/06 18:08:02 1.119
+++ loncom/interface/lonparmset.pm 2006/05/01 19:37:33 1.298
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set parameters for assessments
#
-# $Id: lonparmset.pm,v 1.119 2003/08/06 18:08:02 matthew Exp $
+# $Id: lonparmset.pm,v 1.298 2006/05/01 19:37:33 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -61,25 +61,19 @@ use Apache::loncommon;
use GDBM_File;
use Apache::lonhomework;
use Apache::lonxml;
+use Apache::lonlocal;
+use Apache::lonnavmaps;
+# --- Caches local to lonparmset
-my %courseopt;
-my %useropt;
+my $parmhashid;
my %parmhash;
+my $symbsid;
+my %symbs;
+my $rulesid;
+my %rules;
-my @ids;
-my %symbp;
-my %mapp;
-my %typep;
-my %keyp;
-
-my %maptitles;
-
-my $uname;
-my $udom;
-my $uhome;
-my $csec;
-my $coursename;
+# --- end local caches
##################################################
##################################################
@@ -94,16 +88,19 @@ Inputs: $what - a parameter spec (inclu
$id - a bighash Id number
$def - the resource's default value 'stupid emacs
-Returns: A list, the first item is the index into the remaining list of items of parm valuse that is the active one, the list consists of parm values at the 11 possible levels
+Returns: A list, the first item is the index into the remaining list of items of parm valuse that is the active one, the list consists of parm values at the 14 possible levels
-11- resource default
-10- map default
-9 - General Course
-8 - Map or Folder level in course
-7 - resource level in course
-6 - General for section
-5 - Map or Folder level for section
-4 - resource level in section
+14 - General Course
+13 - Map or Folder level in course
+12- resource default
+11- map default
+10 - resource level in course
+9 - General for section
+8 - Map or Folder level for section
+7 - resource level in section
+6 - General for group
+5 - Map or Folder level for group
+4 - resource level in group
3 - General for specific student
2 - Map or Folder level for specific student
1 - resource level for specific student
@@ -111,87 +108,391 @@ Returns: A list, the first item is the
=cut
##################################################
-##################################################
sub parmval {
- my ($what,$id,$def)=@_;
+ my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
+ return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
+ $cgroup,$courseopt);
+}
+
+sub parmval_by_symb {
+ my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
+# load caches
+ &cacheparmhash();
+
+ my $useropt=&Apache::lonnet::get_userresdata($uname,$udom);
+
my $result='';
my @outpar=();
# ----------------------------------------------------- Cascading lookup scheme
+ my $map=(&Apache::lonnet::decode_symb($symb))[0];
- my $symbparm=$symbp{$id}.'.'.$what;
- my $mapparm=$mapp{$id}.'___(all).'.$what;
+ my $symbparm=$symb.'.'.$what;
+ my $mapparm=$map.'___(all).'.$what;
- my $seclevel=$ENV{'request.course.id'}.'.['.$csec.'].'.$what;
- my $seclevelr=$ENV{'request.course.id'}.'.['.$csec.'].'.$symbparm;
- my $seclevelm=$ENV{'request.course.id'}.'.['.$csec.'].'.$mapparm;
+ my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
+ my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
+ my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
- my $courselevel=$ENV{'request.course.id'}.'.'.$what;
- my $courselevelr=$ENV{'request.course.id'}.'.'.$symbparm;
- my $courselevelm=$ENV{'request.course.id'}.'.'.$mapparm;
+ my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
+ my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
+ my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
-# -------------------------------------------------------- first, check default
+ my $courselevel=$env{'request.course.id'}.'.'.$what;
+ my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
+ my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
- if ($def) { $outpar[11]=$def; $result=11; }
-# ----------------------------------------------------- second, check map parms
+# --------------------------------------------------------- first, check course
- my $thisparm=$parmhash{$symbparm};
- if ($thisparm) { $outpar[10]=$thisparm; $result=10; }
-
-# --------------------------------------------------------- third, check course
-
- if (defined($courseopt{$courselevel})) {
- $outpar[9]=$courseopt{$courselevel};
- $result=9;
+ if (defined($$courseopt{$courselevel})) {
+ $outpar[14]=$$courseopt{$courselevel};
+ $result=14;
}
- if (defined($courseopt{$courselevelm})) {
- $outpar[8]=$courseopt{$courselevelm};
- $result=8;
+ if (defined($$courseopt{$courselevelm})) {
+ $outpar[13]=$$courseopt{$courselevelm};
+ $result=13;
}
- if (defined($courseopt{$courselevelr})) {
- $outpar[7]=$courseopt{$courselevelr};
- $result=7;
+# ------------------------------------------------------- second, check default
+
+ if (defined($def)) { $outpar[12]=$def; $result=12; }
+
+# ------------------------------------------------------ third, check map parms
+
+ my $thisparm=$parmhash{$symbparm};
+ if (defined($thisparm)) { $outpar[11]=$thisparm; $result=11; }
+
+ if (defined($$courseopt{$courselevelr})) {
+ $outpar[10]=$$courseopt{$courselevelr};
+ $result=10;
}
+# ------------------------------------------------------ fourth, back to course
if (defined($csec)) {
- if (defined($courseopt{$seclevel})) {
- $outpar[6]=$courseopt{$seclevel};
- $result=6;
+ if (defined($$courseopt{$seclevel})) {
+ $outpar[9]=$$courseopt{$seclevel};
+ $result=9;
}
- if (defined($courseopt{$seclevelm})) {
- $outpar[5]=$courseopt{$seclevelm};
- $result=5;
+ if (defined($$courseopt{$seclevelm})) {
+ $outpar[8]=$$courseopt{$seclevelm};
+ $result=8;
}
- if (defined($courseopt{$seclevelr})) {
- $outpar[4]=$courseopt{$seclevelr};
- $result=4;
+ if (defined($$courseopt{$seclevelr})) {
+ $outpar[7]=$$courseopt{$seclevelr};
+ $result=7;
}
}
+# ------------------------------------------------------ fifth, check course group
+ if (defined($cgroup)) {
+ if (defined($$courseopt{$grplevel})) {
+ $outpar[6]=$$courseopt{$grplevel};
+ $result=6;
+ }
+ if (defined($$courseopt{$grplevelm})) {
+ $outpar[5]=$$courseopt{$grplevelm};
+ $result=5;
+ }
+ if (defined($$courseopt{$grplevelr})) {
+ $outpar[4]=$$courseopt{$grplevelr};
+ $result=4;
+ }
+ }
-# ---------------------------------------------------------- fourth, check user
+# ---------------------------------------------------------- fifth, check user
if (defined($uname)) {
- if (defined($useropt{$courselevel})) {
- $outpar[3]=$useropt{$courselevel};
+ if (defined($$useropt{$courselevel})) {
+ $outpar[3]=$$useropt{$courselevel};
$result=3;
}
- if (defined($useropt{$courselevelm})) {
- $outpar[2]=$useropt{$courselevelm};
+ if (defined($$useropt{$courselevelm})) {
+ $outpar[2]=$$useropt{$courselevelm};
$result=2;
}
- if (defined($useropt{$courselevelr})) {
- $outpar[1]=$useropt{$courselevelr};
+ if (defined($$useropt{$courselevelr})) {
+ $outpar[1]=$$useropt{$courselevelr};
$result=1;
}
}
return ($result,@outpar);
}
+sub resetparmhash {
+ $parmhashid='';
+}
+
+sub cacheparmhash {
+ if ($parmhashid eq $env{'request.course.fn'}) { return; }
+ my %parmhashfile;
+ if (tie(%parmhashfile,'GDBM_File',
+ $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
+ %parmhash=%parmhashfile;
+ untie %parmhashfile;
+ $parmhashid=$env{'request.course.fn'};
+ }
+}
+
+sub resetsymbcache {
+ $symbsid='';
+}
+
+sub symbcache {
+ my $id=shift;
+ if ($symbsid ne $env{'request.course.id'}) {
+ %symbs=();
+ }
+ unless ($symbs{$id}) {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if ($id=~/\./) {
+ my $resource=$navmap->getById($id);
+ $symbs{$id}=$resource->symb();
+ } else {
+ my $resource=$navmap->getByMapPc($id);
+ $symbs{$id}=&Apache::lonnet::declutter($resource->src());
+ }
+ $symbsid=$env{'request.course.id'};
+ }
+ return $symbs{$id};
+}
+
+sub resetrulescache {
+ $rulesid='';
+}
+
+sub rulescache {
+ my $id=shift;
+ if ($rulesid ne $env{'request.course.id'}) {
+ %rules=();
+ }
+ unless (defined($rules{$id})) {
+ my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
+ %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
+ $rulesid=$env{'request.course.id'};
+ }
+ return $rules{$id};
+}
+
+sub preset_defaults {
+ my $type=shift;
+ if (&rulescache($type.'_action') eq 'default') {
+# yes, there is something
+ return (&rulescache($type.'_hours'),
+ &rulescache($type.'_min'),
+ &rulescache($type.'_sec'),
+ &rulescache($type.'_value'));
+ } else {
+# nothing there or something else
+ return ('','','','','');
+ }
+}
+
+##################################################
+
+sub date_sanity_info {
+ my $checkdate=shift;
+ unless ($checkdate) { return ''; }
+ my $result='';
+ my $crsprefix='course.'.$env{'request.course.id'}.'.';
+ if ($env{$crsprefix.'default_enrollment_end_date'}) {
+ if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
+ $result.='
'.&mt('After course enrollment end!');
+ }
+ }
+ if ($env{$crsprefix.'default_enrollment_start_date'}) {
+ if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
+ $result.='
'.&mt('Before course enrollment start!');
+ }
+ }
+ return $result;
+}
+##################################################
+##################################################
+#
+# Store a parameter by ID
+#
+# Takes
+# - resource id
+# - name of parameter
+# - level
+# - new value
+# - new type
+# - username
+# - userdomain
+
+sub storeparm {
+ my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
+ &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
+}
+
+#
+# Store a parameter by symb
+#
+# Takes
+# - symb
+# - name of parameter
+# - level
+# - new value
+# - new type
+# - username
+# - userdomain
+
+my %recstack;
+sub storeparm_by_symb {
+ my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
+ unless ($recflag) {
+# first time call
+ %recstack=();
+ $recflag=1;
+ }
+# store parameter
+ &storeparm_by_symb_inner
+ ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
+# don't do anything if parameter was reset
+ unless ($nval) { return; }
+ my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
+# remember that this was set
+ $recstack{$parm}=1;
+# what does this trigger?
+ foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
+# don't backfire
+ unless ((!$triggered) || ($recstack{$triggered})) {
+ my $action=&rulescache($triggered.'_action');
+ my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
+# set triggered parameter on same level
+ my $newspnam=$prefix.$triggered;
+ my $newvalue='';
+ my $active=1;
+ if ($action=~/^when\_setting/) {
+# are there restrictions?
+ if (&rulescache($triggered.'_triggervalue')=~/\w/) {
+ $active=0;
+ foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
+ if (lc($possiblevalue) eq lc($nval)) { $active=1; }
+ }
+ }
+ $newvalue=&rulescache($triggered.'_value');
+ } else {
+ my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
+ if ($action=~/^later\_than/) {
+ $newvalue=$nval+$totalsecs;
+ } else {
+ $newvalue=$nval-$totalsecs;
+ }
+ }
+ if ($active) {
+ &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
+ $uname,$udom,$csec,$recflag,$cgroup);
+ }
+ }
+ }
+ return '';
+}
+
+sub log_parmset {
+ return &Apache::lonnet::instructor_log('parameterlog',@_);
+}
+
+sub storeparm_by_symb_inner {
+# ---------------------------------------------------------- Get symb, map, etc
+ my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
+# ---------------------------------------------------------- Construct prefixes
+ $spnam=~s/\_([^\_]+)$/\.$1/;
+ my $map=(&Apache::lonnet::decode_symb($symb))[0];
+ my $symbparm=$symb.'.'.$spnam;
+ my $mapparm=$map.'___(all).'.$spnam;
+
+ my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
+ my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
+ my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
+
+ my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
+ my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
+ my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
+
+ my $courselevel=$env{'request.course.id'}.'.'.$spnam;
+ my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
+ my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
+
+ my $storeunder='';
+ if (($snum==14) || ($snum==3)) { $storeunder=$courselevel; }
+ if (($snum==13) || ($snum==2)) { $storeunder=$courselevelm; }
+ if (($snum==10) || ($snum==1)) { $storeunder=$courselevelr; }
+ if ($snum==9) { $storeunder=$seclevel; }
+ if ($snum==8) { $storeunder=$seclevelm; }
+ if ($snum==7) { $storeunder=$seclevelr; }
+ if ($snum==6) { $storeunder=$grplevel; }
+ if ($snum==5) { $storeunder=$grplevelm; }
+ if ($snum==4) { $storeunder=$grplevelr; }
+
+
+ my $delete;
+ if ($nval eq '') { $delete=1;}
+ my %storecontent = ($storeunder => $nval,
+ $storeunder.'.type' => $ntype);
+ my $reply='';
+ if ($snum>3) {
+# ---------------------------------------------------------------- Store Course
+#
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+# Expire sheets
+ &Apache::lonnet::expirespread('','','studentcalc');
+ if (($snum==10) || ($snum==7) || ($snum==4)) {
+ &Apache::lonnet::expirespread('','','assesscalc',$symb);
+ } elsif (($snum==11) || ($snum==8) || ($snum==5)) {
+ &Apache::lonnet::expirespread('','','assesscalc',$map);
+ } else {
+ &Apache::lonnet::expirespread('','','assesscalc');
+ }
+# Store parameter
+ if ($delete) {
+ $reply=&Apache::lonnet::del
+ ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
+ &log_parmset(\%storecontent,1);
+ } else {
+ $reply=&Apache::lonnet::cput
+ ('resourcedata',\%storecontent,$cdom,$cnum);
+ &log_parmset(\%storecontent);
+ }
+ &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
+ } else {
+# ------------------------------------------------------------------ Store User
+#
+# Expire sheets
+ &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
+ if ($snum==1) {
+ &Apache::lonnet::expirespread
+ ($uname,$udom,'assesscalc',$symb);
+ } elsif ($snum==2) {
+ &Apache::lonnet::expirespread
+ ($uname,$udom,'assesscalc',$map);
+ } else {
+ &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
+ }
+# Store parameter
+ if ($delete) {
+ $reply=&Apache::lonnet::del
+ ('resourcedata',[keys(%storecontent)],$udom,$uname);
+ &log_parmset(\%storecontent,1,$uname,$udom);
+ } else {
+ $reply=&Apache::lonnet::cput
+ ('resourcedata',\%storecontent,$udom,$uname);
+ &log_parmset(\%storecontent,0,$uname,$udom);
+ }
+ &Apache::lonnet::devalidateuserresdata($uname,$udom);
+ }
+
+ if ($reply=~/^error\:(.*)/) {
+ return "Write Error: $1";
+ }
+ return '';
+}
+
##################################################
##################################################
@@ -240,8 +541,8 @@ sub valout {
$result.=$sec.' secs ';
}
$result=~s/\s+$//;
- } elsif ($type=~/^date/) {
- $result = localtime($value);
+ } elsif (&isdateparm($type)) {
+ $result = localtime($value).&date_sanity_info($value);
} else {
$result = $value;
}
@@ -271,33 +572,28 @@ sub plink {
my ($type,$dis,$value,$marker,$return,$call)=@_;
my $winvalue=$value;
unless ($winvalue) {
- if ($type=~/^date/) {
- $winvalue=$ENV{'form.recent_'.$type};
+ if (&isdateparm($type)) {
+ $winvalue=$env{'form.recent_'.$type};
} else {
- $winvalue=$ENV{'form.recent_'.(split(/\_/,$type))[0]};
+ $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
}
}
- return
+ my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
+ my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
+ unless (defined($winvalue)) { $winvalue=$val; }
+ return '
'. ''. - &valout($value,$type).''; + .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."'".');">'. + &valout($value,$type).' |