treeCompTest.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Tree Comp Test</title>
  6. <link rel="stylesheet" href="libs/bootstrap.min.css">
  7. <link rel="stylesheet" href="libs/codemirror/codemirror.css">
  8. <link rel="stylesheet" href="libs/font-awesome.min.css">
  9. <link rel="stylesheet" href="libs/summernote/summernote.css">
  10. <link rel="stylesheet" href="libs/multi-select.css">
  11. <link rel="stylesheet" href="src/blockpy.css">
  12. <!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">-->
  13. <!-- JQuery, D3, Math.js, Bootstrap -->
  14. <script type="text/javascript" src="libs/jquery.js"></script>
  15. <script type="text/javascript" src="libs/jquery-ui.min.js"></script>
  16. <script type="text/javascript" src="libs/jquery.hotkeys.js"></script>
  17. <script type="text/javascript" src="libs/jquery.multi-select.js"></script>
  18. <script type="text/javascript" src="libs/d3.min.js"></script>
  19. <script type="text/javascript" src="libs/math.0.19.0.min.js"></script>
  20. <script type="text/javascript" src="libs/bootstrap.min.js"></script>
  21. <script type="text/javascript" src="libs/bootstrap-wysiwyg.js"></script>
  22. <script type="text/javascript" src="libs/mindmup-editabletable.js"></script>
  23. <script type="text/javascript" src="libs/codemirror/codemirror.js"></script>
  24. <script type="text/javascript" src="libs/codemirror/python.js"></script>
  25. <script type="text/javascript" src="libs/codemirror/htmlmixed.js"></script>
  26. <script type="text/javascript" src="libs/codemirror/xml.js"></script>
  27. <script type="text/javascript" src="libs/knockout-3.4.0.js"></script>
  28. <script type="text/javascript" src="libs/stringify.js"></script>
  29. <!-- Summernote, a rich text editor -->
  30. <script type="text/javascript" src="libs/summernote/summernote.min.js"></script>
  31. <script type="text/javascript" src="libs/summernote/summernote-ext-hint.js"></script>
  32. <script type="text/javascript" src="libs/summernote/summernote-ext-video.js"></script>
  33. <!-- Blockly -->
  34. <script type="text/javascript" src="blockly/blockly_uncompressed.js"></script>
  35. <script type="text/javascript" src="blockly/blocks_compressed.js"></script>
  36. <script type="text/javascript" src="blockly/python_compressed.js"></script>
  37. <script type="text/javascript" src="blockly/pseudo_compressed.js"></script>
  38. <script type="text/javascript" src="blockly/javascript_compressed.js"></script>
  39. <script type="text/javascript" src="blockly/msg/js/en.js"></script>
  40. <!-- Skulpt -->
  41. <script type="text/javascript" src="skulpt/dist/skulpt.min.js"></script>
  42. <script type="text/javascript" src="skulpt/dist/skulpt-stdlib.js"></script>
  43. <!-- Source Code -->
  44. <script type="text/javascript" src="src/utilities.js"></script>
  45. <script type="text/javascript" src="src/python_errors.js"></script>
  46. <script type="text/javascript" src="src/ast_node_visitor.js"></script>
  47. <script type="text/javascript" src="src/abstract_interpreter.js"></script>
  48. <script type="text/javascript" src="src/pytifa.js"></script>
  49. <script type="text/javascript" src="src/abstract_interpreter_definitions.js"></script>
  50. <script type="text/javascript" src="src/abstract_interpreter_tests.js"></script>
  51. <script type="text/javascript" src="src/python_to_blockly.js"></script>
  52. <script type="text/javascript" src="src/imported.js"></script>
  53. <script type="text/javascript" src="src/blockly_blocks/class.js"></script>
  54. <script type="text/javascript" src="src/blockly_blocks/comment.js"></script>
  55. <script type="text/javascript" src="src/blockly_blocks/comprehensions.js"></script>
  56. <script type="text/javascript" src="src/blockly_blocks/dict.js"></script>
  57. <script type="text/javascript" src="src/blockly_blocks/if.js"></script>
  58. <script type="text/javascript" src="src/blockly_blocks/io.js"></script>
  59. <script type="text/javascript" src="src/blockly_blocks/lists.js"></script>
  60. <script type="text/javascript" src="src/blockly_blocks/sets.js"></script>
  61. <script type="text/javascript" src="src/blockly_blocks/loops.js"></script>
  62. <script type="text/javascript" src="src/blockly_blocks/parking.js"></script>
  63. <script type="text/javascript" src="src/blockly_blocks/tuple.js"></script>
  64. <script type="text/javascript" src="src/blockly_blocks/turtles.js"></script>
  65. <script type="text/javascript" src="src/blockly_blocks/text.js"></script>
  66. <script type="text/javascript" src="src/blockly_blocks/plots.js"></script>
  67. <script type="text/javascript" src="src/dialog.js"></script>
  68. <script type="text/javascript" src="src/storage.js"></script>
  69. <script type="text/javascript" src="src/printer.js"></script>
  70. <script type="text/javascript" src="src/interface.js"></script>
  71. <script type="text/javascript" src="src/server.js"></script>
  72. <script type="text/javascript" src="src/english.js"></script>
  73. <script type="text/javascript" src="src/corgis.js"></script>
  74. <script type="text/javascript" src="src/history.js"></script>
  75. <script type="text/javascript" src="src/presentation.js"></script>
  76. <script type="text/javascript" src="src/editor.js"></script>
  77. <script type="text/javascript" src="src/feedback.js"></script>
  78. <script type="text/javascript" src="src/toolbar.js"></script>
  79. <script type="text/javascript" src="src/treeMatching.js"></script>
  80. <script type="text/javascript" src="src/sk_mod_instructor_extended.js"></script>
  81. <script type="text/javascript" src="src/sk_mod_instructor.js"></script>
  82. <script type="text/javascript" src="src/engine.js"></script>
  83. <script type="text/javascript" src="src/main.js"></script>
  84. <script type="text/javascript" src="src/treeCompTest.js"></script>
  85. <!--<script type="text/javascript" src="test_corgis/blockpy/tate/tate_blockly.js"></script>
  86. <script type="text/javascript" src="test_corgis/blockpy/tate/tate_skulpt.js"></script>
  87. <script type="text/javascript" src="test_corgis/blockpy/tate/tate_dataset.js"></script>-->
  88. <style>
  89. </style>
  90. <script>
  91. $(document).ready(function() {
  92. blockpy = new BlockPy({
  93. 'blocklyPath': "blockly/",
  94. 'attachmentPoint': document.getElementById('blockpy-div'),
  95. 'instructor': true,
  96. 'developer': true,
  97. 'editor': 'Text',
  98. 'urls': {
  99. //'import_datasets': 'https://think.cs.vt.edu/blockpy/load_corgis/',
  100. //'walk_old_code': 'http://localhost:8000/walk_code/',
  101. //'log_event': 'http://localhost:8000/save_events/'
  102. /*'save_code': 'http://localhost:8000/save_code/',
  103. 'save_success': 'http://localhost:8000/submit_grade/',
  104. 'log_event': 'http://localhost:8000/save_events/'*/
  105. }
  106. });
  107. blockpy.setAssignment(
  108. // settings
  109. {
  110. 'editor': 'Text',
  111. 'read_only': false,
  112. 'disable_semantic_errors': false,
  113. },
  114. // assignment
  115. {
  116. 'introduction': "Welcome to BlockPy. Try running the code below.",
  117. 'name': "#1.2",
  118. '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',
  119. 'parsons': false,
  120. 'starting_code': '',
  121. 'importable': true,
  122. 'initial_view': 'Blocks',
  123. 'modules': {
  124. 'added': ['Functions', 'Data - Weather'],
  125. 'removed': []
  126. }
  127. },
  128. // programs
  129. {
  130. '__main__': ''
  131. }
  132. )
  133. function inIframe () {
  134. try {
  135. return window.self !== window.top;
  136. } catch (e) {
  137. return true;
  138. }
  139. }
  140. if (inIframe()) {
  141. $("#blockpy-container").width("100%");
  142. }
  143. function updatePauseButton(){
  144. if(global_isPaused){
  145. document.getElementById("pause-button").innerHTML = "Play";
  146. }else{
  147. document.getElementById("pause-button").innerHTML = "Pause";
  148. }
  149. };
  150. var global_isPaused = false;
  151. const FORWARD_SCRUB = "forward";
  152. const BACKWARD_SCRUB = "backward";
  153. const STOP_SCRUB = "stop"
  154. var global_scrubing = STOP_SCRUB;
  155. var speed = 50;
  156. document.onkeydown = navigationStroke;
  157. function pauseEvent(){
  158. global_isPaused = !global_isPaused;
  159. updatePauseButton();
  160. }
  161. function forwardEvent(){
  162. global_isPaused = true;
  163. global_scrubing = FORWARD_SCRUB;
  164. updatePauseButton();
  165. }
  166. function backEvent(){
  167. global_isPaused = true;
  168. global_scrubing = BACKWARD_SCRUB;
  169. updatePauseButton();
  170. }
  171. function navigationStroke(key){
  172. var KeyNavigationEnabled = document.getElementById("myCheck").checked;
  173. if(KeyNavigationEnabled == true){
  174. key = key || window.event;
  175. if (key.keyCode == '80') {
  176. // p is pressed
  177. pauseEvent();
  178. }
  179. else if (key.keyCode == '37') {
  180. // left arrow
  181. backEvent();
  182. }
  183. else if (key.keyCode == '39') {
  184. // right arrow
  185. forwardEvent();
  186. }
  187. }
  188. }
  189. $('#speed-slider').change(function() {
  190. var sliderValue = document.getElementById("speed-slider").value;
  191. speed = 100 - document.getElementById("speed-slider").value;
  192. document.getElementById("sliderValue").innerHTML = sliderValue;
  193. });
  194. $('#pause-button').click(function() {
  195. global_isPaused = !global_isPaused;
  196. updatePauseButton();
  197. });
  198. $('#forward-button').click(function() {
  199. forwardEvent();
  200. });
  201. $('#backward-button').click(function() {
  202. backEvent();
  203. });
  204. $('#test-button').click(function() {
  205. runTreeCompTestSuite();
  206. });
  207. $('#parse-button').click(function() {
  208. var code = $('#replay-data').val().split(/\n#==========\n/);
  209. var stdCode = null;
  210. var insCode = null;
  211. var insTree = null;
  212. var insAST = null;
  213. var stdAST = null;
  214. var mappings = null;
  215. try{
  216. stdCode = code[0];
  217. insCode = code[1];
  218. insTree = new StretchyTreeMatcher(insCode);
  219. insAST = insTree.rootNode;
  220. stdAST = parseCode(stdCode);
  221. mappings = null;
  222. mappings = insTree.findMatches(stdAST.astNode);
  223. }catch(exception){
  224. console.error("parse failed");
  225. }
  226. console.log(insAST);
  227. console.log(stdAST);
  228. console.log(mappings);
  229. });
  230. function handleCodeEvents(record){
  231. switch (record.action.toLowerCase()) {
  232. case "set":
  233. blockpy.model.programs['__main__'](record.body);
  234. blockpy.components.editor.updateBlocks();
  235. break;
  236. }
  237. }
  238. function executeLastCodeEvent(pastRecords){
  239. var codeEvent = null;
  240. for(i = pastRecords.length-1; i >= 0; i--){
  241. var rawRecord = pastRecords[i];
  242. record = JSON.parse(rawRecord);
  243. if(record.event.toLowerCase() == "code"){
  244. codeEvent = record;
  245. break;
  246. }
  247. }
  248. if(codeEvent != null){
  249. handleCodeEvents(codeEvent);
  250. }
  251. }
  252. function handleFeedbackEvents(record){
  253. var messages = record.body.split("\n");
  254. var detailError = messages[0];
  255. var bodyMessage = "";
  256. var regex = /line (\d{1,})/i;
  257. for(i = 1; i < messages.length; i++){
  258. bodyMessage += messages[i];
  259. }
  260. var results = regex.exec(bodyMessage);
  261. var line = results != null && results.length > 1 ? results[1] : null;
  262. try{
  263. switch (record.action.toLowerCase()) {
  264. case "success":
  265. blockpy.components.feedback.complete(detailError, bodyMessage, line);
  266. break;
  267. case "editor error":
  268. blockpy.components.feedback.editorError(detailError, bodyMessage, line);
  269. break;
  270. case "no errors":
  271. blockpy.components.feedback.noErrors(detailError, bodyMessage, line);
  272. break;
  273. case "syntax error":
  274. blockpy.components.feedback.syntaxError(detailError, bodyMessage, line);
  275. break;
  276. case "semantic error":
  277. blockpy.components.feedback.semanticError(detailError, bodyMessage, line);
  278. break;
  279. case "internal error":
  280. blockpy.components.feedback.internalError(detailError, bodyMessage, line);
  281. break;
  282. case "instructor feedback":
  283. blockpy.components.feedback.instructorFeedback(detailError, bodyMessage, line);
  284. break;
  285. case "empty program":
  286. blockpy.components.feedback.emptyProgram(detailError, bodyMessage, line);
  287. break;
  288. default:
  289. console.log(record.action.toLowerCase());
  290. break;
  291. // ...
  292. }
  293. }catch(err){
  294. console.error(err);
  295. }
  296. };
  297. $('#replay-button').click(function() {
  298. var records = $('#replay-data').val().split(/\r?\n/);
  299. var previousTime = null;
  300. var pastRecords = [];
  301. var goingBackwards = false;
  302. var clearRunFlag = false;
  303. function processAnother(recordsLeft) {
  304. var gap = 100;
  305. var moveForward = true;
  306. if(global_isPaused){
  307. switch(global_scrubing){
  308. case BACKWARD_SCRUB:
  309. if(pastRecords.length > 1){
  310. blockpy.components.feedback.clearEditorErrors();
  311. blockpy.components.feedback.clear();
  312. recordsLeft.unshift(pastRecords.pop());
  313. recordsLeft.unshift(pastRecords.pop());
  314. goingBackwards = true;
  315. //TODO: Handle when going backwards to a feedback event
  316. }else{
  317. moveForward = false;
  318. }
  319. //NOTE: This cascades into FORWARD_SCRUB
  320. case FORWARD_SCRUB:
  321. global_scrubing = STOP_SCRUB;
  322. previousTime = null;
  323. break;
  324. default:
  325. moveForward = false;
  326. break;
  327. };
  328. }
  329. if(moveForward && recordsLeft.length > 0){
  330. blockpy.components.feedback.clearEditorErrors();
  331. blockpy.components.feedback.clear();
  332. var rawRecord = recordsLeft.shift();
  333. var record = JSON.parse(rawRecord);
  334. pastRecords.push(rawRecord);
  335. switch (record.event.toLowerCase()) {
  336. case "code":
  337. handleCodeEvents(record);
  338. break;
  339. case "feedback":
  340. if(goingBackwards){
  341. executeLastCodeEvent(pastRecords);
  342. }
  343. handleFeedbackEvents(record);
  344. break;
  345. }
  346. var cur_time = new Date(record.time*1000);
  347. if(!global_isPaused){
  348. gap = previousTime != null ? record.time - previousTime : 0;
  349. gap = (gap > 2000 ? 2000 : gap)*speed;
  350. previousTime = record.time;
  351. //var cur_time = new Date(record.time*1000);
  352. //var cur_time = record.time;
  353. //cur_time = cur_time.getHours();
  354. console.log(gap + ": " + cur_time.getHours() + ":" + cur_time.getMinutes() + ":" + cur_time.getSeconds() + ":" + cur_time.getMilliseconds() + "/" + record.time + ", ass: " + record.assignment + ", user: " + record.user);
  355. }else{
  356. console.log("freeze frame" + ": " + cur_time.getHours() + ":" + cur_time.getMinutes() + ":" + cur_time.getSeconds() + ":" + cur_time.getMilliseconds() + "/" + record.time + ", ass:" + record.assignment + ", user: " + record.user);
  357. }
  358. //blockpy.components.editor.getPngFromBlocks
  359. }
  360. if(!clearRunFlag){
  361. setTimeout(function() {processAnother(recordsLeft)}, gap);
  362. }
  363. }
  364. processAnother(records);
  365. });
  366. });
  367. </script>
  368. </head>
  369. <body>
  370. <div style="width:900px; margin:0 auto;" id='blockpy-container'> <!-- 900px -->
  371. <!-- Replay stuff -->
  372. <textarea class="form-control" rows="10" id='replay-data'></textarea>
  373. <button type='button' class='btn btn-submit' id='replay-button'>Replay</button>
  374. <button type='button' class='btn btn-submit' id='pause-button'>Pause</button>
  375. <button type='button' class='btn btn-submit' id='backward-button'>Backward</button>
  376. <button type='button' class='btn btn-submit' id='forward-button'>Forward</button>
  377. KeyNavigation: <input type="checkbox" id="myCheck" checked="check">
  378. <input type="range" id="speed-slider" value="50" min="1" max="100">
  379. <p id="sliderValue" value="50"></p>
  380. <button type='button' class='btn btn-submit' id='test-button'>Test</button>
  381. <button type='button' class='btn btn-submit' id='parse-button'>Parse</button>
  382. <div id="blockpy-div" style='height:100%'></div>
  383. </div>
  384. <script>
  385. </script>
  386. </body>
  387. </html>