Merge pull request #3952 from christianbeeznest/lti-provider3

Plugin: LTI Provider: Remove demo game as tool provider - #3894
pull/3998/head
Yannick Warnier 4 years ago committed by GitHub
commit 2682c2ce90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      plugin/lti_provider/tool/api/score.php
  2. 49
      plugin/lti_provider/web/api/score.php
  3. 51
      plugin/lti_provider/web/api/scoreboard.php
  4. 20
      plugin/lti_provider/web/configure.php
  5. 32
      plugin/lti_provider/web/game.php
  6. 8
      plugin/lti_provider/web/login.php
  7. 56
      plugin/lti_provider/web/static/breakout.css
  8. 464
      plugin/lti_provider/web/static/breakout.js
  9. 35
      plugin/lti_provider/web/view/game.tpl

@ -16,12 +16,6 @@ if (!isset($_REQUEST['exeId'])) {
$launchData = $launch->getLaunchData(); $launchData = $launch->getLaunchData();
$label = 'Score';
$courseClient = $launchData['https://purl.imsglobal.org/spec/lti/claim/resource_link']['title'];
if (!empty($courseClient)) {
$label = $courseClient;
}
$exeId = (int) $_REQUEST['exeId']; $exeId = (int) $_REQUEST['exeId'];
$trackInfo = Exercise::get_stat_track_exercise_info_by_exe_id($exeId); $trackInfo = Exercise::get_stat_track_exercise_info_by_exe_id($exeId);
$score = $trackInfo['exe_result']; $score = $trackInfo['exe_result'];
@ -41,7 +35,7 @@ $score = Packback\Lti1p3\LtiGrade::new()
$scoreLineitem = Packback\Lti1p3\LtiLineitem::new() $scoreLineitem = Packback\Lti1p3\LtiLineitem::new()
->setTag('score') ->setTag('score')
->setScoreMaximum($weight) ->setScoreMaximum($weight)
->setLabel($label) ->setLabel('Score')
->setResourceId($launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']); ->setResourceId($launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']);
$grades->putGrade($score, $scoreLineitem); $grades->putGrade($score, $scoreLineitem);

