Annotation of loncom/interface/lonspreadsheet.pm, revision 1.1
1.1 ! www 1: # The LearningOnline Network with CAPA
! 2: # Spreadsheet/Grades Display Handler
! 3: #
! 4: # 11/11,11/15 Gerd Kortemeyer
! 5:
! 6: package Apache::lonspreadsheet;
! 7:
! 8: use strict;
! 9: use Safe;
! 10: use Opcode;
! 11: use vars qw(%v %t %f);
! 12: use Apache::lonnet;
! 13: use Apache::Constants qw(:common);
! 14:
! 15: sub deffunc {
! 16: my $safeeval=shift;
! 17: my $code=<<'ENDDEFS';
! 18: # ---------------------------------------------------- Inside of the safe space
! 19:
! 20: sub mask {
! 21: my ($lower,$upper)=@_;
! 22:
! 23: $lower=~/([A-Z]|\*)(\d+|\*)/;
! 24: my $la=$1;
! 25: my $ld=$2;
! 26:
! 27: $upper=~/([A-Z]|\*)(\d+|\*)/;
! 28: my $ua=$1;
! 29: my $ud=$2;
! 30: my $alpha='';
! 31: my $num='';
! 32:
! 33: if (($la eq '*') || ($ua eq '*')) {
! 34: $alpha='[A-Z]';
! 35: } else {
! 36: $alpha='['.$la.'-'.$ua.']';
! 37: }
! 38:
! 39: if (($ld eq '*') || ($ud eq '*')) {
! 40: $num='\d+';
! 41: } else {
! 42: if (length($ld)!=length($ud)) {
! 43: $num.='(';
! 44: map {
! 45: $num.='['.$_.'-9]';
! 46: } ($ld=~m/\d/g);
! 47: if (length($ud)-length($ld)>1) {
! 48: $num.='|\d{'.(length($ld)+1).','.(length($ud)-1).'}';
! 49: }
! 50: $num.='|';
! 51: map {
! 52: $num.='[0-'.$_.']';
! 53: } ($ud=~m/\d/g);
! 54: $num.=')';
! 55: } else {
! 56: my @lda=($ld=~m/\d/g);
! 57: my @uda=($ud=~m/\d/g);
! 58: my $i; $j=0;
! 59: for ($i=0;$i<=$#lda;$i++) {
! 60: if ($lda[$i]==$uda[$i]) {
! 61: $num.=$lda[$i];
! 62: $j=$i;
! 63: }
! 64: }
! 65: if ($j<$#lda-1) {
! 66: $num.='('.$lda[$j+1];
! 67: for ($i=$j+2;$i<=$#lda;$i++) {
! 68: $num.='['.$lda[$i].'-9]';
! 69: }
! 70: if ($uda[$j+1]-$lda[$j+1]>1) {
! 71: $num.='|['.($lda[$j+1]+1).'-'.($uda[$j+1]-1).']\d{'.
! 72: ($#lda-$j-1).'}';
! 73: }
! 74: $num.='|'.$uda[$j+1];
! 75: for ($i=$j+2;$i<=$#uda;$i++) {
! 76: $num.='[0-'.$uda[$i].']';
! 77: }
! 78: $num.=')';
! 79: } else {
! 80: $num.='['.$lda[$#lda].'-'.$uda[$#uda].']';
! 81: }
! 82: }
! 83: }
! 84: return '^'.$alpha.$num.'$';
! 85: }
! 86:
! 87:
! 88: sub NUM {
! 89: my $mask=mask(@_);
! 90: my $num=0;
! 91: map {
! 92: $num++;
! 93: } grep /$mask/,keys %v;
! 94: return $num;
! 95: }
! 96:
! 97: sub BIN {
! 98: my ($low,$high,$lower,$upper)=@_;
! 99: my $mask=mask($lower,$upper);
! 100: my $num=0;
! 101: map {
! 102: if (($v{$_}>=$low) && ($v{$_}<=$high)) {
! 103: $num++;
! 104: }
! 105: } grep /$mask/,keys %v;
! 106: return $num;
! 107: }
! 108:
! 109:
! 110: sub SUM {
! 111: my $mask=mask(@_);
! 112: my $sum=0;
! 113: map {
! 114: $sum+=$v{$_};
! 115: } grep /$mask/,keys %v;
! 116: return $sum;
! 117: }
! 118:
! 119: sub MEAN {
! 120: my $mask=mask(@_);
! 121: my $sum=0; my $num=0;
! 122: map {
! 123: $sum+=$v{$_};
! 124: $num++;
! 125: } grep /$mask/,keys %v;
! 126: if ($num) {
! 127: return $sum/$num;
! 128: } else {
! 129: return undef;
! 130: }
! 131: }
! 132:
! 133: sub STDDEV {
! 134: my $mask=mask(@_);
! 135: my $sum=0; my $num=0;
! 136: map {
! 137: $sum+=$v{$_};
! 138: $num++;
! 139: } grep /$mask/,keys %v;
! 140: unless ($num>1) { return undef; }
! 141: my $mean=$sum/$num;
! 142: $sum=0;
! 143: map {
! 144: $sum+=($v{$_}-$mean)**2;
! 145: } grep /$mask/,keys %v;
! 146: return sqrt($sum/($num-1));
! 147: }
! 148:
! 149: sub PROD {
! 150: my $mask=mask(@_);
! 151: my $prod=1;
! 152: map {
! 153: $prod*=$v{$_};
! 154: } grep /$mask/,keys %v;
! 155: return $prod;
! 156: }
! 157:
! 158: sub MAX {
! 159: my $mask=mask(@_);
! 160: my $max='-';
! 161: map {
! 162: unless ($max) { $max=$v{$_}; }
! 163: if (($v{$_}>$max) || ($max eq '-')) { $max=$v{$_}; }
! 164: } grep /$mask/,keys %v;
! 165: return $max;
! 166: }
! 167:
! 168: sub MIN {
! 169: my $mask=mask(@_);
! 170: my $min='-';
! 171: map {
! 172: unless ($max) { $max=$v{$_}; }
! 173: if (($v{$_}<$min) || ($min eq '-')) { $min=$v{$_}; }
! 174: } grep /$mask/,keys %v;
! 175: return $min;
! 176: }
! 177:
! 178: sub SUMMAX {
! 179: my ($num,$lower,$upper)=@_;
! 180: my $mask=mask($lower,$upper);
! 181: my @inside=();
! 182: map {
! 183: $inside[$#inside+1]=$v{$_};
! 184: } grep /$mask/,keys %v;
! 185: @inside=sort(@inside);
! 186: my $sum=0; my $i;
! 187: for ($i=$#inside;(($i>$#inside-$num) && ($i>=0));$i--) {
! 188: $sum+=$inside[$i];
! 189: }
! 190: return $sum;
! 191: }
! 192:
! 193: sub SUMMIN {
! 194: my ($num,$lower,$upper)=@_;
! 195: my $mask=mask($lower,$upper);
! 196: my @inside=();
! 197: map {
! 198: $inside[$#inside+1]=$v{$_};
! 199: } grep /$mask/,keys %v;
! 200: @inside=sort(@inside);
! 201: my $sum=0; my $i;
! 202: for ($i=0;(($i<$num) && ($i<=$#inside));$i++) {
! 203: $sum+=$inside[$i];
! 204: }
! 205: return $sum;
! 206: }
! 207:
! 208:
! 209: # ------------------------------------------- End of "Inside of the safe space"
! 210: ENDDEFS
! 211: $safeeval->reval($code);
! 212: }
! 213:
! 214: sub sett {
! 215: %t=();
! 216: map {
! 217: if ($f{$_}) {
! 218: $t{$_}=$f{$_};
! 219: $t{$_}=~s/\.+/\,/g;
! 220: $t{$_}=~s/(^|[^\"\'])([A-Z]\d+)/$1\$v\{\'$2\'\}/g;
! 221: }
! 222: } keys %f;
! 223: }
! 224:
! 225: sub calcv {
! 226: my $safeeval=shift;
! 227: %v=();
! 228: my $notfinished=1;
! 229: my $depth=0;
! 230: while ($notfinished) {
! 231: $notfinished=0;
! 232: map {
! 233: my $old=$v{$_};
! 234: $v{$_}=$safeeval->reval($t{$_});
! 235: if ($@) {
! 236: %v=();
! 237: return $@;
! 238: }
! 239: if ($v{$_} ne $old) { $notfinished=1; }
! 240: } keys %t;
! 241: $depth++;
! 242: if ($depth>100) {
! 243: %v=();
! 244: return 'Maximum calculation depth exceeded';
! 245: }
! 246: }
! 247: return '';
! 248: }
! 249:
! 250: sub handler {
! 251: %v=();
! 252: %t=();
! 253: %f=();
! 254: my $safeeval = new Safe;
! 255: $safeeval->permit("entereval");
! 256: $safeeval->permit(":base_math");
! 257: $safeeval->permit("sort");
! 258: $safeeval->deny(":base_io");
! 259: # $safeeval->share_from('Apache::lonnet',['&EXT']);
! 260: $safeeval->share('%v','%t','%f');
! 261: &deffunc($safeeval);
! 262: $f{'A3'}=5;
! 263: $f{'A4'}=3;
! 264: $f{'A5'}=8;
! 265: $f{'E100'}=5;
! 266: $f{'C3'}='A3+6';
! 267: $f{'B4'}='8+int(C3/3)';
! 268: $f{'C7'}='A3+B4';
! 269: $f{'G8'}='MEAN("E*")';
! 270: $f{'G5'}='A3+SUMMIN(2,"A*")';
! 271: $f{'G6'}='A3+SUM("A*")';
! 272: $f{'G7'}='STDDEV("A*")';
! 273: $f{'G9'}='NUM("G*")';
! 274: $f{'H10'}='MEAN("E*")';
! 275: $f{'G10'}='BIN(3,5,"A*")';
! 276: &sett();
! 277: print &calcv($safeeval)."\n";
! 278: print $v{'C7'}."\n";
! 279: print $t{'G5'}.' - '.$v{'G5'}."\n";
! 280: print $t{'G6'}.' - '.$v{'G6'}."\n";
! 281: print $t{'G7'}.' - '.$v{'G7'}."\n";
! 282: print $t{'G8'}.' - '.$v{'G8'}."\n";
! 283: print $t{'G9'}.' - '.$v{'G9'}."\n";
! 284: print $t{'G10'}.' - '.$v{'G10'}."\n";
! 285: }
! 286:
! 287: 1;
! 288: __END__
! 289:
! 290:
! 291:
! 292:
! 293:
! 294:
! 295:
! 296:
! 297:
! 298:
! 299:
! 300:
! 301:
! 302:
! 303:
! 304:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>