<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Tree Comp Test</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> <script type="text/javascript" src="libs/stringify.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/pytifa.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/blockly_blocks/plots.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="src/treeCompTest.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': 'from post_test_feedbackAPI import*\nimport post_test_feedbackAPI as dice\n\nmissing_addition_slot_empty()\nwrong_compare_list()\nwrong_for_inside_if()\nmissing_if_in_for()\nwrong_should_be_counting()\nmissing_counting_list()\nmissing_append_in_iteration()\nmissing_append_list_initialization()\nwrong_append_list_initiatization()\nwrong_not_append_to_list()\nappend_list_wrong_slot()\nhistogram_argument_not_list()\nhistogram_wrong_list()\nhistogram_missing()\nplot_show_missing()\n', 'parsons': false, 'starting_code': '', 'importable': true, 'initial_view': 'Blocks', 'modules': { 'added': ['Functions', 'Data - Weather'], 'removed': [] } }, // programs { '__main__': '' } ) 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(); }); $('#test-button').click(function() { runTreeCompTestSuite(); }); $('#parse-button').click(function() { var code = $('#replay-data').val().split(/\n#==========\n/); var stdCode = null; var insCode = null; var insTree = null; var insAST = null; var stdAST = null; var mappings = null; try{ stdCode = code[0]; insCode = code[1]; insTree = new StretchyTreeMatcher(insCode); insAST = insTree.rootNode; stdAST = parseCode(stdCode); mappings = null; mappings = insTree.findMatches(stdAST.astNode); }catch(exception){ console.error("parse failed"); } console.log(insAST); console.log(stdAST); console.log(mappings); }); 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="10" 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> <button type='button' class='btn btn-submit' id='test-button'>Test</button> <button type='button' class='btn btn-submit' id='parse-button'>Parse</button> <div id="blockpy-div" style='height:100%'></div> </div> <script> </script> </body> </html>