Skip to content

Commit

Permalink
Added a grader and an example for turtle graphics parsons
Browse files Browse the repository at this point in the history
  • Loading branch information
vkaravir committed Jun 24, 2014
1 parent 9784638 commit f41fd53
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 2 deletions.
96 changes: 96 additions & 0 deletions examples/turtle-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!doctype html>
<html>
<head>
<title>Example of js-parsons turtle graphics assignment</title>
<link href="../parsons.css" rel="stylesheet" />
<link href="../lib/prettify.css" rel="stylesheet" />
<script src="../lib/prettify.js"></script>
<meta charset="UTF-8" />
</head>
<body>
<h2>Example of js-parsons turtle graphics assignment</h2>
<p>Construct a program by drag&amp;dropping and reordering lines from the
left to the right.
The constructed program should draw a triangle like shown below.</p>
<style>
canvas {
border: 1px solid black;
}
.turtleFeedback {
height: 350px;
}
.turtle {
float: left;
left: 0; top: 0;
-webkit-transform: scale(0.5);
-webkit-transform-origin: 0 0;
height: 300px;
width: 350px;
}
</style>
<div class="turtleFeedback">
<div class="model turtle">
<h3>Model Drawing</h3>
<canvas id="modelCanvas" width="600" height="600"></canvas>
</div>
<div class="student turtle">
<h3>Your Drawing</h3>
<canvas id="studentCanvas" width="600" height="600"></canvas>
</div>
</div>
<div style="clear:both;"></div>
<p>
<a href="#" id="newInstanceLink">New instance</a>
<a href="#" id="feedbackLink">Get feedback</a>
</p>
<div style="clear:both;"></div>
<div id="sortableTrash" class="sortable-code"></div>
<div id="sortable" class="sortable-code"></div>
<div id="unittest"></div>
<script src="../lib/jquery.min.js"></script>
<script src="../lib/jquery-ui.min.js"></script>
<script src="../lib/underscore-min.js"></script>
<script src="../lib/lis.js"></script>
<script src="../parsons.js"></script>
<script src="../lib/skulpt.js"></script>
<script src="../lib/skulpt-stdlib.js"></script>
<script>
$(document).ready(function(){
var initial = 'REPEAT 3 TIMES\nforward(100)\nleft(120)\nENDREPEAT';
var parson;
Sk.canvas = "studentCanvas";
parson = new ParsonsWidget({
'sortableId': 'sortable',
'trashId': 'sortableTrash',
'max_wrong_lines': 1,
turtleModelCode: "modelTurtle.color(160, 160, 160)\nmodelTurtle.speed(0)\n" +
"modelTurtle.forward(100)\n" +
"modelTurtle.left(120)\nmodelTurtle.forward(100)\nmodelTurtle.left(120)\nmodelTurtle.forward(100)\n" +
"modelTurtle.left(120)",
'grader': ParsonsWidget._graders.TurtleGrader,
'executable_code': "for i in range(0,3):\n" +
"myTurtle.forward(100)\n" +
"myTurtle.left(120)\n" +
"pass",
'programmingLang': "pseudo"
});
parson.init(initial);
parson.shuffleLines();
$("#newInstanceLink").click(function(event){
event.preventDefault();
parson.shuffleLines();
});
$("#feedbackLink").click(function(event){
event.preventDefault();
var fb = parson.getFeedback();
// $("#unittest").html("<h2>Feedback from testing your program:</h2>" + fb.feedback);
if (fb.success) {
alert("Great job, you solved the exercise!");
} else {
alert("Sorry, your solution does not match the model image");
}
});
});
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion lib/skulpt-stdlib.js

Large diffs are not rendered by default.

66 changes: 65 additions & 1 deletion parsons.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@
// formats a Skulpt variable to the corresponding Python value
VariableCheckGrader.prototype.formatVariableValue = function(varValue) {
var varType = typeof varValue;
console.log(varValue, varType);
if (varType === "undefined" || varValue === null) {
return "None";
} else if (varType === "string") { // show strings in quotes
Expand Down Expand Up @@ -271,6 +270,71 @@
return { html: feedback, "log_errors": log_errors, success: all_passed };
};

// A grader to be used for exercises which draw turtle graphics.
// Required options:
// - turtleModelCode: The code constructing the model drawing. The turtle is initialized
// to modelTurtle variable, so your code should use that variable.
//
// Options that can be specified (that is, optional):
// - turtlePenDown: a boolean specifying whether or not the pen should be put down
// initially for the student constructed code
// - turtleModelCanvas: ID of the canvas DOM element where the model solution will be drawn.
// Defaults to modelCanvas.
// - turtleStudentCanvas: ID of the canvas DOM element where student turtle will draw.
// Defaults to studentCanvas.
//
// Grading is based on comparing the commands executed by the model and student turtle.
// If the executable_code option is also specified, the code on each line of that option will
// be executed instead of the code in the student constructed lines. Note, that the student
// code should use the variable myTurtle for commands to control the turtle in order for the
// grading to work.
var TurtleGrader = function(p) {
this.parson = p;
// execute the model solution turtlet path to have the target "picture" visible in the
// beginning
var modelCommands = this._executeTurtleModel();

// specify variable tests for the commands executed by the student turtlet and the model
var penDown = typeof p.options.turtlePenDown === "boolean"?p.options.turtlePenDown:true;
var vartests = [
{initcode: "import parsonturtle\nmyTurtle = parsonturtle.ParsonTurtle()\n" +
"myTurtle.speed(0.3)\nmyTurtle.pensize(3)\n" +
(penDown ? "" : "myTurtle.up()\n"), // set the state of the pen
code: "commands = myTurtle.commands()",
message: "", variables: {commands: modelCommands}}
];
// set the vartests in the parson options
p.options.vartests = vartests;
};
// expose the grader to ParsonsWidget._graders
graders.TurtleGrader = TurtleGrader;
// copy the python execution functions from VariableCheckGrader
TurtleGrader.prototype._python_exec = VariableCheckGrader.prototype._python_exec;
TurtleGrader.prototype._variablesAfterExecution = VariableCheckGrader.prototype._variablesAfterExecution;
// Execute the model turtlet code
TurtleGrader.prototype._executeTurtleModel = function() {
var code = "import parsonturtle\nmodelTurtle = parsonturtle.ParsonTurtle()\n" +
this.parson.options.turtleModelCode +
"\ncommands = modelTurtle.commands()\n";
Sk.canvas = this.parson.options.turtleModelCanvas || "modelCanvas";
var result = this._variablesAfterExecution(code, ["commands"]);
if (!result.variables || !result.variables.commands || !result.variables.commands.v) {
return "None";
}
return result.variables.commands.v;
};
// grade the student solution
TurtleGrader.prototype.grade = function() {
// set the correct canvas where the turtle should draw
Sk.canvas = this.parson.options.turtleStudentCanvas || "studentCanvas";
// Pass the grading on to either the LangTranslationGrader or VariableChecker
if (this.parson.options.executable_code) {
return new LanguageTranslationGrader(this.parson).grade();
} else {
return new VariableCheckGrader(this.parson).grade();
}
};

// Grader that will execute student code and Skulpt unittests
var UnitTestGrader = function(parson) {
this.parson = parson;
Expand Down

0 comments on commit f41fd53

Please sign in to comment.