@ -1,49 +0,0 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../../../main/inc/global.inc.php';
require_once __DIR__.'/../../src/LtiProvider.php';
$launch = LtiProvider::create()->launch(true, $_REQUEST['launch_id']);
if (!$launch->hasAgs()) {
throw new Exception("Don't have grades!");
}
$grades = $launch->getAgs();
$score = Packback\Lti1p3\LtiGrade::new()
->setScoreGiven($_REQUEST['score'])
->setScoreMaximum(100)
->setTimestamp(date(DateTime::ISO8601))
->setActivityProgress('Completed')
->setGradingProgress('FullyGraded')
->setUserId($launch->getLaunchData()['sub']);
$scoreLineitem = Packback\Lti1p3\LtiLineitem::new()
->setTag('score')
->setScoreMaximum(100)
->setLabel('Score')
->setResourceId($launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']);
$grades->putGrade($score, $scoreLineitem);
$time = Packback\Lti1p3\LtiGrade::new()
->setScoreGiven($_REQUEST['time'])
->setScoreMaximum(999)
->setTimestamp(DateTime::ISO8601)
->setActivityProgress('Completed')
->setGradingProgress('FullyGraded')
->setUserId($launch->getLaunchData()['sub']);
$timeLineitem = Packback\Lti1p3\LtiLineitem::new()
->setTag('time')
->setScoreMaximum(999)
->setLabel('Time Taken')
->setResourceId('time'.$launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']);
$grades->putGrade($time, $timeLineitem);
echo '{"success" : true}';

@ -1,51 +0,0 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../../../main/inc/global.inc.php';
require_once __DIR__.'/../../src/LtiProvider.php';
$launch = LtiProvider::create()->launch(true, $_REQUEST['launch_id']);
if (!$launch->hasNrps()) {
throw new Exception("Don't have names and roles!");
}
if (!$launch->hasAgs()) {
throw new Exception("Don't have grades!");
}
$ags = $launch->getAgs();
$scoreLineitem = Packback\Lti1p3\LtiLineitem::new()
->setTag('score')
->setScoreMaximum(100)
->setLabel('Score')
->setResourceId($launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']);
$scores = $ags->getGrades($scoreLineitem);
$timeLineitem = Packback\Lti1p3\LtiLineitem::new()
->setTag('time')
->setScoreMaximum(999)
->setLabel('Time Taken')
->setResourceId('time'.$launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id']);
$times = $ags->getGrades($timeLineitem);
$members = $launch->getNrps()->getMembers();
$scoreboard = [];
foreach ($scores as $score) {
$result = ['score' => $score['resultScore']];
foreach ($times as $time) {
if ($time['userId'] === $score['userId']) {
$result['time'] = $time['resultScore'];
break;
}
}
foreach ($members as $member) {
if ($member['user_id'] === $score['userId']) {
$result['name'] = $member['name'];
break;
}
}
$scoreboard[] = $result;
}
echo json_encode($scoreboard);

@ -1,20 +0,0 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../../main/inc/global.inc.php';
require_once __DIR__.'/../src/LtiProvider.php';
use Packback\Lti1p3;
$launch = LtiProvider::create()->launch(true, $_REQUEST['launch_id']);
if (!$launch->isDeepLinkLaunch()) {
throw new Exception("Must be a deep link!");
}
$resource = LtiDeepLinkResource::new()
->setUrl(api_get_path(WEB_PLUGIN_PATH)."lti_provider/web/game.php")
->setCustomParams(['difficulty' => $_REQUEST['diff']])
->setTitle('Breakout ' . $_REQUEST['diff'] . ' mode!');
$launch->getDeepLink()
->outputResponseForm([$resource]);

@ -1,32 +0,0 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../../main/inc/global.inc.php';
require_once __DIR__.'/../src/LtiProvider.php';
use Packback\Lti1p3;
$launch = LtiProvider::create()->launch();
$htmlHeadXtra[] = api_get_css(
api_get_path(WEB_PLUGIN_PATH).'lti_provider/web/static/breakout.css'
);
$template = new Template('Game demo');
$courseCode = $launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/context']['label'];
$diff = 'normal';
if ($launch->isDeepLinkLaunch()) {
$diff = $launch->getLaunchData()['https://purl.imsglobal.org/spec/lti/claim/custom']['difficulty'];
}
$username = $launch->getLaunchData()['given_name'];
$template->assign('launch', $launch);
$template->assign('courseCode', $courseCode);
$template->assign('diff', $diff);
$template->assign('username', $username);
$content = $template->fetch('lti_provider/web/view/game.tpl');
$template->assign('content', $content);
$template->display_no_layout_template();
?>

@ -1,8 +0,0 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../../main/inc/global.inc.php';
require_once __DIR__.'/../src/LtiProvider.php';
use Packback\Lti1p3;
LtiProvider::create()->login($_REQUEST);

@ -1,56 +0,0 @@
body {
font-family: 'Gugi', cursive;
}
#scoreboard {
border: solid 1px #000;
border-left: none;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
padding-bottom: 12px;
background: linear-gradient(to bottom, rgb(0, 0, 0), rgb(0, 0, 50) 500px);
color: white;
}
th, td {
color: white;
}
.dl-config {
font-family: Verdana, Geneva, Tahoma, sans-serif;
display: block;
width: 400px;
position: absolute;
left:50%;
margin-left: -200px;
}
.dl-config h1 {
text-align: center;
}
.dl-config ul {
list-style: none;
padding: 0;
}
.dl-config ul li a {
display: block;
width: 200px;
height:50px;
text-align: center;
border: black solid 1px;
border-radius: 15px;
margin:auto;
text-decoration: none;
color: black;
margin-top:8px;
font-size: 30px;
line-height: 46px;
}
.dl-config ul li a:hover {
background-color: #dddddd;
}
#game-screen {
position: relative;
height: 550px;
width: 100%;
}
#btn-again {
right: 0px;
position: absolute;
}

@ -1,464 +0,0 @@
var c = document.getElementById("breakout");
var ctx = window.c.getContext("2d");
var bgctx = document.getElementById("breakoutbg").getContext("2d");
bgctx.beginPath();
var bggrad = ctx.createLinearGradient(0,0,0,c.height);
bggrad.addColorStop(0,"rgb(0, 0, 0)");
bggrad.addColorStop(1,"rgb(0, 0, 50)");
bgctx.fillStyle = bggrad;
bgctx.rect(0, 0, c.width, c.height);
bgctx.fill();
bgctx.font = "10px Gugi";
bgctx.fillStyle = '#FFFFFF';
bgctx.textAlign = "left";
bgctx.fillText("Powered By Turnitin", 6, c.height-6);
var score = 0;
var difficulty = {
hard: {
speed_multiplier:1.5
},
normal: {
speed_multiplier:1
},
easy: {
speed_multiplier:0.7
},
}
var ball = {
pos : {
x: window.c.width/2-200,
y : window.c.height/2-2,
},
vel : {
x : 6 * difficulty[curr_diff]['speed_multiplier'],
y : 6 * difficulty[curr_diff]['speed_multiplier'],
},
r: 10,
rot: 0,
velr: 0,
render: function() {
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
if (this.oob(window.c.width, this.pos.x, this.r)) {
this.vel.x = -this.vel.x;
this.pos.x += this.vel.x;
this.pos.y -= this.vel.y;
}
if (this.oob(window.c.height, this.pos.y, this.r)) {
if (this.pos.y > window.c.height - this.r) {
window.endGame();
}
this.vel.y = -this.vel.y;
this.pos.y += this.vel.y;
this.pos.x -= this.vel.x;
}
window.ctx.save();
window.ctx.beginPath();
var gradient = ctx.createRadialGradient(this.pos.x, this.pos.y, 2, this.pos.x, this.pos.y, 10);
window.ctx.fillStyle = "rgb(255, 232, 102)";
window.ctx.strokeStyle = "rgb(255, 232, 102)";
window.ctx.setLineDash([5,5]);
window.ctx.lineWidth = 4;
window.ctx.translate(this.pos.x, this.pos.y);
window.ctx.rotate(this.rot * Math.PI);
window.ctx.arc(0, 0, this.r, 0, 2 * Math.PI);
if (this.vel.x > 0) {
this.velr = 0.01;
} else if (this.vel.x < 0) {
this.velr = -0.01;
} else {
this.velr = 0;
}
this.rot += this.velr;
window.ctx.fill();
window.ctx.stroke();
window.ctx.restore();
},
oob : function(max, curr, offset) {
if (curr < offset || curr > (max-offset)) {
return true;
}
},
left : function() {
return this.pos.x - this.r;
},
right : function() {
return this.pos.x + this.r;
},
top : function() {
return this.pos.y - this.r;
},
bottom : function() {
return this.pos.y + this.r;
},
};
var paddle = {
pos : {
x: window.c.width/2+2,
y : window.c.height-40,
},
width : 80,
height : 20,
render: function() {
window.ctx.beginPath();
var gradient = ctx.createLinearGradient(this.pos.x,this.pos.y,this.pos.x,this.pos.y + this.height);
gradient.addColorStop(0,"#999999");
gradient.addColorStop(0.7,"#eeeeee");
gradient.addColorStop(1,"#999999");
ctx.fillStyle = gradient;
var hh = this.height/2;
window.ctx.arc(this.pos.x + hh, this.pos.y + hh, hh, 0.5 * Math.PI, 1.5 * Math.PI);
window.ctx.rect(this.pos.x + hh, this.pos.y, this.width - this.height, this.height);
window.ctx.arc(this.pos.x + this.width - hh, this.pos.y + hh, hh, 1.5 * Math.PI, 0.5 * Math.PI);
window.ctx.fill();
window.ctx.stroke();
},
left : function() {
return this.pos.x;
},
right : function() {
return this.pos.x + this.width;
},
top : function() {
return this.pos.y;
},
bottom : function() {
return this.pos.y + this.height;
},
test_hit : function() {
var hitx = this.test_hit_x();
var hity = this.test_hit_y();
if (!hitx || !hity) {
return 0;
}
if (hity) {
window.ball.vel.y = -Math.abs(window.ball.vel.y);
window.ball.pos.y += window.ball.vel.y;
window.ball.pos.x -= window.ball.vel.x;
}
if (hitx) {
var xdiff = window.ball.pos.x - (this.pos.x + (this.width/2));
window.ball.vel.x = (xdiff > 0 ? Math.ceil(xdiff / 5) : Math.floor(xdiff / 5)) * difficulty[curr_diff]['speed_multiplier'];
window.ball.pos.x += window.ball.vel.x;
}
return 1;
},
test_hit_x : function() {
if (this.left() > window.ball.right()) {
return 0;
}
if (this.right() < window.ball.left()) {
return 0;
}
return 1;
},
test_hit_y : function() {
if (this.top() > window.ball.bottom()) {
return 0;
}
if (this.bottom() < window.ball.top()) {
return 0;
}
return 1;
},
move : function() {
if (window.press_left) {
if (this.pos.x > 0) {
this.pos.x -= 8;
}
}
if (window.press_right) {
if (this.pos.x < window.c.width - this.width) {
this.pos.x += 8;
}
}
}
};
function fire() {
this.r = 0,
this.a = 0,
this.render = function() {
if (this.a < 0.2) {
this.reset();
}
this.pos.x += this.vel.x + (Math.random() * 2) - 1;
this.pos.y += this.vel.y + (Math.random() * 2) - 1;
this.r *= 0.95;
this.a *= 0.95;
window.ctx.beginPath();
window.ctx.fillStyle = 'rgba(' + (239 - this.green) +', ' + this.green + ', 66,'+ this.a +')';
window.ctx.arc(this.pos.x, this.pos.y, this.r, 0, 2 * Math.PI);
window.ctx.fill();
if (this.green < 232) {
this.green += 8;
}
},
this.reset = function() {
this.pos = {
x: window.ball.pos.x,
y : window.ball.pos.y,
};
this.vel = {
x : (Math.random() * 4) - 2,
y : (Math.random() * 4) - 2,
};
this.r = (Math.random() * 5) + 1;
this.a = 0.9;
this.green = 62;
}
}
function brick() {
this.id = 0,
this.pos = {
x: 40,
y: 40,
},
this.vely = 0,
this.rot = 0,
this.velr = 0,
this.hit = false,
this.last_hitx = false,
this.last_hity = false,
this.width = 40,
this.height = 20,
this.render = function() {
if (this.hit) {
if (this.pos.y > window.c.height + 60) {
return;
}
this.vely++;
this.pos.y += this.vely;
ctx.save()
window.ctx.beginPath();
this.rot += this.velr;
ctx.translate(this.pos.x + (this.width/2), this.pos.y + (this.height/2));
ctx.rotate(this.rot * Math.PI);
var gradient = ctx.createRadialGradient(-(this.width/2) +10, -(this.height/2) +5, 0, -(this.width/2) + 40, -(this.height/2) + 15, 40);
gradient.addColorStop(0, 'rgba(137, 211, 234, 0.2)');
gradient.addColorStop(1, 'rgba(137, 211, 234, 1)');
ctx.strokeStyle = 'rgba(254, 254, 254, 0.8)';
ctx.fillStyle = gradient;
window.ctx.rect(-(this.width/2), -(this.height/2), this.width, this.height);
window.ctx.fill();
window.ctx.stroke();
ctx.restore();
return;
}
window.ctx.beginPath();
var gradient = ctx.createRadialGradient(this.pos.x + 10, this.pos.y + 5, 0, this.pos.x + 40, this.pos.y + 15, 40);
gradient.addColorStop(0, 'rgba(137, 211, 234, 0.2)');
gradient.addColorStop(1, 'rgba(137, 211, 234, 1)');
ctx.strokeStyle = 'rgba(254, 254, 254, 0.8)';
ctx.fillStyle = gradient;
window.ctx.rect(this.pos.x, this.pos.y, this.width, this.height);
window.ctx.fill();
window.ctx.stroke();
},
this.test_hit = function() {
if (this.hit) {
return 0;
}
var hitx = this.test_hit_x();
var hity = this.test_hit_y();
if (!hitx || !hity) {
this.last_hitx = hitx;
this.last_hity = hity;
return 0;
}
if (this.last_hity) {
window.ball.vel.y = -window.ball.vel.y;
window.ball.pos.y += window.ball.vel.y;
window.ball.pos.x -= window.ball.vel.x;
}
if (this.last_hitx) {
window.ball.vel.x = -window.ball.vel.x;
window.ball.pos.x += window.ball.vel.x;
window.ball.pos.y -= window.ball.vel.y;
}
if (!this.last_hity && this.last_hitx) {
window.ball.vel.x = -window.ball.vel.x;
window.ball.pos.x += window.ball.vel.x;
window.ball.vel.y = -window.ball.vel.y;
window.ball.pos.y += window.ball.vel.y;
}
this.last_hitx = hitx;
this.last_hity = hity;
this.hit = true;
this.velr = (Math.random() * 0.04) - 0.02;
window.score++;
return 1;
},
this.test_hit_x = function() {
if (this.left() > window.ball.right()) {
return 0;
}
if (this.right() < window.ball.left()) {
return 0;
}
return 1;
},
this.test_hit_y = function() {
if (this.top() > window.ball.bottom()) {
return 0;
}
if (this.bottom() < window.ball.top()) {
return 0;
}
return 1;
},
this.left = function() {
return this.pos.x;
},
this.right = function() {
return this.pos.x + this.width;
},
this.top = function() {
return this.pos.y;
},
this.bottom = function() {
return this.pos.y + this.height;
}
};
press_left = false;
press_right = false;
document.addEventListener('keydown', (event) => {
const keyName = event.key;
if (keyName == "ArrowLeft") {
press_left = true;
}
if (keyName == "ArrowRight") {
press_right = true;
}
});
document.addEventListener('keyup', (event) => {
const keyName = event.key;
if (keyName == "ArrowLeft") {
press_left = false;
}
if (keyName == "ArrowRight") {
press_right = false;
}
if (keyName == " ") {
if (pause && !gameover) {
if (!start_time) {
start_time = Math.floor(Date.now() / 1000);
}
pause = false;
frame();
} else {
pause = true;
}
}
});
var bricks = [];
for (var h = 0; h < 6; h++) {
for (var w = 0; w < 18; w++) {
var brickid = (18*h)+w;
bricks[brickid] = new brick();
bricks[brickid].pos.x = 40+(w*40);
bricks[brickid].pos.y = 40+(h*20);
bricks[brickid].id = brickid;
}
}
var fires = [];
for (var i = 0; i < 80; i++) {
fires[i] = new fire();
}
startFireCount = 1;
pause = true;
gameover = false;
var frame = function() {
if (window.score >= window.bricks.length) {
endGame();
}
window.ctx.clearRect(0, 0, window.c.width, window.c.height);
for (var i = 0; i < window.bricks.length; i++) {
window.bricks[i].render();
}
for (var i = 0; i < window.bricks.length; i++) {
if (window.bricks[i].test_hit()) {
break;
}
}
for (var i = 0; i < window.fires.length && i < startFireCount; i++) {
window.fires[i].render();
}
if (startFireCount <= window.fires.length) {
startFireCount++;
}
window.paddle.move();
window.paddle.render();
window.paddle.test_hit();
window.ball.render();
if (pause) {
if (!gameover) {
ctx.font = "50px Gugi";
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = "center";
ctx.fillText("Ready " + curr_user_name, c.width/2, c.height/2);
ctx.fillText("Press Space to Start", c.width/2, c.height/2 + 60);
}
} else {
requestAnimationFrame(frame);
}
}
start_time = false;
document.fonts.load('50px Gugi').then(frame);
var endGame = function() {
window.pause = true;
window.gameover = true;
window.submitScore();
}
var refreshScoreBoard = function() {
var scores = JSON.parse(this.responseText);
console.log(scores);
var output = '<tr><th>Score</th><th>Time</th><th>Name</th></tr>';
for (var i = 0; i < scores.length; i++) {
output += '<tr><td>' + scores[i].score + '</td><td>' + scores[i].time + 's</td><td>' + scores[i].name + '</td></tr>';
}
document.getElementById("leadertable").innerHTML = output;
}
var submitScore = function() {
var time_taken = Math.floor(Date.now() / 1000) - start_time;
var xhttp = new XMLHttpRequest();
xhttp.addEventListener("load", getScoreBoard);
xhttp.open("GET", "api/score.php?launch_id=" + launch_id + "&score=" + window.score + "&time=" + time_taken, false);
xhttp.send();
}
var getScoreBoard = function() {
var xhttp = new XMLHttpRequest();
xhttp.addEventListener("load", refreshScoreBoard);
xhttp.open("GET", "api/scoreboard.php?launch_id=" + launch_id, true);
xhttp.send();
}
getScoreBoard();

@ -1,35 +0,0 @@
<link href="https://fonts.googleapis.com/css?family=Gugi" rel="stylesheet">
{% if launch.isDeepLinkLaunch %}
<div class="dl-config">
<h1>Pick a Difficulty</h1>
<ul>
<li><a href="{{ _p.web_plugin }}lti_provider/web/configure.php?diff=easy&launch_id={{ launch.getLaunchId }}">Easy</a></li>
<li><a href="{{ _p.web_plugin }}lti_provider/web/configure.php?diff=normal&launch_id={{ launch.getLaunchId }}">Normal</a></li>
<li><a href="{{ _p.web_plugin }}lti_provider/web/configure.php?diff=hard&launch_id={{ launch.getLaunchId }}">Hard</a></li>
</ul>
</div>
{% else %}
<div id="game-screen">
<div style="position:absolute;width:1000px;margin-left:-500px;left:50%; display:block">
<div id="scoreboard" style="position:absolute; right:0; width:200px; height:486px">
<h3 style="margin-left:12px;">Scoreboard - {{ courseCode }}</h3>
<table id="leadertable" style="margin-left:12px;">
</table>
</div>
<canvas id="breakoutbg" width="800" height="500" style="position:absolute;left:0;border:0;">
</canvas>
<canvas id="breakout" width="800" height="500" style="position:absolute;left:0;">
</canvas>
</div>
</div>
<div class="clearfix"></div>
<button onclick="location.reload()" class="btn btn-sm" id="btn-again">Play Again</button>
<script>
var curr_diff = "{{ diff }}";
var curr_user_name = "{{ username }}";
var launch_id = "{{ launch.getLaunchId }}";
</script>
<script type="text/javascript" src="{{ _p.web_plugin }}lti_provider/web/static/breakout.js" charset="utf-8"></script>
{% endif %}
Loading…
Cancel
Save