Annotation of loncom/homework/lonr.pm, revision 1.1
1.1 ! www 1: # The LearningOnline Network with CAPA
! 2: # Interface routines to R CAS
! 3: #
! 4: # $Id: Exp $
! 5: #
! 6: # Copyright Michigan State University Board of Trustees
! 7: #
! 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
! 9: #
! 10: # LON-CAPA is free software; you can redistribute it and/or modify
! 11: # it under the terms of the GNU General Public License as published by
! 12: # the Free Software Foundation; either version 2 of the License, or
! 13: # (at your option) any later version.
! 14: #
! 15: # LON-CAPA is distributed in the hope that it will be useful,
! 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
! 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 18: # GNU General Public License for more details.
! 19: #
! 20: # You should have received a copy of the GNU General Public License
! 21: # along with LON-CAPA; if not, write to the Free Software
! 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 23: #
! 24: # /home/httpd/html/adm/gpl.txt
! 25: #
! 26: # http://www.lon-capa.org/
! 27: #
! 28:
! 29: package Apache::lonr;
! 30:
! 31: use strict;
! 32: use IO::Socket;
! 33: use Apache::lonnet;
! 34: use Apache::response();
! 35: use LONCAPA;
! 36:
! 37: sub connect {
! 38: return IO::Socket::UNIX->new(Peer => $Apache::lonnet::perlvar{'lonSockDir'}.'/rsock',
! 39: Type => SOCK_STREAM,
! 40: Timeout => 10);
! 41: }
! 42:
! 43: sub disconnect {
! 44: my ($socket)=@_;
! 45: if ($socket) { close($socket); }
! 46: }
! 47:
! 48: sub rreply {
! 49: my ($socket,$cmd)=@_;
! 50: if ($socket) {
! 51: print $socket &escape($cmd)."\n";
! 52: my $reply=<$socket>;
! 53: chomp($reply);
! 54: if ($reply=~/^Incorrect/) { $reply='Error: '.$reply; }
! 55: return &unescape($reply);
! 56: } else {
! 57: return 'Error: no connection.';
! 58: }
! 59: }
! 60:
! 61: sub blacklisted {
! 62: my ($cmd)=@_;
! 63: foreach my $forbidden (
! 64: '\? ','\?','%i\d+','%o','batch','block'
! 65: ,'compil','concat','describe','display2d','file','inchar'
! 66: ,'includ','lisp','load','outchar','plot','quit'
! 67: ,'read','reset','save','stin','stout','stringout'
! 68: ,'system','translat','ttyoff','with_stdout','writefile'
! 69: ) {
! 70: if ($cmd=~/$forbidden/s) { return 1; }
! 71: }
! 72: return 0;
! 73: }
! 74:
! 75: sub r_allowed_libraries {
! 76: return (
! 77: "absimp","affine","atensor","atrig1","augmented_lagrangian","contrib_ode","ctensor","descriptive","diag",
! 78: "eigen","facexp","fft","fourie","functs","ggf","grobner","impdiff","ineq","interpol","itensor","lapack",
! 79: "lbfgs","lindstedt","linearalgebra","lsquares","makeOrders","mnewton","mchrpl","ntrig","orthopoly",
! 80: "quadpack","rducon","romberg","scifac","simplex","solve_rec","sqdnst","stats","sterling","sym","units",
! 81: "vect","zeilberger");
! 82: }
! 83:
! 84: sub r_is_allowed_library {
! 85: my ($library)=@_;
! 86: foreach my $allowed_library (&r_allowed_libraries()) {
! 87: if ($library eq $allowed_library) { return 1; }
! 88: }
! 89: return 0;
! 90: }
! 91:
! 92: sub runscript {
! 93: my ($socket,$fullscript,$libraries)=@_;
! 94: if (&blacklisted($fullscript)) { return 'Error: blacklisted'; }
! 95: my $reply;
! 96: $fullscript=~s/[\n\r\l]//gs;
! 97: if ($libraries) {
! 98: foreach my $library (split(/\s*\,\s*/,$libraries)) {
! 99: unless ($library=~/\w/) { next; }
! 100: if (&r_is_allowed_library($library)) {
! 101: $reply=&rreply($socket,'library('.$library.');'."\n");
! 102: if ($reply=~/^Error\:/) { return $reply; }
! 103: } else {
! 104: return 'Error: blacklisted';
! 105: }
! 106: }
! 107: }
! 108: foreach my $line (split(/\;/s,$fullscript)) {
! 109: if ($line=~/\w/) { $reply=&rreply($socket,$line.";\n"); }
! 110: if ($reply=~/^Error\:/) { return $reply; }
! 111: }
! 112: $reply=~s/^\s*//gs;
! 113: $reply=~s/\s*$//gs;
! 114: &Apache::lonxml::debug("r $fullscript \n reply $reply");
! 115: return $reply;
! 116: }
! 117:
! 118: sub r_cas_formula_fix {
! 119: my ($expression)=@_;
! 120: return &Apache::response::implicit_multiplication($expression);
! 121: }
! 122:
! 123: sub r_run {
! 124: my ($script,$submission,$argument,$libraries) = @_;
! 125: my $socket=&connect();
! 126: my @submissionarray=split(/\s*\,\s*/,$submission);
! 127: for (my $i=0;$i<=$#submissionarray;$i++) {
! 128: my $n=$i+1;
! 129: my $fixedsubmission=&r_cas_formula_fix($submissionarray[$i]);
! 130: $script=~s/RESPONSE\[$n\]/$fixedsubmission/gs;
! 131: }
! 132: my @argumentarray=@{$argument};
! 133: for (my $i=0;$i<=$#argumentarray;$i++) {
! 134: my $n=$i+1;
! 135: my $fixedargument=&r_cas_formula_fix($argumentarray[$i]);
! 136: $script=~s/LONCAPALIST\[$n\]/$fixedargument/gs;
! 137: }
! 138: my $reply=&runscript($socket,$script,$libraries);
! 139: &disconnect($socket);
! 140: if ($reply=~/^\s*true\s*$/i) { return 'EXACT_ANS'; }
! 141: if ($reply=~/^\s*false\s*$/i) { return 'INCORRECT'; }
! 142: return 'BAD_FORMULA';
! 143: }
! 144:
! 145: sub r_eval {
! 146: my ($script,$libraries) = @_;
! 147: my $socket=&connect();
! 148: my $reply=&runscript($socket,$script,$libraries);
! 149: &disconnect($socket);
! 150: return $reply;
! 151: }
! 152:
! 153:
! 154: sub compareterms {
! 155: my ($socket,$terma,$termb)=@_;
! 156: my $difference=$terma.'-('.$termb.')';
! 157: if (&blacklisted($difference)) { return 'Error: blacklisted'; }
! 158: my $reply=&rreply($socket,$difference.';');
! 159: if ($reply=~/^\s*0\s*$/) { return 'true'; }
! 160: if ($reply=~/^Error\:/) { return $reply; }
! 161: return 'false';
! 162: }
! 163:
! 164: sub r_check {
! 165: my ($response,$answer,$reterror) = @_;
! 166: my $socket=&connect();
! 167: my $reply=&compareterms($socket,$response,$answer);
! 168: &disconnect($socket);
! 169: # integer to string mappings come from capaParser.h
! 170: # 1 maps to 'EXACT_ANS'
! 171: if ($reply eq 'true') { return 1; }
! 172: # 11 maps to 'BAD_FORMULA'
! 173: if ($reply=~/^Error\:/) { return 11; }
! 174: # 7 maps to 'INCORRECT'
! 175: return 7;
! 176: }
! 177:
! 178: 1;
! 179: __END__;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>