123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>BlockPy Replay</title>
-
- <link rel="stylesheet" href="libs/bootstrap.min.css">
- <link rel="stylesheet" href="libs/codemirror/codemirror.css">
- <link rel="stylesheet" href="libs/font-awesome.min.css">
- <link rel="stylesheet" href="libs/summernote/summernote.css">
- <link rel="stylesheet" href="libs/multi-select.css">
- <link rel="stylesheet" href="src/blockpy.css">
- <!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">-->
-
- <!-- JQuery, D3, Math.js, Bootstrap -->
- <script type="text/javascript" src="libs/jquery.js"></script>
- <script type="text/javascript" src="libs/jquery-ui.min.js"></script>
- <script type="text/javascript" src="libs/jquery.hotkeys.js"></script>
- <script type="text/javascript" src="libs/jquery.multi-select.js"></script>
- <script type="text/javascript" src="libs/d3.min.js"></script>
- <script type="text/javascript" src="libs/math.0.19.0.min.js"></script>
- <script type="text/javascript" src="libs/bootstrap.min.js"></script>
- <script type="text/javascript" src="libs/bootstrap-wysiwyg.js"></script>
- <script type="text/javascript" src="libs/mindmup-editabletable.js"></script>
- <script type="text/javascript" src="libs/codemirror/codemirror.js"></script>
- <script type="text/javascript" src="libs/codemirror/python.js"></script>
- <script type="text/javascript" src="libs/codemirror/htmlmixed.js"></script>
- <script type="text/javascript" src="libs/codemirror/xml.js"></script>
- <script type="text/javascript" src="libs/knockout-3.4.0.js"></script>
-
- <!-- Summernote, a rich text editor -->
- <script type="text/javascript" src="libs/summernote/summernote.min.js"></script>
- <script type="text/javascript" src="libs/summernote/summernote-ext-hint.js"></script>
- <script type="text/javascript" src="libs/summernote/summernote-ext-video.js"></script>
-
- <!-- Blockly -->
- <script type="text/javascript" src="blockly/blockly_uncompressed.js"></script>
- <script type="text/javascript" src="blockly/blocks_compressed.js"></script>
- <script type="text/javascript" src="blockly/python_compressed.js"></script>
- <script type="text/javascript" src="blockly/pseudo_compressed.js"></script>
- <script type="text/javascript" src="blockly/javascript_compressed.js"></script>
- <script type="text/javascript" src="blockly/msg/js/en.js"></script>
-
- <!-- Skulpt -->
- <script type="text/javascript" src="skulpt/dist/skulpt.min.js"></script>
- <script type="text/javascript" src="skulpt/dist/skulpt-stdlib.js"></script>
-
- <!-- Source Code -->
- <script type="text/javascript" src="src/utilities.js"></script>
- <script type="text/javascript" src="src/python_errors.js"></script>
- <script type="text/javascript" src="src/ast_node_visitor.js"></script>
- <script type="text/javascript" src="src/abstract_interpreter.js"></script>
- <script type="text/javascript" src="src/abstract_interpreter_definitions.js"></script>
- <script type="text/javascript" src="src/abstract_interpreter_tests.js"></script>
- <script type="text/javascript" src="src/python_to_blockly.js"></script>
- <script type="text/javascript" src="src/imported.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/class.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/comment.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/comprehensions.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/dict.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/if.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/io.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/lists.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/sets.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/loops.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/parking.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/tuple.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/turtles.js"></script>
- <script type="text/javascript" src="src/blockly_blocks/text.js"></script>
- <script type="text/javascript" src="src/dialog.js"></script>
- <script type="text/javascript" src="src/storage.js"></script>
- <script type="text/javascript" src="src/printer.js"></script>
- <script type="text/javascript" src="src/interface.js"></script>
- <script type="text/javascript" src="src/server.js"></script>
- <script type="text/javascript" src="src/english.js"></script>
- <script type="text/javascript" src="src/corgis.js"></script>
- <script type="text/javascript" src="src/history.js"></script>
- <script type="text/javascript" src="src/presentation.js"></script>
- <script type="text/javascript" src="src/editor.js"></script>
- <script type="text/javascript" src="src/feedback.js"></script>
- <script type="text/javascript" src="src/toolbar.js"></script>
- <script type="text/javascript" src="src/treeMatching.js"></script>
- <script type="text/javascript" src="src/sk_mod_instructor_extended.js"></script>
- <script type="text/javascript" src="src/sk_mod_instructor.js"></script>
- <script type="text/javascript" src="src/engine.js"></script>
- <script type="text/javascript" src="src/main.js"></script>
-
- <!--<script type="text/javascript" src="test_corgis/blockpy/tate/tate_blockly.js"></script>
- <script type="text/javascript" src="test_corgis/blockpy/tate/tate_skulpt.js"></script>
- <script type="text/javascript" src="test_corgis/blockpy/tate/tate_dataset.js"></script>-->
-
- <style>
- </style>
- <script>
- $(document).ready(function() {
- blockpy = new BlockPy({
- 'blocklyPath': "blockly/",
- 'attachmentPoint': document.getElementById('blockpy-div'),
- 'instructor': true,
- 'developer': true,
- 'editor': 'Text',
- 'urls': {
- 'import_datasets': 'https://think.cs.vt.edu/blockpy/load_corgis/',
- //'walk_old_code': 'http://localhost:8000/walk_code/',
- //'log_event': 'http://localhost:8000/save_events/'
- /*'save_code': 'http://localhost:8000/save_code/',
- 'save_success': 'http://localhost:8000/submit_grade/',
- 'log_event': 'http://localhost:8000/save_events/'*/
- }
- });
- blockpy.setAssignment(
- // settings
- {
- 'editor': 'Text',
- 'read_only': false,
- 'disable_semantic_errors': false,
- },
- // assignment
- {
- 'introduction': "Welcome to BlockPy. Try running the code below.",
- 'name': "#1.2",
- 'give_feedback': 'import instructor_histogram as ins_hist\nimport instructor_append as ins_app\nimport instructor_iteration as ins_iter\nimport instructor_filter as ins_filt\nimport iteration_context as ins_cont\nins_app.missing_append_in_iteration()\nins_app.wrong_not_append_to_list()\nins_app.missing_append_list_initialization()\nins_app.wrong_append_list_initiatization()\nins_app.append_list_wrong_slot()\n',
- 'parsons': false,
- 'starting_code': '',
- 'importable': true,
- 'initial_view': 'Blocks',
- 'modules': {
- 'added': ['Functions', 'Data - Weather'],
- 'removed': []
- }
- },
- // programs
- {
- '__main__': 'import matplotlib.pyplot as plt\nquakes = [1,2,3,4]\nquakes_in_miles = []\nfor quake in quakes:\n quakes_in_miles.append(quake * 0.62)\nplt.hist(quakes_in_miles)\nplt.xlabel("Depth in Miles")\nplt.ylabel("Number of Earthquakes")\nplt.title("Distribution of Depth in Miles of Earthquakes")\nplt.show()\n'
- }
- )
-
- function inIframe () {
- try {
- return window.self !== window.top;
- } catch (e) {
- return true;
- }
- }
- if (inIframe()) {
- $("#blockpy-container").width("100%");
- }
- function updatePauseButton(){
- if(global_isPaused){
- document.getElementById("pause-button").innerHTML = "Play";
- }else{
- document.getElementById("pause-button").innerHTML = "Pause";
- }
- };
- var global_isPaused = false;
- const FORWARD_SCRUB = "forward";
- const BACKWARD_SCRUB = "backward";
- const STOP_SCRUB = "stop"
- var global_scrubing = STOP_SCRUB;
- var speed = 50;
- document.onkeydown = navigationStroke;
-
- function pauseEvent(){
- global_isPaused = !global_isPaused;
- updatePauseButton();
- }
- function forwardEvent(){
- global_isPaused = true;
- global_scrubing = FORWARD_SCRUB;
- updatePauseButton();
- }
- function backEvent(){
- global_isPaused = true;
- global_scrubing = BACKWARD_SCRUB;
- updatePauseButton();
- }
- function navigationStroke(key){
- var KeyNavigationEnabled = document.getElementById("myCheck").checked;
- if(KeyNavigationEnabled == true){
- key = key || window.event;
- if (key.keyCode == '80') {
- // p is pressed
- pauseEvent();
- }
- else if (key.keyCode == '37') {
- // left arrow
- backEvent();
- }
- else if (key.keyCode == '39') {
- // right arrow
- forwardEvent();
- }
- }
- }
- $('#speed-slider').change(function() {
- var sliderValue = document.getElementById("speed-slider").value;
- speed = 100 - document.getElementById("speed-slider").value;
- document.getElementById("sliderValue").innerHTML = sliderValue;
- });
- $('#pause-button').click(function() {
- global_isPaused = !global_isPaused;
- updatePauseButton();
- });
- $('#forward-button').click(function() {
- forwardEvent();
- });
- $('#backward-button').click(function() {
- backEvent();
- });
-
- function handleCodeEvents(record){
- switch (record.action.toLowerCase()) {
- case "set":
- blockpy.model.programs['__main__'](record.body);
- blockpy.components.editor.updateBlocks();
- break;
- }
- }
- function executeLastCodeEvent(pastRecords){
- var codeEvent = null;
- for(i = pastRecords.length-1; i >= 0; i--){
- var rawRecord = pastRecords[i];
- record = JSON.parse(rawRecord);
- if(record.event.toLowerCase() == "code"){
- codeEvent = record;
- break;
- }
- }
- if(codeEvent != null){
- handleCodeEvents(codeEvent);
- }
- }
- function handleFeedbackEvents(record){
- var messages = record.body.split("\n");
- var detailError = messages[0];
- var bodyMessage = "";
- var regex = /line (\d{1,})/i;
- for(i = 1; i < messages.length; i++){
- bodyMessage += messages[i];
- }
- var results = regex.exec(bodyMessage);
- var line = results != null && results.length > 1 ? results[1] : null;
- try{
- switch (record.action.toLowerCase()) {
- case "success":
- blockpy.components.feedback.complete(detailError, bodyMessage, line);
- break;
- case "editor error":
- blockpy.components.feedback.editorError(detailError, bodyMessage, line);
- break;
- case "no errors":
- blockpy.components.feedback.noErrors(detailError, bodyMessage, line);
- break;
- case "syntax error":
- blockpy.components.feedback.syntaxError(detailError, bodyMessage, line);
- break;
- case "semantic error":
- blockpy.components.feedback.semanticError(detailError, bodyMessage, line);
- break;
- case "internal error":
- blockpy.components.feedback.internalError(detailError, bodyMessage, line);
- break;
- case "instructor feedback":
- blockpy.components.feedback.instructorFeedback(detailError, bodyMessage, line);
- break;
- case "empty program":
- blockpy.components.feedback.emptyProgram(detailError, bodyMessage, line);
- break;
- default:
- console.log(record.action.toLowerCase());
- break;
- // ...
- }
- }catch(err){
- console.error(err);
- }
- };
- $('#replay-button').click(function() {
- var records = $('#replay-data').val().split(/\r?\n/);
- var previousTime = null;
- var pastRecords = [];
- var goingBackwards = false;
- var clearRunFlag = false;
- function processAnother(recordsLeft) {
- var gap = 100;
- var moveForward = true;
- if(global_isPaused){
- switch(global_scrubing){
- case BACKWARD_SCRUB:
- if(pastRecords.length > 1){
- blockpy.components.feedback.clearEditorErrors();
- blockpy.components.feedback.clear();
- recordsLeft.unshift(pastRecords.pop());
- recordsLeft.unshift(pastRecords.pop());
- goingBackwards = true;
- //TODO: Handle when going backwards to a feedback event
- }else{
- moveForward = false;
- }
- //NOTE: This cascades into FORWARD_SCRUB
- case FORWARD_SCRUB:
- global_scrubing = STOP_SCRUB;
- previousTime = null;
- break;
- default:
- moveForward = false;
- break;
- };
- }
- if(moveForward && recordsLeft.length > 0){
- blockpy.components.feedback.clearEditorErrors();
- blockpy.components.feedback.clear();
- var rawRecord = recordsLeft.shift();
- var record = JSON.parse(rawRecord);
- pastRecords.push(rawRecord);
- switch (record.event.toLowerCase()) {
- case "code":
- handleCodeEvents(record);
- break;
- case "feedback":
- if(goingBackwards){
- executeLastCodeEvent(pastRecords);
- }
- handleFeedbackEvents(record);
- break;
- }
- var cur_time = new Date(record.time*1000);
- if(!global_isPaused){
- gap = previousTime != null ? record.time - previousTime : 0;
- gap = (gap > 2000 ? 2000 : gap)*speed;
- previousTime = record.time;
- //var cur_time = new Date(record.time*1000);
- //var cur_time = record.time;
- //cur_time = cur_time.getHours();
- console.log(gap + ": " + cur_time.getHours() + ":" + cur_time.getMinutes() + ":" + cur_time.getSeconds() + ":" + cur_time.getMilliseconds() + "/" + record.time + ", ass: " + record.assignment + ", user: " + record.user);
- }else{
- console.log("freeze frame" + ": " + cur_time.getHours() + ":" + cur_time.getMinutes() + ":" + cur_time.getSeconds() + ":" + cur_time.getMilliseconds() + "/" + record.time + ", ass:" + record.assignment + ", user: " + record.user);
- }
- //blockpy.components.editor.getPngFromBlocks
- }
- if(!clearRunFlag){
- setTimeout(function() {processAnother(recordsLeft)}, gap);
- }
- }
- processAnother(records);
- });
- });
- </script>
- </head>
- <body>
- <div style="width:900px; margin:0 auto;" id='blockpy-container'> <!-- 900px -->
- <!-- Replay stuff -->
- <textarea class="form-control" rows="3" id='replay-data'></textarea>
- <button type='button' class='btn btn-submit' id='replay-button'>Replay</button>
- <button type='button' class='btn btn-submit' id='pause-button'>Pause</button>
- <button type='button' class='btn btn-submit' id='backward-button'>Backward</button>
- <button type='button' class='btn btn-submit' id='forward-button'>Forward</button>
- KeyNavigation: <input type="checkbox" id="myCheck" checked="check">
- <input type="range" id="speed-slider" value="50" min="1" max="100">
- <p id="sliderValue" value="50"></p>
- <div id="blockpy-div" style='height:100%'></div>
- </div>
- <script>
- </script>
- </body>
- </html>
|