--- loncom/lti/ltiutils.pm	2018/04/14 02:30:07	1.6
+++ loncom/lti/ltiutils.pm	2018/05/15 04:59:22	1.10
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA LTI interactions 
 #
-# $Id: ltiutils.pm,v 1.6 2018/04/14 02:30:07 raeburn Exp $
+# $Id: ltiutils.pm,v 1.10 2018/05/15 04:59:22 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -34,6 +34,7 @@ use Digest::SHA;
 use UUID::Tiny ':std';
 use Apache::lonnet;
 use Apache::loncommon;
+use Math::Round();
 use LONCAPA qw(:DEFAULT :match);
 
 #
@@ -324,6 +325,7 @@ sub sign_params {
     if ($sigmethod eq '') {
         $sigmethod = 'HMAC-SHA1';
     }
+    srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.
     my $nonce = Digest::SHA::sha1_hex(sprintf("%06x%06x",rand(0xfffff0),rand(0xfffff0)));
     my $request = Net::OAuth->request("request token")->new(
             consumer_key => $key,
@@ -473,22 +475,44 @@ sub release_tool_lock {
 #
 
 sub lti_provider_scope {
-    my ($tail,$cdom,$cnum) = @_;
-    my ($scope,$realuri);
-    if ($tail =~ m{^/uploaded/$cdom/$cnum/(?:default|supplemental)(?:|_\d+)\.(?:sequence|page)(|___\d+___.+)$}) {
+    my ($tail,$cdom,$cnum,$getunenc) = @_;
+    my ($scope,$realuri,$passkey,$unencsymb);
+    if ($tail =~ m{^/?uploaded/$cdom/$cnum/(?:default|supplemental)(?:|_\d+)\.(?:sequence|page)(|___\d+___.+)$}) {
         my $rest = $1;
         if ($rest eq '') {
             $scope = 'map';
             $realuri = $tail;
         } else {
-            $scope = 'resource';
             my ($map,$resid,$url) = &Apache::lonnet::decode_symb($tail);
             $realuri = &Apache::lonnet::clutter($url);
-            if (($url =~ /\.sequence$/) &&
-                ($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement')) {
-                $realuri .= '?navmap=1';
+            if ($url =~ /\.sequence$/) {
+                $scope = 'map';
             } else {
+                $scope = 'resource';
                 $realuri .= '?symb='.$tail;
+                $passkey = $tail;
+                if ($getunenc) {
+                    $unencsymb = $tail;
+                }
+            }
+        }
+    } elsif ($tail =~ m{^/?res/$match_domain/$match_username/.+\.(?:sequence|page)(|___\d+___.+)$}) {
+        my $rest = $1;
+        if ($rest eq '') {
+            $scope = 'map';
+            $realuri = $tail;
+        } else {
+            my ($map,$resid,$url) = &Apache::lonnet::decode_symb($tail);
+            $realuri = &Apache::lonnet::clutter($url);
+            if ($url =~ /\.sequence$/) {
+                $scope = 'map';
+            } else {
+                $scope = 'resource';
+                $realuri .= '?symb='.$tail;
+                $passkey = $tail;
+                if ($getunenc) {
+                    $unencsymb = $tail;
+                }
             }
         }
     } elsif ($tail =~ m{^/tiny/$cdom/(\w+)$}) {
@@ -513,30 +537,76 @@ sub lti_provider_scope {
             } else {
                 $scope = 'resource';
             }
+            $passkey = $symb;
             if ((&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i) &&
                 (!$env{'request.role.adv'})) {
                 $realuri = &Apache::lonenc::encrypted(&Apache::lonnet::clutter($url));
-                if (($url =~ /\.sequence$/) &&
-                    ($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement')) {
-                    $realuri .= '?navmap=1';
-                } else {
+                if ($scope eq 'resource') {
                     $realuri .= '?symb='.&Apache::lonenc::encrypted($symb);
                 }
             } else {
                 $realuri = &Apache::lonnet::clutter($url);
-                if (($url =~ /\.sequence$/) &&
-                    ($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement')) {
-                    $realuri .= '?navmap=1';
-                } else {
+                if ($scope eq 'resource') {
                     $realuri .= '?symb='.$symb;
                 }
             }
+            if ($getunenc) {
+                $unencsymb = $symb;
+            }
         }
-    } elsif ($tail =~ m{^/$cdom/$cnum$}) {
+    } elsif (($tail =~ m{^/$cdom/$cnum$}) || ($tail eq '')) {
         $scope = 'course';
         $realuri = '/adm/navmaps';
+        $passkey = $tail;
+    }
+    if ($scope eq 'map') {
+        $passkey = $realuri;
+    }
+    if (wantarray) {
+        return ($scope,$realuri,$unencsymb);
+    } else {
+        return $passkey;
+    }
+}
+
+sub send_grade {
+    my ($id,$url,$ckey,$secret,$scoretype,$total,$possible) = @_;
+    my $score;
+    if ($possible > 0) {
+        if ($scoretype eq 'ratio') {
+            $score = Math::Round::round($total).'/'.Math::Round::round($possible);
+        } elsif ($scoretype eq 'percentage') {
+            $score = (100.0*$total)/$possible;
+            $score = Math::Round::round($score);
+        } else {
+            $score = $total/$possible;
+            $score = sprintf("%.2f",$score);
+        }
+    }
+    my $date = &Apache::loncommon::utc_string(time);
+    my %ltiparams = (
+        lti_version                   => 'LTI-1p0',
+        lti_message_type              => 'basic-lis-updateresult',
+        sourcedid                     => $id,
+        result_resultscore_textstring => $score,
+        result_resultscore_language   => 'en-US',
+        result_resultvaluesourcedid   => $scoretype,
+        result_statusofresult         => 'final',
+        result_date                   => $date,
+    );
+    my $hashref = &sign_params($url,$ckey,$secret,\%ltiparams);
+    if (ref($hashref) eq 'HASH') {
+        my $request=new HTTP::Request('POST',$url);
+        $request->content(join('&',map {
+                          my $name = escape($_);
+                          "$name=" . ( ref($hashref->{$_}) eq 'ARRAY'
+                          ? join("&$name=", map {escape($_) } @{$hashref->{$_}})
+                          : &escape($hashref->{$_}) );
+        } keys(%{$hashref})));
+        my $response = &LONCAPA::LWPReq::makerequest('',$request,'','',10);
+        my $message=$response->status_line;
+#FIXME Handle case where pass back of score to LTI Consumer failed.
     }
-    return ($scope,$realuri);
 }
 
 1;