From 0c4d4e69d0525c7a8074fda44798ce68527d8f95 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 13:21:41 +0200 Subject: [PATCH 01/25] AnimatedCircle: fix typo --- AnimationLibrary/AnimatedCircle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AnimationLibrary/AnimatedCircle.js b/AnimationLibrary/AnimatedCircle.js index 5dee8ef..f1a71d4 100644 --- a/AnimationLibrary/AnimatedCircle.js +++ b/AnimationLibrary/AnimatedCircle.js @@ -108,7 +108,7 @@ AnimatedCircle.prototype.draw = function(ctx) ctx.fill(); ctx.stroke(); ctx.textAlign = 'center'; - ctx.font = this.textHegiht.toString() + 'px sans-serif'; + ctx.font = this.textHeight.toString() + 'px sans-serif'; ctx.textBaseline = 'middle'; ctx.lineWidth = 1; ctx.fillStyle = this.foregroundColor; From 804395c84e66cc258ef3b8b51a881e902623ec96 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 13:22:16 +0200 Subject: [PATCH 02/25] add .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..600d2d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file From 5082a585a0ea87ec2653f6e2c2cfb8a39cbd0213 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 13:25:28 +0200 Subject: [PATCH 03/25] improve code structure- no global variables- call all methods via objects- no hard-coded html elements- allow multiple managers to co-exist --- AlgorithmLibrary/Algorithm.js | 192 +++++++++--------- AnimationLibrary/AnimationMain.js | 320 ++++++++++++++---------------- AnimationLibrary/ObjectManager.js | 4 +- 3 files changed, 248 insertions(+), 268 deletions(-) diff --git a/AlgorithmLibrary/Algorithm.js b/AlgorithmLibrary/Algorithm.js index 32943cd..87ad62e 100644 --- a/AlgorithmLibrary/Algorithm.js +++ b/AlgorithmLibrary/Algorithm.js @@ -24,100 +24,6 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco -function addLabelToAlgorithmBar(labelName) -{ - var element = document.createTextNode(labelName); - - var tableEntry = document.createElement("td"); - tableEntry.appendChild(element); - - - var controlBar = document.getElementById("AlgorithmSpecificControls"); - - //Append the element in page (in span). - controlBar.appendChild(tableEntry); - return element; -} - -// TODO: Make this stackable like radio butons -// (keep backwards compatible, thought) -function addCheckboxToAlgorithmBar(boxLabel) -{ - var element = document.createElement("input"); - - element.setAttribute("type", "checkbox"); - element.setAttribute("value", boxLabel); - - var label = document.createTextNode(boxLabel); - - var tableEntry = document.createElement("td"); - tableEntry.appendChild(element); - tableEntry.appendChild(label); - - var controlBar = document.getElementById("AlgorithmSpecificControls"); - - //Append the element in page (in span). - controlBar.appendChild(tableEntry); - return element; -} - -function addRadioButtonGroupToAlgorithmBar(buttonNames, groupName) -{ - var buttonList = []; - var newTable = document.createElement("table"); - - for (var i = 0; i < buttonNames.length; i++) - { - var midLevel = document.createElement("tr"); - var bottomLevel = document.createElement("td"); - - var button = document.createElement("input"); - button.setAttribute("type", "radio"); - button.setAttribute("name", groupName); - button.setAttribute("value", buttonNames[i]); - bottomLevel.appendChild(button); - midLevel.appendChild(bottomLevel); - var txtNode = document.createTextNode(" " + buttonNames[i]); - bottomLevel.appendChild(txtNode); - newTable.appendChild(midLevel); - buttonList.push(button); - } - - var topLevelTableEntry = document.createElement("td"); - topLevelTableEntry.appendChild(newTable); - - var controlBar = document.getElementById("AlgorithmSpecificControls"); - controlBar.appendChild(topLevelTableEntry); - - return buttonList -} - - -function addControlToAlgorithmBar(type, name) { - - var element = document.createElement("input"); - - element.setAttribute("type", type); - element.setAttribute("value", name); -// element.setAttribute("name", name); - - - var tableEntry = document.createElement("td"); - - tableEntry.appendChild(element); - - - var controlBar = document.getElementById("AlgorithmSpecificControls"); - - //Append the element in page (in span). - controlBar.appendChild(tableEntry); - return element; - -} - - - - function Algorithm(am) { @@ -396,3 +302,101 @@ Algorithm.prototype.cmd = function() } } + +// Algorithm bar methods ////////////////// + +Algorithm.prototype.addLabelToAlgorithmBar = function(labelName) +{ + var element = document.createTextNode(labelName); + + var tableEntry = document.createElement("td"); + tableEntry.appendChild(element); + + //Append the element in page (in span). + var controlBar = this.animationManager.algorithmControlBar; + if(controlBar) + controlBar.appendChild(tableEntry); + + return element; +} + +// TODO: Make this stackable like radio butons +// (keep backwards compatible, thought) +Algorithm.prototype.addCheckboxToAlgorithmBar = function(boxLabel) +{ + var element = document.createElement("input"); + + element.setAttribute("type", "checkbox"); + element.setAttribute("value", boxLabel); + + var label = document.createTextNode(boxLabel); + + var tableEntry = document.createElement("td"); + tableEntry.appendChild(element); + tableEntry.appendChild(label); + + //Append the element in page (in span). + var controlBar = this.animationManager.algorithmControlBar; + if(controlBar) + controlBar.appendChild(tableEntry); + + return element; +} + +Algorithm.prototype.addRadioButtonGroupToAlgorithmBar = function(buttonNames, groupName) +{ + var buttonList = []; + var newTable = document.createElement("table"); + + for (var i = 0; i < buttonNames.length; i++) + { + var midLevel = document.createElement("tr"); + var bottomLevel = document.createElement("td"); + + var button = document.createElement("input"); + button.setAttribute("type", "radio"); + button.setAttribute("name", groupName); + button.setAttribute("value", buttonNames[i]); + bottomLevel.appendChild(button); + midLevel.appendChild(bottomLevel); + var txtNode = document.createTextNode(" " + buttonNames[i]); + bottomLevel.appendChild(txtNode); + newTable.appendChild(midLevel); + buttonList.push(button); + } + + var topLevelTableEntry = document.createElement("td"); + topLevelTableEntry.appendChild(newTable); + + var controlBar = this.animationManager.algorithmControlBar; + if(controlBar) + controlBar.appendChild(topLevelTableEntry); + + return buttonList +} + + +Algorithm.prototype.addControlToAlgorithmBar = function(type, name) { + + var element = document.createElement("input"); + + element.setAttribute("type", type); + element.setAttribute("value", name); +// element.setAttribute("name", name); + + + var tableEntry = document.createElement("td"); + + tableEntry.appendChild(element); + + //Append the element in page (in span). + var controlBar = this.animationManager.algorithmControlBar; + if(controlBar) + controlBar.appendChild(tableEntry); + + return element; + +} + + + diff --git a/AnimationLibrary/AnimationMain.js b/AnimationLibrary/AnimationMain.js index cdc4482..97d3964 100644 --- a/AnimationLibrary/AnimationMain.js +++ b/AnimationLibrary/AnimationMain.js @@ -26,8 +26,8 @@ // Global timer used for doing animation callbacks. // TODO: Make this an instance variable of Animation Manager. -var timer; -var swapped = false; +// var timer; +// var swapped = false; function reorderSibling(node1, node2) @@ -39,13 +39,13 @@ function reorderSibling(node1, node2) function swapControlDiv() { - swapped = !swapped; - if (swapped) { - reorderSibling(document.getElementById('canvas'), document.getElementById('generalAnimationControlSection')); + this.swapped = !this.swapped; + if (this.swapped) { + reorderSibling(this.canvas, this.generalControlBar.parentNode); setCookie("VisualizationControlSwapped", "true", 30); } else { - reorderSibling(document.getElementById('generalAnimationControlSection'), document.getElementById('canvas')); + reorderSibling(this.generalControlBar.parentNode, this.canvas); setCookie("VisualizationControlSwapped", "false", 30); } @@ -83,20 +83,20 @@ var ANIMATION_SPEED_DEFAULT = 75; // TODO: Move these out of global space into animation manager? -var objectManager; -var animationManager; -var canvas; +// var objectManager; +// var animationManager; +// var canvas; -var paused = false; -var playPauseBackButton; -var skipBackButton; -var stepBackButton; -var stepForwardButton; -var skipForwardButton; +// var paused = false; +// var playPauseBackButton; +// var skipBackButton; +// var stepBackButton; +// var stepForwardButton; +// var skipForwardButton; -var widthEntry; -var heightEntry; -var sizeButton; +// var widthEntry; +// var heightEntry; +// var sizeButton; @@ -144,43 +144,44 @@ function returnSubmit(field, funct, maxsize, intOnly) function animWaiting() { - stepForwardButton.disabled = false; - if (skipBackButton.disabled == false) + this.stepForwardButton.disabled = false; + if (this.skipBackButton.disabled == false) { - stepBackButton.disabled = false; + this.stepBackButton.disabled = false; } - objectManager.statusReport.setText("Animation Paused"); - objectManager.statusReport.setForegroundColor("#FF0000"); + this.objectManager.statusReport.setText("Animation Paused"); + this.objectManager.statusReport.setForegroundColor("#FF0000"); } function animStarted() { - skipForwardButton.disabled = false; - skipBackButton.disabled = false; - stepForwardButton.disabled = true; - stepBackButton.disabled = true; - objectManager.statusReport.setText("Animation Running"); - objectManager.statusReport.setForegroundColor("#009900"); + this.skipForwardButton.disabled = false; + this.skipBackButton.disabled = false; + this.stepForwardButton.disabled = true; + this.stepBackButton.disabled = true; + this.objectManager.statusReport.setText("Animation Running"); + this.objectManager.statusReport.setForegroundColor("#009900"); } function animEnded() { - skipForwardButton.disabled = true; - stepForwardButton.disabled = true; - if (skipBackButton.disabled == false && paused) + this.skipForwardButton.disabled = true; + this.stepForwardButton.disabled = true; + if (this.skipBackButton.disabled == false && this.paused) { - stepBackButton.disabled = false; + this.stepBackButton.disabled = false; } - objectManager.statusReport.setText("Animation Completed"); - objectManager.statusReport.setForegroundColor("#000000"); + // this.objectManager.statusReport.setText("Animation Completed"); + this.objectManager.statusReport.setText(""); + this.objectManager.statusReport.setForegroundColor("#000000"); } function anumUndoUnavailable() { - skipBackButton.disabled = true; - stepBackButton.disabled = true; + this.skipBackButton.disabled = true; + this.stepBackButton.disabled = true; } @@ -188,116 +189,58 @@ function timeout() { // We need to set the timeout *first*, otherwise if we // try to clear it later, we get behavior we don't want ... - timer = setTimeout('timeout()', 30); - animationManager.update(); - objectManager.draw(); + this.timer = setTimeout(timeout.bind(this), 30); + this.update(); + this.objectManager.draw(); } -function doStep() -{ - animationManager.step(); -} - - -function doSkip() -{ - animationManager.skipForward(); -} - - -function doSkipBack() -{ - animationManager.skipBack(); -} - - -function doStepBack() -{ - animationManager.stepBack(); -} function doPlayPause() { - paused = !paused; - if (paused) + this.paused = !this.paused; + if (this.paused) { - playPauseBackButton.setAttribute("value", "play"); - if (skipBackButton.disabled == false) + this.playPauseBackButton.setAttribute("value", "play"); + if (this.skipBackButton.disabled == false) { - stepBackButton.disabled = false; + this.stepBackButton.disabled = false; } } else { - playPauseBackButton.setAttribute("value", "pause"); + this.playPauseBackButton.setAttribute("value", "pause"); } - animationManager.SetPaused(paused); + this.SetPaused(this.paused); } -function addControl(type, name, location) { - - var element = document.createElement("input"); - - element.setAttribute("type", type); - element.setAttribute("value", name); - - var tableEntry = document.createElement("td"); - - tableEntry.appendChild(element); - - - var controlBar = document.getElementById(tableEntry); - - //Append the element in page (in span). - controlBar.appendChild(element); - return element; - -} - -function addControlToAnimationBar(type,name,containerType) +// Creates and returs an AnimationManager +function initCanvas(canvas, generalControlBar, algorithmControlBar) { - if (containerType == undefined) - { - containerType = "input"; - } - var element = document.createElement(containerType); - - element.setAttribute("type", type); - element.setAttribute("value", name); - - - var tableEntry = document.createElement("td"); - - tableEntry.appendChild(element); - - var controlBar = document.getElementById("GeneralAnimationControls"); - - //Append the element in page (in span). - controlBar.appendChild(tableEntry); - return element; - -} - - -function initCanvas() -{ - canvas = document.getElementById("canvas"); - objectManager = new ObjectManager(); - animationManager = new AnimationManager(objectManager); - - skipBackButton = addControlToAnimationBar("Button", "Skip Back"); - skipBackButton.onclick = animationManager.skipBack.bind(animationManager); - stepBackButton = addControlToAnimationBar("Button", "Step Back"); - stepBackButton.onclick = animationManager.stepBack.bind(animationManager); - playPauseBackButton = addControlToAnimationBar("Button", "Pause"); - playPauseBackButton.onclick = doPlayPause ; - stepForwardButton = addControlToAnimationBar("Button", "Step Forward"); - stepForwardButton.onclick = animationManager.step.bind(animationManager) ; - skipForwardButton = addControlToAnimationBar("Button", "Skip Forward"); - skipForwardButton.onclick = animationManager.skipForward.bind(animationManager); + // UI nodes should be given, otherwise use defaults. + // This is the only place where getElementById is used + if(!canvas) canvas = document.getElementById("canvas"); + if(!generalControlBar) generalControlBar = document.getElementById('GeneralAnimationControls'); + if(!algorithmControlBar) algorithmControlBar = document.getElementById("AlgorithmSpecificControls"); + + var objectManager = new ObjectManager(canvas); + var animationManager = new AnimationManager(objectManager); + animationManager.canvas = canvas; + animationManager.generalControlBar = generalControlBar; + animationManager.algorithmControlBar = algorithmControlBar; + + animationManager.skipBackButton = animationManager.addControlToAnimationBar("Button", "Skip Back"); + animationManager.skipBackButton.onclick = animationManager.skipBack.bind(animationManager); + animationManager.stepBackButton = animationManager.addControlToAnimationBar("Button", "Step Back"); + animationManager.stepBackButton.onclick = animationManager.stepBack.bind(animationManager); + animationManager.playPauseBackButton = animationManager.addControlToAnimationBar("Button", "Pause"); + animationManager.playPauseBackButton.onclick = doPlayPause.bind(animationManager); + animationManager.stepForwardButton = animationManager.addControlToAnimationBar("Button", "Step Forward"); + animationManager.stepForwardButton.onclick = animationManager.step.bind(animationManager) ; + animationManager.skipForwardButton = animationManager.addControlToAnimationBar("Button", "Skip Forward"); + animationManager.skipForwardButton.onclick = animationManager.skipForward.bind(animationManager); var element = document.createElement("div"); @@ -308,7 +251,6 @@ function initCanvas() var tableEntry = document.createElement("td"); - var controlBar = document.getElementById("GeneralAnimationControls"); @@ -337,7 +279,8 @@ function initCanvas() //Append the element in page (in span). - controlBar.appendChild(tableEntry); + if(generalControlBar) + generalControlBar.appendChild(tableEntry); //tableEntry.appendChild(element); @@ -351,6 +294,7 @@ function initCanvas() speed = parseInt(speed); } + if(generalControlBar) { $(element).slider({ animate: true, value: speed, @@ -363,6 +307,7 @@ function initCanvas() } }); + } animationManager.SetSpeed(speed); @@ -390,10 +335,10 @@ function initCanvas() } var swappedControls=getCookie("VisualizationControlSwapped"); - swapped = swappedControls == "true" - if (swapped) + this.swapped = swappedControls == "true" + if (this.swapped) { - reorderSibling(document.getElementById('canvas'), document.getElementById('generalAnimationControlSection')); + reorderSibling(this.canvas, this.generalControlBar.parentNode); } canvas.width = width; @@ -404,36 +349,38 @@ function initCanvas() tableEntry = document.createElement("td"); txtNode = document.createTextNode(" w:"); tableEntry.appendChild(txtNode); - controlBar.appendChild(tableEntry); + if(generalControlBar) + generalControlBar.appendChild(tableEntry); - widthEntry = addControlToAnimationBar("Text", canvas.width); - widthEntry.size = 4; - widthEntry.onkeydown = this.returnSubmit(widthEntry, animationManager.changeSize.bind(animationManager), 4, true); + animationManager.widthEntry = animationManager.addControlToAnimationBar("Text", canvas.width); + animationManager.widthEntry.size = 4; + animationManager.widthEntry.onkeydown = this.returnSubmit(animationManager.widthEntry, animationManager.changeSize.bind(animationManager), 4, true); tableEntry = document.createElement("td"); txtNode = document.createTextNode(" h:"); tableEntry.appendChild(txtNode); - controlBar.appendChild(tableEntry); + if(generalControlBar) + generalControlBar.appendChild(tableEntry); - heightEntry = addControlToAnimationBar("Text", canvas.height); - heightEntry.onkeydown = this.returnSubmit(heightEntry, animationManager.changeSize.bind(animationManager), 4, true); + animationManager.heightEntry = animationManager.addControlToAnimationBar("Text", canvas.height); + animationManager.heightEntry.onkeydown = this.returnSubmit(animationManager.heightEntry, animationManager.changeSize.bind(animationManager), 4, true); // heightEntry.size = 4; - sizeButton = addControlToAnimationBar("Button", "Change Canvas Size"); + animationManager.sizeButton = animationManager.addControlToAnimationBar("Button", "Change Canvas Size"); - sizeButton.onclick = animationManager.changeSize.bind(animationManager) ; + animationManager.sizeButton.onclick = animationManager.changeSize.bind(animationManager) ; - swapButton = addControlToAnimationBar("Button", "Move Controls"); - swapButton.onclick = swapControlDiv; + animationManager.swapButton = animationManager.addControlToAnimationBar("Button", "Move Controls"); + animationManager.swapButton.onclick = swapControlDiv.bind(animationManager); - animationManager.addListener("AnimationStarted", this, animStarted); - animationManager.addListener("AnimationEnded", this, this.animEnded); - animationManager.addListener("AnimationWaiting", this, this.animWaiting); - animationManager.addListener("AnimationUndoUnavailable", this, this.anumUndoUnavailable); + animationManager.addListener("AnimationStarted", animationManager, animStarted); + animationManager.addListener("AnimationEnded", animationManager, animEnded); + animationManager.addListener("AnimationWaiting", animationManager, animWaiting); + animationManager.addListener("AnimationUndoUnavailable", animationManager, anumUndoUnavailable); objectManager.width = canvas.width; objectManager.height = canvas.height; return animationManager; @@ -447,8 +394,12 @@ function AnimationManager(objectManager) // All animation is done by manipulating objects in\ // this container this.animatedObjects = objectManager; + // TODO: change this to animatedObjects later + this.objectManager = objectManager; // Control variables for stopping / starting animation + // TODO: not sure what's the difference between paused and animationPaused + this.paused = false; this.animationPaused = false; this.awaitingStep = false; @@ -533,27 +484,27 @@ function AnimationManager(objectManager) this.changeSize = function() { - var width = parseInt(widthEntry.value); - var height = parseInt(heightEntry.value); + var width = parseInt(this.widthEntry.value); + var height = parseInt(this.heightEntry.value); if (width > 100) { - canvas.width = width; + this.canvas.width = width; this.animatedObjects.width = width; setCookie("VisualizationWidth", String(width), 30); } if (height > 100) { - canvas.height = height; + this.canvas.height = height; this.animatedObjects.height = height; setCookie("VisualizationHeight", String(height), 30); } - width.value = canvas.width; - heightEntry.value = canvas.height; + width.value = this.canvas.width; + this.heightEntry.value = this.canvas.height; this.animatedObjects.draw(); - this.fireEvent("CanvasSizeChanged",{width:canvas.width, height:canvas.height}); + this.fireEvent("CanvasSizeChanged",{width:this.canvas.width, height:this.canvas.height}); } this.startNextBlock = function() @@ -566,7 +517,7 @@ function AnimationManager(objectManager) this.currentlyAnimating = false; this.awaitingStep = false; this.fireEvent("AnimationEnded","NoData"); - clearTimeout(timer); + clearTimeout(this.timer); this.animatedObjects.update(); this.animatedObjects.draw(); @@ -1014,7 +965,7 @@ function AnimationManager(objectManager) // which represents the animation to start this.StartNewAnimation = function(commands) { - clearTimeout(timer); + clearTimeout(this.timer); if (this.AnimationSteps != null) { this.previousAnimationSteps.push(this.AnimationSteps); @@ -1033,7 +984,7 @@ function AnimationManager(objectManager) this.startNextBlock(); this.currentlyAnimating = true; this.fireEvent("AnimationStarted","NoData"); - timer = setTimeout('timeout()', 30); + this.timer = setTimeout(timeout.bind(this), 30); } @@ -1045,14 +996,14 @@ function AnimationManager(objectManager) { // TODO: Get events working correctly! this.fireEvent("AnimationStarted","NoData"); - clearTimeout(timer); + clearTimeout(this.timer); this.awaitingStep = false; this.undoLastBlock(); // Re-kick thie timer. The timer may or may not be running at this point, // so to be safe we'll kill it and start it again. - clearTimeout(timer); - timer = setTimeout('timeout()', 30); + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); } @@ -1063,8 +1014,8 @@ function AnimationManager(objectManager) this.undoLastBlock(); // Re-kick thie timer. The timer may or may not be running at this point, // so to be safe we'll kill it and start it again. - clearTimeout(timer); - timer = setTimeout('timeout()', 30); + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); } @@ -1079,8 +1030,8 @@ function AnimationManager(objectManager) this.currentlyAnimating = true; // Re-kick thie timer. The timer should be going now, but we've had some difficulty with // it timing itself out, so we'll be safe and kick it now. - clearTimeout(timer); - timer = setTimeout('timeout()', 30); + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); } } @@ -1094,7 +1045,7 @@ function AnimationManager(objectManager) this.undoAnimationStepIndicesStack = []; this.AnimationSteps = null; this.fireEvent("AnimationUndoUnavailable","NoData"); - clearTimeout(timer); + clearTimeout(this.timer); this.animatedObjects.update(); this.animatedObjects.draw(); @@ -1130,7 +1081,7 @@ function AnimationManager(objectManager) keepUndoing = this.finishUndoBlock(this.undoStack.pop()); } - clearTimeout(timer); + clearTimeout(this.timer); this.animatedObjects.update(); this.animatedObjects.draw(); if (this.undoStack == null || this.undoStack.length == 0) @@ -1146,7 +1097,7 @@ function AnimationManager(objectManager) this.clearHistory(); this.animatedObjects.clearAllObjects(); this.animatedObjects.draw(); - clearTimeout(timer); + clearTimeout(this.timer); } this.skipForward = function() @@ -1185,7 +1136,7 @@ function AnimationManager(objectManager) this.animatedObjects.runFast = false; this.fireEvent("AnimationEnded","NoData"); - clearTimeout(timer); + clearTimeout(this.timer); this.animatedObjects.update(); this.animatedObjects.draw(); } @@ -1218,7 +1169,7 @@ function AnimationManager(objectManager) this.fireEvent("AnimationUndoUnavailable","NoData"); } - clearTimeout(timer); + clearTimeout(this.timer); this.animatedObjects.update(); this.animatedObjects.draw(); @@ -1350,7 +1301,32 @@ function AnimationManager(objectManager) AnimationManager.prototype = new EventListener(); AnimationManager.prototype.constructor = AnimationManager; - +AnimationManager.prototype.addControlToAnimationBar = function(type,name,containerType) +{ + // return a dummy object if we're not using a control bar + if(!this.generalControlBar) + return {}; + if (containerType == undefined) + { + containerType = "input"; + } + var element = document.createElement(containerType); + + element.setAttribute("type", type); + element.setAttribute("value", name); + + + var tableEntry = document.createElement("td"); + + tableEntry.appendChild(element); + + + //Append the element in page (in span). + this.generalControlBar.appendChild(tableEntry); + return element; + +} + function SingleAnimation(id, fromX, fromY, toX, toY) { this.objectID = id; diff --git a/AnimationLibrary/ObjectManager.js b/AnimationLibrary/ObjectManager.js index d7ae6d1..7dd6b3d 100644 --- a/AnimationLibrary/ObjectManager.js +++ b/AnimationLibrary/ObjectManager.js @@ -42,14 +42,14 @@ // an assert-like structure that can be turned off for production?) // 2. Refactor this code so that it uses the same object syntax (with // prototypes) as te rest of the code. (low priority) -function ObjectManager() +function ObjectManager(canvas) { this.Nodes = []; this.Edges = []; this.BackEdges = []; this.activeLayers = []; this.activeLayers[0] = true; - this.ctx = document.getElementById('canvas').getContext('2d'); + this.ctx = canvas.getContext('2d'); this.framenum = 0; this.width = 0; this.height = 0; From 5fffd6ba7c30463866128100fd141ee0c73afab2 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 13:34:03 +0200 Subject: [PATCH 04/25] call Algorithm methods in OO way --- AlgorithmLibrary/AVL.js | 14 ++++++------ AlgorithmLibrary/BFS.js | 12 +++++----- AlgorithmLibrary/BPlusTree.js | 26 +++++++++++----------- AlgorithmLibrary/BST.js | 14 ++++++------ AlgorithmLibrary/BTree.js | 28 ++++++++++++------------ AlgorithmLibrary/BinomialQueue.js | 10 ++++----- AlgorithmLibrary/BucketSort.js | 4 ++-- AlgorithmLibrary/ChangingCoordinate2D.js | 14 ++++++------ AlgorithmLibrary/ChangingCoordinate3D.js | 16 +++++++------- AlgorithmLibrary/ClosedHash.js | 8 +++---- AlgorithmLibrary/ComparisonSort.js | 16 +++++++------- AlgorithmLibrary/ConnectedComponent.js | 2 +- AlgorithmLibrary/CountingSort.js | 4 ++-- AlgorithmLibrary/DFS.js | 4 ++-- AlgorithmLibrary/DPChange.js | 12 +++++----- AlgorithmLibrary/DPFib.js | 8 +++---- AlgorithmLibrary/DPLCS.js | 10 ++++----- AlgorithmLibrary/DPMatrixMultiply.js | 10 ++++----- AlgorithmLibrary/DijkstraPrim.js | 6 ++--- AlgorithmLibrary/DisjointSet.js | 22 +++++++++---------- AlgorithmLibrary/FibonacciHeap.js | 10 ++++----- AlgorithmLibrary/Floyd.js | 2 +- AlgorithmLibrary/Graph.js | 8 +++---- AlgorithmLibrary/Hash.js | 14 ++++++------ AlgorithmLibrary/Heap.js | 10 ++++----- AlgorithmLibrary/HeapSort.js | 4 ++-- AlgorithmLibrary/Huffman.js | 4 ++-- AlgorithmLibrary/Kruskal.js | 2 +- AlgorithmLibrary/LeftistHeap.js | 10 ++++----- AlgorithmLibrary/MyAlgorithm.js | 8 +++---- AlgorithmLibrary/QueueArray.js | 8 +++---- AlgorithmLibrary/QueueLL.js | 8 +++---- AlgorithmLibrary/RadixSort.js | 6 ++--- AlgorithmLibrary/RadixTree.js | 14 ++++++------ AlgorithmLibrary/RecFact.js | 4 ++-- AlgorithmLibrary/RecQueens.js | 4 ++-- AlgorithmLibrary/RecReverse.js | 4 ++-- AlgorithmLibrary/RedBlack.js | 16 +++++++------- AlgorithmLibrary/RotateScale2D.js | 16 +++++++------- AlgorithmLibrary/RotateScale3D.js | 20 ++++++++--------- AlgorithmLibrary/RotateTranslate2D.js | 14 ++++++------ AlgorithmLibrary/Search.js | 8 +++---- AlgorithmLibrary/SimpleStack.js | 6 ++--- AlgorithmLibrary/SkewHeap.js | 8 +++---- AlgorithmLibrary/SplayTree.js | 14 ++++++------ AlgorithmLibrary/StackArray.js | 8 +++---- AlgorithmLibrary/StackLL.js | 8 +++---- AlgorithmLibrary/TST.js | 14 ++++++------ AlgorithmLibrary/TestAlgorithmOld.js | 2 +- AlgorithmLibrary/TopoSortDFS.js | 2 +- AlgorithmLibrary/TopoSortIndegree.js | 2 +- AlgorithmLibrary/Trie.js | 14 ++++++------ AlgorithmLibrary/TrinarySearchTree.js | 14 ++++++------ source.html | 14 ++++++------ 54 files changed, 270 insertions(+), 270 deletions(-) diff --git a/AlgorithmLibrary/AVL.js b/AlgorithmLibrary/AVL.js index 2e7d374..88c742f 100644 --- a/AlgorithmLibrary/AVL.js +++ b/AlgorithmLibrary/AVL.js @@ -83,19 +83,19 @@ AVL.prototype.init = function(am, w, h) AVL.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/BFS.js b/AlgorithmLibrary/BFS.js index 9035e58..d63bff1 100644 --- a/AlgorithmLibrary/BFS.js +++ b/AlgorithmLibrary/BFS.js @@ -54,10 +54,10 @@ BFS.superclass = Graph.prototype; BFS.prototype.addControls = function() { addLabelToAlgorithmBar("Start Vertex: "); - this.startField = addControlToAlgorithmBar("Text", ""); + this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); this.startField.size = 2; - this.startButton = addControlToAlgorithmBar("Button", "Run BFS"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run BFS"); this.startButton.onclick = this.startCallback.bind(this); BFS.superclass.addControls.call(this); } @@ -98,10 +98,10 @@ BFS.prototype.setup = function() this.cmd("CreateLabel", this.nextIndex++, "Parent", PARENT_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); this.cmd("CreateLabel", this.nextIndex++, "Visited", VISITED_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); this.cmd("CreateLabel", this.nextIndex++, "BFS Queue", QUEUE_START_X, QUEUE_START_Y - 30, 0); - animationManager.setAllLayers([0, this.currentLayer]); - animationManager.StartNewAnimation(this.commands); - animationManager.skipForward(); - animationManager.clearHistory(); + this.animationManager.setAllLayers([0, this.currentLayer]); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); this.highlightCircleL = this.nextIndex++; this.highlightCircleAL = this.nextIndex++; this.highlightCircleAM= this.nextIndex++ diff --git a/AlgorithmLibrary/BPlusTree.js b/AlgorithmLibrary/BPlusTree.js index 45ed997..4771471 100644 --- a/AlgorithmLibrary/BPlusTree.js +++ b/AlgorithmLibrary/BPlusTree.js @@ -89,9 +89,9 @@ BPlusTree.prototype.init = function(am, w, h) this.moveLabel1ID = this.nextIndex++; this.moveLabel2ID = this.nextIndex++; - animationManager.StartNewAnimation(this.commands); - animationManager.skipForward(); - animationManager.clearHistory(); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); this.commands = new Array(); this.first_print_pos_y = h - 3 * PRINT_VERTICAL_GAP; @@ -105,35 +105,35 @@ BPlusTree.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); this.controls.push(this.deleteField); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); this.controls.push(this.deleteButton); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); this.controls.push(this.findField); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); this.controls.push(this.findButton); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); this.controls.push(this.printButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); @@ -144,7 +144,7 @@ BPlusTree.prototype.addControls = function() radioButtonNames.push("Max. Degree = " + String(i)); } - this.maxDegreeRadioButtons = addRadioButtonGroupToAlgorithmBar(radioButtonNames, "MaxDegree"); + this.maxDegreeRadioButtons = this.addRadioButtonGroupToAlgorithmBar(radioButtonNames, "MaxDegree"); this.maxDegreeRadioButtons[0].checked = true; for(i = 0; i < this.maxDegreeRadioButtons.length; i++) @@ -153,7 +153,7 @@ BPlusTree.prototype.addControls = function() } -// this.premptiveSplitBox = addCheckboxToAlgorithmBar("Preemtive Split / Merge (Even max degree only)"); +// this.premptiveSplitBox = this.addCheckboxToAlgorithmBar("Preemtive Split / Merge (Even max degree only)"); // this.premptiveSplitBox.onclick = this.premtiveSplitCallback.bind(this); diff --git a/AlgorithmLibrary/BST.js b/AlgorithmLibrary/BST.js index 6af9c41..f6b5797 100644 --- a/AlgorithmLibrary/BST.js +++ b/AlgorithmLibrary/BST.js @@ -75,19 +75,19 @@ BST.prototype.init = function(am, w, h) BST.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/BTree.js b/AlgorithmLibrary/BTree.js index b544d06..9a0f210 100644 --- a/AlgorithmLibrary/BTree.js +++ b/AlgorithmLibrary/BTree.js @@ -92,9 +92,9 @@ BTree.prototype.init = function(am, w, h) this.moveLabel1ID = this.nextIndex++; this.moveLabel2ID = this.nextIndex++; - animationManager.StartNewAnimation(this.commands); - animationManager.skipForward(); - animationManager.clearHistory(); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); this.commands = new Array(); this.first_print_pos_y = h - 3 * PRINT_VERTICAL_GAP; @@ -108,35 +108,35 @@ BTree.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); this.controls.push(this.deleteField); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); this.controls.push(this.deleteButton); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); this.controls.push(this.findField); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); this.controls.push(this.findButton); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); this.controls.push(this.printButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); @@ -147,7 +147,7 @@ BTree.prototype.addControls = function() radioButtonNames.push("Max. Degree = " + String(i)); } - this.maxDegreeRadioButtons = addRadioButtonGroupToAlgorithmBar(radioButtonNames, "MaxDegree"); + this.maxDegreeRadioButtons = this.addRadioButtonGroupToAlgorithmBar(radioButtonNames, "MaxDegree"); this.maxDegreeRadioButtons[0].checked = true; for(i = 0; i < this.maxDegreeRadioButtons.length; i++) @@ -156,7 +156,7 @@ BTree.prototype.addControls = function() } - this.premptiveSplitBox = addCheckboxToAlgorithmBar("Preemtive Split / Merge (Even max degree only)"); + this.premptiveSplitBox = this.addCheckboxToAlgorithmBar("Preemtive Split / Merge (Even max degree only)"); this.premptiveSplitBox.onclick = this.premtiveSplitCallback.bind(this); @@ -246,7 +246,7 @@ BTree.prototype.maxDegreeChangedHandler = function(newMaxDegree, event) if (this.max_degree != newMaxDegree) { this.implementAction(this.changeDegree.bind(this), newMaxDegree); - animationManager.skipForward(); + this.animationManager.skipForward(); animationManager.clearHistory(); diff --git a/AlgorithmLibrary/BinomialQueue.js b/AlgorithmLibrary/BinomialQueue.js index 7884320..6614c54 100644 --- a/AlgorithmLibrary/BinomialQueue.js +++ b/AlgorithmLibrary/BinomialQueue.js @@ -73,23 +73,23 @@ BinomialQueue.prototype.init = function(am, w, h) BinomialQueue.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.removeSmallestButton = addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); this.controls.push(this.removeSmallestButton); - this.clearHeapButton = addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); this.clearHeapButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearHeapButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Logical Representation", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", "Internal Representation", ], "BQueueRep"); diff --git a/AlgorithmLibrary/BucketSort.js b/AlgorithmLibrary/BucketSort.js index d3e30cb..162ba83 100644 --- a/AlgorithmLibrary/BucketSort.js +++ b/AlgorithmLibrary/BucketSort.js @@ -76,10 +76,10 @@ BucketSort.prototype.init = function(am, w, h) BucketSort.prototype.addControls = function() { - this.resetButton = addControlToAlgorithmBar("Button", "Randomize List"); + this.resetButton = this.addControlToAlgorithmBar("Button", "Randomize List"); this.resetButton.onclick = this.resetCallback.bind(this); - this.bucketSortButton = addControlToAlgorithmBar("Button", "Bucket Sort"); + this.bucketSortButton = this.addControlToAlgorithmBar("Button", "Bucket Sort"); this.bucketSortButton.onclick = this.bucketSortCallback.bind(this); } diff --git a/AlgorithmLibrary/ChangingCoordinate2D.js b/AlgorithmLibrary/ChangingCoordinate2D.js index d6a4e44..1e8563d 100644 --- a/AlgorithmLibrary/ChangingCoordinate2D.js +++ b/AlgorithmLibrary/ChangingCoordinate2D.js @@ -505,24 +505,24 @@ ChangeCoordinate2D.prototype.addControls = function() addLabelToAlgorithmBar("x"); - this.xField = addControlToAlgorithmBar("Text", ""); + this.xField = this.addControlToAlgorithmBar("Text", ""); this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); this.controls.push(this.xField); addLabelToAlgorithmBar("y"); - this.yField = addControlToAlgorithmBar("Text", ""); + this.yField = this.addControlToAlgorithmBar("Text", ""); this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); this.controls.push(this.yField); - var transformButton = addControlToAlgorithmBar("Button", "Transform Point"); + var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); transformButton.onclick = this.transformPointCallback.bind(this); this.controls.push(transformButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", "World Space -> Hand Space", ], "Transform Type"); @@ -541,7 +541,7 @@ ChangeCoordinate2D.prototype.addControls = function() - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Row Major", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", "Column Major", ], "RankType"); @@ -557,7 +557,7 @@ ChangeCoordinate2D.prototype.addControls = function() this.colMajorButton.checked = !this.rowMajor; - this.showAxisBox = addCheckboxToAlgorithmBar("Show all axes"); + this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); this.showAxisBox.checked = true; @@ -565,7 +565,7 @@ ChangeCoordinate2D.prototype.addControls = function() - var moveObjectsButton = addControlToAlgorithmBar("Button", "Move Objects"); + var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); this.controls.push(moveObjectsButton); diff --git a/AlgorithmLibrary/ChangingCoordinate3D.js b/AlgorithmLibrary/ChangingCoordinate3D.js index 24a4a4a..dc7cbfd 100644 --- a/AlgorithmLibrary/ChangingCoordinate3D.js +++ b/AlgorithmLibrary/ChangingCoordinate3D.js @@ -588,32 +588,32 @@ ChangeCoordinate3D.prototype.addControls = function() addLabelToAlgorithmBar("x"); - this.xField = addControlToAlgorithmBar("Text", ""); + this.xField = this.addControlToAlgorithmBar("Text", ""); this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); this.controls.push(this.xField); addLabelToAlgorithmBar("y"); - this.yField = addControlToAlgorithmBar("Text", ""); + this.yField = this.addControlToAlgorithmBar("Text", ""); this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); this.controls.push(this.yField); addLabelToAlgorithmBar("z"); - this.zField = addControlToAlgorithmBar("Text", ""); + this.zField = this.addControlToAlgorithmBar("Text", ""); this.zField.onkeydown = this.returnSubmitFloat(this.zField, this.transformPointCallback.bind(this), 4, true); this.controls.push(this.zField); - var transformButton = addControlToAlgorithmBar("Button", "Transform Point"); + var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); transformButton.onclick = this.transformPointCallback.bind(this); this.controls.push(transformButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", "World Space -> Hand Space", ], "Transform Type"); @@ -632,7 +632,7 @@ ChangeCoordinate3D.prototype.addControls = function() - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Row Major", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", "Column Major", ], "RankType"); @@ -648,7 +648,7 @@ ChangeCoordinate3D.prototype.addControls = function() this.colMajorButton.checked = !this.rowMajor; - this.showAxisBox = addCheckboxToAlgorithmBar("Show all axes"); + this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); this.showAxisBox.checked = true; @@ -656,7 +656,7 @@ ChangeCoordinate3D.prototype.addControls = function() - var moveObjectsButton = addControlToAlgorithmBar("Button", "Move Objects"); + var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); this.controls.push(moveObjectsButton); diff --git a/AlgorithmLibrary/ClosedHash.js b/AlgorithmLibrary/ClosedHash.js index 2adcee4..aa8d26d 100644 --- a/AlgorithmLibrary/ClosedHash.js +++ b/AlgorithmLibrary/ClosedHash.js @@ -82,7 +82,7 @@ ClosedHash.prototype.addControls = function() ClosedHash.superclass.addControls.call(this); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Linear Probing: f(i) = i", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Linear Probing: f(i) = i", "Quadratic Probing: f(i) = i * i", "Double Hashing: f(i) = i * hash2(elem)"], "CollisionStrategy"); @@ -342,9 +342,9 @@ ClosedHash.prototype.setup = function() this.cmd("SetForegroundColor", nextID, INDEX_COLOR); } this.cmd("CreateLabel", this.ExplainLabel, "", 10, 25, 0); - animationManager.StartNewAnimation(this.commands); - animationManager.skipForward(); - animationManager.clearHistory(); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); this.resetIndex = this.nextIndex; } diff --git a/AlgorithmLibrary/ComparisonSort.js b/AlgorithmLibrary/ComparisonSort.js index 163fb32..3b4f520 100644 --- a/AlgorithmLibrary/ComparisonSort.js +++ b/AlgorithmLibrary/ComparisonSort.js @@ -85,28 +85,28 @@ ComparisonSort.prototype.init = function(am, w, h) ComparisonSort.prototype.addControls = function() { - this.resetButton = addControlToAlgorithmBar("Button", "Randomize Array"); + this.resetButton = this.addControlToAlgorithmBar("Button", "Randomize Array"); this.resetButton.onclick = this.resetCallback.bind(this); - this.insertSortButton = addControlToAlgorithmBar("Button", "Insertion Sort"); + this.insertSortButton = this.addControlToAlgorithmBar("Button", "Insertion Sort"); this.insertSortButton.onclick = this.insertSortCallback.bind(this); - this.selectSortButton = addControlToAlgorithmBar("Button", "Selection Sort"); + this.selectSortButton = this.addControlToAlgorithmBar("Button", "Selection Sort"); this.selectSortButton.onclick = this.selectSortCallback.bind(this); - this.bubbleSortButton = addControlToAlgorithmBar("Button", "Bubble Sort"); + this.bubbleSortButton = this.addControlToAlgorithmBar("Button", "Bubble Sort"); this.bubbleSortButton.onclick = this.bubbleSortCallback.bind(this); - this.quickSortButton = addControlToAlgorithmBar("Button", "Quick Sort"); + this.quickSortButton = this.addControlToAlgorithmBar("Button", "Quick Sort"); this.quickSortButton.onclick = this.quickSortCallback.bind(this); - this.mergeSortButton = addControlToAlgorithmBar("Button", "Merge Sort"); + this.mergeSortButton = this.addControlToAlgorithmBar("Button", "Merge Sort"); this.mergeSortButton.onclick = this.mergeSortCallback.bind(this); - this.shellSortButton = addControlToAlgorithmBar("Button", "Shell Sort"); + this.shellSortButton = this.addControlToAlgorithmBar("Button", "Shell Sort"); this.shellSortButton.onclick = this.shellSortCallback.bind(this); - this.sizeButton = addControlToAlgorithmBar("Button", "Change Size"); + this.sizeButton = this.addControlToAlgorithmBar("Button", "Change Size"); this.sizeButton.onclick = this.changeSizeCallback.bind(this); } diff --git a/AlgorithmLibrary/ConnectedComponent.js b/AlgorithmLibrary/ConnectedComponent.js index 89d5fd1..45a9e8f 100644 --- a/AlgorithmLibrary/ConnectedComponent.js +++ b/AlgorithmLibrary/ConnectedComponent.js @@ -84,7 +84,7 @@ ConnectedComponent.superclass = Graph.prototype; ConnectedComponent.prototype.addControls = function() { - this.startButton = addControlToAlgorithmBar("Button", "Run Connected Component"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run Connected Component"); this.startButton.onclick = this.startCallback.bind(this); ConnectedComponent.superclass.addControls.call(this, false); } diff --git a/AlgorithmLibrary/CountingSort.js b/AlgorithmLibrary/CountingSort.js index fcbbfd1..dfa61e2 100644 --- a/AlgorithmLibrary/CountingSort.js +++ b/AlgorithmLibrary/CountingSort.js @@ -84,10 +84,10 @@ CountingSort.prototype.sizeChanged = function(newWidth, newHeight) CountingSort.prototype.addControls = function() { - this.resetButton = addControlToAlgorithmBar("Button", "Randomize List"); + this.resetButton = this.addControlToAlgorithmBar("Button", "Randomize List"); this.resetButton.onclick = this.resetCallback.bind(this); - this.countingsSortButton = addControlToAlgorithmBar("Button", "Counting Sort"); + this.countingsSortButton = this.addControlToAlgorithmBar("Button", "Counting Sort"); this.countingsSortButton.onclick = this.countingSortCallback.bind(this); } diff --git a/AlgorithmLibrary/DFS.js b/AlgorithmLibrary/DFS.js index 96536c1..0bc9e23 100644 --- a/AlgorithmLibrary/DFS.js +++ b/AlgorithmLibrary/DFS.js @@ -55,9 +55,9 @@ DFS.superclass = Graph.prototype; DFS.prototype.addControls = function() { addLabelToAlgorithmBar("Start Vertex: "); - this.startField = addControlToAlgorithmBar("Text", ""); + this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); - this.startButton = addControlToAlgorithmBar("Button", "Run DFS"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run DFS"); this.startButton.onclick = this.startCallback.bind(this); DFS.superclass.addControls.call(this); } diff --git a/AlgorithmLibrary/DPChange.js b/AlgorithmLibrary/DPChange.js index e89fc31..b854ee4 100644 --- a/AlgorithmLibrary/DPChange.js +++ b/AlgorithmLibrary/DPChange.js @@ -168,24 +168,24 @@ DPChange.prototype.init = function(am, w, h) DPChange.prototype.addControls = function() { this.controls = []; - this.fibField = addControlToAlgorithmBar("Text", ""); + this.fibField = this.addControlToAlgorithmBar("Text", ""); this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); this.controls.push(this.fibField); - this.recursiveButton = addControlToAlgorithmBar("Button", "Change Recursive"); + this.recursiveButton = this.addControlToAlgorithmBar("Button", "Change Recursive"); this.recursiveButton.onclick = this.recursiveCallback.bind(this); this.controls.push(this.recursiveButton); - this.tableButton = addControlToAlgorithmBar("Button", "Change Table"); + this.tableButton = this.addControlToAlgorithmBar("Button", "Change Table"); this.tableButton.onclick = this.tableCallback.bind(this); this.controls.push(this.tableButton); - this.memoizedButton = addControlToAlgorithmBar("Button", "Change Memoized"); + this.memoizedButton = this.addControlToAlgorithmBar("Button", "Change Memoized"); this.memoizedButton.onclick = this.memoizedCallback.bind(this); this.controls.push(this.memoizedButton); - this.greedyButton = addControlToAlgorithmBar("Button", "Change Greedy"); + this.greedyButton = this.addControlToAlgorithmBar("Button", "Change Greedy"); this.greedyButton.onclick = this.greedyCallback.bind(this); this.controls.push(this.greedyButton); @@ -205,7 +205,7 @@ DPChange.prototype.addControls = function() coinLabels.push(nextLabel); } - this.coinTypeButtons = addRadioButtonGroupToAlgorithmBar(coinLabels, "CoinType"); + this.coinTypeButtons = this.addRadioButtonGroupToAlgorithmBar(coinLabels, "CoinType"); for (i = 0; i < this.coinTypeButtons.length; i++) { diff --git a/AlgorithmLibrary/DPFib.js b/AlgorithmLibrary/DPFib.js index 6d023e8..d6930cd 100644 --- a/AlgorithmLibrary/DPFib.js +++ b/AlgorithmLibrary/DPFib.js @@ -106,19 +106,19 @@ DPFib.prototype.init = function(am, w, h) DPFib.prototype.addControls = function() { this.controls = []; - this.fibField = addControlToAlgorithmBar("Text", ""); + this.fibField = this.addControlToAlgorithmBar("Text", ""); this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); this.controls.push(this.fibField); - this.recursiveButton = addControlToAlgorithmBar("Button", "Fibonacci Recursive"); + this.recursiveButton = this.addControlToAlgorithmBar("Button", "Fibonacci Recursive"); this.recursiveButton.onclick = this.recursiveCallback.bind(this); this.controls.push(this.recursiveButton); - this.tableButton = addControlToAlgorithmBar("Button", "Fibonacci Table"); + this.tableButton = this.addControlToAlgorithmBar("Button", "Fibonacci Table"); this.tableButton.onclick = this.tableCallback.bind(this); this.controls.push(this.tableButton); - this.memoizedButton = addControlToAlgorithmBar("Button", "Fibonacci Memoized"); + this.memoizedButton = this.addControlToAlgorithmBar("Button", "Fibonacci Memoized"); this.memoizedButton.onclick = this.memoizedCallback.bind(this); this.controls.push(this.memoizedButton); diff --git a/AlgorithmLibrary/DPLCS.js b/AlgorithmLibrary/DPLCS.js index 2fcf595..07862eb 100644 --- a/AlgorithmLibrary/DPLCS.js +++ b/AlgorithmLibrary/DPLCS.js @@ -115,24 +115,24 @@ DPLCS.prototype.addControls = function() { this.controls = []; addLabelToAlgorithmBar("S1:"); - this.S1Field = addControlToAlgorithmBar("Text", ""); + this.S1Field = this.addControlToAlgorithmBar("Text", ""); this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); this.controls.push(this.S1Field); addLabelToAlgorithmBar("S2:"); - this.S2Field = addControlToAlgorithmBar("Text", ""); + this.S2Field = this.addControlToAlgorithmBar("Text", ""); this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); this.controls.push(this.S2Field); - this.recursiveButton = addControlToAlgorithmBar("Button", "LCS Recursive"); + this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); this.recursiveButton.onclick = this.recursiveCallback.bind(this); this.controls.push(this.recursiveButton); - this.tableButton = addControlToAlgorithmBar("Button", "LCS Table"); + this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); this.tableButton.onclick = this.tableCallback.bind(this); this.controls.push(this.tableButton); - this.memoizedButton = addControlToAlgorithmBar("Button", "LCS Memoized"); + this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); this.memoizedButton.onclick = this.memoizedCallback.bind(this); this.controls.push(this.memoizedButton); diff --git a/AlgorithmLibrary/DPMatrixMultiply.js b/AlgorithmLibrary/DPMatrixMultiply.js index be9a628..f309721 100644 --- a/AlgorithmLibrary/DPMatrixMultiply.js +++ b/AlgorithmLibrary/DPMatrixMultiply.js @@ -116,24 +116,24 @@ DPMatrixMultiply.prototype.addControls = function() { this.controls = []; addLabelToAlgorithmBar("S1:"); - this.S1Field = addControlToAlgorithmBar("Text", ""); + this.S1Field = this.addControlToAlgorithmBar("Text", ""); this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); this.controls.push(this.S1Field); addLabelToAlgorithmBar("S2:"); - this.S2Field = addControlToAlgorithmBar("Text", ""); + this.S2Field = this.addControlToAlgorithmBar("Text", ""); this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); this.controls.push(this.S2Field); - this.recursiveButton = addControlToAlgorithmBar("Button", "LCS Recursive"); + this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); this.recursiveButton.onclick = this.recursiveCallback.bind(this); this.controls.push(this.recursiveButton); - this.tableButton = addControlToAlgorithmBar("Button", "LCS Table"); + this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); this.tableButton.onclick = this.tableCallback.bind(this); this.controls.push(this.tableButton); - this.memoizedButton = addControlToAlgorithmBar("Button", "LCS Memoized"); + this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); this.memoizedButton.onclick = this.memoizedCallback.bind(this); this.controls.push(this.memoizedButton); diff --git a/AlgorithmLibrary/DijkstraPrim.js b/AlgorithmLibrary/DijkstraPrim.js index a3d65b4..d98bb14 100644 --- a/AlgorithmLibrary/DijkstraPrim.js +++ b/AlgorithmLibrary/DijkstraPrim.js @@ -52,17 +52,17 @@ DijkstraPrim.superclass = Graph.prototype; DijkstraPrim.prototype.addControls = function() { addLabelToAlgorithmBar("Start Vertex: "); - this.startField = addControlToAlgorithmBar("Text", ""); + this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); this.startField.size = 2 if (this.runningDijkstra) { - this.startButton = addControlToAlgorithmBar("Button", "Run Dijkstra"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run Dijkstra"); } else { - this.startButton = addControlToAlgorithmBar("Button", "Run Prim"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run Prim"); } this.startButton.onclick = this.startCallback.bind(this); diff --git a/AlgorithmLibrary/DisjointSet.js b/AlgorithmLibrary/DisjointSet.js index 8cfdcd7..6988495 100644 --- a/AlgorithmLibrary/DisjointSet.js +++ b/AlgorithmLibrary/DisjointSet.js @@ -94,41 +94,41 @@ DisjointSet.prototype.addControls = function() this.controls = []; - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4, true); this.controls.push(this.findField); - var findButton = addControlToAlgorithmBar("Button", "Find"); + var findButton = this.addControlToAlgorithmBar("Button", "Find"); findButton.onclick = this.findCallback.bind(this); this.controls.push(findButton); - this.unionField1 = addControlToAlgorithmBar("Text", ""); + this.unionField1 = this.addControlToAlgorithmBar("Text", ""); this.unionField1.onkeydown = this.returnSubmit(this.unionField1, this.unionCallback.bind(this), 4, true); this.controls.push(this.unionField1); - this.unionField2 = addControlToAlgorithmBar("Text", ""); + this.unionField2 = this.addControlToAlgorithmBar("Text", ""); this.unionField2.onkeydown = this.returnSubmit(this.unionField2, this.unionCallback.bind(this), 4, true); - this.unionButton = addControlToAlgorithmBar("Button", "Union"); + this.unionButton = this.addControlToAlgorithmBar("Button", "Union"); this.unionButton.onclick = this.unionCallback.bind(this); this.controls.push(this.unionField2); - this.pathCompressionBox = addCheckboxToAlgorithmBar("Path Compression"); + this.pathCompressionBox = this.addCheckboxToAlgorithmBar("Path Compression"); this.pathCompressionBox.onclick = this.pathCompressionChangeCallback.bind(this); this.controls.push(this.pathCompressionBox); - this.unionByRankBox = addCheckboxToAlgorithmBar("Union By Rank"); + this.unionByRankBox = this.addCheckboxToAlgorithmBar("Union By Rank"); this.unionByRankBox.onclick = this.unionByRankChangeCallback.bind(this); this.controls.push(this.unionByRankBox); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Rank = # of nodes", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rank = # of nodes", "Rank = estimated height", ], "RankType"); @@ -168,9 +168,9 @@ DisjointSet.prototype.setup = function() } - animationManager.StartNewAnimation(this.commands); - animationManager.skipForward(); - animationManager.clearHistory(); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); } diff --git a/AlgorithmLibrary/FibonacciHeap.js b/AlgorithmLibrary/FibonacciHeap.js index 93f7760..a053b25 100644 --- a/AlgorithmLibrary/FibonacciHeap.js +++ b/AlgorithmLibrary/FibonacciHeap.js @@ -80,23 +80,23 @@ FibonacciHeap.prototype.init = function(am, w, h) FibonacciHeap.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.removeSmallestButton = addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); this.controls.push(this.removeSmallestButton); - this.clearHeapButton = addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); this.clearHeapButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearHeapButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Logical Representation", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", "Internal Representation", ], "BQueueRep"); diff --git a/AlgorithmLibrary/Floyd.js b/AlgorithmLibrary/Floyd.js index 7079bb7..522fd18 100644 --- a/AlgorithmLibrary/Floyd.js +++ b/AlgorithmLibrary/Floyd.js @@ -80,7 +80,7 @@ Floyd.superclass = Graph.prototype; Floyd.prototype.addControls = function() { - this.startButton = addControlToAlgorithmBar("Button", "Run Floyd-Warshall"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run Floyd-Warshall"); this.startButton.onclick = this.startCallback.bind(this); Floyd.superclass.addControls.call(this); diff --git a/AlgorithmLibrary/Graph.js b/AlgorithmLibrary/Graph.js index 0577d8b..71f57b0 100644 --- a/AlgorithmLibrary/Graph.js +++ b/AlgorithmLibrary/Graph.js @@ -186,12 +186,12 @@ Graph.prototype.addControls = function(addDirection) { addDirection = true; } - this.newGraphButton = addControlToAlgorithmBar("Button", "New Graph"); + this.newGraphButton = this.addControlToAlgorithmBar("Button", "New Graph"); this.newGraphButton.onclick = this.newGraphCallback.bind(this); if (addDirection) { - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Directed Graph", "Undirected Graph"], "GraphType"); + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Directed Graph", "Undirected Graph"], "GraphType"); this.directedGraphButton = radioButtonList[0]; this.directedGraphButton.onclick = this.directedGraphCallback.bind(this, true); this.undirectedGraphButton = radioButtonList[1]; @@ -201,14 +201,14 @@ Graph.prototype.addControls = function(addDirection) } - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Small Graph", "Large Graph"], "GraphSize"); + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small Graph", "Large Graph"], "GraphSize"); this.smallGraphButton = radioButtonList[0]; this.smallGraphButton.onclick = this.smallGraphCallback.bind(this); this.largeGraphButton = radioButtonList[1]; this.largeGraphButton.onclick = this.largeGraphCallback.bind(this); this.smallGraphButton.checked = true; - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Logical Representation", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", "Adjacency List Representation", "Adjacency Matrix Representation" ], diff --git a/AlgorithmLibrary/Hash.js b/AlgorithmLibrary/Hash.js index c7d16e2..807b09b 100644 --- a/AlgorithmLibrary/Hash.js +++ b/AlgorithmLibrary/Hash.js @@ -73,27 +73,27 @@ Hash.prototype.init = function(am, w, h) Hash.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.size = MAX_HASH_LENGTH; this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), MAX_HASH_LENGTH, true); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.size = MAX_HASH_LENGTH; this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), MAX_HASH_LENGTH, true); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.size = MAX_HASH_LENGTH; this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), MAX_HASH_LENGTH, true); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Hash Integer", "Hash Strings"], "HashType"); + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hash Integer", "Hash Strings"], "HashType"); this.hashIntegerButton = radioButtonList[0]; this.hashIntegerButton.onclick = this.changeHashTypeCallback.bind(this, true); // this.hashIntegerButton.onclick = this.hashIntegerCallback.bind(this); diff --git a/AlgorithmLibrary/Heap.js b/AlgorithmLibrary/Heap.js index 6c6d8a7..3f5e5a4 100644 --- a/AlgorithmLibrary/Heap.js +++ b/AlgorithmLibrary/Heap.js @@ -74,15 +74,15 @@ Heap.prototype.init = function(am) Heap.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4, true); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.removeSmallestButton = addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); - this.clearHeapButton = addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); this.clearHeapButton.onclick = this.clearCallback.bind(this); - this.buildHeapButton = addControlToAlgorithmBar("Button", "BuildHeap"); + this.buildHeapButton = this.addControlToAlgorithmBar("Button", "BuildHeap"); this.buildHeapButton.onclick = this.buildHeapCallback.bind(this); } diff --git a/AlgorithmLibrary/HeapSort.js b/AlgorithmLibrary/HeapSort.js index d753d4e..a799d7a 100644 --- a/AlgorithmLibrary/HeapSort.js +++ b/AlgorithmLibrary/HeapSort.js @@ -76,9 +76,9 @@ HeapSort.prototype.init = function(am) HeapSort.prototype.addControls = function() { - this.randomizeArrayButton = addControlToAlgorithmBar("Button", "Randomize Array"); + this.randomizeArrayButton = this.addControlToAlgorithmBar("Button", "Randomize Array"); this.randomizeArrayButton.onclick = this.randomizeCallback.bind(this); - this.heapsortButton = addControlToAlgorithmBar("Button", "Heap Sort"); + this.heapsortButton = this.addControlToAlgorithmBar("Button", "Heap Sort"); this.heapsortButton.onclick = this.heapsortCallback.bind(this); } diff --git a/AlgorithmLibrary/Huffman.js b/AlgorithmLibrary/Huffman.js index a216afd..deecd78 100644 --- a/AlgorithmLibrary/Huffman.js +++ b/AlgorithmLibrary/Huffman.js @@ -76,9 +76,9 @@ Huffman.prototype.init = function(am, w, h) Huffman.prototype.addControls = function() { - this.encodeField = addControlToAlgorithmBar("Text", ""); + this.encodeField = this.addControlToAlgorithmBar("Text", ""); this.encodeField.onkeydown = this.returnSubmit(this.encodeField, this.encodeCallback.bind(this), 50); - this.encodeButton = addControlToAlgorithmBar("Button", "Encode"); + this.encodeButton = this.addControlToAlgorithmBar("Button", "Encode"); this.encodeButton.onclick = this.encodeCallback.bind(this); } diff --git a/AlgorithmLibrary/Kruskal.js b/AlgorithmLibrary/Kruskal.js index 9c542a6..491c797 100644 --- a/AlgorithmLibrary/Kruskal.js +++ b/AlgorithmLibrary/Kruskal.js @@ -67,7 +67,7 @@ Kruskal.superclass = Graph.prototype; Kruskal.prototype.addControls = function() { - this.startButton = addControlToAlgorithmBar("Button", "Run Kruskal"); + this.startButton = this.addControlToAlgorithmBar("Button", "Run Kruskal"); this.startButton.onclick = this.startCallback.bind(this); Kruskal.superclass.addControls.call(this, false); diff --git a/AlgorithmLibrary/LeftistHeap.js b/AlgorithmLibrary/LeftistHeap.js index d48803f..a9298df 100644 --- a/AlgorithmLibrary/LeftistHeap.js +++ b/AlgorithmLibrary/LeftistHeap.js @@ -79,23 +79,23 @@ LeftistHeap.prototype.init = function(am, w, h) LeftistHeap.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.removeSmallestButton = addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); this.controls.push(this.removeSmallestButton); - this.clearHeapButton = addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); this.clearHeapButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearHeapButton); - this.showNPLBox = addCheckboxToAlgorithmBar("Show Null Path Lengths"); + this.showNPLBox = this.addCheckboxToAlgorithmBar("Show Null Path Lengths"); this.showNPLBox.checked = true; this.showNPLBox.onclick = this.NPLChangedHandler.bind(this); diff --git a/AlgorithmLibrary/MyAlgorithm.js b/AlgorithmLibrary/MyAlgorithm.js index 6f3e414..f363c4b 100644 --- a/AlgorithmLibrary/MyAlgorithm.js +++ b/AlgorithmLibrary/MyAlgorithm.js @@ -59,13 +59,13 @@ MyAlgorithm.prototype.addControls = function() // There are libraries that help with text entry, buttons, check boxes, radio groups // // To add a button myButton: - // this.mybytton = addControlToAlgorithmBar("Button", "MyButtonText"); + // this.mybytton = this.addControlToAlgorithmBar("Button", "MyButtonText"); // this.mybytton.onclick = this.myCallback.bind(this); // this.controls.push(this.mybutton); // where myCallback is a method on this function that implemnts the callback // // To add a text field myField: - // this.myField = addControlToAlgorithmBar("Text", ""); + // this.myField = this.addControlToAlgorithmBar("Text", ""); // this.myField.onkeydown = this.returnSubmit(this.myField, // this.anotherCallback.bind(this), // callback to make when return is pressed // maxFieldLen, // integer, max number of characters allowed in field @@ -73,12 +73,12 @@ MyAlgorithm.prototype.addControls = function() // this.controls.push(this.myField); // // To add a textbox: - // this.myCheckbox = addCheckboxToAlgorithmBar("Checkbox Label"); + // this.myCheckbox = this.addCheckboxToAlgorithmBar("Checkbox Label"); // this.myCheckbox.onclick = this.checkboxCallback.bind(this); // this.controls.push(myCheckbox); // // To add a radio button group: - // this.radioButtonList = addRadioButtonGroupToAlgorithmBar(["radio button label 1", + // this.radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["radio button label 1", // "radio button label 2", // "radio button label 3"], // "MyButtonGroupName"); diff --git a/AlgorithmLibrary/QueueArray.js b/AlgorithmLibrary/QueueArray.js index 15190ec..90748f0 100644 --- a/AlgorithmLibrary/QueueArray.js +++ b/AlgorithmLibrary/QueueArray.js @@ -79,18 +79,18 @@ QueueArray.prototype.init = function(am, w, h) QueueArray.prototype.addControls = function() { this.controls = []; - this.enqueueField = addControlToAlgorithmBar("Text", ""); + this.enqueueField = this.addControlToAlgorithmBar("Text", ""); this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); - this.enqueueButton = addControlToAlgorithmBar("Button", "Enqueue"); + this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); this.enqueueButton.onclick = this.enqueueCallback.bind(this); this.controls.push(this.enqueueField); this.controls.push(this.enqueueButton); - this.dequeueButton = addControlToAlgorithmBar("Button", "Dequeue"); + this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); this.dequeueButton.onclick = this.dequeueCallback.bind(this); this.controls.push(this.dequeueButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear Queue"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); diff --git a/AlgorithmLibrary/QueueLL.js b/AlgorithmLibrary/QueueLL.js index 18c9a1c..54688a4 100644 --- a/AlgorithmLibrary/QueueLL.js +++ b/AlgorithmLibrary/QueueLL.js @@ -83,18 +83,18 @@ QueueLL.prototype.init = function(am, w, h) QueueLL.prototype.addControls = function() { this.controls = []; - this.enqueueField = addControlToAlgorithmBar("Text", ""); + this.enqueueField = this.addControlToAlgorithmBar("Text", ""); this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); - this.enqueueButton = addControlToAlgorithmBar("Button", "Enqueue"); + this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); this.enqueueButton.onclick = this.enqueueCallback.bind(this); this.controls.push(this.enqueueField); this.controls.push(this.enqueueButton); - this.dequeueButton = addControlToAlgorithmBar("Button", "Dequeue"); + this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); this.dequeueButton.onclick = this.dequeueCallback.bind(this); this.controls.push(this.dequeueButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear Queue"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); diff --git a/AlgorithmLibrary/RadixSort.js b/AlgorithmLibrary/RadixSort.js index ddd3865..6096c4e 100644 --- a/AlgorithmLibrary/RadixSort.js +++ b/AlgorithmLibrary/RadixSort.js @@ -82,10 +82,10 @@ RadixSort.prototype.sizeChanged = function(newWidth, newHeight) RadixSort.prototype.addControls = function() { - this.resetButton = addControlToAlgorithmBar("Button", "Randomize List"); + this.resetButton = this.addControlToAlgorithmBar("Button", "Randomize List"); this.resetButton.onclick = this.resetCallback.bind(this); - this.radixSortButton = addControlToAlgorithmBar("Button", "Radix Sort"); + this.radixSortButton = this.addControlToAlgorithmBar("Button", "Radix Sort"); this.radixSortButton.onclick = this.radixSortCallback.bind(this); } @@ -319,7 +319,7 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("SetAlpha", this.counterIndices[i], 1); } } - animationManager.StartNewAnimation(this.commands); + this.animationManager.StartNewAnimation(this.commands); } diff --git a/AlgorithmLibrary/RadixTree.js b/AlgorithmLibrary/RadixTree.js index f99c9ea..e39d1a4 100644 --- a/AlgorithmLibrary/RadixTree.js +++ b/AlgorithmLibrary/RadixTree.js @@ -108,19 +108,19 @@ RadixTree.prototype.findIndexDifference = function(s1, s2, id, wordIndex) RadixTree.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeypress = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 12,false); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 12); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 12); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/RecFact.js b/AlgorithmLibrary/RecFact.js index a51650c..207c0b0 100644 --- a/AlgorithmLibrary/RecFact.js +++ b/AlgorithmLibrary/RecFact.js @@ -78,11 +78,11 @@ RecFact.prototype.init = function(am, w, h) RecFact.prototype.addControls = function() { this.controls = []; - this.factorialField = addControlToAlgorithmBar("Text", ""); + this.factorialField = this.addControlToAlgorithmBar("Text", ""); this.factorialField.onkeydown = this.returnSubmit(this.factorialField, this.factorialCallback.bind(this), 2, true); this.controls.push(this.factorialField); - this.factorialButton = addControlToAlgorithmBar("Button", "Factorial"); + this.factorialButton = this.addControlToAlgorithmBar("Button", "Factorial"); this.factorialButton.onclick = this.factorialCallback.bind(this); this.controls.push(this.factorialButton); diff --git a/AlgorithmLibrary/RecQueens.js b/AlgorithmLibrary/RecQueens.js index ccca873..f1b858e 100644 --- a/AlgorithmLibrary/RecQueens.js +++ b/AlgorithmLibrary/RecQueens.js @@ -111,11 +111,11 @@ Queens.prototype.addControls = function() this.controls = []; addLabelToAlgorithmBar("Board size: (1-8)"); - this.sizeField = addControlToAlgorithmBar("Text", ""); + this.sizeField = this.addControlToAlgorithmBar("Text", ""); this.sizeField.onkeydown = this.returnSubmit(this.sizeField, this.queensCallback.bind(this), 2, true); this.controls.push(this.sizeField); - this.queensButton = addControlToAlgorithmBar("Button", "Queens"); + this.queensButton = this.addControlToAlgorithmBar("Button", "Queens"); this.queensButton.onclick = this.queensCallback.bind(this); this.controls.push(this.queensButton); diff --git a/AlgorithmLibrary/RecReverse.js b/AlgorithmLibrary/RecReverse.js index 5a98ebb..89a9c6d 100644 --- a/AlgorithmLibrary/RecReverse.js +++ b/AlgorithmLibrary/RecReverse.js @@ -78,11 +78,11 @@ Reverse.prototype.init = function(am, w, h) Reverse.prototype.addControls = function() { this.controls = []; - this.reverseField = addControlToAlgorithmBar("Text", ""); + this.reverseField = this.addControlToAlgorithmBar("Text", ""); this.reverseField.onkeydown = this.returnSubmit(this.reverseField, this.reverseCallback.bind(this), 10, false); this.controls.push(this.reverseField); - this.reverseButton = addControlToAlgorithmBar("Button", "Reverse"); + this.reverseButton = this.addControlToAlgorithmBar("Button", "Reverse"); this.reverseButton.onclick = this.reverseCallback.bind(this); this.controls.push(this.reverseButton); diff --git a/AlgorithmLibrary/RedBlack.js b/AlgorithmLibrary/RedBlack.js index 51e18ba..e38c488 100644 --- a/AlgorithmLibrary/RedBlack.js +++ b/AlgorithmLibrary/RedBlack.js @@ -56,22 +56,22 @@ RedBlack.prototype.init = function(am, w, h) RedBlack.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); - this.showNullLeaves = addCheckboxToAlgorithmBar("Show Null Leaves"); + this.showNullLeaves = this.addCheckboxToAlgorithmBar("Show Null Leaves"); this.showNullLeaves.onclick = this.showNullLeavesCallback.bind(this); this.showNullLeaves.checked = false;; diff --git a/AlgorithmLibrary/RotateScale2D.js b/AlgorithmLibrary/RotateScale2D.js index aaf70bc..f86be6f 100644 --- a/AlgorithmLibrary/RotateScale2D.js +++ b/AlgorithmLibrary/RotateScale2D.js @@ -213,30 +213,30 @@ RotateScale2D.prototype.addControls = function() addLabelToAlgorithmBar("Rotation Angle"); - this.rotationField = addControlToAlgorithmBar("Text", ""); + this.rotationField = this.addControlToAlgorithmBar("Text", ""); this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); this.controls.push(this.rotationField); addLabelToAlgorithmBar("Scale X"); - this.scaleXField = addControlToAlgorithmBar("Text", ""); + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); this.controls.push(this.scaleXField); addLabelToAlgorithmBar("Scale Y"); - this.scaleYField = addControlToAlgorithmBar("Text", ""); + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); this.controls.push(this.scaleYField); - var transformButton = addControlToAlgorithmBar("Button", "Transform"); + var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); transformButton.onclick = this.transformCallback.bind(this); this.controls.push(transformButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Row Major", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", "Column Major", ], "RankType"); @@ -251,7 +251,7 @@ RotateScale2D.prototype.addControls = function() this.rowMajorButton.checked = this.rowMajor; this.colMajorButton.checked = !this.rowMajor; - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["+y Up", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", "+y Down", ], "yAxisDirection"); @@ -266,7 +266,7 @@ RotateScale2D.prototype.addControls = function() this.posYUpButton.checked = this.posYUp; this.posYDownButton.checked = !this.posYUp; - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Rotate, then scale", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rotate, then scale", "Scale, then rotate", ], "RotateFirst"); @@ -281,7 +281,7 @@ RotateScale2D.prototype.addControls = function() this.rotateScaleButton.checked = this.rotateFirst; this.scaleRotateButton.checked = !this.rotateFirst; - var changeShapeButton = addControlToAlgorithmBar("Button", "Change Shape"); + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); changeShapeButton.onclick = this.changeShapeCallback.bind(this); this.controls.push(changeShapeButton); diff --git a/AlgorithmLibrary/RotateScale3D.js b/AlgorithmLibrary/RotateScale3D.js index 40bcc7c..61fdc18 100644 --- a/AlgorithmLibrary/RotateScale3D.js +++ b/AlgorithmLibrary/RotateScale3D.js @@ -292,25 +292,25 @@ RotateScale3D.prototype.addControls = function() addLabelToAlgorithmBar("X Angle"); - this.rotationFieldX = addControlToAlgorithmBar("Text", ""); + this.rotationFieldX = this.addControlToAlgorithmBar("Text", ""); this.rotationFieldX.onkeydown = this.returnSubmitFloat(this.rotationFieldX, this.rotateCallback.bind(this), 4, true); this.controls.push(this.rotationFieldX); addLabelToAlgorithmBar("Y Angle"); - this.rotationFieldY = addControlToAlgorithmBar("Text", ""); + this.rotationFieldY = this.addControlToAlgorithmBar("Text", ""); this.rotationFieldY.onkeydown = this.returnSubmitFloat(this.rotationFieldY, this.rotateCallback.bind(this), 4, true); this.controls.push(this.rotationFieldY); addLabelToAlgorithmBar("Z Angle"); - this.rotationFieldZ = addControlToAlgorithmBar("Text", ""); + this.rotationFieldZ = this.addControlToAlgorithmBar("Text", ""); this.rotationFieldZ.onkeydown = this.returnSubmitFloat(this.rotationFieldZ, this.rotateCallback.bind(this), 4, true); this.controls.push(this.rotationFieldZ); - var rotateButton = addControlToAlgorithmBar("Button", "Rotate"); + var rotateButton = this.addControlToAlgorithmBar("Button", "Rotate"); rotateButton.onclick = this.rotateCallback.bind(this); this.controls.push(rotateButton); @@ -318,31 +318,31 @@ RotateScale3D.prototype.addControls = function() addLabelToAlgorithmBar("Scale X"); - this.scaleXField = addControlToAlgorithmBar("Text", ""); + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.scaleCallback.bind(this), 4, true); this.controls.push(this.scaleXField); addLabelToAlgorithmBar("Scale Y"); - this.scaleYField = addControlToAlgorithmBar("Text", ""); + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.scaleCallback.bind(this), 4, true); this.controls.push(this.scaleYField); addLabelToAlgorithmBar("Scale Z"); - this.scaleZField = addControlToAlgorithmBar("Text", ""); + this.scaleZField = this.addControlToAlgorithmBar("Text", ""); this.scaleZField.onkeydown = this.returnSubmitFloat(this.scaleZField, this.scaleCallback.bind(this), 4, true); this.controls.push(this.scaleZField); - var scaleButton = addControlToAlgorithmBar("Button", "Scale"); + var scaleButton = this.addControlToAlgorithmBar("Button", "Scale"); scaleButton.onclick = this.scaleCallback.bind(this); this.controls.push(scaleButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Row Major", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", "Column Major", ], "RankType"); @@ -359,7 +359,7 @@ RotateScale3D.prototype.addControls = function() - var changeShapeButton = addControlToAlgorithmBar("Button", "Change Shape"); + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); changeShapeButton.onclick = this.changeShapeCallback.bind(this); this.controls.push(changeShapeButton); diff --git a/AlgorithmLibrary/RotateTranslate2D.js b/AlgorithmLibrary/RotateTranslate2D.js index 35068c5..5105131 100644 --- a/AlgorithmLibrary/RotateTranslate2D.js +++ b/AlgorithmLibrary/RotateTranslate2D.js @@ -273,30 +273,30 @@ RotateTranslate2D.prototype.addControls = function() addLabelToAlgorithmBar("Rotation Angle"); - this.rotationField = addControlToAlgorithmBar("Text", ""); + this.rotationField = this.addControlToAlgorithmBar("Text", ""); this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); this.controls.push(this.rotationField); addLabelToAlgorithmBar("Translate X"); - this.scaleXField = addControlToAlgorithmBar("Text", ""); + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); this.controls.push(this.scaleXField); addLabelToAlgorithmBar("Translate Y"); - this.scaleYField = addControlToAlgorithmBar("Text", ""); + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); this.controls.push(this.scaleYField); - var transformButton = addControlToAlgorithmBar("Button", "Transform"); + var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); transformButton.onclick = this.transformCallback.bind(this); this.controls.push(transformButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Row Major", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", "Column Major", ], "RankType"); @@ -311,7 +311,7 @@ RotateTranslate2D.prototype.addControls = function() this.rowMajorButton.checked = this.rowMajor; this.colMajorButton.checked = !this.rowMajor; - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["+y Up", + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", "+y Down", ], "yAxisDirection"); @@ -327,7 +327,7 @@ RotateTranslate2D.prototype.addControls = function() this.posYDownButton.checked = !this.posYUp; - var changeShapeButton = addControlToAlgorithmBar("Button", "Change Shape"); + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); changeShapeButton.onclick = this.changeShapeCallback.bind(this); this.controls.push(changeShapeButton); diff --git a/AlgorithmLibrary/Search.js b/AlgorithmLibrary/Search.js index 000bbf2..e0c7ca7 100644 --- a/AlgorithmLibrary/Search.js +++ b/AlgorithmLibrary/Search.js @@ -148,20 +148,20 @@ Search.prototype.init = function(am, w, h) Search.prototype.addControls = function() { this.controls = []; - this.searchField = addControlToAlgorithmBar("Text", ""); + this.searchField = this.addControlToAlgorithmBar("Text", ""); this.searchField.onkeydown = this.returnSubmit(this.searchField, null, 6, true); - this.linearSearchButton = addControlToAlgorithmBar("Button", "Linear Search"); + this.linearSearchButton = this.addControlToAlgorithmBar("Button", "Linear Search"); this.linearSearchButton.onclick = this.linearSearchCallback.bind(this); this.controls.push(this.searchField); this.controls.push(this.linearSearchButton); - this.binarySearchButton = addControlToAlgorithmBar("Button", "Binary Search"); + this.binarySearchButton = this.addControlToAlgorithmBar("Button", "Binary Search"); this.binarySearchButton.onclick = this.binarySearchCallback.bind(this); this.controls.push(this.binarySearchButton); - var radioButtonList = addRadioButtonGroupToAlgorithmBar(["Small", "Large"], "List Size"); + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small", "Large"], "List Size"); this.smallListButton = radioButtonList[0]; this.smallListButton.onclick = this.smallListCallback.bind(this); this.largeListButton = radioButtonList[1]; diff --git a/AlgorithmLibrary/SimpleStack.js b/AlgorithmLibrary/SimpleStack.js index 87fe957..361fd98 100644 --- a/AlgorithmLibrary/SimpleStack.js +++ b/AlgorithmLibrary/SimpleStack.js @@ -68,18 +68,18 @@ SimpleStack.prototype.addControls = function() this.controls = []; - this.pushField = addControlToAlgorithmBar("Text", ""); + this.pushField = this.addControlToAlgorithmBar("Text", ""); this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), // callback to make when return is pressed 4, // integer, max number of characters allowed in field false); // boolean, true of only digits can be entered. this.controls.push(this.pushField); - this.pushButton = addControlToAlgorithmBar("Button", "Push"); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); this.pushButton.onclick = this.pushCallback.bind(this); this.controls.push(this.pushButton); - this.popButton = addControlToAlgorithmBar("Button", "Pop"); + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); this.popButton.onclick = this.popCallback.bind(this); this.controls.push(this.popButton); } diff --git a/AlgorithmLibrary/SkewHeap.js b/AlgorithmLibrary/SkewHeap.js index 214d628..aefe10a 100644 --- a/AlgorithmLibrary/SkewHeap.js +++ b/AlgorithmLibrary/SkewHeap.js @@ -76,19 +76,19 @@ SkewHeap.prototype.init = function(am, w, h) SkewHeap.prototype.addControls = function() { this.controls = []; - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); this.controls.push(this.insertField); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.controls.push(this.insertButton); - this.removeSmallestButton = addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); this.controls.push(this.removeSmallestButton); - this.clearHeapButton = addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); this.clearHeapButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearHeapButton); diff --git a/AlgorithmLibrary/SplayTree.js b/AlgorithmLibrary/SplayTree.js index 873e970..ae2eec4 100644 --- a/AlgorithmLibrary/SplayTree.js +++ b/AlgorithmLibrary/SplayTree.js @@ -75,19 +75,19 @@ SPLAYTREE.prototype.init = function(am, w, h) SPLAYTREE.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 4); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/StackArray.js b/AlgorithmLibrary/StackArray.js index 7d78679..18a0afc 100644 --- a/AlgorithmLibrary/StackArray.js +++ b/AlgorithmLibrary/StackArray.js @@ -70,18 +70,18 @@ StackArray.prototype.init = function(am, w, h) StackArray.prototype.addControls = function() { this.controls = []; - this.pushField = addControlToAlgorithmBar("Text", ""); + this.pushField = this.addControlToAlgorithmBar("Text", ""); this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); - this.pushButton = addControlToAlgorithmBar("Button", "Push"); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); this.pushButton.onclick = this.pushCallback.bind(this); this.controls.push(this.pushField); this.controls.push(this.pushButton); - this.popButton = addControlToAlgorithmBar("Button", "Pop"); + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); this.popButton.onclick = this.popCallback.bind(this); this.controls.push(this.popButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear Stack"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); diff --git a/AlgorithmLibrary/StackLL.js b/AlgorithmLibrary/StackLL.js index b9c9ea2..d0d788e 100644 --- a/AlgorithmLibrary/StackLL.js +++ b/AlgorithmLibrary/StackLL.js @@ -77,18 +77,18 @@ StackLL.prototype.init = function(am, w, h) StackLL.prototype.addControls = function() { this.controls = []; - this.pushField = addControlToAlgorithmBar("Text", ""); + this.pushField = this.addControlToAlgorithmBar("Text", ""); this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); - this.pushButton = addControlToAlgorithmBar("Button", "Push"); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); this.pushButton.onclick = this.pushCallback.bind(this); this.controls.push(this.pushField); this.controls.push(this.pushButton); - this.popButton = addControlToAlgorithmBar("Button", "Pop"); + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); this.popButton.onclick = this.popCallback.bind(this); this.controls.push(this.popButton); - this.clearButton = addControlToAlgorithmBar("Button", "Clear Stack"); + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); this.clearButton.onclick = this.clearCallback.bind(this); this.controls.push(this.clearButton); diff --git a/AlgorithmLibrary/TST.js b/AlgorithmLibrary/TST.js index 526b929..8aac03d 100644 --- a/AlgorithmLibrary/TST.js +++ b/AlgorithmLibrary/TST.js @@ -84,19 +84,19 @@ Ternary.prototype.init = function(am, w, h) Ternary.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeypress = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 12,false); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 12); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 12); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/TestAlgorithmOld.js b/AlgorithmLibrary/TestAlgorithmOld.js index 2c5e150..2efac8f 100644 --- a/AlgorithmLibrary/TestAlgorithmOld.js +++ b/AlgorithmLibrary/TestAlgorithmOld.js @@ -48,7 +48,7 @@ TestAlgorithm.prototype.init = function(am) TestAlgorithm.prototype.addControls = function() { - this.doWorkButton = addControlToAlgorithmBar("Button", "Do Work"); + this.doWorkButton = this.addControlToAlgorithmBar("Button", "Do Work"); this.doWorkButton.onclick = this.doWork.bind(this); } diff --git a/AlgorithmLibrary/TopoSortDFS.js b/AlgorithmLibrary/TopoSortDFS.js index 6619f64..56e6753 100644 --- a/AlgorithmLibrary/TopoSortDFS.js +++ b/AlgorithmLibrary/TopoSortDFS.js @@ -80,7 +80,7 @@ TopoSortDFS.superclass = Graph.prototype; TopoSortDFS.prototype.addControls = function() { - this.startButton = addControlToAlgorithmBar("Button", "Do Topological Sort"); + this.startButton = this.addControlToAlgorithmBar("Button", "Do Topological Sort"); this.startButton.onclick = this.startCallback.bind(this); TopoSortDFS.superclass.addControls.call(this, false); } diff --git a/AlgorithmLibrary/TopoSortIndegree.js b/AlgorithmLibrary/TopoSortIndegree.js index f27fa59..204d47c 100644 --- a/AlgorithmLibrary/TopoSortIndegree.js +++ b/AlgorithmLibrary/TopoSortIndegree.js @@ -64,7 +64,7 @@ TopoSortIndegree.superclass = Graph.prototype; TopoSortIndegree.prototype.addControls = function() { - this.startButton = addControlToAlgorithmBar("Button", "Do Topological Sort"); + this.startButton = this.addControlToAlgorithmBar("Button", "Do Topological Sort"); this.startButton.onclick = this.startCallback.bind(this); TopoSortIndegree.superclass.addControls.call(this, false); } diff --git a/AlgorithmLibrary/Trie.js b/AlgorithmLibrary/Trie.js index 3e6be39..7c84d6c 100644 --- a/AlgorithmLibrary/Trie.js +++ b/AlgorithmLibrary/Trie.js @@ -82,19 +82,19 @@ Trie.prototype.init = function(am, w, h) Trie.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeypress = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 12,false); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); - this.deleteField = addControlToAlgorithmBar("Text", ""); + this.deleteField = this.addControlToAlgorithmBar("Text", ""); this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 12); - this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); + this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 12); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); - this.printButton = addControlToAlgorithmBar("Button", "Print"); + this.printButton = this.addControlToAlgorithmBar("Button", "Print"); this.printButton.onclick = this.printCallback.bind(this); } diff --git a/AlgorithmLibrary/TrinarySearchTree.js b/AlgorithmLibrary/TrinarySearchTree.js index ecc92d8..fedb018 100644 --- a/AlgorithmLibrary/TrinarySearchTree.js +++ b/AlgorithmLibrary/TrinarySearchTree.js @@ -82,19 +82,19 @@ Ternary.prototype.init = function(am, w, h) Ternary.prototype.addControls = function() { - this.insertField = addControlToAlgorithmBar("Text", ""); + this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeypress = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 12,false); - this.insertButton = addControlToAlgorithmBar("Button", "Insert"); + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); -// this.deleteField = addControlToAlgorithmBar("Text", ""); +// this.deleteField = this.addControlToAlgorithmBar("Text", ""); // this.deleteField.onkeydown = this.returnSubmit(this.deleteField, this.deleteCallback.bind(this), 12); -// this.deleteButton = addControlToAlgorithmBar("Button", "Delete"); +// this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); // this.deleteButton.onclick = this.deleteCallback.bind(this); - this.findField = addControlToAlgorithmBar("Text", ""); + this.findField = this.addControlToAlgorithmBar("Text", ""); this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 12); - this.findButton = addControlToAlgorithmBar("Button", "Find"); + this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); -// this.printButton = addControlToAlgorithmBar("Button", "Print"); +// this.printButton = this.addControlToAlgorithmBar("Button", "Print"); // this.printButton.onclick = this.printCallback.bind(this); } diff --git a/source.html b/source.html index 9192925..7993de5 100644 --- a/source.html +++ b/source.html @@ -196,13 +196,13 @@

Using Algorithm function

// There are libraries that help with text entry, buttons, check boxes, radio groups // // To add a button myButton: - // this.mybytton = addControlToAlgorithmBar("Button", "MyButtonText"); + // this.mybytton = this.addControlToAlgorithmBar("Button", "MyButtonText"); // this.mybytton.onclick = this.myCallback.bind(this); // this.controls.push(this.mybutton); // where myCallback is a method on this function that implemnts the callback // // To add a text field myField: - // this.myField = addControlToAlgorithmBar("Text", ""); + // this.myField = this.addControlToAlgorithmBar("Text", ""); // this.myField.onkeydown = this.returnSubmit(this.myField, // this.anotherCallback.bind(this), // callback to make when return is pressed // maxFieldLen, // integer, max number of characters allowed in field @@ -210,12 +210,12 @@

Using Algorithm function

// this.controls.push(this.myField); // // To add a textbox: - // this.myCheckbox = addCheckboxToAlgorithmBar("Checkbox Label"); + // this.myCheckbox = this.addCheckboxToAlgorithmBar("Checkbox Label"); // this.myCheckbox.onclick = this.checkboxCallback.bind(this); // this.controls.push(myCheckbox); // // To add a radio button group: - // this.radioButtonList = addRadioButtonGroupToAlgorithmBar(["radio button label 1", + // this.radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["radio button label 1", // "radio button label 2", // "radio button label 3"], // "MyButtonGroupName"); @@ -888,18 +888,18 @@

Simple Stack Example

this.controls = []; - this.pushField = addControlToAlgorithmBar("Text", ""); + this.pushField = this.addControlToAlgorithmBar("Text", ""); this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), // callback to make when return is pressed 4, // integer, max number of characters allowed in field false); // boolean, true of only digits can be entered. this.controls.push(this.pushField); - this.pushButton = addControlToAlgorithmBar("Button", "Push"); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); this.pushButton.onclick = this.pushCallback.bind(this); this.controls.push(this.pushButton); - this.popButton = addControlToAlgorithmBar("Button", "Pop"); + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); this.popButton.onclick = this.popCallback.bind(this); this.controls.push(this.popButton); } From ba9249ccca4dfb4448f7cbd330a94effaa152706 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 17:05:17 +0200 Subject: [PATCH 05/25] proper subclassing Class.prototype should be an object whose prototype is Super.prototype, but _without_ calling Super. Super's constuctor should be called from Class' constructor on each object creation. --- AlgorithmLibrary/AVL.js | 5 +- AlgorithmLibrary/BFS.js | 12 +- AlgorithmLibrary/BPlusTree.js | 4 +- AlgorithmLibrary/BST.js | 5 +- AlgorithmLibrary/BTree.js | 4 +- AlgorithmLibrary/BinomialQueue.js | 4 +- AlgorithmLibrary/BucketSort.js | 4 +- AlgorithmLibrary/ChangingCoordinate2D.js | 3330 ++++++++++---------- AlgorithmLibrary/ChangingCoordinate3D.js | 3542 +++++++++++----------- AlgorithmLibrary/ClosedHash.js | 9 +- AlgorithmLibrary/ClosedHashBucket.js | 8 +- AlgorithmLibrary/ComparisonSort.js | 4 +- AlgorithmLibrary/ConnectedComponent.js | 8 +- AlgorithmLibrary/CountingSort.js | 4 +- AlgorithmLibrary/DFS.js | 12 +- AlgorithmLibrary/DPChange.js | 4 +- AlgorithmLibrary/DPFib.js | 4 +- AlgorithmLibrary/DPLCS.js | 1655 +++++----- AlgorithmLibrary/DPMatrixMultiply.js | 1525 +++++----- AlgorithmLibrary/DijkstraPrim.js | 13 +- AlgorithmLibrary/DisjointSet.js | 4 +- AlgorithmLibrary/EventTest.js | 6 +- AlgorithmLibrary/FibonacciHeap.js | 4 +- AlgorithmLibrary/Floyd.js | 9 +- AlgorithmLibrary/Graph.js | 12 +- AlgorithmLibrary/Hash.js | 13 +- AlgorithmLibrary/Heap.js | 5 +- AlgorithmLibrary/HeapSort.js | 5 +- AlgorithmLibrary/Huffman.js | 5 +- AlgorithmLibrary/Kruskal.js | 10 +- AlgorithmLibrary/LeftistHeap.js | 4 +- AlgorithmLibrary/MyAlgorithm.js | 5 +- AlgorithmLibrary/OpenHash.js | 8 +- AlgorithmLibrary/QueueArray.js | 4 +- AlgorithmLibrary/QueueLL.js | 4 +- AlgorithmLibrary/RadixSort.js | 4 +- AlgorithmLibrary/RadixTree.js | 5 +- AlgorithmLibrary/RecFact.js | 9 +- AlgorithmLibrary/RecQueens.js | 904 +++--- AlgorithmLibrary/RecReverse.js | 9 +- AlgorithmLibrary/Recursive.js | 13 +- AlgorithmLibrary/RedBlack.js | 5 +- AlgorithmLibrary/RotateScale2D.js | 1990 ++++++------ AlgorithmLibrary/RotateScale3D.js | 2308 +++++++------- AlgorithmLibrary/RotateTranslate2D.js | 1910 ++++++------ AlgorithmLibrary/Search.js | 4 +- AlgorithmLibrary/SimpleStack.js | 5 +- AlgorithmLibrary/SkewHeap.js | 4 +- AlgorithmLibrary/SplayTree.js | 5 +- AlgorithmLibrary/StackArray.js | 4 +- AlgorithmLibrary/StackLL.js | 4 +- AlgorithmLibrary/TST.js | 5 +- AlgorithmLibrary/TestAlgorithmOld.js | 5 +- AlgorithmLibrary/TopoSortDFS.js | 10 +- AlgorithmLibrary/TopoSortIndegree.js | 10 +- AlgorithmLibrary/Trie.js | 5 +- AlgorithmLibrary/TrinarySearchTree.js | 5 +- AnimationLibrary/AnimatedBTreeNode.js | 32 +- AnimationLibrary/AnimatedCircle.js | 10 +- AnimationLibrary/AnimatedLabel.js | 10 +- AnimationLibrary/AnimatedLinkedList.js | 36 +- AnimationLibrary/AnimatedRectangle.js | 9 +- AnimationLibrary/AnimationMain.js | 5 +- AnimationLibrary/CustomEvents.js | 52 +- AnimationLibrary/HighlightCircle.js | 10 +- AnimationLibrary/UndoFunctions.js | 51 +- BFS.html | 6 +- source.html | 10 +- 68 files changed, 8758 insertions(+), 8950 deletions(-) diff --git a/AlgorithmLibrary/AVL.js b/AlgorithmLibrary/AVL.js index 88c742f..486eb7e 100644 --- a/AlgorithmLibrary/AVL.js +++ b/AlgorithmLibrary/AVL.js @@ -29,10 +29,7 @@ function AVL(am, w, h) this.init(am, w, h); } - -AVL.prototype = new Algorithm(); -AVL.prototype.constructor = AVL; -AVL.superclass = Algorithm.prototype; +AVL.inheritFrom(Algorithm); // Various constants diff --git a/AlgorithmLibrary/BFS.js b/AlgorithmLibrary/BFS.js index d63bff1..3dd3456 100644 --- a/AlgorithmLibrary/BFS.js +++ b/AlgorithmLibrary/BFS.js @@ -41,19 +41,17 @@ var QUEUE_START_Y = 50; var QUEUE_SPACING = 30; -function BFS(am) +function BFS(am, w, h) { - this.init(am); - + // call superclass' constructor, which calls init + BFS.superclass.constructor.call(this, am, w, h); } +BFS.inheritFrom(Graph); -BFS.prototype = new Graph(); -BFS.prototype.constructor = BFS; -BFS.superclass = Graph.prototype; BFS.prototype.addControls = function() { - addLabelToAlgorithmBar("Start Vertex: "); + this.addLabelToAlgorithmBar("Start Vertex: "); this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); this.startField.size = 2; diff --git a/AlgorithmLibrary/BPlusTree.js b/AlgorithmLibrary/BPlusTree.js index 4771471..743df48 100644 --- a/AlgorithmLibrary/BPlusTree.js +++ b/AlgorithmLibrary/BPlusTree.js @@ -55,9 +55,7 @@ function BPlusTree(am, w, h) } -BPlusTree.prototype = new Algorithm(); -BPlusTree.prototype.varructor = BPlusTree; -BPlusTree.superclass = Algorithm.prototype; +BPlusTree.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/BST.js b/AlgorithmLibrary/BST.js index f6b5797..142b5c9 100644 --- a/AlgorithmLibrary/BST.js +++ b/AlgorithmLibrary/BST.js @@ -48,10 +48,7 @@ function BST(am, w, h) { this.init(am, w, h); } - -BST.prototype = new Algorithm(); -BST.prototype.constructor = BST; -BST.superclass = Algorithm.prototype; +BST.inheritFrom(Algorithm); BST.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/BTree.js b/AlgorithmLibrary/BTree.js index 9a0f210..af1e1ec 100644 --- a/AlgorithmLibrary/BTree.js +++ b/AlgorithmLibrary/BTree.js @@ -57,9 +57,7 @@ function BTree(am, w, h) } -BTree.prototype = new Algorithm(); -BTree.prototype.varructor = BTree; -BTree.superclass = Algorithm.prototype; +BTree.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/BinomialQueue.js b/AlgorithmLibrary/BinomialQueue.js index 6614c54..8cb7715 100644 --- a/AlgorithmLibrary/BinomialQueue.js +++ b/AlgorithmLibrary/BinomialQueue.js @@ -53,9 +53,7 @@ function BinomialQueue(am, w, h) } -BinomialQueue.prototype = new Algorithm(); -BinomialQueue.prototype.constructor = BinomialQueue; -BinomialQueue.superclass = Algorithm.prototype; +BinomialQueue.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/BucketSort.js b/AlgorithmLibrary/BucketSort.js index 162ba83..b46c482 100644 --- a/AlgorithmLibrary/BucketSort.js +++ b/AlgorithmLibrary/BucketSort.js @@ -56,9 +56,7 @@ var ARRAY_SIZE_SMALL = 30; var ARRAY_Y_POS = 350; -BucketSort.prototype = new Algorithm(); -BucketSort.prototype.constructor = BucketSort; -BucketSort.superclass = Algorithm.prototype; +BucketSort.inheritFrom(Algorithm); BucketSort.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/ChangingCoordinate2D.js b/AlgorithmLibrary/ChangingCoordinate2D.js index 1e8563d..6794e24 100644 --- a/AlgorithmLibrary/ChangingCoordinate2D.js +++ b/AlgorithmLibrary/ChangingCoordinate2D.js @@ -1,1666 +1,1664 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function ChangeCoordinate2D(am, w, h) -{ - this.init(am, w, h); -} - - -ChangeCoordinate2D.prototype = new Algorithm(); -ChangeCoordinate2D.prototype.constructor = ChangeCoordinate2D; -ChangeCoordinate2D.superclass = Algorithm.prototype; - -ChangeCoordinate2D.XAxisYPos = 300; -ChangeCoordinate2D.XAxisStart = 100; -ChangeCoordinate2D.XAxisEnd = 700; - -ChangeCoordinate2D.MATRIX_ELEM_WIDTH = 50; -ChangeCoordinate2D.MATRIX_ELEM_HEIGHT = 15; - - -ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING = 10; -ChangeCoordinate2D.EQUALS_SPACING = 30; - -ChangeCoordinate2D.ROBOT_MATRIX_START_X = 10 + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; -ChangeCoordinate2D.ROBOT_MATRIX_START_Y = 30; - -ChangeCoordinate2D.HAND_MATRIX_START_X = 10 +2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; -ChangeCoordinate2D.HAND_MATRIX_START_Y = 10 + 25 + 20 + 3*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; - - -ChangeCoordinate2D.ROBOT_POSITION_START_X = ChangeCoordinate2D.ROBOT_MATRIX_START_X + 4*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + 100; -ChangeCoordinate2D.HAND_POSITION_START_X = ChangeCoordinate2D.HAND_MATRIX_START_X + 4*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + 100; - - -ChangeCoordinate2D.ROBOT_POSITION_START_Y = ChangeCoordinate2D.ROBOT_MATRIX_START_Y; -ChangeCoordinate2D.HAND_POSITION_START_Y = ChangeCoordinate2D.HAND_MATRIX_START_Y; - - -ChangeCoordinate2D.YAxisXPos = 400; -ChangeCoordinate2D.YAxisStart = 100; -ChangeCoordinate2D.YAxisEnd = 500; - -ChangeCoordinate2D.ROBOT_POINTS = [[-15,100],[15,100],[15,80],[30,80],[30,-10],[15,-10], [15, -100], [0,-100],[0,-30],[0,-100], [-15, -100], - [-15, -10], [-30, -10], [-30, 80],[-15, 80]]; - - -ChangeCoordinate2D.HAND_POINTS = [[0,0],[-10,0],[-10,10], [-6, 10], [-6, 6], [6, 6], [6, 10], [10, 10], [10, 0]]; - -ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT = [0, 40]; - - - -ChangeCoordinate2D.ROBOT_MATRIX_VALUES = [[[Math.cos(Math.PI / 8), Math.sin(Math.PI / 8)],[-Math.sin(Math.PI / 8), Math.cos(Math.PI / 8)]], - [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4)],[-Math.sin(Math.PI / 4), Math.cos(Math.PI / 4)]], - [[Math.cos(0), Math.sin(0)],[-Math.sin(0), Math.cos(0)]], - [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4)],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4)]]]; - - -ChangeCoordinate2D.ROBOT_POSITION_VALUES = [[75, 50], [200,100],[100,100], [100, 200]]; - - -ChangeCoordinate2D.HAND_MATRIX_VALUES = [[[Math.cos(-Math.PI / 6), Math.sin(-Math.PI / 6)],[-Math.sin(-Math.PI / 6), Math.cos(-Math.PI / 6)]], - [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4)],[-Math.sin(Math.PI / 4), Math.cos(-Math.PI / 4)]], - [[Math.cos(0), Math.sin(0)],[-Math.sin(0), Math.cos(0)]], - [[Math.cos(Math.PI/2), Math.sin(Math.PI/2)],[-Math.sin(Math.PI/2), Math.cos(Math.PI/2)]]]; - - -ChangeCoordinate2D.HAND_POSITION_VALUES = [[80,30],[30,90],[100,100],[-50, -20]]; - - -//ChangeCoordinate2D.ROBOT_POINTS = [[-20, 40], [20,40],[ - - - -ChangeCoordinate2D.AXIS_CENTER = [[750,470],[750,150],[100, 550]]; - -ChangeCoordinate2D.AXIS_COLOR_0 = "#990000" -ChangeCoordinate2D.AXIS_COLOR_1 = "#009900" -ChangeCoordinate2D.AXIS_COLOR_2 = "#000099" - -ChangeCoordinate2D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; -ChangeCoordinate2D.LOCAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.LOCAL_VERTEX_FOREGORUND_COLOR; -ChangeCoordinate2D.LOCAL_EDGE_COLOR = "#000000"; - -ChangeCoordinate2D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; -ChangeCoordinate2D.GLOBAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.GLOBAL_VERTEX_FOREGORUND_COLOR; -ChangeCoordinate2D.GLOBAL_EDGE_COLOR = "#00FF00"; - - - -ChangeCoordinate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; -ChangeCoordinate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.VERTEX_FOREGORUND_COLOR; -ChangeCoordinate2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; - - -ChangeCoordinate2D.TRANSFORMED_POINT_COLORS = ["#990000", "#009900", "#000099"] - - -ChangeCoordinate2D.VECTOR_COLOR = "#FF0000"; - -ChangeCoordinate2D.VERTEX_WIDTH = 3; -ChangeCoordinate2D.VERTEX_HEIGHT = ChangeCoordinate2D.VERTEX_WIDTH; - -ChangeCoordinate2D.prototype.init = function(am, w, h) -{ - var sc = ChangeCoordinate2D.superclass.init.call(this, am, w, h); - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.addControls(); - this.currentShape = 0; - - this.commands = []; - this.nextIndex = 0; - - this.PositionIndex = 0; - - this.RobotPositionValues = ChangeCoordinate2D.ROBOT_POSITION_VALUES[this.PositionIndex]; - this.RobotMatrixValues = ChangeCoordinate2D.ROBOT_MATRIX_VALUES[this.PositionIndex]; - this.HandPositionValues = ChangeCoordinate2D.HAND_POSITION_VALUES[this.PositionIndex]; - this.HandMatrixValues = ChangeCoordinate2D.HAND_MATRIX_VALUES[this.PositionIndex]; - - this.setupAxis(); - - this.robotLabel1ID = this.nextIndex++; - this.handLabel1ID = this.nextIndex++; - this.robotLabel2ID = this.nextIndex++; - this.handLabel2ID = this.nextIndex++; - - this.cmd("CreateLabel", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)", ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.robotLabel1ID, "#0000FF"); - - this.cmd("CreateLabel", this.robotLabel2ID, "Robot Space to World Space\n(Position)", ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.robotLabel2ID, "#0000FF"); - - - - this.RobotMatrix = this.createMatrix(this.RobotMatrixValues, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y); - this.resetMatrixLabels(this.RobotMatrix); - this.HandMatrix = this.createMatrix(this.HandMatrixValues, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y); - this.resetMatrixLabels(this.HandMatrix); - - this.cmd("CreateLabel", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)", ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.handLabel1ID, "#0000FF"); - - this.cmd("CreateLabel", this.handLabel2ID, "Hand Space to Robot Space\n(Position)", ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.handLabel2ID, "#0000FF"); - - - - this.RobotPosition = this.createMatrix([this.RobotPositionValues], ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y); - this.resetMatrixLabels(this.RobotMatrix); - this.HandPosition = this.createMatrix([this.HandPositionValues], ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); - this.resetMatrixLabels(this.HandMatrix); - - - var i; - this.RobotPointWorldIDs = new Array(ChangeCoordinate2D.ROBOT_POINTS.length); - this.RobotPointRobotIDs = new Array(ChangeCoordinate2D.ROBOT_POINTS.length); - this.HandPointWorldIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); - this.HandPointRobotIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); - this.HandPointHandIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); - this.RobotHandAttachRobotID = this.nextIndex++; - this.RobotHandAttachWorldID = this.nextIndex++; - for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) - { - this.RobotPointWorldIDs[i] = this.nextIndex++; - this.RobotPointRobotIDs[i] = this.nextIndex++; - } - for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) - { - this.HandPointWorldIDs[i] = this.nextIndex++; - this.HandPointRobotIDs[i] = this.nextIndex++; - this.HandPointHandIDs[i] = this.nextIndex++; - } - - this.savedNextIndex = this.nextIndex; - this.setupObjects(); - this.setupObjectGraphic(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); - this.animationManager.setAllLayers([0, 1]); - this.lastLocalToGlobal = true; - this.oldIDs = []; - - -} - -ChangeCoordinate2D.prototype.addAxis = function(origin, x1, x2, y1, y2, color) -{ - var idArray = []; - var originID = this.nextIndex++; - idArray.push(originID); - this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); - this.cmd("SetAlpha", originID, 0); - - var axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, x1[0], x1[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, x2[0], x2[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, y1[0], y1[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, y2[0], y2[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - - var labelID = this.nextIndex++; - this.cmd("CreateLabel", labelID, "+y", y2[0] - 10, y2[1] + 10); - this.cmd("SetForegroundColor", labelID, color); - idArray.push(labelID); - - - labelID = this.nextIndex++; - this.cmd("CreateLabel", labelID, "+x", x2[0] - 10, x2[1] + 10); - this.cmd("SetForegroundColor", labelID, color); - idArray.push(labelID); - return idArray; -} - - -ChangeCoordinate2D.prototype.transformPoint = function(point, matrix, position) -{ - return this.add(this.multiply([point], matrix), [position])[0]; -} - - -ChangeCoordinate2D.prototype.setupExtraAxes = function() -{ - var robotOrigin = this.RobotPositionValues; - var x1 = this.transformPoint([-150, 0], this.RobotMatrixValues, this.RobotPositionValues); - var x2 = this.transformPoint([150, 0], this.RobotMatrixValues, this.RobotPositionValues); - var y1 = this.transformPoint([0, -150], this.RobotMatrixValues, this.RobotPositionValues); - var y2 = this.transformPoint([0, 150], this.RobotMatrixValues, this.RobotPositionValues); - - this.otherAxes = []; - - var tmpAxis = this.addAxis(this.worldToScreenSpace(robotOrigin, 2), - this.worldToScreenSpace(x1, 2), - this.worldToScreenSpace(x2, 2), - this.worldToScreenSpace(y1, 2), - this.worldToScreenSpace(y2, 2), - ChangeCoordinate2D.AXIS_COLOR_1); - - this.otherAxes.push(tmpAxis); - - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - this.setAxisAlpha(tmpAxis, 0.5); - - - var handOrigin = this.HandPositionValues; - x1 = this.transformPoint([-150, 0], this.HandMatrixValues, this.HandPositionValues); - x2 = this.transformPoint([150, 0], this.HandMatrixValues, this.HandPositionValues); - y1 = this.transformPoint([0, -150], this.HandMatrixValues, this.HandPositionValues); - y2 = this.transformPoint([0, 150], this.HandMatrixValues, this.HandPositionValues); - - - tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 1), - this.worldToScreenSpace(x1, 1), - this.worldToScreenSpace(x2, 1), - this.worldToScreenSpace(y1, 1), - this.worldToScreenSpace(y2, 1), - ChangeCoordinate2D.AXIS_COLOR_0); - - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - this.setAxisAlpha(tmpAxis, 0.5); - - - this.otherAxes.push(tmpAxis); - - - handOrigin = this.transformPoint(handOrigin, this.RobotMatrixValues, this.RobotPositionValues); - x1 = this.transformPoint(x1, this.RobotMatrixValues, this.RobotPositionValues); - x2 = this.transformPoint(x2, this.RobotMatrixValues, this.RobotPositionValues); - y1 = this.transformPoint(y1, this.RobotMatrixValues, this.RobotPositionValues); - y2 = this.transformPoint(y2, this.RobotMatrixValues, this.RobotPositionValues); - - - tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 2), - this.worldToScreenSpace(x1, 2), - this.worldToScreenSpace(x2, 2), - this.worldToScreenSpace(y1, 2), - this.worldToScreenSpace(y2, 2), - ChangeCoordinate2D.AXIS_COLOR_0); - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - - this.setAxisAlpha(tmpAxis, 0.5); - - this.otherAxes.push(tmpAxis); - -} - - -ChangeCoordinate2D.prototype.setupAxis = function() -{ - - this.axisHand = this.addAxis(this.worldToScreenSpace([0,0], 0), - this.worldToScreenSpace([-150, 0], 0), - this.worldToScreenSpace([150,0], 0), - this.worldToScreenSpace([0, -150], 0), - this.worldToScreenSpace([0, 150], 0), - ChangeCoordinate2D.AXIS_COLOR_0); - this.setAxisAlpha(this.axisHand, 0.5); - - this.axisRobot = this.addAxis(this.worldToScreenSpace([0,0], 1), - this.worldToScreenSpace([-150, 0], 1), - this.worldToScreenSpace([150,0], 1), - this.worldToScreenSpace([0, -150], 1), - this.worldToScreenSpace([0, 150], 1), - ChangeCoordinate2D.AXIS_COLOR_1); - this.setAxisAlpha(this.axisRobot, 0.5); - - this.axisWorld = this.addAxis(this.worldToScreenSpace([0,0], 2), - this.worldToScreenSpace([-50, 0], 2), - this.worldToScreenSpace([400,0], 2), - this.worldToScreenSpace([0, -50], 2), - this.worldToScreenSpace([0, 400], 2), - ChangeCoordinate2D.AXIS_COLOR_2); - this.setAxisAlpha(this.axisWorld, 0.5); - - this.setupExtraAxes(); - - - - - -} - - -ChangeCoordinate2D.prototype.setAxisAlpha = function(axisList, newAlpha) -{ - for (var i = 0; i < axisList.length; i++) - { - this.cmd("SetAlpha", axisList[i], newAlpha); - if (i > 0) - { - this.cmd("SetEdgeAlpha", axisList[0], axisList[i], newAlpha); - } - } - -} - -ChangeCoordinate2D.prototype.setupObjects = function() -{ - - var i; - for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) - { - - - var point = this.worldToScreenSpace(ChangeCoordinate2D.ROBOT_POINTS[i], 1); - this.cmd("CreateRectangle", this.RobotPointRobotIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.RobotPointRobotIDs[i-1], this.RobotPointRobotIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(ChangeCoordinate2D.ROBOT_POINTS[i], this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point, 2); - - this.cmd("CreateRectangle", this.RobotPointWorldIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.RobotPointWorldIDs[i-1], this.RobotPointWorldIDs[i], "#000000", 0, 0); - } - } - this.cmd("Connect", this.RobotPointRobotIDs[this.RobotPointRobotIDs.length - 1], this.RobotPointRobotIDs[0], "#000000", 0, 0); - this.cmd("Connect", this.RobotPointWorldIDs[this.RobotPointWorldIDs.length - 1], this.RobotPointWorldIDs[0], "#000000", 0, 0); - - - for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) - { - - - var point = this.worldToScreenSpace(ChangeCoordinate2D.HAND_POINTS[i], 0); - this.cmd("CreateRectangle", this.HandPointHandIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointHandIDs[i-1], this.HandPointHandIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(ChangeCoordinate2D.HAND_POINTS[i], this.HandMatrixValues, this.HandPositionValues); - var point2 = this.worldToScreenSpace(point, 1); - - this.cmd("CreateRectangle", this.HandPointRobotIDs[i], "", 0, 0, point2[0], point2[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointRobotIDs[i-1], this.HandPointRobotIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(point, this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point,2); - - this.cmd("CreateRectangle", this.HandPointWorldIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointWorldIDs[i-1], this.HandPointWorldIDs[i], "#000000", 0, 0); - } - - - } - this.cmd("Connect", this.HandPointHandIDs[this.HandPointHandIDs.length - 1], this.HandPointHandIDs[0], "#000000", 0, 0); - this.cmd("Connect", this.HandPointRobotIDs[this.HandPointRobotIDs.length - 1], this.HandPointRobotIDs[0], "#000000", 0, 0); - this.cmd("Connect", this.HandPointWorldIDs[this.HandPointWorldIDs.length - 1], this.HandPointWorldIDs[0], "#000000", 0, 0); - - - point = this.worldToScreenSpace(ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT, 1); - this.cmd("CreateRectangle", this.RobotHandAttachRobotID, "", 0, 0, point[0], point[1]); - this.cmd("Connect", this.RobotHandAttachRobotID, this.HandPointRobotIDs[0], "#000000", 0, 0); - - point = this.transformPoint(ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT, this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point, 2); - this.cmd("CreateRectangle", this.RobotHandAttachWorldID, "", 0, 0, point[0], point[1]); - this.cmd("Connect", this.RobotHandAttachWorldID, this.HandPointWorldIDs[0], "#000000", 0, 0); -} - - -ChangeCoordinate2D.prototype.worldToScreenSpace = function(point, space) -{ - var transformedPoint = new Array(2); - - return [point[0] + ChangeCoordinate2D.AXIS_CENTER[space][0], - -point[1] + ChangeCoordinate2D.AXIS_CENTER[space][1]]; -} - - - - -ChangeCoordinate2D.prototype.removeOldIDs = function() -{ - var i; - for (i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs = []; -} - - - -ChangeCoordinate2D.prototype.setupObjectGraphic = function() -{ - var i; - - - - -} - -ChangeCoordinate2D.prototype.addControls = function() -{ - this.controls = []; - - addLabelToAlgorithmBar("x"); - - this.xField = this.addControlToAlgorithmBar("Text", ""); - this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); - this.controls.push(this.xField); - - addLabelToAlgorithmBar("y"); - - this.yField = this.addControlToAlgorithmBar("Text", ""); - this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); - this.controls.push(this.yField); - - var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); - transformButton.onclick = this.transformPointCallback.bind(this); - this.controls.push(transformButton); - - - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", - "World Space -> Hand Space", - ], - "Transform Type"); - this.handToWorldButton = radioButtonList[0]; - this.handToWorldButton.onclick = this.transformTypeChangedCallback.bind(this, false); - this.controls.push(this.handToWorldButton); - - - this.worldToHandButton = radioButtonList[1]; - this.worldToHandButton.onclick = this.transformTypeChangedCallback.bind(this, true); - this.controls.push(this.worldToHandButton); - - this.worldToHandButton.checked = this.lastLocalToGlobal; - this.handToWorldButton.checked = !this.lastLocalToGlobal; - - - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", - "Column Major", - ], - "RankType"); - this.rowMajorButton = radioButtonList[0]; - this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); - this.controls.push(this.rowMajorButton); - - this.colMajorButton = radioButtonList[1]; - this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); - this.controls.push(this.colMajorButton); - - this.rowMajorButton.checked = this.rowMajor; - this.colMajorButton.checked = !this.rowMajor; - - - this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); - this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); - this.showAxisBox.checked = true; - - //this.controls.push(this.showAxisBox); - - - - var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); - moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); - - this.controls.push(moveObjectsButton); - -} - - - -ChangeCoordinate2D.prototype.showAllAxesCallback = function() -{ - if (this.showAxisBox.checked) - { - this.animationManager.setAllLayers([0,1]); - } - else - { - this.animationManager.setAllLayers([0]); - } - - -} - - -ChangeCoordinate2D.prototype.reset = function() -{ - this.rowMajor = true; - this.rowMajorButton.checked = this.rowMajor; - this.nextIndex = this.savedNextIndex; -} - - -ChangeCoordinate2D.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -ChangeCoordinate2D.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -ChangeCoordinate2D.prototype.transformTypeChangedCallback = function(globalToLocal) -{ - if (this.lastLocalToGlobal == globalToLocal) - { - this.implementAction(this.changeTransformType.bind(this,globalToLocal)); - } -} - - - - -ChangeCoordinate2D.prototype.changeRowColMajorCallback = function(rowMajor) -{ - if (this.rowMajor != rowMajor) - { - this.implementAction(this.changeRowCol.bind(this), rowMajor); - } -} - -ChangeCoordinate2D.prototype.transposeVisual = function(matrix) -{ - if (matrix.data.length == matrix.data[0].length) - { - var matrixSize = matrix.data.length; - var i, j, tmp, moveLabel1, moveLabel2; - var moveLabels = []; - for (i = 1; i < matrixSize; i++) - { - for (j = 0; j <= i; j++) - { - this.cmd("SetText", matrix.dataID[i][j], ""); - this.cmd("SetText", matrix.dataID[j][i], ""); - moveLabel1 = this.nextIndex++; - moveLabel2 = this.nextIndex++; - moveLabels.push(moveLabel1); - moveLabels.push(moveLabel2); - this.cmd("CreateLabel", moveLabel1, - matrix.data[i][j], matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - this.cmd("CreateLabel", moveLabel2, - matrix.data[j][i], matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - this.cmd("Move", moveLabel1, matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - this.cmd("Move", moveLabel2, matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + j * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - tmp = matrix.data[i][j]; - matrix.data[i][j] = matrix.data[j][i]; - matrix.data[j][i] = tmp; - } - } - this.cmd("Step"); - for (i = 0; i < moveLabels.length; i++) - { - this.cmd("Delete", moveLabels[i]); - } - this.resetMatrixLabels(matrix); - return matrix; - } - else - { - var savedData = matrix.data; - var newData = new Array(savedData[0].length); - var i,j; - for (i = 0; i < savedData[0].length; i++) - { - newData[i] = []; - } - for (i = 0; i < savedData.length; i++) - { - for (j = 0; j < savedData[0].length; j++) - { - newData[j][i] = savedData[i][j]; - } - - } - var newMatrix = this.createMatrix(newData, matrix.x, matrix.y); - this.deleteMatrix(matrix); - return newMatrix; - } -} - -ChangeCoordinate2D.prototype.changeRowCol = function(rowMajor) -{ - this.commands = new Array(); - this.rowMajor= rowMajor; - if (this.rowMajorButton.checked != this.rowMajor) - { - this.rowMajorButton.checked = this.rowMajor; - } - if (this.colMajorButton.checked == this.rowMajor) - { - this.colMajorButton.checked = !this.rowMajor; - } - this.removeOldIDs(); - this.RobotMatrix = this.transposeVisual(this.RobotMatrix); - this.RobotPosition = this.transposeVisual(this.RobotPosition); - this.HandMatrix = this.transposeVisual(this.HandMatrix); - this.HandPosition = this.transposeVisual(this.HandPosition); - - - return this.commands; -} - - -ChangeCoordinate2D.prototype.fixNumber = function(value, defaultVal) -{ - if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) - { - value = defaultVal; - } - else - { - value = String(parseFloat(value)); - } - return value -} - -ChangeCoordinate2D.prototype.transformPointCallback = function() -{ - - - this.xField.value = this.fixNumber(this.xField.value, "0"); - this.yField.value = this.fixNumber(this.yField.value, "0"); - this.implementAction(this.doPointTransform.bind(this), this.xField.value + ";" + this.yField.value); - -} - - -ChangeCoordinate2D.prototype.doPointTransform = function(params) -{ - if (this.lastLocalToGlobal) - { - return this.localToGlobal(params); - } - else - { - return this.globalToLocal(params); - } -} - - - - - -ChangeCoordinate2D.prototype.rotatePoint = function(point, matrix, xPos, yPos, fromSpace, toSpace) -{ - var logicalPoint; - var descriptLabel = this.nextIndex++; - // this.oldIDs.push(descriptLabel); - this.cmd("CreateLabel", descriptLabel, "", xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, - yPos + 2*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + 3, 0); - - var inertialPositionMatrix; - - if (this.rowMajor) - { - inertialPositionMatrix = this.createMatrix([["", ""]], xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, - yPos); - } - else - { - inertialPositionMatrix = this.createMatrix([[""], [""]], - xPos + 3 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, - yPos); - - } - var equalLabel1 = this.nextIndex++; - this.oldIDs.push(equalLabel1); - if (this.rowMajor) - { - opX = xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; - } - else - { - opX = xPos + 3 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2 + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; - opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; - - - } - - this.cmd("CreateLabel", equalLabel1, "=", opX , opY); - if (this.rowMajor) - { - this.multiplyMatrix(point, matrix, inertialPositionMatrix, descriptLabel); - - } - else - { - this.multiplyMatrix(matrix, point, inertialPositionMatrix, descriptLabel); - - } - this.addMatrixIDsToList(inertialPositionMatrix, this.oldIDs); - this.cmd("Delete", descriptLabel); - var inertialPositionID = this.nextIndex++; - if (this.rowMajor) - { - logicalPoint = inertialPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [inertialPositionMatrix.data[0][0], inertialPositionMatrix.data[1][0]]; - } - screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); - - - this.cmd("CreateCircle", inertialPositionID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", inertialPositionID, ChangeCoordinate2D.VERTEX_WIDTH); - - var originID = this.nextIndex++; - this.oldIDs.push(originID); - var origin = this.worldToScreenSpace([0,0], fromSpace); - - - this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); - - this.cmd("Connect", originID, inertialPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - - - return [inertialPositionMatrix, inertialPositionID, originID]; -} - -ChangeCoordinate2D.prototype.translatePoint = function(point, transVector, xPos, yPos, fromSpace, toSpace, pointID) -{ - var logicalPoint = new Array(2); - var robotPositionMatrix; - if (this.rowMajor) - { - logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; - logicalPoint[1] = point.data[0][1] + transVector.data[0][1]; - robotPositionMatrix = this.createMatrix([["", ""]], xPos + 2*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, - yPos); - } - else - { - logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; - logicalPoint[1] = point.data[1][0] + transVector.data[1][0]; - robotPositionMatrix = this.createMatrix([[""],[""]], xPos + ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, - yPos); - - } - - var addLabel1 = this.nextIndex++; - var equalLabel3 = this.nextIndex++; - this.oldIDs.push(addLabel1); - this.oldIDs.push(equalLabel3); - var op2X, op2Y; - if (this.rowMajor) - { - opX = xPos + 2*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; - op2X = xPos - ChangeCoordinate2D.EQUALS_SPACING / 2; - op2Y = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; - - } - else - { - opX = xPos + ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; - op2X = xPos - ChangeCoordinate2D.EQUALS_SPACING / 2; - op2Y = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; - - - } - this.cmd("CreateLabel", equalLabel3, "=",opX , opY); - this.cmd("CreateLabel", addLabel1, "+",op2X , op2Y); - - - - - this.addMatrix(point, transVector, robotPositionMatrix); - this.addMatrixIDsToList(robotPositionMatrix, this.oldIDs); - - var screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); - - var robotPositionID = this.nextIndex++; - - this.cmd("CreateCircle", robotPositionID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", robotPositionID, ChangeCoordinate2D.VERTEX_WIDTH); - - - this.cmd("Connect",pointID, robotPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - this.cmd("Step") - - - - var originID = this.nextIndex++; - this.oldIDs.push(originID); - var origin = this.worldToScreenSpace([0,0], fromSpace); - - this.cmd("CreateCircle", originID, "", origin[0], origin[1]); - this.cmd("SetWidth", originID, 0); - this.cmd("SetAlpha", originID, 0); - - this.cmd("Connect",originID, robotPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - - return [robotPositionMatrix, robotPositionID, originID]; - - -} - - -ChangeCoordinate2D.prototype.addMultiply = function(position, transVector, rotMatrix, transX, transY, rotX, rotY, initialPointID, fromSpace, toSpace) -{ - - var posMatrixAndPointID = this.translatePoint(position, transVector, transX, transY, fromSpace, toSpace, initialPointID); - var newPosition = posMatrixAndPointID[0]; - var pointID = posMatrixAndPointID[1]; - var originID = posMatrixAndPointID[2]; - - this.cmd("Step"); - - this.cmd("Disconnect", initialPointID, pointID); - - if (this.rowMajor) - { - this.moveMatrix(newPosition, rotX - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING,transY) - } - else - { - this.moveMatrix(newPosition, rotX + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, transY) - } - - - var posMatrixAndPointID = this.rotatePoint(newPosition, rotMatrix, rotX, rotY, fromSpace, toSpace); - this.cmd("Delete", pointID); - this.cmd("Step"); - - var robotPositionMatrix = posMatrixAndPointID[0]; - var robotPositionID = posMatrixAndPointID[1]; - var movingOriginID = posMatrixAndPointID[2]; - - var origin = this.worldToScreenSpace([0,0], toSpace); - this.cmd("Move", movingOriginID, origin[0], origin[1]); - - - var logicalPoint; - if (this.rowMajor) - { - logicalPoint = robotPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0]]; - } - - - - - var screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); - this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); - - this.cmd("Step"); - - - this.oldIDs.push(robotPositionID); - - - return [robotPositionMatrix, robotPositionID ]; -} - - -ChangeCoordinate2D.prototype.multiplyAdd = function(position, rotMatrix, transVector, rotX, rotY, transX, transY, fromSpace, toSpace) -{ - var posMatrixAndPointID = this.rotatePoint(position, rotMatrix, rotX, rotY, fromSpace, toSpace); - var inertialPositionMatrix = posMatrixAndPointID[0]; - var inertialPositionID = posMatrixAndPointID[1]; - - - this.cmd("Step"); - - if (this.rowMajor) - { - this.moveMatrix(inertialPositionMatrix, transX - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.EQUALS_SPACING,transY) - } - else - { - this.moveMatrix(inertialPositionMatrix, transX - ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.EQUALS_SPACING, transY) - } - - - posMatrixAndPointID = this.translatePoint(inertialPositionMatrix, transVector, transX, transY, fromSpace, toSpace, inertialPositionID); - var robotPositionMatrix = posMatrixAndPointID[0]; - var robotPositionID = posMatrixAndPointID[1]; - var movingOriginID = posMatrixAndPointID[2]; - - this.oldIDs.push(robotPositionID); - - var logicalPoint; - if (this.rowMajor) - { - logicalPoint = robotPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0]]; - } - - - this.cmd("Step"); - - this.cmd("Delete", inertialPositionID); - origin = this.worldToScreenSpace([0,0], toSpace); - this.cmd("Move", movingOriginID, origin[0], origin[1]); - screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); - this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); - - this.cmd("Step"); - return robotPositionMatrix; - -} - -ChangeCoordinate2D.prototype.localToGlobal = function (params) -{ - this.commands = []; - this.removeOldIDs(); - - - var paramList = params.split(";"); - var x = parseFloat(paramList[0]); - var y = parseFloat(paramList[1]); - - var opX, opY; - - - var screenPoint = this.worldToScreenSpace([x,y], 0); - var logicalPoint; - - var pointInHandSpaceID = this.nextIndex++; - this.oldIDs.push(pointInHandSpaceID); - - this.cmd("CreateCircle", pointInHandSpaceID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", pointInHandSpaceID, ChangeCoordinate2D.VERTEX_WIDTH); - - this.cmd("Connect", this.axisHand[0], pointInHandSpaceID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[0], 0, 1, ""); - - var initialPointMatrix; - if (this.rowMajor) - { - initialPointMatrix = this.createMatrix([[x, y]], ChangeCoordinate2D.HAND_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate2D.HAND_MATRIX_START_Y); - } - else - { - initialPointMatrix = this.createMatrix([[x], [y]], ChangeCoordinate2D.HAND_MATRIX_START_X + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate2D.HAND_MATRIX_START_Y); - - } - this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); - this.cmd("Step"); - - var robotPositionMatrix = this.multiplyAdd(initialPointMatrix, this.HandMatrix, this.HandPosition, - ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y, - ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y, - 0, 1); - - - - - if (this.rowMajor) - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate2D.ROBOT_MATRIX_START_Y); - } - else - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X + 2* ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate2D.ROBOT_MATRIX_START_Y); - - } - - - this.multiplyAdd(robotPositionMatrix, this.RobotMatrix, this.RobotPosition, - ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y, - ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y, - 1, 2); - - - - - - return this.commands; -} - -ChangeCoordinate2D.prototype.changeTransformType = function(globalToLocal) -{ - this.commands = []; - this.lastLocalToGlobal = !globalToLocal; - this.removeOldIDs(); - if (globalToLocal) - { - this.cmd("SetText", this.robotLabel1ID, "World Space to Robot Space\n(Orientation)"); - - } - else - { - this.cmd("SetText", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)"); - } - this.cmd("Step"); - this.RobotMatrix = this.transposeVisual(this.RobotMatrix) - - if (globalToLocal) - { - this.cmd("SetText", this.robotLabel2ID, "World Space to Robot Space\n(Position)"); - - } - else - { - this.cmd("SetText", this.robotLabel2ID, "Robot Space to World Space\n(Position)"); - } - this.cmd("Step"); - this.negateMatrixVisual(this.RobotPosition); - this.cmd("Step"); - - if (globalToLocal) - { - this.cmd("SetText", this.handLabel1ID, "Robot Space to Hand Space\n(Orientation)"); - - } - else - { - this.cmd("SetText", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)"); - } - - this.cmd("Step"); - this.HandMatrix = this.transposeVisual(this.HandMatrix) - - if (globalToLocal) - { - this.cmd("SetText", this.handLabel2ID, "Robot Space to Hand Space\n(Position)"); - - } - else - { - this.cmd("SetText", this.handLabel2ID, "Hand Space to Robot Space\n(Position)"); - } - this.cmd("Step"); - this.negateMatrixVisual(this.HandPosition); - this.cmd("Step"); - - if (globalToLocal) - { - this.cmd("Move", this.robotLabel1ID, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y - 25); - this.moveMatrix(this.RobotMatrix, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y) - - this.cmd("Move", this.robotLabel2ID, ChangeCoordinate2D.ROBOT_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25); - this.moveMatrix(this.RobotPosition, ChangeCoordinate2D.ROBOT_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y) - - this.cmd("Move", this.handLabel1ID, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y - 25); - this.moveMatrix(this.HandMatrix, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); - - - this.cmd("Move", this.handLabel2ID, ChangeCoordinate2D.HAND_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25); - this.moveMatrix(this.HandPosition, ChangeCoordinate2D.HAND_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y); - } - else - { - this.cmd("Move", this.robotLabel1ID, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25); - this.moveMatrix(this.RobotMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y) - - this.cmd("Move", this.robotLabel2ID, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y - 25); - this.moveMatrix(this.RobotPosition, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y) - - this.cmd("Move", this.handLabel1ID, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25); - this.moveMatrix(this.HandMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y); - - this.cmd("Move", this.handLabel2ID, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y - 25); - this.moveMatrix(this.HandPosition, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); - - } - return this.commands; -} - - -ChangeCoordinate2D.prototype.negateMatrixVisual = function(matrix) -{ - var i,j - for (i = 0; i < matrix.data.length; i++) - { - for (j = 0; j < matrix.data[i].length; j++) - { - matrix.data[i][j] = -matrix.data[i][j] - } - } - this.resetMatrixLabels(matrix); -} - - -ChangeCoordinate2D.prototype.globalToLocal = function(params) -{ - this.commands = []; - this.removeOldIDs(); - - - var paramList = params.split(";"); - var x = parseFloat(paramList[0]); - var y = parseFloat(paramList[1]); - - var opX, opY; - - - var screenPoint = this.worldToScreenSpace([x,y], 2); - var logicalPoint; - - var pointInWorldSpaceID = this.nextIndex++; - this.oldIDs.push(pointInWorldSpaceID); - this.cmd("CreateCircle", pointInWorldSpaceID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", pointInWorldSpaceID, ChangeCoordinate2D.VERTEX_WIDTH); - this.cmd("Connect", this.axisWorld[0], pointInWorldSpaceID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[2], 0, 1, ""); - - var initialPointMatrix; - if (this.rowMajor) - { - initialPointMatrix = this.createMatrix([[x, y]], ChangeCoordinate2D.ROBOT_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - ChangeCoordinate2D.ROBOT_MATRIX_START_Y); - } - else - { - initialPointMatrix = this.createMatrix([[x], [y]], ChangeCoordinate2D.ROBOT_MATRIX_START_X - ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - ChangeCoordinate2D.ROBOT_MATRIX_START_Y); - - } - this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); - this.cmd("Step"); - - var positionAndID = this.addMultiply(initialPointMatrix, this.RobotPosition, this.RobotMatrix, - ChangeCoordinate2D.ROBOT_MATRIX_START_X + ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y, - ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y, - pointInWorldSpaceID, - 2, 1); - - var robotPositionMatrix = positionAndID[0]; - var newPositionID = positionAndID[1]; - - if (this.rowMajor) - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - ChangeCoordinate2D.HAND_MATRIX_START_Y); - } - else - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X - ChangeCoordinate2D.MATRIX_ELEM_WIDTH, - ChangeCoordinate2D.HAND_MATRIX_START_Y); - - } - - - this.addMultiply(robotPositionMatrix, this.HandPosition, this.HandMatrix, - ChangeCoordinate2D.HAND_MATRIX_START_X + ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y, - ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y, - newPositionID, - 1, 0); - - - - return this.commands; -} - -ChangeCoordinate2D.prototype.moveObjectsCallback = function() -{ - this.implementAction(this.moveObjects.bind(this), 0); -} - -ChangeCoordinate2D.prototype.moveObjects = function() -{ - this.commands = []; - this.removeOldIDs(); - var i, j; - - for (i = 0; i < this.otherAxes.length; i++) - { - for (j = 0; j < this.otherAxes[i].length; j++) - { - this.cmd("Delete", this.otherAxes[i][j]); - } - } - - - var i; - for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) - { - - this.cmd("Delete", this.RobotPointRobotIDs[i]); - this.cmd("Delete", this.RobotPointWorldIDs[i]); - } - for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) - { - this.cmd("Delete", this.HandPointHandIDs[i]); - this.cmd("Delete", this.HandPointRobotIDs[i]); - this.cmd("Delete", this.HandPointWorldIDs[i]); - } - this.cmd("Delete", this.RobotHandAttachRobotID); - this.cmd("Delete", this.RobotHandAttachWorldID); - this.PositionIndex+= 1; - if (this.PositionIndex >= ChangeCoordinate2D.ROBOT_POSITION_VALUES.length) - { - this.PositionIndex = 0; - } - - this.RobotPositionValues = ChangeCoordinate2D.ROBOT_POSITION_VALUES[this.PositionIndex]; - this.RobotMatrixValues = ChangeCoordinate2D.ROBOT_MATRIX_VALUES[this.PositionIndex]; - this.HandPositionValues = ChangeCoordinate2D.HAND_POSITION_VALUES[this.PositionIndex]; - this.HandMatrixValues = ChangeCoordinate2D.HAND_MATRIX_VALUES[this.PositionIndex]; - - this.setupExtraAxes(); - this.setupObjects(); - - - this.RobotPosition.data = [this.RobotPositionValues]; - this.RobotMatrix.data = this.RobotMatrixValues; - this.HandPosition.data = [this.HandPositionValues]; - this.HandMatrix.data =this.HandMatrixValues; - if (!this.rowMajor) - { - this.RobotPosition.transpose(); - this.RobotMatrix.transpose(); - this.HandPosition.transpose(); - this.HandMatrix.transpose(); - } - this.resetMatrixLabels(this.RobotMatrix); - this.resetMatrixLabels(this.RobotPosition); - this.resetMatrixLabels(this.HandMatrix); - this.resetMatrixLabels(this.HandPosition); - - - return this.commands; -} - - -function toRadians(degrees) -{ - return (degrees * 2 * Math.PI) / 360.0; -} - - -ChangeCoordinate2D.prototype.addMatrix = function(mat1, mat2, mat3) -{ - var i; - var j; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat1.data[i].length; j++) - { - explainText = ""; - var value = 0; - this.cmd("SetHighlight", mat1.dataID[i][j], 1); - this.cmd("SetHighlight", mat2.dataID[i][j], 1); - this.cmd("Step"); - mat3.data[i][j] = this.standardize(mat1.data[i][j] + mat2.data[i][j]); - this.cmd("SetHighlight", mat1.dataID[i][j], 0); - this.cmd("SetHighlight", mat2.dataID[i][j], 0); - this.cmd("SetText", mat3.dataID[i][j], mat3.data[i][j]); - this.cmd("Step"); - } - } -} - - - - -ChangeCoordinate2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) -{ - var i; - var j; - var explainText = ""; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat2.data[0].length; j++) - { - var explainText = ""; - var value = 0; - for (k = 0; k < mat2.data.length; k++) - { - this.cmd("SetHighlight", mat1.dataID[i][k], 1); - this.cmd("SetHighlight", mat2.dataID[k][j], 1); - if (explainText != "") - { - explainText = explainText + " + "; - } - value = value + mat1.data[i][k] * mat2.data[k][j]; - explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); - this.cmd("SetText", explainID, explainText); - this.cmd("Step"); - this.cmd("SetHighlight", mat1.dataID[i][k], 0); - this.cmd("SetHighlight", mat2.dataID[k][j], 0); - } - value = this.standardize(value); - explainText += " = " + String(value); - this.cmd("SetText", explainID, explainText); - mat3.data[i][j] = value; - this.cmd("SetText", mat3.dataID[i][j], value); - this.cmd("Step"); - } - } - this.cmd("SetText", explainID, ""); - - -} - -ChangeCoordinate2D.prototype.standardize = function(lab) -{ - var newLab = Math.round(lab * 1000) / 1000; - if (isNaN(newLab)) - { - return lab; - } - else - { - return newLab; - } -} - - -ChangeCoordinate2D.prototype.resetMatrixLabels = function(mat) -{ - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - mat.data[i][j] = this.standardize(mat.data[i][j]); - this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); - } - } -} - - - -ChangeCoordinate2D.prototype.moveMatrix = function(mat, x, y) -{ - var height = mat.data.length; - var width = 0; - - var i, j; - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - } - - - this.cmd("Move", mat.leftBrack1, x, y); - this.cmd("Move", mat.leftBrack2, x, y); - this.cmd("Move", mat.leftBrack3, x, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - - this.cmd("Move", mat.rightBrack1, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack2, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack3, x+ width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Move", mat.dataID[i][j], - x + j*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2, - y + i*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2); - } - } - mat.x = x; - mat.y = y; -} - - - - -ChangeCoordinate2D.prototype.addMatrixIDsToList = function(mat, list) -{ - list.push(mat.leftBrack1); - list.push(mat.leftBrack2); - list.push(mat.leftBrack3); - list.push(mat.rightBrack1); - list.push(mat.rightBrack2); - list.push(mat.rightBrack3); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - list.push(mat.dataID[i][j]); - } - - } -} - -ChangeCoordinate2D.prototype.deleteMatrix = function(mat) -{ - var IDList = []; - this.addMatrixIDsToList(mat, IDList); - var i; - for (i = 0; i < IDList.length; i++) - { - this.cmd("Delete", IDList[i]); - } -} - - - - -ChangeCoordinate2D.prototype.aplyFunctionToMatrixElems = function(mat, command, value) -{ - this.cmd(command, mat.leftBrack1, value); - this.cmd(command, mat.leftBrack2, value); - this.cmd(command, mat.leftBrack3, value); - this.cmd(command, mat.rightBrack1, value); - this.cmd(command, mat.rightBrack2, value); - this.cmd(command, mat.rightBrack3, value); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd(command, mat.dataID[i][j], value); - } - } -} - - - -// Multiply two (data only!) matrices (not complete matrix object with graphics, just -// the data -ChangeCoordinate2D.prototype.multiply = function(lhs, rhs) -{ - var resultMat = new Array(lhs.length); - var i, j, k; - - for (i = 0; i < lhs.length; i++) - { - resultMat[i] = new Array(rhs[0].length); - } - for (i = 0; i < lhs.length; i++) - { - for (j = 0; j < rhs[0].length; j++) - { - var value = 0; - for (k = 0; k < rhs.length; k++) - { - value = value + lhs[i][k] * rhs[k][j]; - } - resultMat[i][j] = value; - } - } - return resultMat; -} - -// Add two (data only!) matrices (not complete matrix object with graphics, just -// the data) -ChangeCoordinate2D.prototype.add = function(lhs, rhs) -{ - var resultMat = new Array(lhs.length); - var i,j; - - for (i = 0; i < lhs.length; i++) - { - resultMat[i] = new Array(lhs[i].length); - for (j = 0; j < lhs[i].length; j++) - { - resultMat[i][j] = lhs[i][j] + rhs[i][j]; - - } - } - return resultMat; -} - - -ChangeCoordinate2D.prototype.createMatrix = function(contents, x, y) -{ - var mat = new Matrix(contents, x, y); - mat.leftBrack1 = this.nextIndex++; - mat.leftBrack2 = this.nextIndex++; - mat.leftBrack3 = this.nextIndex++; - mat.rightBrack1 = this.nextIndex++; - mat.rightBrack2 = this.nextIndex++; - mat.rightBrack3 = this.nextIndex++; - - var height = mat.data.length; - var width = 0; - - var i, j; - mat.dataID = new Array(mat.data.length); - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - mat.dataID[i] = new Array(mat.data[i].length); - for (j = 0; j < mat.data[i].length; j++) - { - mat.dataID[i][j] = this.nextIndex++; - } - } - - this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); - this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); - this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT , "left","center"); - - this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y, "right","center"); - this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y, "center","top"); - this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT , "right","center"); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], - x + j*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2, - y + i*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2); - } - } - return mat; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new ChangeCoordinate2D(animManag, canvas.width, canvas.height); -} - -function Matrix(contents, x, y) -{ - this.data = contents; - this.x = x; - this.y = y; -} - -Matrix.prototype.transpose = function() -{ - var newData = new Array(this.data[0].length); - var i,j; - for (i = 0; i < this.data[0].length; i++) - { - newData[i] = new Array(this.data.length); - } - for (i = 0; i < this.data.length; i++) - { - for (j = 0; j < this.data[i].length; j++) - { - newData[j][i] = this.data[i][j]; - } - } - this.data = newData; -} - - - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function ChangeCoordinate2D(am, w, h) +{ + this.init(am, w, h); +} + + +ChangeCoordinate2D.inheritFrom(Algorithm); + +ChangeCoordinate2D.XAxisYPos = 300; +ChangeCoordinate2D.XAxisStart = 100; +ChangeCoordinate2D.XAxisEnd = 700; + +ChangeCoordinate2D.MATRIX_ELEM_WIDTH = 50; +ChangeCoordinate2D.MATRIX_ELEM_HEIGHT = 15; + + +ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING = 10; +ChangeCoordinate2D.EQUALS_SPACING = 30; + +ChangeCoordinate2D.ROBOT_MATRIX_START_X = 10 + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; +ChangeCoordinate2D.ROBOT_MATRIX_START_Y = 30; + +ChangeCoordinate2D.HAND_MATRIX_START_X = 10 +2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; +ChangeCoordinate2D.HAND_MATRIX_START_Y = 10 + 25 + 20 + 3*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; + + +ChangeCoordinate2D.ROBOT_POSITION_START_X = ChangeCoordinate2D.ROBOT_MATRIX_START_X + 4*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + 100; +ChangeCoordinate2D.HAND_POSITION_START_X = ChangeCoordinate2D.HAND_MATRIX_START_X + 4*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + 100; + + +ChangeCoordinate2D.ROBOT_POSITION_START_Y = ChangeCoordinate2D.ROBOT_MATRIX_START_Y; +ChangeCoordinate2D.HAND_POSITION_START_Y = ChangeCoordinate2D.HAND_MATRIX_START_Y; + + +ChangeCoordinate2D.YAxisXPos = 400; +ChangeCoordinate2D.YAxisStart = 100; +ChangeCoordinate2D.YAxisEnd = 500; + +ChangeCoordinate2D.ROBOT_POINTS = [[-15,100],[15,100],[15,80],[30,80],[30,-10],[15,-10], [15, -100], [0,-100],[0,-30],[0,-100], [-15, -100], + [-15, -10], [-30, -10], [-30, 80],[-15, 80]]; + + +ChangeCoordinate2D.HAND_POINTS = [[0,0],[-10,0],[-10,10], [-6, 10], [-6, 6], [6, 6], [6, 10], [10, 10], [10, 0]]; + +ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT = [0, 40]; + + + +ChangeCoordinate2D.ROBOT_MATRIX_VALUES = [[[Math.cos(Math.PI / 8), Math.sin(Math.PI / 8)],[-Math.sin(Math.PI / 8), Math.cos(Math.PI / 8)]], + [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4)],[-Math.sin(Math.PI / 4), Math.cos(Math.PI / 4)]], + [[Math.cos(0), Math.sin(0)],[-Math.sin(0), Math.cos(0)]], + [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4)],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4)]]]; + + +ChangeCoordinate2D.ROBOT_POSITION_VALUES = [[75, 50], [200,100],[100,100], [100, 200]]; + + +ChangeCoordinate2D.HAND_MATRIX_VALUES = [[[Math.cos(-Math.PI / 6), Math.sin(-Math.PI / 6)],[-Math.sin(-Math.PI / 6), Math.cos(-Math.PI / 6)]], + [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4)],[-Math.sin(Math.PI / 4), Math.cos(-Math.PI / 4)]], + [[Math.cos(0), Math.sin(0)],[-Math.sin(0), Math.cos(0)]], + [[Math.cos(Math.PI/2), Math.sin(Math.PI/2)],[-Math.sin(Math.PI/2), Math.cos(Math.PI/2)]]]; + + +ChangeCoordinate2D.HAND_POSITION_VALUES = [[80,30],[30,90],[100,100],[-50, -20]]; + + +//ChangeCoordinate2D.ROBOT_POINTS = [[-20, 40], [20,40],[ + + + +ChangeCoordinate2D.AXIS_CENTER = [[750,470],[750,150],[100, 550]]; + +ChangeCoordinate2D.AXIS_COLOR_0 = "#990000" +ChangeCoordinate2D.AXIS_COLOR_1 = "#009900" +ChangeCoordinate2D.AXIS_COLOR_2 = "#000099" + +ChangeCoordinate2D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; +ChangeCoordinate2D.LOCAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.LOCAL_VERTEX_FOREGORUND_COLOR; +ChangeCoordinate2D.LOCAL_EDGE_COLOR = "#000000"; + +ChangeCoordinate2D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; +ChangeCoordinate2D.GLOBAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.GLOBAL_VERTEX_FOREGORUND_COLOR; +ChangeCoordinate2D.GLOBAL_EDGE_COLOR = "#00FF00"; + + + +ChangeCoordinate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; +ChangeCoordinate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = ChangeCoordinate2D.VERTEX_FOREGORUND_COLOR; +ChangeCoordinate2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; + + +ChangeCoordinate2D.TRANSFORMED_POINT_COLORS = ["#990000", "#009900", "#000099"] + + +ChangeCoordinate2D.VECTOR_COLOR = "#FF0000"; + +ChangeCoordinate2D.VERTEX_WIDTH = 3; +ChangeCoordinate2D.VERTEX_HEIGHT = ChangeCoordinate2D.VERTEX_WIDTH; + +ChangeCoordinate2D.prototype.init = function(am, w, h) +{ + var sc = ChangeCoordinate2D.superclass.init.call(this, am, w, h); + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.addControls(); + this.currentShape = 0; + + this.commands = []; + this.nextIndex = 0; + + this.PositionIndex = 0; + + this.RobotPositionValues = ChangeCoordinate2D.ROBOT_POSITION_VALUES[this.PositionIndex]; + this.RobotMatrixValues = ChangeCoordinate2D.ROBOT_MATRIX_VALUES[this.PositionIndex]; + this.HandPositionValues = ChangeCoordinate2D.HAND_POSITION_VALUES[this.PositionIndex]; + this.HandMatrixValues = ChangeCoordinate2D.HAND_MATRIX_VALUES[this.PositionIndex]; + + this.setupAxis(); + + this.robotLabel1ID = this.nextIndex++; + this.handLabel1ID = this.nextIndex++; + this.robotLabel2ID = this.nextIndex++; + this.handLabel2ID = this.nextIndex++; + + this.cmd("CreateLabel", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)", ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.robotLabel1ID, "#0000FF"); + + this.cmd("CreateLabel", this.robotLabel2ID, "Robot Space to World Space\n(Position)", ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.robotLabel2ID, "#0000FF"); + + + + this.RobotMatrix = this.createMatrix(this.RobotMatrixValues, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y); + this.resetMatrixLabels(this.RobotMatrix); + this.HandMatrix = this.createMatrix(this.HandMatrixValues, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y); + this.resetMatrixLabels(this.HandMatrix); + + this.cmd("CreateLabel", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)", ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.handLabel1ID, "#0000FF"); + + this.cmd("CreateLabel", this.handLabel2ID, "Hand Space to Robot Space\n(Position)", ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.handLabel2ID, "#0000FF"); + + + + this.RobotPosition = this.createMatrix([this.RobotPositionValues], ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y); + this.resetMatrixLabels(this.RobotMatrix); + this.HandPosition = this.createMatrix([this.HandPositionValues], ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); + this.resetMatrixLabels(this.HandMatrix); + + + var i; + this.RobotPointWorldIDs = new Array(ChangeCoordinate2D.ROBOT_POINTS.length); + this.RobotPointRobotIDs = new Array(ChangeCoordinate2D.ROBOT_POINTS.length); + this.HandPointWorldIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); + this.HandPointRobotIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); + this.HandPointHandIDs = new Array(ChangeCoordinate2D.HAND_POINTS.length); + this.RobotHandAttachRobotID = this.nextIndex++; + this.RobotHandAttachWorldID = this.nextIndex++; + for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) + { + this.RobotPointWorldIDs[i] = this.nextIndex++; + this.RobotPointRobotIDs[i] = this.nextIndex++; + } + for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) + { + this.HandPointWorldIDs[i] = this.nextIndex++; + this.HandPointRobotIDs[i] = this.nextIndex++; + this.HandPointHandIDs[i] = this.nextIndex++; + } + + this.savedNextIndex = this.nextIndex; + this.setupObjects(); + this.setupObjectGraphic(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); + this.animationManager.setAllLayers([0, 1]); + this.lastLocalToGlobal = true; + this.oldIDs = []; + + +} + +ChangeCoordinate2D.prototype.addAxis = function(origin, x1, x2, y1, y2, color) +{ + var idArray = []; + var originID = this.nextIndex++; + idArray.push(originID); + this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); + this.cmd("SetAlpha", originID, 0); + + var axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, x1[0], x1[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, x2[0], x2[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, y1[0], y1[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, y2[0], y2[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + + var labelID = this.nextIndex++; + this.cmd("CreateLabel", labelID, "+y", y2[0] - 10, y2[1] + 10); + this.cmd("SetForegroundColor", labelID, color); + idArray.push(labelID); + + + labelID = this.nextIndex++; + this.cmd("CreateLabel", labelID, "+x", x2[0] - 10, x2[1] + 10); + this.cmd("SetForegroundColor", labelID, color); + idArray.push(labelID); + return idArray; +} + + +ChangeCoordinate2D.prototype.transformPoint = function(point, matrix, position) +{ + return this.add(this.multiply([point], matrix), [position])[0]; +} + + +ChangeCoordinate2D.prototype.setupExtraAxes = function() +{ + var robotOrigin = this.RobotPositionValues; + var x1 = this.transformPoint([-150, 0], this.RobotMatrixValues, this.RobotPositionValues); + var x2 = this.transformPoint([150, 0], this.RobotMatrixValues, this.RobotPositionValues); + var y1 = this.transformPoint([0, -150], this.RobotMatrixValues, this.RobotPositionValues); + var y2 = this.transformPoint([0, 150], this.RobotMatrixValues, this.RobotPositionValues); + + this.otherAxes = []; + + var tmpAxis = this.addAxis(this.worldToScreenSpace(robotOrigin, 2), + this.worldToScreenSpace(x1, 2), + this.worldToScreenSpace(x2, 2), + this.worldToScreenSpace(y1, 2), + this.worldToScreenSpace(y2, 2), + ChangeCoordinate2D.AXIS_COLOR_1); + + this.otherAxes.push(tmpAxis); + + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + this.setAxisAlpha(tmpAxis, 0.5); + + + var handOrigin = this.HandPositionValues; + x1 = this.transformPoint([-150, 0], this.HandMatrixValues, this.HandPositionValues); + x2 = this.transformPoint([150, 0], this.HandMatrixValues, this.HandPositionValues); + y1 = this.transformPoint([0, -150], this.HandMatrixValues, this.HandPositionValues); + y2 = this.transformPoint([0, 150], this.HandMatrixValues, this.HandPositionValues); + + + tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 1), + this.worldToScreenSpace(x1, 1), + this.worldToScreenSpace(x2, 1), + this.worldToScreenSpace(y1, 1), + this.worldToScreenSpace(y2, 1), + ChangeCoordinate2D.AXIS_COLOR_0); + + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + this.setAxisAlpha(tmpAxis, 0.5); + + + this.otherAxes.push(tmpAxis); + + + handOrigin = this.transformPoint(handOrigin, this.RobotMatrixValues, this.RobotPositionValues); + x1 = this.transformPoint(x1, this.RobotMatrixValues, this.RobotPositionValues); + x2 = this.transformPoint(x2, this.RobotMatrixValues, this.RobotPositionValues); + y1 = this.transformPoint(y1, this.RobotMatrixValues, this.RobotPositionValues); + y2 = this.transformPoint(y2, this.RobotMatrixValues, this.RobotPositionValues); + + + tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 2), + this.worldToScreenSpace(x1, 2), + this.worldToScreenSpace(x2, 2), + this.worldToScreenSpace(y1, 2), + this.worldToScreenSpace(y2, 2), + ChangeCoordinate2D.AXIS_COLOR_0); + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + + this.setAxisAlpha(tmpAxis, 0.5); + + this.otherAxes.push(tmpAxis); + +} + + +ChangeCoordinate2D.prototype.setupAxis = function() +{ + + this.axisHand = this.addAxis(this.worldToScreenSpace([0,0], 0), + this.worldToScreenSpace([-150, 0], 0), + this.worldToScreenSpace([150,0], 0), + this.worldToScreenSpace([0, -150], 0), + this.worldToScreenSpace([0, 150], 0), + ChangeCoordinate2D.AXIS_COLOR_0); + this.setAxisAlpha(this.axisHand, 0.5); + + this.axisRobot = this.addAxis(this.worldToScreenSpace([0,0], 1), + this.worldToScreenSpace([-150, 0], 1), + this.worldToScreenSpace([150,0], 1), + this.worldToScreenSpace([0, -150], 1), + this.worldToScreenSpace([0, 150], 1), + ChangeCoordinate2D.AXIS_COLOR_1); + this.setAxisAlpha(this.axisRobot, 0.5); + + this.axisWorld = this.addAxis(this.worldToScreenSpace([0,0], 2), + this.worldToScreenSpace([-50, 0], 2), + this.worldToScreenSpace([400,0], 2), + this.worldToScreenSpace([0, -50], 2), + this.worldToScreenSpace([0, 400], 2), + ChangeCoordinate2D.AXIS_COLOR_2); + this.setAxisAlpha(this.axisWorld, 0.5); + + this.setupExtraAxes(); + + + + + +} + + +ChangeCoordinate2D.prototype.setAxisAlpha = function(axisList, newAlpha) +{ + for (var i = 0; i < axisList.length; i++) + { + this.cmd("SetAlpha", axisList[i], newAlpha); + if (i > 0) + { + this.cmd("SetEdgeAlpha", axisList[0], axisList[i], newAlpha); + } + } + +} + +ChangeCoordinate2D.prototype.setupObjects = function() +{ + + var i; + for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) + { + + + var point = this.worldToScreenSpace(ChangeCoordinate2D.ROBOT_POINTS[i], 1); + this.cmd("CreateRectangle", this.RobotPointRobotIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.RobotPointRobotIDs[i-1], this.RobotPointRobotIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(ChangeCoordinate2D.ROBOT_POINTS[i], this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point, 2); + + this.cmd("CreateRectangle", this.RobotPointWorldIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.RobotPointWorldIDs[i-1], this.RobotPointWorldIDs[i], "#000000", 0, 0); + } + } + this.cmd("Connect", this.RobotPointRobotIDs[this.RobotPointRobotIDs.length - 1], this.RobotPointRobotIDs[0], "#000000", 0, 0); + this.cmd("Connect", this.RobotPointWorldIDs[this.RobotPointWorldIDs.length - 1], this.RobotPointWorldIDs[0], "#000000", 0, 0); + + + for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) + { + + + var point = this.worldToScreenSpace(ChangeCoordinate2D.HAND_POINTS[i], 0); + this.cmd("CreateRectangle", this.HandPointHandIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointHandIDs[i-1], this.HandPointHandIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(ChangeCoordinate2D.HAND_POINTS[i], this.HandMatrixValues, this.HandPositionValues); + var point2 = this.worldToScreenSpace(point, 1); + + this.cmd("CreateRectangle", this.HandPointRobotIDs[i], "", 0, 0, point2[0], point2[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointRobotIDs[i-1], this.HandPointRobotIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(point, this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point,2); + + this.cmd("CreateRectangle", this.HandPointWorldIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointWorldIDs[i-1], this.HandPointWorldIDs[i], "#000000", 0, 0); + } + + + } + this.cmd("Connect", this.HandPointHandIDs[this.HandPointHandIDs.length - 1], this.HandPointHandIDs[0], "#000000", 0, 0); + this.cmd("Connect", this.HandPointRobotIDs[this.HandPointRobotIDs.length - 1], this.HandPointRobotIDs[0], "#000000", 0, 0); + this.cmd("Connect", this.HandPointWorldIDs[this.HandPointWorldIDs.length - 1], this.HandPointWorldIDs[0], "#000000", 0, 0); + + + point = this.worldToScreenSpace(ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT, 1); + this.cmd("CreateRectangle", this.RobotHandAttachRobotID, "", 0, 0, point[0], point[1]); + this.cmd("Connect", this.RobotHandAttachRobotID, this.HandPointRobotIDs[0], "#000000", 0, 0); + + point = this.transformPoint(ChangeCoordinate2D.ROBOT_HAND_ATTACH_POINT, this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point, 2); + this.cmd("CreateRectangle", this.RobotHandAttachWorldID, "", 0, 0, point[0], point[1]); + this.cmd("Connect", this.RobotHandAttachWorldID, this.HandPointWorldIDs[0], "#000000", 0, 0); +} + + +ChangeCoordinate2D.prototype.worldToScreenSpace = function(point, space) +{ + var transformedPoint = new Array(2); + + return [point[0] + ChangeCoordinate2D.AXIS_CENTER[space][0], + -point[1] + ChangeCoordinate2D.AXIS_CENTER[space][1]]; +} + + + + +ChangeCoordinate2D.prototype.removeOldIDs = function() +{ + var i; + for (i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs = []; +} + + + +ChangeCoordinate2D.prototype.setupObjectGraphic = function() +{ + var i; + + + + +} + +ChangeCoordinate2D.prototype.addControls = function() +{ + this.controls = []; + + this.addLabelToAlgorithmBar("x"); + + this.xField = this.addControlToAlgorithmBar("Text", ""); + this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); + this.controls.push(this.xField); + + this.addLabelToAlgorithmBar("y"); + + this.yField = this.addControlToAlgorithmBar("Text", ""); + this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); + this.controls.push(this.yField); + + var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); + transformButton.onclick = this.transformPointCallback.bind(this); + this.controls.push(transformButton); + + + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", + "World Space -> Hand Space", + ], + "Transform Type"); + this.handToWorldButton = radioButtonList[0]; + this.handToWorldButton.onclick = this.transformTypeChangedCallback.bind(this, false); + this.controls.push(this.handToWorldButton); + + + this.worldToHandButton = radioButtonList[1]; + this.worldToHandButton.onclick = this.transformTypeChangedCallback.bind(this, true); + this.controls.push(this.worldToHandButton); + + this.worldToHandButton.checked = this.lastLocalToGlobal; + this.handToWorldButton.checked = !this.lastLocalToGlobal; + + + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", + "Column Major", + ], + "RankType"); + this.rowMajorButton = radioButtonList[0]; + this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); + this.controls.push(this.rowMajorButton); + + this.colMajorButton = radioButtonList[1]; + this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); + this.controls.push(this.colMajorButton); + + this.rowMajorButton.checked = this.rowMajor; + this.colMajorButton.checked = !this.rowMajor; + + + this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); + this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); + this.showAxisBox.checked = true; + + //this.controls.push(this.showAxisBox); + + + + var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); + moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); + + this.controls.push(moveObjectsButton); + +} + + + +ChangeCoordinate2D.prototype.showAllAxesCallback = function() +{ + if (this.showAxisBox.checked) + { + this.animationManager.setAllLayers([0,1]); + } + else + { + this.animationManager.setAllLayers([0]); + } + + +} + + +ChangeCoordinate2D.prototype.reset = function() +{ + this.rowMajor = true; + this.rowMajorButton.checked = this.rowMajor; + this.nextIndex = this.savedNextIndex; +} + + +ChangeCoordinate2D.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +ChangeCoordinate2D.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +ChangeCoordinate2D.prototype.transformTypeChangedCallback = function(globalToLocal) +{ + if (this.lastLocalToGlobal == globalToLocal) + { + this.implementAction(this.changeTransformType.bind(this,globalToLocal)); + } +} + + + + +ChangeCoordinate2D.prototype.changeRowColMajorCallback = function(rowMajor) +{ + if (this.rowMajor != rowMajor) + { + this.implementAction(this.changeRowCol.bind(this), rowMajor); + } +} + +ChangeCoordinate2D.prototype.transposeVisual = function(matrix) +{ + if (matrix.data.length == matrix.data[0].length) + { + var matrixSize = matrix.data.length; + var i, j, tmp, moveLabel1, moveLabel2; + var moveLabels = []; + for (i = 1; i < matrixSize; i++) + { + for (j = 0; j <= i; j++) + { + this.cmd("SetText", matrix.dataID[i][j], ""); + this.cmd("SetText", matrix.dataID[j][i], ""); + moveLabel1 = this.nextIndex++; + moveLabel2 = this.nextIndex++; + moveLabels.push(moveLabel1); + moveLabels.push(moveLabel2); + this.cmd("CreateLabel", moveLabel1, + matrix.data[i][j], matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + this.cmd("CreateLabel", moveLabel2, + matrix.data[j][i], matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + this.cmd("Move", moveLabel1, matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + this.cmd("Move", moveLabel2, matrix.x + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2 + j * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + tmp = matrix.data[i][j]; + matrix.data[i][j] = matrix.data[j][i]; + matrix.data[j][i] = tmp; + } + } + this.cmd("Step"); + for (i = 0; i < moveLabels.length; i++) + { + this.cmd("Delete", moveLabels[i]); + } + this.resetMatrixLabels(matrix); + return matrix; + } + else + { + var savedData = matrix.data; + var newData = new Array(savedData[0].length); + var i,j; + for (i = 0; i < savedData[0].length; i++) + { + newData[i] = []; + } + for (i = 0; i < savedData.length; i++) + { + for (j = 0; j < savedData[0].length; j++) + { + newData[j][i] = savedData[i][j]; + } + + } + var newMatrix = this.createMatrix(newData, matrix.x, matrix.y); + this.deleteMatrix(matrix); + return newMatrix; + } +} + +ChangeCoordinate2D.prototype.changeRowCol = function(rowMajor) +{ + this.commands = new Array(); + this.rowMajor= rowMajor; + if (this.rowMajorButton.checked != this.rowMajor) + { + this.rowMajorButton.checked = this.rowMajor; + } + if (this.colMajorButton.checked == this.rowMajor) + { + this.colMajorButton.checked = !this.rowMajor; + } + this.removeOldIDs(); + this.RobotMatrix = this.transposeVisual(this.RobotMatrix); + this.RobotPosition = this.transposeVisual(this.RobotPosition); + this.HandMatrix = this.transposeVisual(this.HandMatrix); + this.HandPosition = this.transposeVisual(this.HandPosition); + + + return this.commands; +} + + +ChangeCoordinate2D.prototype.fixNumber = function(value, defaultVal) +{ + if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) + { + value = defaultVal; + } + else + { + value = String(parseFloat(value)); + } + return value +} + +ChangeCoordinate2D.prototype.transformPointCallback = function() +{ + + + this.xField.value = this.fixNumber(this.xField.value, "0"); + this.yField.value = this.fixNumber(this.yField.value, "0"); + this.implementAction(this.doPointTransform.bind(this), this.xField.value + ";" + this.yField.value); + +} + + +ChangeCoordinate2D.prototype.doPointTransform = function(params) +{ + if (this.lastLocalToGlobal) + { + return this.localToGlobal(params); + } + else + { + return this.globalToLocal(params); + } +} + + + + + +ChangeCoordinate2D.prototype.rotatePoint = function(point, matrix, xPos, yPos, fromSpace, toSpace) +{ + var logicalPoint; + var descriptLabel = this.nextIndex++; + // this.oldIDs.push(descriptLabel); + this.cmd("CreateLabel", descriptLabel, "", xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, + yPos + 2*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + 3, 0); + + var inertialPositionMatrix; + + if (this.rowMajor) + { + inertialPositionMatrix = this.createMatrix([["", ""]], xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, + yPos); + } + else + { + inertialPositionMatrix = this.createMatrix([[""], [""]], + xPos + 3 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, + yPos); + + } + var equalLabel1 = this.nextIndex++; + this.oldIDs.push(equalLabel1); + if (this.rowMajor) + { + opX = xPos + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; + } + else + { + opX = xPos + 3 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2 + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING; + opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; + + + } + + this.cmd("CreateLabel", equalLabel1, "=", opX , opY); + if (this.rowMajor) + { + this.multiplyMatrix(point, matrix, inertialPositionMatrix, descriptLabel); + + } + else + { + this.multiplyMatrix(matrix, point, inertialPositionMatrix, descriptLabel); + + } + this.addMatrixIDsToList(inertialPositionMatrix, this.oldIDs); + this.cmd("Delete", descriptLabel); + var inertialPositionID = this.nextIndex++; + if (this.rowMajor) + { + logicalPoint = inertialPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [inertialPositionMatrix.data[0][0], inertialPositionMatrix.data[1][0]]; + } + screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); + + + this.cmd("CreateCircle", inertialPositionID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", inertialPositionID, ChangeCoordinate2D.VERTEX_WIDTH); + + var originID = this.nextIndex++; + this.oldIDs.push(originID); + var origin = this.worldToScreenSpace([0,0], fromSpace); + + + this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); + + this.cmd("Connect", originID, inertialPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + + + return [inertialPositionMatrix, inertialPositionID, originID]; +} + +ChangeCoordinate2D.prototype.translatePoint = function(point, transVector, xPos, yPos, fromSpace, toSpace, pointID) +{ + var logicalPoint = new Array(2); + var robotPositionMatrix; + if (this.rowMajor) + { + logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; + logicalPoint[1] = point.data[0][1] + transVector.data[0][1]; + robotPositionMatrix = this.createMatrix([["", ""]], xPos + 2*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, + yPos); + } + else + { + logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; + logicalPoint[1] = point.data[1][0] + transVector.data[1][0]; + robotPositionMatrix = this.createMatrix([[""],[""]], xPos + ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING, + yPos); + + } + + var addLabel1 = this.nextIndex++; + var equalLabel3 = this.nextIndex++; + this.oldIDs.push(addLabel1); + this.oldIDs.push(equalLabel3); + var op2X, op2Y; + if (this.rowMajor) + { + opX = xPos + 2*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; + op2X = xPos - ChangeCoordinate2D.EQUALS_SPACING / 2; + op2Y = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2; + + } + else + { + opX = xPos + ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; + op2X = xPos - ChangeCoordinate2D.EQUALS_SPACING / 2; + op2Y = yPos + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT; + + + } + this.cmd("CreateLabel", equalLabel3, "=",opX , opY); + this.cmd("CreateLabel", addLabel1, "+",op2X , op2Y); + + + + + this.addMatrix(point, transVector, robotPositionMatrix); + this.addMatrixIDsToList(robotPositionMatrix, this.oldIDs); + + var screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); + + var robotPositionID = this.nextIndex++; + + this.cmd("CreateCircle", robotPositionID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", robotPositionID, ChangeCoordinate2D.VERTEX_WIDTH); + + + this.cmd("Connect",pointID, robotPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + this.cmd("Step") + + + + var originID = this.nextIndex++; + this.oldIDs.push(originID); + var origin = this.worldToScreenSpace([0,0], fromSpace); + + this.cmd("CreateCircle", originID, "", origin[0], origin[1]); + this.cmd("SetWidth", originID, 0); + this.cmd("SetAlpha", originID, 0); + + this.cmd("Connect",originID, robotPositionID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + + return [robotPositionMatrix, robotPositionID, originID]; + + +} + + +ChangeCoordinate2D.prototype.addMultiply = function(position, transVector, rotMatrix, transX, transY, rotX, rotY, initialPointID, fromSpace, toSpace) +{ + + var posMatrixAndPointID = this.translatePoint(position, transVector, transX, transY, fromSpace, toSpace, initialPointID); + var newPosition = posMatrixAndPointID[0]; + var pointID = posMatrixAndPointID[1]; + var originID = posMatrixAndPointID[2]; + + this.cmd("Step"); + + this.cmd("Disconnect", initialPointID, pointID); + + if (this.rowMajor) + { + this.moveMatrix(newPosition, rotX - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING,transY) + } + else + { + this.moveMatrix(newPosition, rotX + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, transY) + } + + + var posMatrixAndPointID = this.rotatePoint(newPosition, rotMatrix, rotX, rotY, fromSpace, toSpace); + this.cmd("Delete", pointID); + this.cmd("Step"); + + var robotPositionMatrix = posMatrixAndPointID[0]; + var robotPositionID = posMatrixAndPointID[1]; + var movingOriginID = posMatrixAndPointID[2]; + + var origin = this.worldToScreenSpace([0,0], toSpace); + this.cmd("Move", movingOriginID, origin[0], origin[1]); + + + var logicalPoint; + if (this.rowMajor) + { + logicalPoint = robotPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0]]; + } + + + + + var screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); + this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); + + this.cmd("Step"); + + + this.oldIDs.push(robotPositionID); + + + return [robotPositionMatrix, robotPositionID ]; +} + + +ChangeCoordinate2D.prototype.multiplyAdd = function(position, rotMatrix, transVector, rotX, rotY, transX, transY, fromSpace, toSpace) +{ + var posMatrixAndPointID = this.rotatePoint(position, rotMatrix, rotX, rotY, fromSpace, toSpace); + var inertialPositionMatrix = posMatrixAndPointID[0]; + var inertialPositionID = posMatrixAndPointID[1]; + + + this.cmd("Step"); + + if (this.rowMajor) + { + this.moveMatrix(inertialPositionMatrix, transX - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.EQUALS_SPACING,transY) + } + else + { + this.moveMatrix(inertialPositionMatrix, transX - ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.EQUALS_SPACING, transY) + } + + + posMatrixAndPointID = this.translatePoint(inertialPositionMatrix, transVector, transX, transY, fromSpace, toSpace, inertialPositionID); + var robotPositionMatrix = posMatrixAndPointID[0]; + var robotPositionID = posMatrixAndPointID[1]; + var movingOriginID = posMatrixAndPointID[2]; + + this.oldIDs.push(robotPositionID); + + var logicalPoint; + if (this.rowMajor) + { + logicalPoint = robotPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0]]; + } + + + this.cmd("Step"); + + this.cmd("Delete", inertialPositionID); + origin = this.worldToScreenSpace([0,0], toSpace); + this.cmd("Move", movingOriginID, origin[0], origin[1]); + screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); + this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); + + this.cmd("Step"); + return robotPositionMatrix; + +} + +ChangeCoordinate2D.prototype.localToGlobal = function (params) +{ + this.commands = []; + this.removeOldIDs(); + + + var paramList = params.split(";"); + var x = parseFloat(paramList[0]); + var y = parseFloat(paramList[1]); + + var opX, opY; + + + var screenPoint = this.worldToScreenSpace([x,y], 0); + var logicalPoint; + + var pointInHandSpaceID = this.nextIndex++; + this.oldIDs.push(pointInHandSpaceID); + + this.cmd("CreateCircle", pointInHandSpaceID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", pointInHandSpaceID, ChangeCoordinate2D.VERTEX_WIDTH); + + this.cmd("Connect", this.axisHand[0], pointInHandSpaceID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[0], 0, 1, ""); + + var initialPointMatrix; + if (this.rowMajor) + { + initialPointMatrix = this.createMatrix([[x, y]], ChangeCoordinate2D.HAND_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate2D.HAND_MATRIX_START_Y); + } + else + { + initialPointMatrix = this.createMatrix([[x], [y]], ChangeCoordinate2D.HAND_MATRIX_START_X + 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate2D.HAND_MATRIX_START_Y); + + } + this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); + this.cmd("Step"); + + var robotPositionMatrix = this.multiplyAdd(initialPointMatrix, this.HandMatrix, this.HandPosition, + ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y, + ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y, + 0, 1); + + + + + if (this.rowMajor) + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH - ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate2D.ROBOT_MATRIX_START_Y); + } + else + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X + 2* ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate2D.ROBOT_MATRIX_START_Y); + + } + + + this.multiplyAdd(robotPositionMatrix, this.RobotMatrix, this.RobotPosition, + ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y, + ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y, + 1, 2); + + + + + + return this.commands; +} + +ChangeCoordinate2D.prototype.changeTransformType = function(globalToLocal) +{ + this.commands = []; + this.lastLocalToGlobal = !globalToLocal; + this.removeOldIDs(); + if (globalToLocal) + { + this.cmd("SetText", this.robotLabel1ID, "World Space to Robot Space\n(Orientation)"); + + } + else + { + this.cmd("SetText", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)"); + } + this.cmd("Step"); + this.RobotMatrix = this.transposeVisual(this.RobotMatrix) + + if (globalToLocal) + { + this.cmd("SetText", this.robotLabel2ID, "World Space to Robot Space\n(Position)"); + + } + else + { + this.cmd("SetText", this.robotLabel2ID, "Robot Space to World Space\n(Position)"); + } + this.cmd("Step"); + this.negateMatrixVisual(this.RobotPosition); + this.cmd("Step"); + + if (globalToLocal) + { + this.cmd("SetText", this.handLabel1ID, "Robot Space to Hand Space\n(Orientation)"); + + } + else + { + this.cmd("SetText", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)"); + } + + this.cmd("Step"); + this.HandMatrix = this.transposeVisual(this.HandMatrix) + + if (globalToLocal) + { + this.cmd("SetText", this.handLabel2ID, "Robot Space to Hand Space\n(Position)"); + + } + else + { + this.cmd("SetText", this.handLabel2ID, "Hand Space to Robot Space\n(Position)"); + } + this.cmd("Step"); + this.negateMatrixVisual(this.HandPosition); + this.cmd("Step"); + + if (globalToLocal) + { + this.cmd("Move", this.robotLabel1ID, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y - 25); + this.moveMatrix(this.RobotMatrix, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y) + + this.cmd("Move", this.robotLabel2ID, ChangeCoordinate2D.ROBOT_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25); + this.moveMatrix(this.RobotPosition, ChangeCoordinate2D.ROBOT_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y) + + this.cmd("Move", this.handLabel1ID, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y - 25); + this.moveMatrix(this.HandMatrix, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); + + + this.cmd("Move", this.handLabel2ID, ChangeCoordinate2D.HAND_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25); + this.moveMatrix(this.HandPosition, ChangeCoordinate2D.HAND_MATRIX_START_X+ ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y); + } + else + { + this.cmd("Move", this.robotLabel1ID, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y - 25); + this.moveMatrix(this.RobotMatrix, ChangeCoordinate2D.ROBOT_MATRIX_START_X, ChangeCoordinate2D.ROBOT_MATRIX_START_Y) + + this.cmd("Move", this.robotLabel2ID, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y - 25); + this.moveMatrix(this.RobotPosition, ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y) + + this.cmd("Move", this.handLabel1ID, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y - 25); + this.moveMatrix(this.HandMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X, ChangeCoordinate2D.HAND_MATRIX_START_Y); + + this.cmd("Move", this.handLabel2ID, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y - 25); + this.moveMatrix(this.HandPosition, ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y); + + } + return this.commands; +} + + +ChangeCoordinate2D.prototype.negateMatrixVisual = function(matrix) +{ + var i,j + for (i = 0; i < matrix.data.length; i++) + { + for (j = 0; j < matrix.data[i].length; j++) + { + matrix.data[i][j] = -matrix.data[i][j] + } + } + this.resetMatrixLabels(matrix); +} + + +ChangeCoordinate2D.prototype.globalToLocal = function(params) +{ + this.commands = []; + this.removeOldIDs(); + + + var paramList = params.split(";"); + var x = parseFloat(paramList[0]); + var y = parseFloat(paramList[1]); + + var opX, opY; + + + var screenPoint = this.worldToScreenSpace([x,y], 2); + var logicalPoint; + + var pointInWorldSpaceID = this.nextIndex++; + this.oldIDs.push(pointInWorldSpaceID); + this.cmd("CreateCircle", pointInWorldSpaceID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", pointInWorldSpaceID, ChangeCoordinate2D.VERTEX_WIDTH); + this.cmd("Connect", this.axisWorld[0], pointInWorldSpaceID, ChangeCoordinate2D.TRANSFORMED_POINT_COLORS[2], 0, 1, ""); + + var initialPointMatrix; + if (this.rowMajor) + { + initialPointMatrix = this.createMatrix([[x, y]], ChangeCoordinate2D.ROBOT_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + ChangeCoordinate2D.ROBOT_MATRIX_START_Y); + } + else + { + initialPointMatrix = this.createMatrix([[x], [y]], ChangeCoordinate2D.ROBOT_MATRIX_START_X - ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + ChangeCoordinate2D.ROBOT_MATRIX_START_Y); + + } + this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); + this.cmd("Step"); + + var positionAndID = this.addMultiply(initialPointMatrix, this.RobotPosition, this.RobotMatrix, + ChangeCoordinate2D.ROBOT_MATRIX_START_X + ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.ROBOT_MATRIX_START_Y, + ChangeCoordinate2D.ROBOT_POSITION_START_X, ChangeCoordinate2D.ROBOT_POSITION_START_Y, + pointInWorldSpaceID, + 2, 1); + + var robotPositionMatrix = positionAndID[0]; + var newPositionID = positionAndID[1]; + + if (this.rowMajor) + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X - 2 * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + ChangeCoordinate2D.HAND_MATRIX_START_Y); + } + else + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate2D.HAND_MATRIX_START_X - ChangeCoordinate2D.MATRIX_ELEM_WIDTH, + ChangeCoordinate2D.HAND_MATRIX_START_Y); + + } + + + this.addMultiply(robotPositionMatrix, this.HandPosition, this.HandMatrix, + ChangeCoordinate2D.HAND_MATRIX_START_X + ChangeCoordinate2D.EQUALS_SPACING, ChangeCoordinate2D.HAND_MATRIX_START_Y, + ChangeCoordinate2D.HAND_POSITION_START_X, ChangeCoordinate2D.HAND_POSITION_START_Y, + newPositionID, + 1, 0); + + + + return this.commands; +} + +ChangeCoordinate2D.prototype.moveObjectsCallback = function() +{ + this.implementAction(this.moveObjects.bind(this), 0); +} + +ChangeCoordinate2D.prototype.moveObjects = function() +{ + this.commands = []; + this.removeOldIDs(); + var i, j; + + for (i = 0; i < this.otherAxes.length; i++) + { + for (j = 0; j < this.otherAxes[i].length; j++) + { + this.cmd("Delete", this.otherAxes[i][j]); + } + } + + + var i; + for (i = 0; i < ChangeCoordinate2D.ROBOT_POINTS.length; i++) + { + + this.cmd("Delete", this.RobotPointRobotIDs[i]); + this.cmd("Delete", this.RobotPointWorldIDs[i]); + } + for (i = 0; i < ChangeCoordinate2D.HAND_POINTS.length; i++) + { + this.cmd("Delete", this.HandPointHandIDs[i]); + this.cmd("Delete", this.HandPointRobotIDs[i]); + this.cmd("Delete", this.HandPointWorldIDs[i]); + } + this.cmd("Delete", this.RobotHandAttachRobotID); + this.cmd("Delete", this.RobotHandAttachWorldID); + this.PositionIndex+= 1; + if (this.PositionIndex >= ChangeCoordinate2D.ROBOT_POSITION_VALUES.length) + { + this.PositionIndex = 0; + } + + this.RobotPositionValues = ChangeCoordinate2D.ROBOT_POSITION_VALUES[this.PositionIndex]; + this.RobotMatrixValues = ChangeCoordinate2D.ROBOT_MATRIX_VALUES[this.PositionIndex]; + this.HandPositionValues = ChangeCoordinate2D.HAND_POSITION_VALUES[this.PositionIndex]; + this.HandMatrixValues = ChangeCoordinate2D.HAND_MATRIX_VALUES[this.PositionIndex]; + + this.setupExtraAxes(); + this.setupObjects(); + + + this.RobotPosition.data = [this.RobotPositionValues]; + this.RobotMatrix.data = this.RobotMatrixValues; + this.HandPosition.data = [this.HandPositionValues]; + this.HandMatrix.data =this.HandMatrixValues; + if (!this.rowMajor) + { + this.RobotPosition.transpose(); + this.RobotMatrix.transpose(); + this.HandPosition.transpose(); + this.HandMatrix.transpose(); + } + this.resetMatrixLabels(this.RobotMatrix); + this.resetMatrixLabels(this.RobotPosition); + this.resetMatrixLabels(this.HandMatrix); + this.resetMatrixLabels(this.HandPosition); + + + return this.commands; +} + + +function toRadians(degrees) +{ + return (degrees * 2 * Math.PI) / 360.0; +} + + +ChangeCoordinate2D.prototype.addMatrix = function(mat1, mat2, mat3) +{ + var i; + var j; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat1.data[i].length; j++) + { + explainText = ""; + var value = 0; + this.cmd("SetHighlight", mat1.dataID[i][j], 1); + this.cmd("SetHighlight", mat2.dataID[i][j], 1); + this.cmd("Step"); + mat3.data[i][j] = this.standardize(mat1.data[i][j] + mat2.data[i][j]); + this.cmd("SetHighlight", mat1.dataID[i][j], 0); + this.cmd("SetHighlight", mat2.dataID[i][j], 0); + this.cmd("SetText", mat3.dataID[i][j], mat3.data[i][j]); + this.cmd("Step"); + } + } +} + + + + +ChangeCoordinate2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) +{ + var i; + var j; + var explainText = ""; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat2.data[0].length; j++) + { + var explainText = ""; + var value = 0; + for (k = 0; k < mat2.data.length; k++) + { + this.cmd("SetHighlight", mat1.dataID[i][k], 1); + this.cmd("SetHighlight", mat2.dataID[k][j], 1); + if (explainText != "") + { + explainText = explainText + " + "; + } + value = value + mat1.data[i][k] * mat2.data[k][j]; + explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); + this.cmd("SetText", explainID, explainText); + this.cmd("Step"); + this.cmd("SetHighlight", mat1.dataID[i][k], 0); + this.cmd("SetHighlight", mat2.dataID[k][j], 0); + } + value = this.standardize(value); + explainText += " = " + String(value); + this.cmd("SetText", explainID, explainText); + mat3.data[i][j] = value; + this.cmd("SetText", mat3.dataID[i][j], value); + this.cmd("Step"); + } + } + this.cmd("SetText", explainID, ""); + + +} + +ChangeCoordinate2D.prototype.standardize = function(lab) +{ + var newLab = Math.round(lab * 1000) / 1000; + if (isNaN(newLab)) + { + return lab; + } + else + { + return newLab; + } +} + + +ChangeCoordinate2D.prototype.resetMatrixLabels = function(mat) +{ + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + mat.data[i][j] = this.standardize(mat.data[i][j]); + this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); + } + } +} + + + +ChangeCoordinate2D.prototype.moveMatrix = function(mat, x, y) +{ + var height = mat.data.length; + var width = 0; + + var i, j; + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + } + + + this.cmd("Move", mat.leftBrack1, x, y); + this.cmd("Move", mat.leftBrack2, x, y); + this.cmd("Move", mat.leftBrack3, x, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + + this.cmd("Move", mat.rightBrack1, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack2, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack3, x+ width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Move", mat.dataID[i][j], + x + j*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2, + y + i*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2); + } + } + mat.x = x; + mat.y = y; +} + + + + +ChangeCoordinate2D.prototype.addMatrixIDsToList = function(mat, list) +{ + list.push(mat.leftBrack1); + list.push(mat.leftBrack2); + list.push(mat.leftBrack3); + list.push(mat.rightBrack1); + list.push(mat.rightBrack2); + list.push(mat.rightBrack3); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + list.push(mat.dataID[i][j]); + } + + } +} + +ChangeCoordinate2D.prototype.deleteMatrix = function(mat) +{ + var IDList = []; + this.addMatrixIDsToList(mat, IDList); + var i; + for (i = 0; i < IDList.length; i++) + { + this.cmd("Delete", IDList[i]); + } +} + + + + +ChangeCoordinate2D.prototype.aplyFunctionToMatrixElems = function(mat, command, value) +{ + this.cmd(command, mat.leftBrack1, value); + this.cmd(command, mat.leftBrack2, value); + this.cmd(command, mat.leftBrack3, value); + this.cmd(command, mat.rightBrack1, value); + this.cmd(command, mat.rightBrack2, value); + this.cmd(command, mat.rightBrack3, value); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd(command, mat.dataID[i][j], value); + } + } +} + + + +// Multiply two (data only!) matrices (not complete matrix object with graphics, just +// the data +ChangeCoordinate2D.prototype.multiply = function(lhs, rhs) +{ + var resultMat = new Array(lhs.length); + var i, j, k; + + for (i = 0; i < lhs.length; i++) + { + resultMat[i] = new Array(rhs[0].length); + } + for (i = 0; i < lhs.length; i++) + { + for (j = 0; j < rhs[0].length; j++) + { + var value = 0; + for (k = 0; k < rhs.length; k++) + { + value = value + lhs[i][k] * rhs[k][j]; + } + resultMat[i][j] = value; + } + } + return resultMat; +} + +// Add two (data only!) matrices (not complete matrix object with graphics, just +// the data) +ChangeCoordinate2D.prototype.add = function(lhs, rhs) +{ + var resultMat = new Array(lhs.length); + var i,j; + + for (i = 0; i < lhs.length; i++) + { + resultMat[i] = new Array(lhs[i].length); + for (j = 0; j < lhs[i].length; j++) + { + resultMat[i][j] = lhs[i][j] + rhs[i][j]; + + } + } + return resultMat; +} + + +ChangeCoordinate2D.prototype.createMatrix = function(contents, x, y) +{ + var mat = new Matrix(contents, x, y); + mat.leftBrack1 = this.nextIndex++; + mat.leftBrack2 = this.nextIndex++; + mat.leftBrack3 = this.nextIndex++; + mat.rightBrack1 = this.nextIndex++; + mat.rightBrack2 = this.nextIndex++; + mat.rightBrack3 = this.nextIndex++; + + var height = mat.data.length; + var width = 0; + + var i, j; + mat.dataID = new Array(mat.data.length); + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + mat.dataID[i] = new Array(mat.data[i].length); + for (j = 0; j < mat.data[i].length; j++) + { + mat.dataID[i][j] = this.nextIndex++; + } + } + + this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); + this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); + this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT , "left","center"); + + this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y, "right","center"); + this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT, x + width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y, "center","top"); + this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * ChangeCoordinate2D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate2D.MATRIX_ELEM_HEIGHT , "right","center"); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], + x + j*ChangeCoordinate2D.MATRIX_ELEM_WIDTH + ChangeCoordinate2D.MATRIX_ELEM_WIDTH / 2, + y + i*ChangeCoordinate2D.MATRIX_ELEM_HEIGHT + ChangeCoordinate2D.MATRIX_ELEM_HEIGHT / 2); + } + } + return mat; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new ChangeCoordinate2D(animManag, canvas.width, canvas.height); +} + +function Matrix(contents, x, y) +{ + this.data = contents; + this.x = x; + this.y = y; +} + +Matrix.prototype.transpose = function() +{ + var newData = new Array(this.data[0].length); + var i,j; + for (i = 0; i < this.data[0].length; i++) + { + newData[i] = new Array(this.data.length); + } + for (i = 0; i < this.data.length; i++) + { + for (j = 0; j < this.data[i].length; j++) + { + newData[j][i] = this.data[i][j]; + } + } + this.data = newData; +} + + + + + diff --git a/AlgorithmLibrary/ChangingCoordinate3D.js b/AlgorithmLibrary/ChangingCoordinate3D.js index dc7cbfd..93cc6cb 100644 --- a/AlgorithmLibrary/ChangingCoordinate3D.js +++ b/AlgorithmLibrary/ChangingCoordinate3D.js @@ -1,1772 +1,1770 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function ChangeCoordinate3D(am, w, h) -{ - this.init(am, w, h); -} - - -ChangeCoordinate3D.prototype = new Algorithm(); -ChangeCoordinate3D.prototype.constructor = ChangeCoordinate3D; -ChangeCoordinate3D.superclass = Algorithm.prototype; - -ChangeCoordinate3D.XAxisYPos = 300; -ChangeCoordinate3D.XAxisStart = 100; -ChangeCoordinate3D.XAxisEnd = 700; - -ChangeCoordinate3D.MATRIX_ELEM_WIDTH = 40; -ChangeCoordinate3D.MATRIX_ELEM_HEIGHT = 15; - - -ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING = 5; -ChangeCoordinate3D.EQUALS_SPACING = 20; - -ChangeCoordinate3D.ROBOT_MATRIX_START_X = 10 + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; -ChangeCoordinate3D.ROBOT_MATRIX_START_Y = 30; - -ChangeCoordinate3D.HAND_MATRIX_START_X = 10 +3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; -ChangeCoordinate3D.HAND_MATRIX_START_Y = 10 + 25 + 20 + 20 + 3*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; - - -ChangeCoordinate3D.ROBOT_POSITION_START_X = ChangeCoordinate3D.ROBOT_MATRIX_START_X + 5*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + 100; -ChangeCoordinate3D.HAND_POSITION_START_X = ChangeCoordinate3D.HAND_MATRIX_START_X + 5*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + 100; - - -ChangeCoordinate3D.ROBOT_POSITION_START_Y = ChangeCoordinate3D.ROBOT_MATRIX_START_Y; -ChangeCoordinate3D.HAND_POSITION_START_Y = ChangeCoordinate3D.HAND_MATRIX_START_Y; - - -ChangeCoordinate3D.YAxisXPos = 400; -ChangeCoordinate3D.YAxisStart = 100; -ChangeCoordinate3D.YAxisEnd = 500; - -ChangeCoordinate3D.ROBOT_POINTS = [[-15,5,100],[15,5,100],[15, 5,80],[30,5,80],[30,5,-10],[15,5,-10], [15,5, -100], [0,5,-100],[0,5,-30],[0,5,-100], [-15,5, -100], - [-15,5,-10], [-30, 5,-10], [-30, 5, 80],[-15, 5, 80], [-15, 5, 100], - - [-15,-5,100],[15,-5,100],[15, -5,80],[30,-5,80],[30,-5,-10],[15,-5,-10], [15,-5, -100], [0,-5,-100],[0,-5,-30],[0,-5,-100], [-15,-5, -100], - [-15,-5,-10], [-30, -5,-10], [-30, -5, 80],[-15, -5, 80], [-15, -5, 100]]; - -ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS = [[0, 16], [1, 17], [2, 18], [3, 19], [4, 20], [5, 21], [6, 22], [7, 23], [8, 24], [9, 25], - [10, 26], [11, 27], [12, 28], [13, 29], [14, 30], [15, 31]]; - - - -ChangeCoordinate3D.HAND_POINTS = [[0,3, 0],[-10,3, 0],[-10,3, 10], [-6, 3,10], [-6, 3,6], [6, 3,6], [6, 3, 10], [10, 3, 10], [10, 3, 0],[0,3,0], - [0,-3, 0],[-10,-3, 0],[-10,-3, 10], [-6, -3,10], [-6, -3,6], [6, -3,6], [6, -3, 10], [10, -3, 10], [10, -3, 0],[0,-3,0]]; - - - -ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS = [[0, 10], [1, 11], [2, 12], [3, 13], [4, 14], [5, 15], [6, 16], [7, 17], [8, 18], [9, 19]]; - - -ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT = [0, 0,40]; - - -ChangeCoordinate3D.M1 = [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4), 0],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4), 0],[0,0,1]]; -ChangeCoordinate3D.M2 = [[Math.cos(3*Math.PI / 4), 0, Math.sin(3*Math.PI/4)],[0,1,0], [-Math.sin(3*Math.PI/4), 0, Math.cos(3*Math.PI/4)]]; -ChangeCoordinate3D.M3 = [[1,0,0], [0, Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4)],[0, -Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4)]]; - - - -ChangeCoordinate3D.ROBOT_MATRIX_VALUES = [ - [[1,0,0],[0, Math.cos(Math.PI / 6), Math.sin(Math.PI / 6)],[0, -Math.sin(Math.PI / 6), Math.cos(Math.PI / 6)]], - [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4), 0],[-Math.sin(Math.PI / 4), Math.cos(Math.PI / 4), 0], [0,0,1]], - [[Math.cos(0), Math.sin(0), 0],[-Math.sin(0), Math.cos(0), 0], [0, 0, 1]], - [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4), 0],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4), 0],[0,0,1]], - multiply(ChangeCoordinate3D.M2, ChangeCoordinate3D.M3) - - ]; - - -ChangeCoordinate3D.ROBOT_POSITION_VALUES = [[75,0, 40], [200,100, 30],[100,100, 0], [100, 200, 0], [40,50,50]]; - - -ChangeCoordinate3D.HAND_MATRIX_VALUES = [ - [[Math.cos(-Math.PI / 4),0, Math.sin(-Math.PI / 4)],[0,1,0],[-Math.sin(-Math.PI / 4), 0, Math.cos(-Math.PI / 4)]], - [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4), 0],[-Math.sin(Math.PI / 4), Math.cos(-Math.PI / 4), 0], [0,0,1]], - [[Math.cos(0), Math.sin(0), 0],[-Math.sin(0), Math.cos(0), 0], [0,0,1]], - [[Math.cos(Math.PI/2), Math.sin(Math.PI/2), 0],[-Math.sin(Math.PI/2), Math.cos(Math.PI/2), 0], [0,0,1]], - multiply(ChangeCoordinate3D.M1, ChangeCoordinate3D.M2) - ]; - - -ChangeCoordinate3D.HAND_POSITION_VALUES = [[80,0, 20],[30,90, 0],[100,100, 0],[-50, -20, 0], [50,10,20]]; - - -//ChangeCoordinate3D.ROBOT_POINTS = [[-20, 40], [20,40],[ - - -ChangeCoordinate3D.CAMERA_TRANS_ANGLE = toRadians(30); -ChangeCoordinate3D.L = 0.5; - -ChangeCoordinate3D.CAMERA_TRANSFORM = [[1, 0, 0], - [ChangeCoordinate3D.L * Math.cos(ChangeCoordinate3D.CAMERA_TRANS_ANGLE), 0, ChangeCoordinate3D.L * Math.sin(ChangeCoordinate3D.CAMERA_TRANS_ANGLE)], - [0, 0, 1]]; - - -ChangeCoordinate3D.AXIS_CENTER = [[750,470],[750,150],[100, 550]]; - -ChangeCoordinate3D.AXIS_COLOR_0 = "#990000" -ChangeCoordinate3D.AXIS_COLOR_1 = "#009900" -ChangeCoordinate3D.AXIS_COLOR_2 = "#000099" - -ChangeCoordinate3D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; -ChangeCoordinate3D.LOCAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.LOCAL_VERTEX_FOREGORUND_COLOR; -ChangeCoordinate3D.LOCAL_EDGE_COLOR = "#000000"; - -ChangeCoordinate3D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; -ChangeCoordinate3D.GLOBAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.GLOBAL_VERTEX_FOREGORUND_COLOR; -ChangeCoordinate3D.GLOBAL_EDGE_COLOR = "#00FF00"; - - - -ChangeCoordinate3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; -ChangeCoordinate3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.VERTEX_FOREGORUND_COLOR; -ChangeCoordinate3D.TRANSFORMED_EDGE_COLOR = "#66FF66"; - - -ChangeCoordinate3D.TRANSFORMED_POINT_COLORS = ["#990000", "#009900", "#000099"] - - -ChangeCoordinate3D.VECTOR_COLOR = "#FF0000"; - -ChangeCoordinate3D.VERTEX_WIDTH = 3; -ChangeCoordinate3D.VERTEX_HEIGHT = ChangeCoordinate3D.VERTEX_WIDTH; - -ChangeCoordinate3D.prototype.init = function(am, w, h) -{ - var sc = ChangeCoordinate3D.superclass.init.call(this, am, w, h); - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.addControls(); - this.currentShape = 0; - - this.cameraTransform = ChangeCoordinate3D.CAMERA_TRANSFORM; - - this.commands = []; - this.nextIndex = 0; - - this.PositionIndex = 0; - - this.RobotPositionValues = ChangeCoordinate3D.ROBOT_POSITION_VALUES[this.PositionIndex]; - this.RobotMatrixValues = ChangeCoordinate3D.ROBOT_MATRIX_VALUES[this.PositionIndex]; - this.HandPositionValues = ChangeCoordinate3D.HAND_POSITION_VALUES[this.PositionIndex]; - this.HandMatrixValues = ChangeCoordinate3D.HAND_MATRIX_VALUES[this.PositionIndex]; - - this.setupAxis(); - - this.robotLabel1ID = this.nextIndex++; - this.handLabel1ID = this.nextIndex++; - this.robotLabel2ID = this.nextIndex++; - this.handLabel2ID = this.nextIndex++; - - this.cmd("CreateLabel", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)", ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.robotLabel1ID, "#0000FF"); - - this.cmd("CreateLabel", this.robotLabel2ID, "Robot Space to World Space\n(Position)", ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.robotLabel2ID, "#0000FF"); - - - - this.RobotMatrix = this.createMatrix(this.RobotMatrixValues, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y); - this.resetMatrixLabels(this.RobotMatrix); - this.HandMatrix = this.createMatrix(this.HandMatrixValues, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y); - this.resetMatrixLabels(this.HandMatrix); - - this.cmd("CreateLabel", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)", ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.handLabel1ID, "#0000FF"); - - this.cmd("CreateLabel", this.handLabel2ID, "Hand Space to Robot Space\n(Position)", ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25, 0); - this.cmd("SetForegroundColor", this.handLabel2ID, "#0000FF"); - - - - this.RobotPosition = this.createMatrix([this.RobotPositionValues], ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y); - this.resetMatrixLabels(this.RobotMatrix); - this.HandPosition = this.createMatrix([this.HandPositionValues], ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); - this.resetMatrixLabels(this.HandMatrix); - - - var i; - this.RobotPointWorldIDs = new Array(ChangeCoordinate3D.ROBOT_POINTS.length); - this.RobotPointRobotIDs = new Array(ChangeCoordinate3D.ROBOT_POINTS.length); - this.HandPointWorldIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); - this.HandPointRobotIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); - this.HandPointHandIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); - this.RobotHandAttachRobotID = this.nextIndex++; - this.RobotHandAttachWorldID = this.nextIndex++; - for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) - { - this.RobotPointWorldIDs[i] = this.nextIndex++; - this.RobotPointRobotIDs[i] = this.nextIndex++; - } - for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) - { - this.HandPointWorldIDs[i] = this.nextIndex++; - this.HandPointRobotIDs[i] = this.nextIndex++; - this.HandPointHandIDs[i] = this.nextIndex++; - } - - this.savedNextIndex = this.nextIndex; - this.setupObjects(); - this.setupObjectGraphic(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); - this.animationManager.setAllLayers([0, 1]); - this.lastLocalToGlobal = true; - this.oldIDs = []; - - -} - -ChangeCoordinate3D.prototype.addAxis = function(origin, x1, x2, y1, y2, z1, z2, color) -{ - var idArray = []; - var originID = this.nextIndex++; - idArray.push(originID); - this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); - this.cmd("SetAlpha", originID, 0); - - var axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, x1[0], x1[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, x2[0], x2[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, y1[0], y1[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, y2[0], y2[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, z1[0], z1[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - axisID = this.nextIndex++; - this.cmd("CreateRectangle", axisID, "", 0, 0, z2[0], z2[1]); - this.cmd("SetAlpha", axisID, 0); - this.cmd("Connect", originID, axisID, color, 0, 1, ""); - idArray.push(axisID); - - - - var labelID = this.nextIndex++; - this.cmd("CreateLabel", labelID, "+y", y2[0] - 10, y2[1] + 10); - this.cmd("SetForegroundColor", labelID, color); - idArray.push(labelID); - - - labelID = this.nextIndex++; - this.cmd("CreateLabel", labelID, "+x", x2[0] - 10, x2[1] + 10); - this.cmd("SetForegroundColor", labelID, color); - idArray.push(labelID); - - - labelID = this.nextIndex++; - this.cmd("CreateLabel", labelID, "+z", z2[0] - 10, z2[1] + 10); - this.cmd("SetForegroundColor", labelID, color); - idArray.push(labelID); - - - return idArray; -} - - -ChangeCoordinate3D.prototype.transformPoint = function(point, matrix, position) -{ - return this.add(multiply([point], matrix), [position])[0]; -} - - -ChangeCoordinate3D.prototype.setupExtraAxes = function() -{ - var robotOrigin = this.RobotPositionValues; - var x1 = this.transformPoint([-150, 0, 0], this.RobotMatrixValues, this.RobotPositionValues); - var x2 = this.transformPoint([150, 0, 0], this.RobotMatrixValues, this.RobotPositionValues); - var y1 = this.transformPoint([0, -150, 0], this.RobotMatrixValues, this.RobotPositionValues); - var y2 = this.transformPoint([0, 150, 0], this.RobotMatrixValues, this.RobotPositionValues); - var z1 = this.transformPoint([0, 0, -150], this.RobotMatrixValues, this.RobotPositionValues); - var z2 = this.transformPoint([0, 0, 150], this.RobotMatrixValues, this.RobotPositionValues); - - this.otherAxes = []; - - var tmpAxis = this.addAxis(this.worldToScreenSpace(robotOrigin, 2), - this.worldToScreenSpace(x1, 2), - this.worldToScreenSpace(x2, 2), - this.worldToScreenSpace(y1, 2), - this.worldToScreenSpace(y2, 2), - this.worldToScreenSpace(z1, 2), - this.worldToScreenSpace(z2, 2), - ChangeCoordinate3D.AXIS_COLOR_1); - - this.otherAxes.push(tmpAxis); - - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - this.setAxisAlpha(tmpAxis, 0.5); - - - var handOrigin = this.HandPositionValues; - x1 = this.transformPoint([-150, 0, 0], this.HandMatrixValues, this.HandPositionValues); - x2 = this.transformPoint([150, 0, 0], this.HandMatrixValues, this.HandPositionValues); - y1 = this.transformPoint([0, -150, 0], this.HandMatrixValues, this.HandPositionValues); - y2 = this.transformPoint([0, 150, 0], this.HandMatrixValues, this.HandPositionValues); - z1 = this.transformPoint([0, 0, -150], this.HandMatrixValues, this.HandPositionValues); - z2 = this.transformPoint([0, 0, 150], this.HandMatrixValues, this.HandPositionValues); - - - tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 1), - this.worldToScreenSpace(x1, 1), - this.worldToScreenSpace(x2, 1), - this.worldToScreenSpace(y1, 1), - this.worldToScreenSpace(y2, 1), - this.worldToScreenSpace(z1, 1), - this.worldToScreenSpace(z2, 1), - ChangeCoordinate3D.AXIS_COLOR_0); - - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - this.setAxisAlpha(tmpAxis, 0.5); - - - this.otherAxes.push(tmpAxis); - - - handOrigin = this.transformPoint(handOrigin, this.RobotMatrixValues, this.RobotPositionValues); - x1 = this.transformPoint(x1, this.RobotMatrixValues, this.RobotPositionValues); - x2 = this.transformPoint(x2, this.RobotMatrixValues, this.RobotPositionValues); - y1 = this.transformPoint(y1, this.RobotMatrixValues, this.RobotPositionValues); - y2 = this.transformPoint(y2, this.RobotMatrixValues, this.RobotPositionValues); - z1 = this.transformPoint(z1, this.RobotMatrixValues, this.RobotPositionValues); - z2 = this.transformPoint(z2, this.RobotMatrixValues, this.RobotPositionValues); - - - tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 2), - this.worldToScreenSpace(x1, 2), - this.worldToScreenSpace(x2, 2), - this.worldToScreenSpace(y1, 2), - this.worldToScreenSpace(y2, 2), - this.worldToScreenSpace(z1, 2), - this.worldToScreenSpace(z2, 2), - ChangeCoordinate3D.AXIS_COLOR_0); - for (var i = 0; i < tmpAxis.length; i++) - { - this.cmd("SetLayer", tmpAxis[i], 1); - } - - this.setAxisAlpha(tmpAxis, 0.5); - - this.otherAxes.push(tmpAxis); - -} - - -ChangeCoordinate3D.prototype.setupAxis = function() -{ - - this.axisHand = this.addAxis(this.worldToScreenSpace([0,0,0], 0), - this.worldToScreenSpace([-150, 0, 0], 0), - this.worldToScreenSpace([150,0, 0], 0), - this.worldToScreenSpace([0, -150, 0], 0), - this.worldToScreenSpace([0, 150, 0], 0), - this.worldToScreenSpace([0, 0, -150], 0), - this.worldToScreenSpace([0, 0, 150], 0), - ChangeCoordinate3D.AXIS_COLOR_0); - this.setAxisAlpha(this.axisHand, 0.5); - - this.axisRobot = this.addAxis(this.worldToScreenSpace([0,0, 0], 1), - this.worldToScreenSpace([-150, 0, 0], 1), - this.worldToScreenSpace([150,0, 0], 1), - this.worldToScreenSpace([0, -150, 0], 1), - this.worldToScreenSpace([0, 150, 0], 1), - this.worldToScreenSpace([0, 0, -150], 1), - this.worldToScreenSpace([0, 0, 150], 1), - ChangeCoordinate3D.AXIS_COLOR_1); - this.setAxisAlpha(this.axisRobot, 0.5); - - this.axisWorld = this.addAxis(this.worldToScreenSpace([0,0, 0], 2), - this.worldToScreenSpace([-50, 0, 0], 2), - this.worldToScreenSpace([400,0, 0], 2), - this.worldToScreenSpace([0, -50, 0], 2), - this.worldToScreenSpace([0, 400, 0], 2), - this.worldToScreenSpace([0, 0, -50], 2), - this.worldToScreenSpace([0, 0, 400], 2), - ChangeCoordinate3D.AXIS_COLOR_2); - this.setAxisAlpha(this.axisWorld, 0.5); - - this.setupExtraAxes(); - - - - - -} - - -ChangeCoordinate3D.prototype.setAxisAlpha = function(axisList, newAlpha) -{ - for (var i = 0; i < axisList.length; i++) - { - this.cmd("SetAlpha", axisList[i], newAlpha); - if (i > 0) - { - this.cmd("SetEdgeAlpha", axisList[0], axisList[i], newAlpha); - } - } - -} - -ChangeCoordinate3D.prototype.setupObjects = function() -{ - - var i; - for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) - { - - - var point = this.worldToScreenSpace(ChangeCoordinate3D.ROBOT_POINTS[i], 1); - this.cmd("CreateRectangle", this.RobotPointRobotIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.RobotPointRobotIDs[i-1], this.RobotPointRobotIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(ChangeCoordinate3D.ROBOT_POINTS[i], this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point, 2); - - this.cmd("CreateRectangle", this.RobotPointWorldIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.RobotPointWorldIDs[i-1], this.RobotPointWorldIDs[i], "#000000", 0, 0); - } - } - - for (var i = 0; i < ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS.length; i++) - { - this.cmd("Connect", this.RobotPointRobotIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][0]], this.RobotPointRobotIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); - this.cmd("Connect", this.RobotPointWorldIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][0]], this.RobotPointWorldIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); - } - - - - for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) - { - - - var point = this.worldToScreenSpace(ChangeCoordinate3D.HAND_POINTS[i], 0); - this.cmd("CreateRectangle", this.HandPointHandIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointHandIDs[i-1], this.HandPointHandIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(ChangeCoordinate3D.HAND_POINTS[i], this.HandMatrixValues, this.HandPositionValues); - var point2 = this.worldToScreenSpace(point, 1); - - this.cmd("CreateRectangle", this.HandPointRobotIDs[i], "", 0, 0, point2[0], point2[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointRobotIDs[i-1], this.HandPointRobotIDs[i], "#000000", 0, 0); - } - - point = this.transformPoint(point, this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point,2); - - this.cmd("CreateRectangle", this.HandPointWorldIDs[i], "", 0, 0, point[0], point[1]); - if (i > 0) - { - this.cmd("Connect", this.HandPointWorldIDs[i-1], this.HandPointWorldIDs[i], "#000000", 0, 0); - } - } - for (var i = 0; i < ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS.length; i++) - { - this.cmd("Connect", this.HandPointHandIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointHandIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); - this.cmd("Connect", this.HandPointRobotIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointRobotIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); - this.cmd("Connect", this.HandPointWorldIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointWorldIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); - } - - - - point = this.worldToScreenSpace(ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT, 1); - this.cmd("CreateRectangle", this.RobotHandAttachRobotID, "", 0, 0, point[0], point[1]); - this.cmd("Connect", this.RobotHandAttachRobotID, this.HandPointRobotIDs[0], "#000000", 0, 0); - - point = this.transformPoint(ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT, this.RobotMatrixValues, this.RobotPositionValues); - point = this.worldToScreenSpace(point, 2); - this.cmd("CreateRectangle", this.RobotHandAttachWorldID, "", 0, 0, point[0], point[1]); - this.cmd("Connect", this.RobotHandAttachWorldID, this.HandPointWorldIDs[0], "#000000", 0, 0); -} - - - -ChangeCoordinate3D.prototype.worldToScreenSpace = function(point, space) -{ - var transformedPoint = multiply([point], this.cameraTransform)[0]; - var worldSpace = new Array(2); - worldSpace[0] = transformedPoint[0] + ChangeCoordinate3D.AXIS_CENTER[space][0]; - worldSpace[1] = ChangeCoordinate3D.AXIS_CENTER[space][1] - transformedPoint[2]; - - return worldSpace; -} - - - - -ChangeCoordinate3D.prototype.removeOldIDs = function() -{ - var i; - for (i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs = []; -} - - - -ChangeCoordinate3D.prototype.setupObjectGraphic = function() -{ - var i; - - - - -} - -ChangeCoordinate3D.prototype.addControls = function() -{ - this.controls = []; - - addLabelToAlgorithmBar("x"); - - this.xField = this.addControlToAlgorithmBar("Text", ""); - this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); - this.controls.push(this.xField); - - addLabelToAlgorithmBar("y"); - - this.yField = this.addControlToAlgorithmBar("Text", ""); - this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); - this.controls.push(this.yField); - - - addLabelToAlgorithmBar("z"); - - this.zField = this.addControlToAlgorithmBar("Text", ""); - this.zField.onkeydown = this.returnSubmitFloat(this.zField, this.transformPointCallback.bind(this), 4, true); - this.controls.push(this.zField); - - - var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); - transformButton.onclick = this.transformPointCallback.bind(this); - this.controls.push(transformButton); - - - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", - "World Space -> Hand Space", - ], - "Transform Type"); - this.handToWorldButton = radioButtonList[0]; - this.handToWorldButton.onclick = this.transformTypeChangedCallback.bind(this, false); - this.controls.push(this.handToWorldButton); - - - this.worldToHandButton = radioButtonList[1]; - this.worldToHandButton.onclick = this.transformTypeChangedCallback.bind(this, true); - this.controls.push(this.worldToHandButton); - - this.worldToHandButton.checked = this.lastLocalToGlobal; - this.handToWorldButton.checked = !this.lastLocalToGlobal; - - - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", - "Column Major", - ], - "RankType"); - this.rowMajorButton = radioButtonList[0]; - this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); - this.controls.push(this.rowMajorButton); - - this.colMajorButton = radioButtonList[1]; - this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); - this.controls.push(this.colMajorButton); - - this.rowMajorButton.checked = this.rowMajor; - this.colMajorButton.checked = !this.rowMajor; - - - this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); - this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); - this.showAxisBox.checked = true; - - //this.controls.push(this.showAxisBox); - - - - var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); - moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); - - this.controls.push(moveObjectsButton); - -} - - - -ChangeCoordinate3D.prototype.showAllAxesCallback = function() -{ - if (this.showAxisBox.checked) - { - this.animationManager.setAllLayers([0,1]); - } - else - { - this.animationManager.setAllLayers([0]); - } - - -} - - -ChangeCoordinate3D.prototype.reset = function() -{ - this.rowMajor = true; - this.rowMajorButton.checked = this.rowMajor; - this.nextIndex = this.savedNextIndex; -} - - -ChangeCoordinate3D.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -ChangeCoordinate3D.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -ChangeCoordinate3D.prototype.transformTypeChangedCallback = function(globalToLocal) -{ - if (this.lastLocalToGlobal == globalToLocal) - { - this.implementAction(this.changeTransformType.bind(this,globalToLocal)); - } -} - - - - -ChangeCoordinate3D.prototype.changeRowColMajorCallback = function(rowMajor) -{ - if (this.rowMajor != rowMajor) - { - this.implementAction(this.changeRowCol.bind(this), rowMajor); - } -} - -ChangeCoordinate3D.prototype.transposeVisual = function(matrix) -{ - if (matrix.data.length == matrix.data[0].length) - { - var matrixSize = matrix.data.length; - var i, j, tmp, moveLabel1, moveLabel2; - var moveLabels = []; - for (i = 1; i < matrixSize; i++) - { - for (j = 0; j <= i; j++) - { - this.cmd("SetText", matrix.dataID[i][j], ""); - this.cmd("SetText", matrix.dataID[j][i], ""); - moveLabel1 = this.nextIndex++; - moveLabel2 = this.nextIndex++; - moveLabels.push(moveLabel1); - moveLabels.push(moveLabel2); - this.cmd("CreateLabel", moveLabel1, - this.standardize(matrix.data[i][j]), matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - this.cmd("CreateLabel", moveLabel2, - this.standardize(matrix.data[j][i]), matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - this.cmd("Move", moveLabel1, matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - this.cmd("Move", moveLabel2, matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + j * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - tmp = matrix.data[i][j]; - matrix.data[i][j] = matrix.data[j][i]; - matrix.data[j][i] = tmp; - } - } - this.cmd("Step"); - for (i = 0; i < moveLabels.length; i++) - { - this.cmd("Delete", moveLabels[i]); - } - this.resetMatrixLabels(matrix); - return matrix; - } - else - { - var savedData = matrix.data; - var newData = new Array(savedData[0].length); - var i,j; - for (i = 0; i < savedData[0].length; i++) - { - newData[i] = []; - } - for (i = 0; i < savedData.length; i++) - { - for (j = 0; j < savedData[0].length; j++) - { - newData[j][i] = savedData[i][j]; - } - - } - var newMatrix = this.createMatrix(newData, matrix.x, matrix.y); - this.deleteMatrix(matrix); - return newMatrix; - } -} - -ChangeCoordinate3D.prototype.changeRowCol = function(rowMajor) -{ - this.commands = new Array(); - this.rowMajor= rowMajor; - if (this.rowMajorButton.checked != this.rowMajor) - { - this.rowMajorButton.checked = this.rowMajor; - } - if (this.colMajorButton.checked == this.rowMajor) - { - this.colMajorButton.checked = !this.rowMajor; - } - this.removeOldIDs(); - this.RobotMatrix = this.transposeVisual(this.RobotMatrix); - this.RobotPosition = this.transposeVisual(this.RobotPosition); - this.HandMatrix = this.transposeVisual(this.HandMatrix); - this.HandPosition = this.transposeVisual(this.HandPosition); - - - return this.commands; -} - - -ChangeCoordinate3D.prototype.fixNumber = function(value, defaultVal) -{ - if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) - { - value = defaultVal; - } - else - { - value = String(parseFloat(value)); - } - return value -} - -ChangeCoordinate3D.prototype.transformPointCallback = function() -{ - - - this.xField.value = this.fixNumber(this.xField.value, "0"); - this.yField.value = this.fixNumber(this.yField.value, "0"); - this.zField.value = this.fixNumber(this.zField.value, "0"); - this.implementAction(this.doPointTransform.bind(this), this.xField.value + ";" + this.yField.value + ";" + this.zField.value); - -} - - -ChangeCoordinate3D.prototype.doPointTransform = function(params) -{ - if (this.lastLocalToGlobal) - { - return this.localToGlobal(params); - } - else - { - return this.globalToLocal(params); - } -} - - - - - -ChangeCoordinate3D.prototype.rotatePoint = function(point, matrix, xPos, yPos, fromSpace, toSpace) -{ - var logicalPoint; - var descriptLabel = this.nextIndex++; - // this.oldIDs.push(descriptLabel); - if (this.rowMajor) - { - this.cmd("CreateLabel", descriptLabel, "", xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, - yPos + 2*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + 3, 0); - } - else - { - this.cmd("CreateLabel", descriptLabel, "", xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, - yPos + 3*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + 3, 0); - - } - - var inertialPositionMatrix; - - if (this.rowMajor) - { - inertialPositionMatrix = this.createMatrix([["", "", ""]], xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, - yPos); - } - else - { - inertialPositionMatrix = this.createMatrix([[""], [""], [""]], - xPos + 4 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, - yPos); - - } - var equalLabel1 = this.nextIndex++; - this.oldIDs.push(equalLabel1); - if (this.rowMajor) - { - opX = xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; - } - else - { - opX = xPos + 4 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2 + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; - opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; - - - } - - this.cmd("CreateLabel", equalLabel1, "=", opX , opY); - if (this.rowMajor) - { - this.multiplyMatrix(point, matrix, inertialPositionMatrix, descriptLabel, 2); - - } - else - { - this.multiplyMatrix(matrix, point, inertialPositionMatrix, descriptLabel, 2); - - } - this.addMatrixIDsToList(inertialPositionMatrix, this.oldIDs); - this.cmd("Delete", descriptLabel); - var inertialPositionID = this.nextIndex++; - if (this.rowMajor) - { - logicalPoint = inertialPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [inertialPositionMatrix.data[0][0], inertialPositionMatrix.data[1][0], inertialPositionMatrix.data[2][0]]; - } - screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); - - - this.cmd("CreateCircle", inertialPositionID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", inertialPositionID, ChangeCoordinate3D.VERTEX_WIDTH); - - var originID = this.nextIndex++; - this.oldIDs.push(originID); - var origin = this.worldToScreenSpace([0,0,0], fromSpace); - - - this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); - - this.cmd("Connect", originID, inertialPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - - - return [inertialPositionMatrix, inertialPositionID, originID]; -} - -ChangeCoordinate3D.prototype.translatePoint = function(point, transVector, xPos, yPos, fromSpace, toSpace, pointID) -{ - var logicalPoint = new Array(2); - var robotPositionMatrix; - if (this.rowMajor) - { - logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; - logicalPoint[1] = point.data[0][1] + transVector.data[0][1]; - logicalPoint[2] = point.data[0][2] + transVector.data[0][2]; - robotPositionMatrix = this.createMatrix([["", "", ""]], xPos + 3*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, - yPos); - } - else - { - logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; - logicalPoint[1] = point.data[1][0] + transVector.data[1][0]; - logicalPoint[2] = point.data[2][0] + transVector.data[2][0]; - robotPositionMatrix = this.createMatrix([[""],[""], [""]], xPos + ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, - yPos); - - } - - var addLabel1 = this.nextIndex++; - var equalLabel3 = this.nextIndex++; - this.oldIDs.push(addLabel1); - this.oldIDs.push(equalLabel3); - var op2X, op2Y; - if (this.rowMajor) - { - opX = xPos + 3*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; - op2X = xPos - ChangeCoordinate3D.EQUALS_SPACING / 2; - op2Y = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; - - } - else - { - opX = xPos + ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; - opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; - op2X = xPos - ChangeCoordinate3D.EQUALS_SPACING / 2; - op2Y = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; - - - } - this.cmd("CreateLabel", equalLabel3, "=",opX , opY); - this.cmd("CreateLabel", addLabel1, "+",op2X , op2Y); - - - - - this.addMatrix(point, transVector, robotPositionMatrix, 2); - this.addMatrixIDsToList(robotPositionMatrix, this.oldIDs); - - var screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); - - var robotPositionID = this.nextIndex++; - - this.cmd("CreateCircle", robotPositionID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", robotPositionID, ChangeCoordinate3D.VERTEX_WIDTH); - - - this.cmd("Connect",pointID, robotPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - this.cmd("Step") - - - - var originID = this.nextIndex++; - this.oldIDs.push(originID); - var origin = this.worldToScreenSpace([0,0, 0], fromSpace); - - this.cmd("CreateCircle", originID, "", origin[0], origin[1]); - this.cmd("SetWidth", originID, 0); - this.cmd("SetAlpha", originID, 0); - - this.cmd("Connect",originID, robotPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); - - return [robotPositionMatrix, robotPositionID, originID]; - - -} - - -ChangeCoordinate3D.prototype.addMultiply = function(position, transVector, rotMatrix, transX, transY, rotX, rotY, initialPointID, fromSpace, toSpace) -{ - - var posMatrixAndPointID = this.translatePoint(position, transVector, transX, transY, fromSpace, toSpace, initialPointID); - var newPosition = posMatrixAndPointID[0]; - var pointID = posMatrixAndPointID[1]; - var originID = posMatrixAndPointID[2]; - - this.cmd("Step"); - - this.cmd("Disconnect", initialPointID, pointID); - - if (this.rowMajor) - { - this.moveMatrix(newPosition, rotX - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING,transY) - } - else - { - this.moveMatrix(newPosition, rotX + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, transY) - } - - - var posMatrixAndPointID = this.rotatePoint(newPosition, rotMatrix, rotX, rotY, fromSpace, toSpace); - this.cmd("Delete", pointID); - this.cmd("Step"); - - var robotPositionMatrix = posMatrixAndPointID[0]; - var robotPositionID = posMatrixAndPointID[1]; - var movingOriginID = posMatrixAndPointID[2]; - - var origin = this.worldToScreenSpace([0,0, 0], toSpace); - this.cmd("Move", movingOriginID, origin[0], origin[1]); - - - var logicalPoint; - if (this.rowMajor) - { - logicalPoint = robotPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0], robotPositionMatrix.data[2][0]]; - } - - - - - var screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); - this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); - - this.cmd("Step"); - - - this.oldIDs.push(robotPositionID); - - - return [robotPositionMatrix, robotPositionID ]; -} - - -ChangeCoordinate3D.prototype.multiplyAdd = function(position, rotMatrix, transVector, rotX, rotY, transX, transY, fromSpace, toSpace) -{ - var posMatrixAndPointID = this.rotatePoint(position, rotMatrix, rotX, rotY, fromSpace, toSpace); - var inertialPositionMatrix = posMatrixAndPointID[0]; - var inertialPositionID = posMatrixAndPointID[1]; - - - this.cmd("Step"); - - if (this.rowMajor) - { - this.moveMatrix(inertialPositionMatrix, transX - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.EQUALS_SPACING,transY) - } - else - { - this.moveMatrix(inertialPositionMatrix, transX - ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.EQUALS_SPACING, transY) - } - - - posMatrixAndPointID = this.translatePoint(inertialPositionMatrix, transVector, transX, transY, fromSpace, toSpace, inertialPositionID); - var robotPositionMatrix = posMatrixAndPointID[0]; - var robotPositionID = posMatrixAndPointID[1]; - var movingOriginID = posMatrixAndPointID[2]; - - this.oldIDs.push(robotPositionID); - - var logicalPoint; - if (this.rowMajor) - { - logicalPoint = robotPositionMatrix.data[0].slice(0); - - } - else - { - logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0], robotPositionMatrix.data[2][0]]; - } - - - this.cmd("Step"); - - this.cmd("Delete", inertialPositionID); - origin = this.worldToScreenSpace([0,0, 0], toSpace); - this.cmd("Move", movingOriginID, origin[0], origin[1]); - screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); - this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); - - this.cmd("Step"); - return robotPositionMatrix; - -} - -ChangeCoordinate3D.prototype.localToGlobal = function (params) -{ - this.commands = []; - this.removeOldIDs(); - - - var paramList = params.split(";"); - var x = parseFloat(paramList[0]); - var y = parseFloat(paramList[1]); - var z = parseFloat(paramList[2]); - - var opX, opY; - - - var screenPoint = this.worldToScreenSpace([x,y,z], 0); - var logicalPoint; - - var pointInHandSpaceID = this.nextIndex++; - this.oldIDs.push(pointInHandSpaceID); - - this.cmd("CreateCircle", pointInHandSpaceID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", pointInHandSpaceID, ChangeCoordinate3D.VERTEX_WIDTH); - - this.cmd("Connect", this.axisHand[0], pointInHandSpaceID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[0], 0, 1, ""); - - var initialPointMatrix; - if (this.rowMajor) - { - initialPointMatrix = this.createMatrix([[x, y, z]], ChangeCoordinate3D.HAND_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate3D.HAND_MATRIX_START_Y); - } - else - { - initialPointMatrix = this.createMatrix([[x], [y], [z]], ChangeCoordinate3D.HAND_MATRIX_START_X + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate3D.HAND_MATRIX_START_Y); - - } - this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); - this.cmd("Step"); - - var robotPositionMatrix = this.multiplyAdd(initialPointMatrix, this.HandMatrix, this.HandPosition, - ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y, - ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y, - 0, 1); - - - - - if (this.rowMajor) - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate3D.ROBOT_MATRIX_START_Y); - } - else - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X + 3* ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, - ChangeCoordinate3D.ROBOT_MATRIX_START_Y); - - } - - - this.multiplyAdd(robotPositionMatrix, this.RobotMatrix, this.RobotPosition, - ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y, - ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y, - 1, 2); - - - - - - return this.commands; -} - -ChangeCoordinate3D.prototype.changeTransformType = function(globalToLocal) -{ - this.commands = []; - this.lastLocalToGlobal = !globalToLocal; - this.removeOldIDs(); - if (globalToLocal) - { - this.cmd("SetText", this.robotLabel1ID, "World Space to Robot Space\n(Orientation)"); - - } - else - { - this.cmd("SetText", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)"); - } - this.cmd("Step"); - this.RobotMatrix = this.transposeVisual(this.RobotMatrix) - - if (globalToLocal) - { - this.cmd("SetText", this.robotLabel2ID, "World Space to Robot Space\n(Position)"); - - } - else - { - this.cmd("SetText", this.robotLabel2ID, "Robot Space to World Space\n(Position)"); - } - this.cmd("Step"); - this.negateMatrixVisual(this.RobotPosition); - this.cmd("Step"); - - if (globalToLocal) - { - this.cmd("SetText", this.handLabel1ID, "Robot Space to Hand Space\n(Orientation)"); - - } - else - { - this.cmd("SetText", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)"); - } - - this.cmd("Step"); - this.HandMatrix = this.transposeVisual(this.HandMatrix) - - if (globalToLocal) - { - this.cmd("SetText", this.handLabel2ID, "Robot Space to Hand Space\n(Position)"); - - } - else - { - this.cmd("SetText", this.handLabel2ID, "Hand Space to Robot Space\n(Position)"); - } - this.cmd("Step"); - this.negateMatrixVisual(this.HandPosition); - this.cmd("Step"); - - if (globalToLocal) - { - this.cmd("Move", this.robotLabel1ID, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y - 25); - this.moveMatrix(this.RobotMatrix, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y) - - this.cmd("Move", this.robotLabel2ID, ChangeCoordinate3D.ROBOT_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25); - this.moveMatrix(this.RobotPosition, ChangeCoordinate3D.ROBOT_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y) - - this.cmd("Move", this.handLabel1ID, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y - 25); - this.moveMatrix(this.HandMatrix, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); - - - this.cmd("Move", this.handLabel2ID, ChangeCoordinate3D.HAND_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25); - this.moveMatrix(this.HandPosition, ChangeCoordinate3D.HAND_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y); - } - else - { - this.cmd("Move", this.robotLabel1ID, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25); - this.moveMatrix(this.RobotMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y) - - this.cmd("Move", this.robotLabel2ID, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y - 25); - this.moveMatrix(this.RobotPosition, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y) - - this.cmd("Move", this.handLabel1ID, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25); - this.moveMatrix(this.HandMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y); - - this.cmd("Move", this.handLabel2ID, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y - 25); - this.moveMatrix(this.HandPosition, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); - - } - return this.commands; -} - - -ChangeCoordinate3D.prototype.negateMatrixVisual = function(matrix) -{ - var i,j - for (i = 0; i < matrix.data.length; i++) - { - for (j = 0; j < matrix.data[i].length; j++) - { - matrix.data[i][j] = -matrix.data[i][j] - } - } - this.resetMatrixLabels(matrix); -} - - -ChangeCoordinate3D.prototype.globalToLocal = function(params) -{ - this.commands = []; - this.removeOldIDs(); - - - var paramList = params.split(";"); - var x = parseFloat(paramList[0]); - var y = parseFloat(paramList[1]); - var z = parseFloat(paramList[2]); - - var opX, opY; - - - var screenPoint = this.worldToScreenSpace([x,y, z], 2); - var logicalPoint; - - var pointInWorldSpaceID = this.nextIndex++; - this.oldIDs.push(pointInWorldSpaceID); - this.cmd("CreateCircle", pointInWorldSpaceID, "", screenPoint[0], screenPoint[1]); - this.cmd("SetWidth", pointInWorldSpaceID, ChangeCoordinate3D.VERTEX_WIDTH); - this.cmd("Connect", this.axisWorld[0], pointInWorldSpaceID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[2], 0, 1, ""); - - var initialPointMatrix; - if (this.rowMajor) - { - initialPointMatrix = this.createMatrix([[x, y, z]], ChangeCoordinate3D.ROBOT_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - ChangeCoordinate3D.ROBOT_MATRIX_START_Y); - } - else - { - initialPointMatrix = this.createMatrix([[x], [y], [z]], ChangeCoordinate3D.ROBOT_MATRIX_START_X - ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - ChangeCoordinate3D.ROBOT_MATRIX_START_Y); - - } - this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); - this.cmd("Step"); - - var positionAndID = this.addMultiply(initialPointMatrix, this.RobotPosition, this.RobotMatrix, - ChangeCoordinate3D.ROBOT_MATRIX_START_X + ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y, - ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y, - pointInWorldSpaceID, - 2, 1); - - var robotPositionMatrix = positionAndID[0]; - var newPositionID = positionAndID[1]; - - if (this.rowMajor) - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - ChangeCoordinate3D.HAND_MATRIX_START_Y); - } - else - { - this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X - ChangeCoordinate3D.MATRIX_ELEM_WIDTH, - ChangeCoordinate3D.HAND_MATRIX_START_Y); - - } - - - this.addMultiply(robotPositionMatrix, this.HandPosition, this.HandMatrix, - ChangeCoordinate3D.HAND_MATRIX_START_X + ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y, - ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y, - newPositionID, - 1, 0); - - - - return this.commands; -} - -ChangeCoordinate3D.prototype.moveObjectsCallback = function() -{ - this.implementAction(this.moveObjects.bind(this), 0); -} - -ChangeCoordinate3D.prototype.moveObjects = function() -{ - this.commands = []; - this.removeOldIDs(); - var i, j; - - for (i = 0; i < this.otherAxes.length; i++) - { - for (j = 0; j < this.otherAxes[i].length; j++) - { - this.cmd("Delete", this.otherAxes[i][j]); - } - } - - - var i; - for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) - { - - this.cmd("Delete", this.RobotPointRobotIDs[i]); - this.cmd("Delete", this.RobotPointWorldIDs[i]); - } - for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) - { - this.cmd("Delete", this.HandPointHandIDs[i]); - this.cmd("Delete", this.HandPointRobotIDs[i]); - this.cmd("Delete", this.HandPointWorldIDs[i]); - } - this.cmd("Delete", this.RobotHandAttachRobotID); - this.cmd("Delete", this.RobotHandAttachWorldID); - this.PositionIndex+= 1; - if (this.PositionIndex >= ChangeCoordinate3D.ROBOT_POSITION_VALUES.length) - { - this.PositionIndex = 0; - } - - this.RobotPositionValues = ChangeCoordinate3D.ROBOT_POSITION_VALUES[this.PositionIndex]; - this.RobotMatrixValues = ChangeCoordinate3D.ROBOT_MATRIX_VALUES[this.PositionIndex]; - this.HandPositionValues = ChangeCoordinate3D.HAND_POSITION_VALUES[this.PositionIndex]; - this.HandMatrixValues = ChangeCoordinate3D.HAND_MATRIX_VALUES[this.PositionIndex]; - - this.setupExtraAxes(); - this.setupObjects(); - - - this.RobotPosition.data = [this.RobotPositionValues]; - this.RobotMatrix.data = this.RobotMatrixValues; - this.HandPosition.data = [this.HandPositionValues]; - this.HandMatrix.data =this.HandMatrixValues; - if (!this.rowMajor) - { - this.RobotPosition.transpose(); - this.RobotMatrix.transpose(); - this.HandPosition.transpose(); - this.HandMatrix.transpose(); - } - this.resetMatrixLabels(this.RobotMatrix); - this.resetMatrixLabels(this.RobotPosition); - this.resetMatrixLabels(this.HandMatrix); - this.resetMatrixLabels(this.HandPosition); - - - return this.commands; -} - - -function toRadians(degrees) -{ - return (degrees * 2 * Math.PI) / 360.0; -} - - -ChangeCoordinate3D.prototype.addMatrix = function(mat1, mat2, mat3, numDigits) -{ - var i; - var j; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat1.data[i].length; j++) - { - explainText = ""; - var value = 0; - this.cmd("SetHighlight", mat1.dataID[i][j], 1); - this.cmd("SetHighlight", mat2.dataID[i][j], 1); - this.cmd("Step"); - mat3.data[i][j] = mat1.data[i][j] + mat2.data[i][j]; - this.cmd("SetHighlight", mat1.dataID[i][j], 0); - this.cmd("SetHighlight", mat2.dataID[i][j], 0); - this.cmd("SetText", mat3.dataID[i][j], this.standardize(mat3.data[i][j], numDigits)); - this.cmd("Step"); - } - } -} - - - - -ChangeCoordinate3D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID, numDigits) -{ - var i; - var j; - var explainText = ""; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat2.data[0].length; j++) - { - var explainText = ""; - var value = 0; - for (k = 0; k < mat2.data.length; k++) - { - this.cmd("SetHighlight", mat1.dataID[i][k], 1); - this.cmd("SetHighlight", mat2.dataID[k][j], 1); - if (explainText != "") - { - explainText = explainText + " + "; - } - value = value + mat1.data[i][k] * mat2.data[k][j]; - explainText = explainText + this.standardize(String(mat1.data[i][k]), numDigits) + " * " + this.standardize(String(mat2.data[k][j]),numDigits); - this.cmd("SetText", explainID, explainText); - this.cmd("Step"); - this.cmd("SetHighlight", mat1.dataID[i][k], 0); - this.cmd("SetHighlight", mat2.dataID[k][j], 0); - } - explainText += " = " + this.standardize(String(value), numDigits); - this.cmd("SetText", explainID, explainText); - mat3.data[i][j] = value; - this.cmd("SetText", mat3.dataID[i][j], this.standardize(value,numDigits)); - this.cmd("Step"); - } - } - this.cmd("SetText", explainID, ""); - - -} - -ChangeCoordinate3D.prototype.standardize = function(lab, digits) -{ - digits = (digits == undefined) ? 3 : digits; - var shift = Math.pow(10, digits); - var newLab = Math.round(lab * shift) / shift; - if (isNaN(newLab)) - { - return lab; - } - else - { - return newLab; - } -} - - -ChangeCoordinate3D.prototype.resetMatrixLabels = function(mat, numDigits) -{ - var i,j, newLab; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - newLab = this.standardize(mat.data[i][j], numDigits); - this.cmd("SetText", mat.dataID[i][j], newLab); - } - } -} - - - -ChangeCoordinate3D.prototype.moveMatrix = function(mat, x, y) -{ - var height = mat.data.length; - var width = 0; - - var i, j; - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - } - - - this.cmd("Move", mat.leftBrack1, x, y); - this.cmd("Move", mat.leftBrack2, x, y); - this.cmd("Move", mat.leftBrack3, x, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - - this.cmd("Move", mat.rightBrack1, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack2, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack3, x+ width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Move", mat.dataID[i][j], - x + j*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2, - y + i*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2); - } - } - mat.x = x; - mat.y = y; -} - - - - -ChangeCoordinate3D.prototype.addMatrixIDsToList = function(mat, list) -{ - list.push(mat.leftBrack1); - list.push(mat.leftBrack2); - list.push(mat.leftBrack3); - list.push(mat.rightBrack1); - list.push(mat.rightBrack2); - list.push(mat.rightBrack3); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - list.push(mat.dataID[i][j]); - } - - } -} - -ChangeCoordinate3D.prototype.deleteMatrix = function(mat) -{ - var IDList = []; - this.addMatrixIDsToList(mat, IDList); - var i; - for (i = 0; i < IDList.length; i++) - { - this.cmd("Delete", IDList[i]); - } -} - - - - -ChangeCoordinate3D.prototype.aplyFunctionToMatrixElems = function(mat, command, value) -{ - this.cmd(command, mat.leftBrack1, value); - this.cmd(command, mat.leftBrack2, value); - this.cmd(command, mat.leftBrack3, value); - this.cmd(command, mat.rightBrack1, value); - this.cmd(command, mat.rightBrack2, value); - this.cmd(command, mat.rightBrack3, value); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd(command, mat.dataID[i][j], value); - } - } -} - - - -// Multiply two (data only!) matrices (not complete matrix object with graphics, just -// the data -function multiply(lhs, rhs) -{ - var resultMat = new Array(lhs.length); - var i, j, k; - - for (i = 0; i < lhs.length; i++) - { - resultMat[i] = new Array(rhs[0].length); - } - for (i = 0; i < lhs.length; i++) - { - for (j = 0; j < rhs[0].length; j++) - { - var value = 0; - for (k = 0; k < rhs.length; k++) - { - value = value + lhs[i][k] * rhs[k][j]; - } - resultMat[i][j] = value; - } - } - return resultMat; -} - -// Add two (data only!) matrices (not complete matrix object with graphics, just -// the data) -ChangeCoordinate3D.prototype.add = function(lhs, rhs) -{ - var resultMat = new Array(lhs.length); - var i,j; - - for (i = 0; i < lhs.length; i++) - { - resultMat[i] = new Array(lhs[i].length); - for (j = 0; j < lhs[i].length; j++) - { - resultMat[i][j] = lhs[i][j] + rhs[i][j]; - - } - } - return resultMat; -} - - -ChangeCoordinate3D.prototype.createMatrix = function(contents, x, y) -{ - var mat = new Matrix(contents, x, y); - mat.leftBrack1 = this.nextIndex++; - mat.leftBrack2 = this.nextIndex++; - mat.leftBrack3 = this.nextIndex++; - mat.rightBrack1 = this.nextIndex++; - mat.rightBrack2 = this.nextIndex++; - mat.rightBrack3 = this.nextIndex++; - - var height = mat.data.length; - var width = 0; - - var i, j; - mat.dataID = new Array(mat.data.length); - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - mat.dataID[i] = new Array(mat.data[i].length); - for (j = 0; j < mat.data[i].length; j++) - { - mat.dataID[i][j] = this.nextIndex++; - } - } - - this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); - this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); - this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT , "left","center"); - - this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y, "right","center"); - this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y, "center","top"); - this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT , "right","center"); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], - x + j*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2, - y + i*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2); - } - } - return mat; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new ChangeCoordinate3D(animManag, canvas.width, canvas.height); -} - -function Matrix(contents, x, y) -{ - this.data = contents; - this.x = x; - this.y = y; -} - -Matrix.prototype.transpose = function() -{ - var newData = new Array(this.data[0].length); - var i,j; - for (i = 0; i < this.data[0].length; i++) - { - newData[i] = new Array(this.data.length); - } - for (i = 0; i < this.data.length; i++) - { - for (j = 0; j < this.data[i].length; j++) - { - newData[j][i] = this.data[i][j]; - } - } - this.data = newData; -} - - - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function ChangeCoordinate3D(am, w, h) +{ + this.init(am, w, h); +} + + +ChangeCoordinate3D.inheritFrom(Algorithm); + +ChangeCoordinate3D.XAxisYPos = 300; +ChangeCoordinate3D.XAxisStart = 100; +ChangeCoordinate3D.XAxisEnd = 700; + +ChangeCoordinate3D.MATRIX_ELEM_WIDTH = 40; +ChangeCoordinate3D.MATRIX_ELEM_HEIGHT = 15; + + +ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING = 5; +ChangeCoordinate3D.EQUALS_SPACING = 20; + +ChangeCoordinate3D.ROBOT_MATRIX_START_X = 10 + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; +ChangeCoordinate3D.ROBOT_MATRIX_START_Y = 30; + +ChangeCoordinate3D.HAND_MATRIX_START_X = 10 +3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; +ChangeCoordinate3D.HAND_MATRIX_START_Y = 10 + 25 + 20 + 20 + 3*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; + + +ChangeCoordinate3D.ROBOT_POSITION_START_X = ChangeCoordinate3D.ROBOT_MATRIX_START_X + 5*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + 100; +ChangeCoordinate3D.HAND_POSITION_START_X = ChangeCoordinate3D.HAND_MATRIX_START_X + 5*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + 100; + + +ChangeCoordinate3D.ROBOT_POSITION_START_Y = ChangeCoordinate3D.ROBOT_MATRIX_START_Y; +ChangeCoordinate3D.HAND_POSITION_START_Y = ChangeCoordinate3D.HAND_MATRIX_START_Y; + + +ChangeCoordinate3D.YAxisXPos = 400; +ChangeCoordinate3D.YAxisStart = 100; +ChangeCoordinate3D.YAxisEnd = 500; + +ChangeCoordinate3D.ROBOT_POINTS = [[-15,5,100],[15,5,100],[15, 5,80],[30,5,80],[30,5,-10],[15,5,-10], [15,5, -100], [0,5,-100],[0,5,-30],[0,5,-100], [-15,5, -100], + [-15,5,-10], [-30, 5,-10], [-30, 5, 80],[-15, 5, 80], [-15, 5, 100], + + [-15,-5,100],[15,-5,100],[15, -5,80],[30,-5,80],[30,-5,-10],[15,-5,-10], [15,-5, -100], [0,-5,-100],[0,-5,-30],[0,-5,-100], [-15,-5, -100], + [-15,-5,-10], [-30, -5,-10], [-30, -5, 80],[-15, -5, 80], [-15, -5, 100]]; + +ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS = [[0, 16], [1, 17], [2, 18], [3, 19], [4, 20], [5, 21], [6, 22], [7, 23], [8, 24], [9, 25], + [10, 26], [11, 27], [12, 28], [13, 29], [14, 30], [15, 31]]; + + + +ChangeCoordinate3D.HAND_POINTS = [[0,3, 0],[-10,3, 0],[-10,3, 10], [-6, 3,10], [-6, 3,6], [6, 3,6], [6, 3, 10], [10, 3, 10], [10, 3, 0],[0,3,0], + [0,-3, 0],[-10,-3, 0],[-10,-3, 10], [-6, -3,10], [-6, -3,6], [6, -3,6], [6, -3, 10], [10, -3, 10], [10, -3, 0],[0,-3,0]]; + + + +ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS = [[0, 10], [1, 11], [2, 12], [3, 13], [4, 14], [5, 15], [6, 16], [7, 17], [8, 18], [9, 19]]; + + +ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT = [0, 0,40]; + + +ChangeCoordinate3D.M1 = [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4), 0],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4), 0],[0,0,1]]; +ChangeCoordinate3D.M2 = [[Math.cos(3*Math.PI / 4), 0, Math.sin(3*Math.PI/4)],[0,1,0], [-Math.sin(3*Math.PI/4), 0, Math.cos(3*Math.PI/4)]]; +ChangeCoordinate3D.M3 = [[1,0,0], [0, Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4)],[0, -Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4)]]; + + + +ChangeCoordinate3D.ROBOT_MATRIX_VALUES = [ + [[1,0,0],[0, Math.cos(Math.PI / 6), Math.sin(Math.PI / 6)],[0, -Math.sin(Math.PI / 6), Math.cos(Math.PI / 6)]], + [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4), 0],[-Math.sin(Math.PI / 4), Math.cos(Math.PI / 4), 0], [0,0,1]], + [[Math.cos(0), Math.sin(0), 0],[-Math.sin(0), Math.cos(0), 0], [0, 0, 1]], + [[Math.cos(3*Math.PI / 4), Math.sin(3*Math.PI/4), 0],[-Math.sin(3*Math.PI/4), Math.cos(3*Math.PI/4), 0],[0,0,1]], + multiply(ChangeCoordinate3D.M2, ChangeCoordinate3D.M3) + + ]; + + +ChangeCoordinate3D.ROBOT_POSITION_VALUES = [[75,0, 40], [200,100, 30],[100,100, 0], [100, 200, 0], [40,50,50]]; + + +ChangeCoordinate3D.HAND_MATRIX_VALUES = [ + [[Math.cos(-Math.PI / 4),0, Math.sin(-Math.PI / 4)],[0,1,0],[-Math.sin(-Math.PI / 4), 0, Math.cos(-Math.PI / 4)]], + [[Math.cos(Math.PI / 4), Math.sin(Math.PI / 4), 0],[-Math.sin(Math.PI / 4), Math.cos(-Math.PI / 4), 0], [0,0,1]], + [[Math.cos(0), Math.sin(0), 0],[-Math.sin(0), Math.cos(0), 0], [0,0,1]], + [[Math.cos(Math.PI/2), Math.sin(Math.PI/2), 0],[-Math.sin(Math.PI/2), Math.cos(Math.PI/2), 0], [0,0,1]], + multiply(ChangeCoordinate3D.M1, ChangeCoordinate3D.M2) + ]; + + +ChangeCoordinate3D.HAND_POSITION_VALUES = [[80,0, 20],[30,90, 0],[100,100, 0],[-50, -20, 0], [50,10,20]]; + + +//ChangeCoordinate3D.ROBOT_POINTS = [[-20, 40], [20,40],[ + + +ChangeCoordinate3D.CAMERA_TRANS_ANGLE = toRadians(30); +ChangeCoordinate3D.L = 0.5; + +ChangeCoordinate3D.CAMERA_TRANSFORM = [[1, 0, 0], + [ChangeCoordinate3D.L * Math.cos(ChangeCoordinate3D.CAMERA_TRANS_ANGLE), 0, ChangeCoordinate3D.L * Math.sin(ChangeCoordinate3D.CAMERA_TRANS_ANGLE)], + [0, 0, 1]]; + + +ChangeCoordinate3D.AXIS_CENTER = [[750,470],[750,150],[100, 550]]; + +ChangeCoordinate3D.AXIS_COLOR_0 = "#990000" +ChangeCoordinate3D.AXIS_COLOR_1 = "#009900" +ChangeCoordinate3D.AXIS_COLOR_2 = "#000099" + +ChangeCoordinate3D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; +ChangeCoordinate3D.LOCAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.LOCAL_VERTEX_FOREGORUND_COLOR; +ChangeCoordinate3D.LOCAL_EDGE_COLOR = "#000000"; + +ChangeCoordinate3D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; +ChangeCoordinate3D.GLOBAL_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.GLOBAL_VERTEX_FOREGORUND_COLOR; +ChangeCoordinate3D.GLOBAL_EDGE_COLOR = "#00FF00"; + + + +ChangeCoordinate3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; +ChangeCoordinate3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = ChangeCoordinate3D.VERTEX_FOREGORUND_COLOR; +ChangeCoordinate3D.TRANSFORMED_EDGE_COLOR = "#66FF66"; + + +ChangeCoordinate3D.TRANSFORMED_POINT_COLORS = ["#990000", "#009900", "#000099"] + + +ChangeCoordinate3D.VECTOR_COLOR = "#FF0000"; + +ChangeCoordinate3D.VERTEX_WIDTH = 3; +ChangeCoordinate3D.VERTEX_HEIGHT = ChangeCoordinate3D.VERTEX_WIDTH; + +ChangeCoordinate3D.prototype.init = function(am, w, h) +{ + var sc = ChangeCoordinate3D.superclass.init.call(this, am, w, h); + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.addControls(); + this.currentShape = 0; + + this.cameraTransform = ChangeCoordinate3D.CAMERA_TRANSFORM; + + this.commands = []; + this.nextIndex = 0; + + this.PositionIndex = 0; + + this.RobotPositionValues = ChangeCoordinate3D.ROBOT_POSITION_VALUES[this.PositionIndex]; + this.RobotMatrixValues = ChangeCoordinate3D.ROBOT_MATRIX_VALUES[this.PositionIndex]; + this.HandPositionValues = ChangeCoordinate3D.HAND_POSITION_VALUES[this.PositionIndex]; + this.HandMatrixValues = ChangeCoordinate3D.HAND_MATRIX_VALUES[this.PositionIndex]; + + this.setupAxis(); + + this.robotLabel1ID = this.nextIndex++; + this.handLabel1ID = this.nextIndex++; + this.robotLabel2ID = this.nextIndex++; + this.handLabel2ID = this.nextIndex++; + + this.cmd("CreateLabel", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)", ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.robotLabel1ID, "#0000FF"); + + this.cmd("CreateLabel", this.robotLabel2ID, "Robot Space to World Space\n(Position)", ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.robotLabel2ID, "#0000FF"); + + + + this.RobotMatrix = this.createMatrix(this.RobotMatrixValues, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y); + this.resetMatrixLabels(this.RobotMatrix); + this.HandMatrix = this.createMatrix(this.HandMatrixValues, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y); + this.resetMatrixLabels(this.HandMatrix); + + this.cmd("CreateLabel", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)", ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.handLabel1ID, "#0000FF"); + + this.cmd("CreateLabel", this.handLabel2ID, "Hand Space to Robot Space\n(Position)", ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25, 0); + this.cmd("SetForegroundColor", this.handLabel2ID, "#0000FF"); + + + + this.RobotPosition = this.createMatrix([this.RobotPositionValues], ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y); + this.resetMatrixLabels(this.RobotMatrix); + this.HandPosition = this.createMatrix([this.HandPositionValues], ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); + this.resetMatrixLabels(this.HandMatrix); + + + var i; + this.RobotPointWorldIDs = new Array(ChangeCoordinate3D.ROBOT_POINTS.length); + this.RobotPointRobotIDs = new Array(ChangeCoordinate3D.ROBOT_POINTS.length); + this.HandPointWorldIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); + this.HandPointRobotIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); + this.HandPointHandIDs = new Array(ChangeCoordinate3D.HAND_POINTS.length); + this.RobotHandAttachRobotID = this.nextIndex++; + this.RobotHandAttachWorldID = this.nextIndex++; + for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) + { + this.RobotPointWorldIDs[i] = this.nextIndex++; + this.RobotPointRobotIDs[i] = this.nextIndex++; + } + for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) + { + this.HandPointWorldIDs[i] = this.nextIndex++; + this.HandPointRobotIDs[i] = this.nextIndex++; + this.HandPointHandIDs[i] = this.nextIndex++; + } + + this.savedNextIndex = this.nextIndex; + this.setupObjects(); + this.setupObjectGraphic(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); + this.animationManager.setAllLayers([0, 1]); + this.lastLocalToGlobal = true; + this.oldIDs = []; + + +} + +ChangeCoordinate3D.prototype.addAxis = function(origin, x1, x2, y1, y2, z1, z2, color) +{ + var idArray = []; + var originID = this.nextIndex++; + idArray.push(originID); + this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); + this.cmd("SetAlpha", originID, 0); + + var axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, x1[0], x1[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, x2[0], x2[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, y1[0], y1[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, y2[0], y2[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, z1[0], z1[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + axisID = this.nextIndex++; + this.cmd("CreateRectangle", axisID, "", 0, 0, z2[0], z2[1]); + this.cmd("SetAlpha", axisID, 0); + this.cmd("Connect", originID, axisID, color, 0, 1, ""); + idArray.push(axisID); + + + + var labelID = this.nextIndex++; + this.cmd("CreateLabel", labelID, "+y", y2[0] - 10, y2[1] + 10); + this.cmd("SetForegroundColor", labelID, color); + idArray.push(labelID); + + + labelID = this.nextIndex++; + this.cmd("CreateLabel", labelID, "+x", x2[0] - 10, x2[1] + 10); + this.cmd("SetForegroundColor", labelID, color); + idArray.push(labelID); + + + labelID = this.nextIndex++; + this.cmd("CreateLabel", labelID, "+z", z2[0] - 10, z2[1] + 10); + this.cmd("SetForegroundColor", labelID, color); + idArray.push(labelID); + + + return idArray; +} + + +ChangeCoordinate3D.prototype.transformPoint = function(point, matrix, position) +{ + return this.add(multiply([point], matrix), [position])[0]; +} + + +ChangeCoordinate3D.prototype.setupExtraAxes = function() +{ + var robotOrigin = this.RobotPositionValues; + var x1 = this.transformPoint([-150, 0, 0], this.RobotMatrixValues, this.RobotPositionValues); + var x2 = this.transformPoint([150, 0, 0], this.RobotMatrixValues, this.RobotPositionValues); + var y1 = this.transformPoint([0, -150, 0], this.RobotMatrixValues, this.RobotPositionValues); + var y2 = this.transformPoint([0, 150, 0], this.RobotMatrixValues, this.RobotPositionValues); + var z1 = this.transformPoint([0, 0, -150], this.RobotMatrixValues, this.RobotPositionValues); + var z2 = this.transformPoint([0, 0, 150], this.RobotMatrixValues, this.RobotPositionValues); + + this.otherAxes = []; + + var tmpAxis = this.addAxis(this.worldToScreenSpace(robotOrigin, 2), + this.worldToScreenSpace(x1, 2), + this.worldToScreenSpace(x2, 2), + this.worldToScreenSpace(y1, 2), + this.worldToScreenSpace(y2, 2), + this.worldToScreenSpace(z1, 2), + this.worldToScreenSpace(z2, 2), + ChangeCoordinate3D.AXIS_COLOR_1); + + this.otherAxes.push(tmpAxis); + + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + this.setAxisAlpha(tmpAxis, 0.5); + + + var handOrigin = this.HandPositionValues; + x1 = this.transformPoint([-150, 0, 0], this.HandMatrixValues, this.HandPositionValues); + x2 = this.transformPoint([150, 0, 0], this.HandMatrixValues, this.HandPositionValues); + y1 = this.transformPoint([0, -150, 0], this.HandMatrixValues, this.HandPositionValues); + y2 = this.transformPoint([0, 150, 0], this.HandMatrixValues, this.HandPositionValues); + z1 = this.transformPoint([0, 0, -150], this.HandMatrixValues, this.HandPositionValues); + z2 = this.transformPoint([0, 0, 150], this.HandMatrixValues, this.HandPositionValues); + + + tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 1), + this.worldToScreenSpace(x1, 1), + this.worldToScreenSpace(x2, 1), + this.worldToScreenSpace(y1, 1), + this.worldToScreenSpace(y2, 1), + this.worldToScreenSpace(z1, 1), + this.worldToScreenSpace(z2, 1), + ChangeCoordinate3D.AXIS_COLOR_0); + + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + this.setAxisAlpha(tmpAxis, 0.5); + + + this.otherAxes.push(tmpAxis); + + + handOrigin = this.transformPoint(handOrigin, this.RobotMatrixValues, this.RobotPositionValues); + x1 = this.transformPoint(x1, this.RobotMatrixValues, this.RobotPositionValues); + x2 = this.transformPoint(x2, this.RobotMatrixValues, this.RobotPositionValues); + y1 = this.transformPoint(y1, this.RobotMatrixValues, this.RobotPositionValues); + y2 = this.transformPoint(y2, this.RobotMatrixValues, this.RobotPositionValues); + z1 = this.transformPoint(z1, this.RobotMatrixValues, this.RobotPositionValues); + z2 = this.transformPoint(z2, this.RobotMatrixValues, this.RobotPositionValues); + + + tmpAxis = this.addAxis(this.worldToScreenSpace(handOrigin, 2), + this.worldToScreenSpace(x1, 2), + this.worldToScreenSpace(x2, 2), + this.worldToScreenSpace(y1, 2), + this.worldToScreenSpace(y2, 2), + this.worldToScreenSpace(z1, 2), + this.worldToScreenSpace(z2, 2), + ChangeCoordinate3D.AXIS_COLOR_0); + for (var i = 0; i < tmpAxis.length; i++) + { + this.cmd("SetLayer", tmpAxis[i], 1); + } + + this.setAxisAlpha(tmpAxis, 0.5); + + this.otherAxes.push(tmpAxis); + +} + + +ChangeCoordinate3D.prototype.setupAxis = function() +{ + + this.axisHand = this.addAxis(this.worldToScreenSpace([0,0,0], 0), + this.worldToScreenSpace([-150, 0, 0], 0), + this.worldToScreenSpace([150,0, 0], 0), + this.worldToScreenSpace([0, -150, 0], 0), + this.worldToScreenSpace([0, 150, 0], 0), + this.worldToScreenSpace([0, 0, -150], 0), + this.worldToScreenSpace([0, 0, 150], 0), + ChangeCoordinate3D.AXIS_COLOR_0); + this.setAxisAlpha(this.axisHand, 0.5); + + this.axisRobot = this.addAxis(this.worldToScreenSpace([0,0, 0], 1), + this.worldToScreenSpace([-150, 0, 0], 1), + this.worldToScreenSpace([150,0, 0], 1), + this.worldToScreenSpace([0, -150, 0], 1), + this.worldToScreenSpace([0, 150, 0], 1), + this.worldToScreenSpace([0, 0, -150], 1), + this.worldToScreenSpace([0, 0, 150], 1), + ChangeCoordinate3D.AXIS_COLOR_1); + this.setAxisAlpha(this.axisRobot, 0.5); + + this.axisWorld = this.addAxis(this.worldToScreenSpace([0,0, 0], 2), + this.worldToScreenSpace([-50, 0, 0], 2), + this.worldToScreenSpace([400,0, 0], 2), + this.worldToScreenSpace([0, -50, 0], 2), + this.worldToScreenSpace([0, 400, 0], 2), + this.worldToScreenSpace([0, 0, -50], 2), + this.worldToScreenSpace([0, 0, 400], 2), + ChangeCoordinate3D.AXIS_COLOR_2); + this.setAxisAlpha(this.axisWorld, 0.5); + + this.setupExtraAxes(); + + + + + +} + + +ChangeCoordinate3D.prototype.setAxisAlpha = function(axisList, newAlpha) +{ + for (var i = 0; i < axisList.length; i++) + { + this.cmd("SetAlpha", axisList[i], newAlpha); + if (i > 0) + { + this.cmd("SetEdgeAlpha", axisList[0], axisList[i], newAlpha); + } + } + +} + +ChangeCoordinate3D.prototype.setupObjects = function() +{ + + var i; + for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) + { + + + var point = this.worldToScreenSpace(ChangeCoordinate3D.ROBOT_POINTS[i], 1); + this.cmd("CreateRectangle", this.RobotPointRobotIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.RobotPointRobotIDs[i-1], this.RobotPointRobotIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(ChangeCoordinate3D.ROBOT_POINTS[i], this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point, 2); + + this.cmd("CreateRectangle", this.RobotPointWorldIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.RobotPointWorldIDs[i-1], this.RobotPointWorldIDs[i], "#000000", 0, 0); + } + } + + for (var i = 0; i < ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS.length; i++) + { + this.cmd("Connect", this.RobotPointRobotIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][0]], this.RobotPointRobotIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); + this.cmd("Connect", this.RobotPointWorldIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][0]], this.RobotPointWorldIDs[ChangeCoordinate3D.ROBOT_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); + } + + + + for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) + { + + + var point = this.worldToScreenSpace(ChangeCoordinate3D.HAND_POINTS[i], 0); + this.cmd("CreateRectangle", this.HandPointHandIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointHandIDs[i-1], this.HandPointHandIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(ChangeCoordinate3D.HAND_POINTS[i], this.HandMatrixValues, this.HandPositionValues); + var point2 = this.worldToScreenSpace(point, 1); + + this.cmd("CreateRectangle", this.HandPointRobotIDs[i], "", 0, 0, point2[0], point2[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointRobotIDs[i-1], this.HandPointRobotIDs[i], "#000000", 0, 0); + } + + point = this.transformPoint(point, this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point,2); + + this.cmd("CreateRectangle", this.HandPointWorldIDs[i], "", 0, 0, point[0], point[1]); + if (i > 0) + { + this.cmd("Connect", this.HandPointWorldIDs[i-1], this.HandPointWorldIDs[i], "#000000", 0, 0); + } + } + for (var i = 0; i < ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS.length; i++) + { + this.cmd("Connect", this.HandPointHandIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointHandIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); + this.cmd("Connect", this.HandPointRobotIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointRobotIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); + this.cmd("Connect", this.HandPointWorldIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][0]], this.HandPointWorldIDs[ChangeCoordinate3D.HAND_EXTRA_CONNECTIONS[i][1]], "#000000", 0, 0, ""); + } + + + + point = this.worldToScreenSpace(ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT, 1); + this.cmd("CreateRectangle", this.RobotHandAttachRobotID, "", 0, 0, point[0], point[1]); + this.cmd("Connect", this.RobotHandAttachRobotID, this.HandPointRobotIDs[0], "#000000", 0, 0); + + point = this.transformPoint(ChangeCoordinate3D.ROBOT_HAND_ATTACH_POINT, this.RobotMatrixValues, this.RobotPositionValues); + point = this.worldToScreenSpace(point, 2); + this.cmd("CreateRectangle", this.RobotHandAttachWorldID, "", 0, 0, point[0], point[1]); + this.cmd("Connect", this.RobotHandAttachWorldID, this.HandPointWorldIDs[0], "#000000", 0, 0); +} + + + +ChangeCoordinate3D.prototype.worldToScreenSpace = function(point, space) +{ + var transformedPoint = multiply([point], this.cameraTransform)[0]; + var worldSpace = new Array(2); + worldSpace[0] = transformedPoint[0] + ChangeCoordinate3D.AXIS_CENTER[space][0]; + worldSpace[1] = ChangeCoordinate3D.AXIS_CENTER[space][1] - transformedPoint[2]; + + return worldSpace; +} + + + + +ChangeCoordinate3D.prototype.removeOldIDs = function() +{ + var i; + for (i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs = []; +} + + + +ChangeCoordinate3D.prototype.setupObjectGraphic = function() +{ + var i; + + + + +} + +ChangeCoordinate3D.prototype.addControls = function() +{ + this.controls = []; + + this.addLabelToAlgorithmBar("x"); + + this.xField = this.addControlToAlgorithmBar("Text", ""); + this.xField.onkeydown = this.returnSubmitFloat(this.xField, this.transformPointCallback.bind(this), 4, true); + this.controls.push(this.xField); + + this.addLabelToAlgorithmBar("y"); + + this.yField = this.addControlToAlgorithmBar("Text", ""); + this.yField.onkeydown = this.returnSubmitFloat(this.yField, this.transformPointCallback.bind(this), 4, true); + this.controls.push(this.yField); + + + this.addLabelToAlgorithmBar("z"); + + this.zField = this.addControlToAlgorithmBar("Text", ""); + this.zField.onkeydown = this.returnSubmitFloat(this.zField, this.transformPointCallback.bind(this), 4, true); + this.controls.push(this.zField); + + + var transformButton = this.addControlToAlgorithmBar("Button", "Transform Point"); + transformButton.onclick = this.transformPointCallback.bind(this); + this.controls.push(transformButton); + + + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Hand Space -> World Space", + "World Space -> Hand Space", + ], + "Transform Type"); + this.handToWorldButton = radioButtonList[0]; + this.handToWorldButton.onclick = this.transformTypeChangedCallback.bind(this, false); + this.controls.push(this.handToWorldButton); + + + this.worldToHandButton = radioButtonList[1]; + this.worldToHandButton.onclick = this.transformTypeChangedCallback.bind(this, true); + this.controls.push(this.worldToHandButton); + + this.worldToHandButton.checked = this.lastLocalToGlobal; + this.handToWorldButton.checked = !this.lastLocalToGlobal; + + + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", + "Column Major", + ], + "RankType"); + this.rowMajorButton = radioButtonList[0]; + this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); + this.controls.push(this.rowMajorButton); + + this.colMajorButton = radioButtonList[1]; + this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); + this.controls.push(this.colMajorButton); + + this.rowMajorButton.checked = this.rowMajor; + this.colMajorButton.checked = !this.rowMajor; + + + this.showAxisBox = this.addCheckboxToAlgorithmBar("Show all axes"); + this.showAxisBox.onclick = this.showAllAxesCallback.bind(this); + this.showAxisBox.checked = true; + + //this.controls.push(this.showAxisBox); + + + + var moveObjectsButton = this.addControlToAlgorithmBar("Button", "Move Objects"); + moveObjectsButton.onclick = this.moveObjectsCallback.bind(this); + + this.controls.push(moveObjectsButton); + +} + + + +ChangeCoordinate3D.prototype.showAllAxesCallback = function() +{ + if (this.showAxisBox.checked) + { + this.animationManager.setAllLayers([0,1]); + } + else + { + this.animationManager.setAllLayers([0]); + } + + +} + + +ChangeCoordinate3D.prototype.reset = function() +{ + this.rowMajor = true; + this.rowMajorButton.checked = this.rowMajor; + this.nextIndex = this.savedNextIndex; +} + + +ChangeCoordinate3D.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +ChangeCoordinate3D.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +ChangeCoordinate3D.prototype.transformTypeChangedCallback = function(globalToLocal) +{ + if (this.lastLocalToGlobal == globalToLocal) + { + this.implementAction(this.changeTransformType.bind(this,globalToLocal)); + } +} + + + + +ChangeCoordinate3D.prototype.changeRowColMajorCallback = function(rowMajor) +{ + if (this.rowMajor != rowMajor) + { + this.implementAction(this.changeRowCol.bind(this), rowMajor); + } +} + +ChangeCoordinate3D.prototype.transposeVisual = function(matrix) +{ + if (matrix.data.length == matrix.data[0].length) + { + var matrixSize = matrix.data.length; + var i, j, tmp, moveLabel1, moveLabel2; + var moveLabels = []; + for (i = 1; i < matrixSize; i++) + { + for (j = 0; j <= i; j++) + { + this.cmd("SetText", matrix.dataID[i][j], ""); + this.cmd("SetText", matrix.dataID[j][i], ""); + moveLabel1 = this.nextIndex++; + moveLabel2 = this.nextIndex++; + moveLabels.push(moveLabel1); + moveLabels.push(moveLabel2); + this.cmd("CreateLabel", moveLabel1, + this.standardize(matrix.data[i][j]), matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + this.cmd("CreateLabel", moveLabel2, + this.standardize(matrix.data[j][i]), matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + this.cmd("Move", moveLabel1, matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ j * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + i * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + this.cmd("Move", moveLabel2, matrix.x + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2+ i * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + matrix.y + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2 + j * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + tmp = matrix.data[i][j]; + matrix.data[i][j] = matrix.data[j][i]; + matrix.data[j][i] = tmp; + } + } + this.cmd("Step"); + for (i = 0; i < moveLabels.length; i++) + { + this.cmd("Delete", moveLabels[i]); + } + this.resetMatrixLabels(matrix); + return matrix; + } + else + { + var savedData = matrix.data; + var newData = new Array(savedData[0].length); + var i,j; + for (i = 0; i < savedData[0].length; i++) + { + newData[i] = []; + } + for (i = 0; i < savedData.length; i++) + { + for (j = 0; j < savedData[0].length; j++) + { + newData[j][i] = savedData[i][j]; + } + + } + var newMatrix = this.createMatrix(newData, matrix.x, matrix.y); + this.deleteMatrix(matrix); + return newMatrix; + } +} + +ChangeCoordinate3D.prototype.changeRowCol = function(rowMajor) +{ + this.commands = new Array(); + this.rowMajor= rowMajor; + if (this.rowMajorButton.checked != this.rowMajor) + { + this.rowMajorButton.checked = this.rowMajor; + } + if (this.colMajorButton.checked == this.rowMajor) + { + this.colMajorButton.checked = !this.rowMajor; + } + this.removeOldIDs(); + this.RobotMatrix = this.transposeVisual(this.RobotMatrix); + this.RobotPosition = this.transposeVisual(this.RobotPosition); + this.HandMatrix = this.transposeVisual(this.HandMatrix); + this.HandPosition = this.transposeVisual(this.HandPosition); + + + return this.commands; +} + + +ChangeCoordinate3D.prototype.fixNumber = function(value, defaultVal) +{ + if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) + { + value = defaultVal; + } + else + { + value = String(parseFloat(value)); + } + return value +} + +ChangeCoordinate3D.prototype.transformPointCallback = function() +{ + + + this.xField.value = this.fixNumber(this.xField.value, "0"); + this.yField.value = this.fixNumber(this.yField.value, "0"); + this.zField.value = this.fixNumber(this.zField.value, "0"); + this.implementAction(this.doPointTransform.bind(this), this.xField.value + ";" + this.yField.value + ";" + this.zField.value); + +} + + +ChangeCoordinate3D.prototype.doPointTransform = function(params) +{ + if (this.lastLocalToGlobal) + { + return this.localToGlobal(params); + } + else + { + return this.globalToLocal(params); + } +} + + + + + +ChangeCoordinate3D.prototype.rotatePoint = function(point, matrix, xPos, yPos, fromSpace, toSpace) +{ + var logicalPoint; + var descriptLabel = this.nextIndex++; + // this.oldIDs.push(descriptLabel); + if (this.rowMajor) + { + this.cmd("CreateLabel", descriptLabel, "", xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, + yPos + 2*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + 3, 0); + } + else + { + this.cmd("CreateLabel", descriptLabel, "", xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, + yPos + 3*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + 3, 0); + + } + + var inertialPositionMatrix; + + if (this.rowMajor) + { + inertialPositionMatrix = this.createMatrix([["", "", ""]], xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, + yPos); + } + else + { + inertialPositionMatrix = this.createMatrix([[""], [""], [""]], + xPos + 4 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, + yPos); + + } + var equalLabel1 = this.nextIndex++; + this.oldIDs.push(equalLabel1); + if (this.rowMajor) + { + opX = xPos + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; + } + else + { + opX = xPos + 4 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2 + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING; + opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; + + + } + + this.cmd("CreateLabel", equalLabel1, "=", opX , opY); + if (this.rowMajor) + { + this.multiplyMatrix(point, matrix, inertialPositionMatrix, descriptLabel, 2); + + } + else + { + this.multiplyMatrix(matrix, point, inertialPositionMatrix, descriptLabel, 2); + + } + this.addMatrixIDsToList(inertialPositionMatrix, this.oldIDs); + this.cmd("Delete", descriptLabel); + var inertialPositionID = this.nextIndex++; + if (this.rowMajor) + { + logicalPoint = inertialPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [inertialPositionMatrix.data[0][0], inertialPositionMatrix.data[1][0], inertialPositionMatrix.data[2][0]]; + } + screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); + + + this.cmd("CreateCircle", inertialPositionID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", inertialPositionID, ChangeCoordinate3D.VERTEX_WIDTH); + + var originID = this.nextIndex++; + this.oldIDs.push(originID); + var origin = this.worldToScreenSpace([0,0,0], fromSpace); + + + this.cmd("CreateRectangle", originID, "", 0, 0, origin[0], origin[1]); + + this.cmd("Connect", originID, inertialPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + + + return [inertialPositionMatrix, inertialPositionID, originID]; +} + +ChangeCoordinate3D.prototype.translatePoint = function(point, transVector, xPos, yPos, fromSpace, toSpace, pointID) +{ + var logicalPoint = new Array(2); + var robotPositionMatrix; + if (this.rowMajor) + { + logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; + logicalPoint[1] = point.data[0][1] + transVector.data[0][1]; + logicalPoint[2] = point.data[0][2] + transVector.data[0][2]; + robotPositionMatrix = this.createMatrix([["", "", ""]], xPos + 3*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, + yPos); + } + else + { + logicalPoint[0] = point.data[0][0] + transVector.data[0][0]; + logicalPoint[1] = point.data[1][0] + transVector.data[1][0]; + logicalPoint[2] = point.data[2][0] + transVector.data[2][0]; + robotPositionMatrix = this.createMatrix([[""],[""], [""]], xPos + ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING, + yPos); + + } + + var addLabel1 = this.nextIndex++; + var equalLabel3 = this.nextIndex++; + this.oldIDs.push(addLabel1); + this.oldIDs.push(equalLabel3); + var op2X, op2Y; + if (this.rowMajor) + { + opX = xPos + 3*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; + op2X = xPos - ChangeCoordinate3D.EQUALS_SPACING / 2; + op2Y = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2; + + } + else + { + opX = xPos + ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.EQUALS_SPACING / 2; + opY = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; + op2X = xPos - ChangeCoordinate3D.EQUALS_SPACING / 2; + op2Y = yPos + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT; + + + } + this.cmd("CreateLabel", equalLabel3, "=",opX , opY); + this.cmd("CreateLabel", addLabel1, "+",op2X , op2Y); + + + + + this.addMatrix(point, transVector, robotPositionMatrix, 2); + this.addMatrixIDsToList(robotPositionMatrix, this.oldIDs); + + var screenPoint = this.worldToScreenSpace(logicalPoint, fromSpace); + + var robotPositionID = this.nextIndex++; + + this.cmd("CreateCircle", robotPositionID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", robotPositionID, ChangeCoordinate3D.VERTEX_WIDTH); + + + this.cmd("Connect",pointID, robotPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + this.cmd("Step") + + + + var originID = this.nextIndex++; + this.oldIDs.push(originID); + var origin = this.worldToScreenSpace([0,0, 0], fromSpace); + + this.cmd("CreateCircle", originID, "", origin[0], origin[1]); + this.cmd("SetWidth", originID, 0); + this.cmd("SetAlpha", originID, 0); + + this.cmd("Connect",originID, robotPositionID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[toSpace], 0, 1, ""); + + return [robotPositionMatrix, robotPositionID, originID]; + + +} + + +ChangeCoordinate3D.prototype.addMultiply = function(position, transVector, rotMatrix, transX, transY, rotX, rotY, initialPointID, fromSpace, toSpace) +{ + + var posMatrixAndPointID = this.translatePoint(position, transVector, transX, transY, fromSpace, toSpace, initialPointID); + var newPosition = posMatrixAndPointID[0]; + var pointID = posMatrixAndPointID[1]; + var originID = posMatrixAndPointID[2]; + + this.cmd("Step"); + + this.cmd("Disconnect", initialPointID, pointID); + + if (this.rowMajor) + { + this.moveMatrix(newPosition, rotX - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING,transY) + } + else + { + this.moveMatrix(newPosition, rotX + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, transY) + } + + + var posMatrixAndPointID = this.rotatePoint(newPosition, rotMatrix, rotX, rotY, fromSpace, toSpace); + this.cmd("Delete", pointID); + this.cmd("Step"); + + var robotPositionMatrix = posMatrixAndPointID[0]; + var robotPositionID = posMatrixAndPointID[1]; + var movingOriginID = posMatrixAndPointID[2]; + + var origin = this.worldToScreenSpace([0,0, 0], toSpace); + this.cmd("Move", movingOriginID, origin[0], origin[1]); + + + var logicalPoint; + if (this.rowMajor) + { + logicalPoint = robotPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0], robotPositionMatrix.data[2][0]]; + } + + + + + var screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); + this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); + + this.cmd("Step"); + + + this.oldIDs.push(robotPositionID); + + + return [robotPositionMatrix, robotPositionID ]; +} + + +ChangeCoordinate3D.prototype.multiplyAdd = function(position, rotMatrix, transVector, rotX, rotY, transX, transY, fromSpace, toSpace) +{ + var posMatrixAndPointID = this.rotatePoint(position, rotMatrix, rotX, rotY, fromSpace, toSpace); + var inertialPositionMatrix = posMatrixAndPointID[0]; + var inertialPositionID = posMatrixAndPointID[1]; + + + this.cmd("Step"); + + if (this.rowMajor) + { + this.moveMatrix(inertialPositionMatrix, transX - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.EQUALS_SPACING,transY) + } + else + { + this.moveMatrix(inertialPositionMatrix, transX - ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.EQUALS_SPACING, transY) + } + + + posMatrixAndPointID = this.translatePoint(inertialPositionMatrix, transVector, transX, transY, fromSpace, toSpace, inertialPositionID); + var robotPositionMatrix = posMatrixAndPointID[0]; + var robotPositionID = posMatrixAndPointID[1]; + var movingOriginID = posMatrixAndPointID[2]; + + this.oldIDs.push(robotPositionID); + + var logicalPoint; + if (this.rowMajor) + { + logicalPoint = robotPositionMatrix.data[0].slice(0); + + } + else + { + logicalPoint = [robotPositionMatrix.data[0][0], robotPositionMatrix.data[1][0], robotPositionMatrix.data[2][0]]; + } + + + this.cmd("Step"); + + this.cmd("Delete", inertialPositionID); + origin = this.worldToScreenSpace([0,0, 0], toSpace); + this.cmd("Move", movingOriginID, origin[0], origin[1]); + screenPoint = this.worldToScreenSpace(logicalPoint, toSpace); + this.cmd("Move", robotPositionID, screenPoint[0], screenPoint[1]); + + this.cmd("Step"); + return robotPositionMatrix; + +} + +ChangeCoordinate3D.prototype.localToGlobal = function (params) +{ + this.commands = []; + this.removeOldIDs(); + + + var paramList = params.split(";"); + var x = parseFloat(paramList[0]); + var y = parseFloat(paramList[1]); + var z = parseFloat(paramList[2]); + + var opX, opY; + + + var screenPoint = this.worldToScreenSpace([x,y,z], 0); + var logicalPoint; + + var pointInHandSpaceID = this.nextIndex++; + this.oldIDs.push(pointInHandSpaceID); + + this.cmd("CreateCircle", pointInHandSpaceID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", pointInHandSpaceID, ChangeCoordinate3D.VERTEX_WIDTH); + + this.cmd("Connect", this.axisHand[0], pointInHandSpaceID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[0], 0, 1, ""); + + var initialPointMatrix; + if (this.rowMajor) + { + initialPointMatrix = this.createMatrix([[x, y, z]], ChangeCoordinate3D.HAND_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate3D.HAND_MATRIX_START_Y); + } + else + { + initialPointMatrix = this.createMatrix([[x], [y], [z]], ChangeCoordinate3D.HAND_MATRIX_START_X + 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate3D.HAND_MATRIX_START_Y); + + } + this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); + this.cmd("Step"); + + var robotPositionMatrix = this.multiplyAdd(initialPointMatrix, this.HandMatrix, this.HandPosition, + ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y, + ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y, + 0, 1); + + + + + if (this.rowMajor) + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH - ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate3D.ROBOT_MATRIX_START_Y); + } + else + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X + 3* ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_MULTIPLY_SPACING, + ChangeCoordinate3D.ROBOT_MATRIX_START_Y); + + } + + + this.multiplyAdd(robotPositionMatrix, this.RobotMatrix, this.RobotPosition, + ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y, + ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y, + 1, 2); + + + + + + return this.commands; +} + +ChangeCoordinate3D.prototype.changeTransformType = function(globalToLocal) +{ + this.commands = []; + this.lastLocalToGlobal = !globalToLocal; + this.removeOldIDs(); + if (globalToLocal) + { + this.cmd("SetText", this.robotLabel1ID, "World Space to Robot Space\n(Orientation)"); + + } + else + { + this.cmd("SetText", this.robotLabel1ID, "Robot Space to World Space\n(Orientation)"); + } + this.cmd("Step"); + this.RobotMatrix = this.transposeVisual(this.RobotMatrix) + + if (globalToLocal) + { + this.cmd("SetText", this.robotLabel2ID, "World Space to Robot Space\n(Position)"); + + } + else + { + this.cmd("SetText", this.robotLabel2ID, "Robot Space to World Space\n(Position)"); + } + this.cmd("Step"); + this.negateMatrixVisual(this.RobotPosition); + this.cmd("Step"); + + if (globalToLocal) + { + this.cmd("SetText", this.handLabel1ID, "Robot Space to Hand Space\n(Orientation)"); + + } + else + { + this.cmd("SetText", this.handLabel1ID, "Hand Space to Robot Space\n(Orientation)"); + } + + this.cmd("Step"); + this.HandMatrix = this.transposeVisual(this.HandMatrix) + + if (globalToLocal) + { + this.cmd("SetText", this.handLabel2ID, "Robot Space to Hand Space\n(Position)"); + + } + else + { + this.cmd("SetText", this.handLabel2ID, "Hand Space to Robot Space\n(Position)"); + } + this.cmd("Step"); + this.negateMatrixVisual(this.HandPosition); + this.cmd("Step"); + + if (globalToLocal) + { + this.cmd("Move", this.robotLabel1ID, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y - 25); + this.moveMatrix(this.RobotMatrix, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y) + + this.cmd("Move", this.robotLabel2ID, ChangeCoordinate3D.ROBOT_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25); + this.moveMatrix(this.RobotPosition, ChangeCoordinate3D.ROBOT_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y) + + this.cmd("Move", this.handLabel1ID, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y - 25); + this.moveMatrix(this.HandMatrix, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); + + + this.cmd("Move", this.handLabel2ID, ChangeCoordinate3D.HAND_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25); + this.moveMatrix(this.HandPosition, ChangeCoordinate3D.HAND_MATRIX_START_X+ ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y); + } + else + { + this.cmd("Move", this.robotLabel1ID, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y - 25); + this.moveMatrix(this.RobotMatrix, ChangeCoordinate3D.ROBOT_MATRIX_START_X, ChangeCoordinate3D.ROBOT_MATRIX_START_Y) + + this.cmd("Move", this.robotLabel2ID, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y - 25); + this.moveMatrix(this.RobotPosition, ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y) + + this.cmd("Move", this.handLabel1ID, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y - 25); + this.moveMatrix(this.HandMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X, ChangeCoordinate3D.HAND_MATRIX_START_Y); + + this.cmd("Move", this.handLabel2ID, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y - 25); + this.moveMatrix(this.HandPosition, ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y); + + } + return this.commands; +} + + +ChangeCoordinate3D.prototype.negateMatrixVisual = function(matrix) +{ + var i,j + for (i = 0; i < matrix.data.length; i++) + { + for (j = 0; j < matrix.data[i].length; j++) + { + matrix.data[i][j] = -matrix.data[i][j] + } + } + this.resetMatrixLabels(matrix); +} + + +ChangeCoordinate3D.prototype.globalToLocal = function(params) +{ + this.commands = []; + this.removeOldIDs(); + + + var paramList = params.split(";"); + var x = parseFloat(paramList[0]); + var y = parseFloat(paramList[1]); + var z = parseFloat(paramList[2]); + + var opX, opY; + + + var screenPoint = this.worldToScreenSpace([x,y, z], 2); + var logicalPoint; + + var pointInWorldSpaceID = this.nextIndex++; + this.oldIDs.push(pointInWorldSpaceID); + this.cmd("CreateCircle", pointInWorldSpaceID, "", screenPoint[0], screenPoint[1]); + this.cmd("SetWidth", pointInWorldSpaceID, ChangeCoordinate3D.VERTEX_WIDTH); + this.cmd("Connect", this.axisWorld[0], pointInWorldSpaceID, ChangeCoordinate3D.TRANSFORMED_POINT_COLORS[2], 0, 1, ""); + + var initialPointMatrix; + if (this.rowMajor) + { + initialPointMatrix = this.createMatrix([[x, y, z]], ChangeCoordinate3D.ROBOT_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + ChangeCoordinate3D.ROBOT_MATRIX_START_Y); + } + else + { + initialPointMatrix = this.createMatrix([[x], [y], [z]], ChangeCoordinate3D.ROBOT_MATRIX_START_X - ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + ChangeCoordinate3D.ROBOT_MATRIX_START_Y); + + } + this.addMatrixIDsToList(initialPointMatrix, this.oldIDs); + this.cmd("Step"); + + var positionAndID = this.addMultiply(initialPointMatrix, this.RobotPosition, this.RobotMatrix, + ChangeCoordinate3D.ROBOT_MATRIX_START_X + ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.ROBOT_MATRIX_START_Y, + ChangeCoordinate3D.ROBOT_POSITION_START_X, ChangeCoordinate3D.ROBOT_POSITION_START_Y, + pointInWorldSpaceID, + 2, 1); + + var robotPositionMatrix = positionAndID[0]; + var newPositionID = positionAndID[1]; + + if (this.rowMajor) + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X - 3 * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + ChangeCoordinate3D.HAND_MATRIX_START_Y); + } + else + { + this.moveMatrix(robotPositionMatrix, ChangeCoordinate3D.HAND_MATRIX_START_X - ChangeCoordinate3D.MATRIX_ELEM_WIDTH, + ChangeCoordinate3D.HAND_MATRIX_START_Y); + + } + + + this.addMultiply(robotPositionMatrix, this.HandPosition, this.HandMatrix, + ChangeCoordinate3D.HAND_MATRIX_START_X + ChangeCoordinate3D.EQUALS_SPACING, ChangeCoordinate3D.HAND_MATRIX_START_Y, + ChangeCoordinate3D.HAND_POSITION_START_X, ChangeCoordinate3D.HAND_POSITION_START_Y, + newPositionID, + 1, 0); + + + + return this.commands; +} + +ChangeCoordinate3D.prototype.moveObjectsCallback = function() +{ + this.implementAction(this.moveObjects.bind(this), 0); +} + +ChangeCoordinate3D.prototype.moveObjects = function() +{ + this.commands = []; + this.removeOldIDs(); + var i, j; + + for (i = 0; i < this.otherAxes.length; i++) + { + for (j = 0; j < this.otherAxes[i].length; j++) + { + this.cmd("Delete", this.otherAxes[i][j]); + } + } + + + var i; + for (i = 0; i < ChangeCoordinate3D.ROBOT_POINTS.length; i++) + { + + this.cmd("Delete", this.RobotPointRobotIDs[i]); + this.cmd("Delete", this.RobotPointWorldIDs[i]); + } + for (i = 0; i < ChangeCoordinate3D.HAND_POINTS.length; i++) + { + this.cmd("Delete", this.HandPointHandIDs[i]); + this.cmd("Delete", this.HandPointRobotIDs[i]); + this.cmd("Delete", this.HandPointWorldIDs[i]); + } + this.cmd("Delete", this.RobotHandAttachRobotID); + this.cmd("Delete", this.RobotHandAttachWorldID); + this.PositionIndex+= 1; + if (this.PositionIndex >= ChangeCoordinate3D.ROBOT_POSITION_VALUES.length) + { + this.PositionIndex = 0; + } + + this.RobotPositionValues = ChangeCoordinate3D.ROBOT_POSITION_VALUES[this.PositionIndex]; + this.RobotMatrixValues = ChangeCoordinate3D.ROBOT_MATRIX_VALUES[this.PositionIndex]; + this.HandPositionValues = ChangeCoordinate3D.HAND_POSITION_VALUES[this.PositionIndex]; + this.HandMatrixValues = ChangeCoordinate3D.HAND_MATRIX_VALUES[this.PositionIndex]; + + this.setupExtraAxes(); + this.setupObjects(); + + + this.RobotPosition.data = [this.RobotPositionValues]; + this.RobotMatrix.data = this.RobotMatrixValues; + this.HandPosition.data = [this.HandPositionValues]; + this.HandMatrix.data =this.HandMatrixValues; + if (!this.rowMajor) + { + this.RobotPosition.transpose(); + this.RobotMatrix.transpose(); + this.HandPosition.transpose(); + this.HandMatrix.transpose(); + } + this.resetMatrixLabels(this.RobotMatrix); + this.resetMatrixLabels(this.RobotPosition); + this.resetMatrixLabels(this.HandMatrix); + this.resetMatrixLabels(this.HandPosition); + + + return this.commands; +} + + +function toRadians(degrees) +{ + return (degrees * 2 * Math.PI) / 360.0; +} + + +ChangeCoordinate3D.prototype.addMatrix = function(mat1, mat2, mat3, numDigits) +{ + var i; + var j; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat1.data[i].length; j++) + { + explainText = ""; + var value = 0; + this.cmd("SetHighlight", mat1.dataID[i][j], 1); + this.cmd("SetHighlight", mat2.dataID[i][j], 1); + this.cmd("Step"); + mat3.data[i][j] = mat1.data[i][j] + mat2.data[i][j]; + this.cmd("SetHighlight", mat1.dataID[i][j], 0); + this.cmd("SetHighlight", mat2.dataID[i][j], 0); + this.cmd("SetText", mat3.dataID[i][j], this.standardize(mat3.data[i][j], numDigits)); + this.cmd("Step"); + } + } +} + + + + +ChangeCoordinate3D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID, numDigits) +{ + var i; + var j; + var explainText = ""; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat2.data[0].length; j++) + { + var explainText = ""; + var value = 0; + for (k = 0; k < mat2.data.length; k++) + { + this.cmd("SetHighlight", mat1.dataID[i][k], 1); + this.cmd("SetHighlight", mat2.dataID[k][j], 1); + if (explainText != "") + { + explainText = explainText + " + "; + } + value = value + mat1.data[i][k] * mat2.data[k][j]; + explainText = explainText + this.standardize(String(mat1.data[i][k]), numDigits) + " * " + this.standardize(String(mat2.data[k][j]),numDigits); + this.cmd("SetText", explainID, explainText); + this.cmd("Step"); + this.cmd("SetHighlight", mat1.dataID[i][k], 0); + this.cmd("SetHighlight", mat2.dataID[k][j], 0); + } + explainText += " = " + this.standardize(String(value), numDigits); + this.cmd("SetText", explainID, explainText); + mat3.data[i][j] = value; + this.cmd("SetText", mat3.dataID[i][j], this.standardize(value,numDigits)); + this.cmd("Step"); + } + } + this.cmd("SetText", explainID, ""); + + +} + +ChangeCoordinate3D.prototype.standardize = function(lab, digits) +{ + digits = (digits == undefined) ? 3 : digits; + var shift = Math.pow(10, digits); + var newLab = Math.round(lab * shift) / shift; + if (isNaN(newLab)) + { + return lab; + } + else + { + return newLab; + } +} + + +ChangeCoordinate3D.prototype.resetMatrixLabels = function(mat, numDigits) +{ + var i,j, newLab; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + newLab = this.standardize(mat.data[i][j], numDigits); + this.cmd("SetText", mat.dataID[i][j], newLab); + } + } +} + + + +ChangeCoordinate3D.prototype.moveMatrix = function(mat, x, y) +{ + var height = mat.data.length; + var width = 0; + + var i, j; + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + } + + + this.cmd("Move", mat.leftBrack1, x, y); + this.cmd("Move", mat.leftBrack2, x, y); + this.cmd("Move", mat.leftBrack3, x, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + + this.cmd("Move", mat.rightBrack1, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack2, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack3, x+ width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Move", mat.dataID[i][j], + x + j*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2, + y + i*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2); + } + } + mat.x = x; + mat.y = y; +} + + + + +ChangeCoordinate3D.prototype.addMatrixIDsToList = function(mat, list) +{ + list.push(mat.leftBrack1); + list.push(mat.leftBrack2); + list.push(mat.leftBrack3); + list.push(mat.rightBrack1); + list.push(mat.rightBrack2); + list.push(mat.rightBrack3); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + list.push(mat.dataID[i][j]); + } + + } +} + +ChangeCoordinate3D.prototype.deleteMatrix = function(mat) +{ + var IDList = []; + this.addMatrixIDsToList(mat, IDList); + var i; + for (i = 0; i < IDList.length; i++) + { + this.cmd("Delete", IDList[i]); + } +} + + + + +ChangeCoordinate3D.prototype.aplyFunctionToMatrixElems = function(mat, command, value) +{ + this.cmd(command, mat.leftBrack1, value); + this.cmd(command, mat.leftBrack2, value); + this.cmd(command, mat.leftBrack3, value); + this.cmd(command, mat.rightBrack1, value); + this.cmd(command, mat.rightBrack2, value); + this.cmd(command, mat.rightBrack3, value); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd(command, mat.dataID[i][j], value); + } + } +} + + + +// Multiply two (data only!) matrices (not complete matrix object with graphics, just +// the data +function multiply(lhs, rhs) +{ + var resultMat = new Array(lhs.length); + var i, j, k; + + for (i = 0; i < lhs.length; i++) + { + resultMat[i] = new Array(rhs[0].length); + } + for (i = 0; i < lhs.length; i++) + { + for (j = 0; j < rhs[0].length; j++) + { + var value = 0; + for (k = 0; k < rhs.length; k++) + { + value = value + lhs[i][k] * rhs[k][j]; + } + resultMat[i][j] = value; + } + } + return resultMat; +} + +// Add two (data only!) matrices (not complete matrix object with graphics, just +// the data) +ChangeCoordinate3D.prototype.add = function(lhs, rhs) +{ + var resultMat = new Array(lhs.length); + var i,j; + + for (i = 0; i < lhs.length; i++) + { + resultMat[i] = new Array(lhs[i].length); + for (j = 0; j < lhs[i].length; j++) + { + resultMat[i][j] = lhs[i][j] + rhs[i][j]; + + } + } + return resultMat; +} + + +ChangeCoordinate3D.prototype.createMatrix = function(contents, x, y) +{ + var mat = new Matrix(contents, x, y); + mat.leftBrack1 = this.nextIndex++; + mat.leftBrack2 = this.nextIndex++; + mat.leftBrack3 = this.nextIndex++; + mat.rightBrack1 = this.nextIndex++; + mat.rightBrack2 = this.nextIndex++; + mat.rightBrack3 = this.nextIndex++; + + var height = mat.data.length; + var width = 0; + + var i, j; + mat.dataID = new Array(mat.data.length); + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + mat.dataID[i] = new Array(mat.data[i].length); + for (j = 0; j < mat.data[i].length; j++) + { + mat.dataID[i][j] = this.nextIndex++; + } + } + + this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); + this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); + this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT , "left","center"); + + this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y, "right","center"); + this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT, x + width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y, "center","top"); + this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * ChangeCoordinate3D.MATRIX_ELEM_WIDTH, y + height * ChangeCoordinate3D.MATRIX_ELEM_HEIGHT , "right","center"); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], + x + j*ChangeCoordinate3D.MATRIX_ELEM_WIDTH + ChangeCoordinate3D.MATRIX_ELEM_WIDTH / 2, + y + i*ChangeCoordinate3D.MATRIX_ELEM_HEIGHT + ChangeCoordinate3D.MATRIX_ELEM_HEIGHT / 2); + } + } + return mat; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new ChangeCoordinate3D(animManag, canvas.width, canvas.height); +} + +function Matrix(contents, x, y) +{ + this.data = contents; + this.x = x; + this.y = y; +} + +Matrix.prototype.transpose = function() +{ + var newData = new Array(this.data[0].length); + var i,j; + for (i = 0; i < this.data[0].length; i++) + { + newData[i] = new Array(this.data.length); + } + for (i = 0; i < this.data.length; i++) + { + for (j = 0; j < this.data[i].length; j++) + { + newData[j][i] = this.data[i][j]; + } + } + this.data = newData; +} + + + + + diff --git a/AlgorithmLibrary/ClosedHash.js b/AlgorithmLibrary/ClosedHash.js index aa8d26d..2078f4b 100644 --- a/AlgorithmLibrary/ClosedHash.js +++ b/AlgorithmLibrary/ClosedHash.js @@ -27,9 +27,10 @@ function ClosedHash(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + ClosedHash.superclass.constructor.call(this, am, w, h); } +ClosedHash.inheritFrom(Hash); var ARRAY_ELEM_WIDTH = 90; var ARRAY_ELEM_HEIGHT = 30; @@ -58,10 +59,6 @@ var INDEX_COLOR = "#0000FF"; -ClosedHash.prototype = new Hash(); -ClosedHash.prototype.constructor = ClosedHash; -ClosedHash.superclass = Hash.prototype; - ClosedHash.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/ClosedHashBucket.js b/AlgorithmLibrary/ClosedHashBucket.js index 382745c..6d1693e 100644 --- a/AlgorithmLibrary/ClosedHashBucket.js +++ b/AlgorithmLibrary/ClosedHashBucket.js @@ -27,9 +27,10 @@ function ClosedHashBucket(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + ClosedHashBucket.superclass.constructor.call(this, am, w, h); } +ClosedHashBucket.inheritFrom(Hash); var ARRAY_ELEM_WIDTH = 90; var ARRAY_ELEM_HEIGHT = 30; @@ -64,9 +65,6 @@ var INDEX_COLOR = "#0000FF"; -ClosedHashBucket.prototype = new Hash(); -ClosedHashBucket.prototype.constructor = ClosedHashBucket; -ClosedHashBucket.superclass = Hash.prototype; ClosedHashBucket.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/ComparisonSort.js b/AlgorithmLibrary/ComparisonSort.js index 3b4f520..9fbd585 100644 --- a/AlgorithmLibrary/ComparisonSort.js +++ b/AlgorithmLibrary/ComparisonSort.js @@ -60,9 +60,7 @@ var QUICKSORT_LINE_COLOR = "#FF0000"; -ComparisonSort.prototype = new Algorithm(); -ComparisonSort.prototype.constructor = ComparisonSort; -ComparisonSort.superclass = Algorithm.prototype; +ComparisonSort.inheritFrom(Algorithm); ComparisonSort.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/ConnectedComponent.js b/AlgorithmLibrary/ConnectedComponent.js index 45a9e8f..7da2962 100644 --- a/AlgorithmLibrary/ConnectedComponent.js +++ b/AlgorithmLibrary/ConnectedComponent.js @@ -74,13 +74,11 @@ var DFS_TREE_COLOR = "#0000FF"; function ConnectedComponent(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + ConnectedComponent.superclass.constructor.call(this, am, w, h); } -ConnectedComponent.prototype = new Graph(); -ConnectedComponent.prototype.constructor = ConnectedComponent; -ConnectedComponent.superclass = Graph.prototype; +ConnectedComponent.inheritFrom(Graph); ConnectedComponent.prototype.addControls = function() { diff --git a/AlgorithmLibrary/CountingSort.js b/AlgorithmLibrary/CountingSort.js index dfa61e2..4117731 100644 --- a/AlgorithmLibrary/CountingSort.js +++ b/AlgorithmLibrary/CountingSort.js @@ -50,9 +50,7 @@ var COUNTER_ARRAY_SIZE = MAX_DATA_VALUE + 1; var ARRAY_SIZE = 30; -CountingSort.prototype = new Algorithm(); -CountingSort.prototype.constructor = CountingSort; -CountingSort.superclass = Algorithm.prototype; +CountingSort.inheritFrom(Algorithm); CountingSort.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/DFS.js b/AlgorithmLibrary/DFS.js index 0bc9e23..abe64da 100644 --- a/AlgorithmLibrary/DFS.js +++ b/AlgorithmLibrary/DFS.js @@ -42,19 +42,17 @@ var QUEUE_START_Y = 50; var QUEUE_SPACING = 30; -function DFS(am) +function DFS(am, w, h) { - this.init(am); - + // call superclass' constructor, which calls init + DFS.superclass.constructor.call(this, am, w, h); } -DFS.prototype = new Graph(); -DFS.prototype.constructor = DFS; -DFS.superclass = Graph.prototype; +DFS.inheritFrom(Graph); DFS.prototype.addControls = function() { - addLabelToAlgorithmBar("Start Vertex: "); + this.addLabelToAlgorithmBar("Start Vertex: "); this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); this.startButton = this.addControlToAlgorithmBar("Button", "Run DFS"); diff --git a/AlgorithmLibrary/DPChange.js b/AlgorithmLibrary/DPChange.js index b854ee4..272ba12 100644 --- a/AlgorithmLibrary/DPChange.js +++ b/AlgorithmLibrary/DPChange.js @@ -32,9 +32,7 @@ function DPChange(am, w, h) } -DPChange.prototype = new Algorithm(); -DPChange.prototype.constructor = DPChange; -DPChange.superclass = Algorithm.prototype; +DPChange.inheritFrom(Algorithm); DPChange.TABLE_ELEM_WIDTH = 30; DPChange.TABLE_ELEM_HEIGHT = 30; diff --git a/AlgorithmLibrary/DPFib.js b/AlgorithmLibrary/DPFib.js index d6930cd..97fe96a 100644 --- a/AlgorithmLibrary/DPFib.js +++ b/AlgorithmLibrary/DPFib.js @@ -32,9 +32,7 @@ function DPFib(am, w, h) } -DPFib.prototype = new Algorithm(); -DPFib.prototype.constructor = DPFib; -DPFib.superclass = Algorithm.prototype; +DPFib.inheritFrom(Algorithm); DPFib.TABLE_ELEM_WIDTH = 40; DPFib.TABLE_ELEM_HEIGHT = 30; diff --git a/AlgorithmLibrary/DPLCS.js b/AlgorithmLibrary/DPLCS.js index 07862eb..bf8f252 100644 --- a/AlgorithmLibrary/DPLCS.js +++ b/AlgorithmLibrary/DPLCS.js @@ -1,829 +1,826 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function DPLCS(am, w, h) -{ - this.init(am, w, h); - -} - -DPLCS.prototype = new Algorithm(); -DPLCS.prototype.constructor = DPLCS; -DPLCS.superclass = Algorithm.prototype; - -DPLCS.TABLE_ELEM_WIDTH = 40; -DPLCS.TABLE_ELEM_HEIGHT = 30; - -DPLCS.TABLE_START_X = 500; -DPLCS.TABLE_START_Y = 80; - - -DPLCS.TABLE_DIFF_X = 100; - -DPLCS.CODE_START_X = 10; -DPLCS.CODE_START_Y = 10; -DPLCS.CODE_LINE_HEIGHT = 14; - -DPLCS.RECURSIVE_START_X = 20; -DPLCS.RECURSIVE_START_Y = 120; -DPLCS.RECURSIVE_DELTA_Y = 14; -DPLCS.RECURSIVE_DELTA_X = 15; -DPLCS.CODE_HIGHLIGHT_COLOR = "#FF0000"; -DPLCS.CODE_STANDARD_COLOR = "#000000"; -DPLCS.MAX_SEQUENCE_LENGTH = 15; - -DPLCS.TABLE_INDEX_COLOR = "#0000FF" -DPLCS.CODE_RECURSIVE_1_COLOR = "#339933"; -DPLCS.CODE_RECURSIVE_2_COLOR = "#0099FF"; - -DPLCS.SEQUENCE_START_X = 30; -DPLCS.SEQUENCE_START_Y = 180; -DPLCS.SEQUENCE_DELTA_X = 10; - - -DPLCS.MAX_VALUE = 20; - -DPLCS.MESSAGE_ID = 0; - -DPLCS.prototype.init = function(am, w, h) -{ - DPLCS.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = [["def ","LCS(S1, S2, x, y)",":"], - [" if (","(x == -1) ", " or ", "(y == -1)", ")" ], - [" return 0"], - [" else if ", "(S1[x] == S2[y])"], - [" return 1 + ","LCS(S1, S2, x-1, y-1)"], - [" else"], - [" return max(", "LCS(S1, S2, x-1, y)", ",", "LCS(S1, S2, x, y-1)", ")"]]; - - this.codeID = Array(this.code.length); - var i, j; - for (i = 0; i < this.code.length; i++) - { - this.codeID[i] = new Array(this.code[i].length); - for (j = 0; j < this.code[i].length; j++) - { - this.codeID[i][j] = this.nextIndex++; - this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPLCS.CODE_START_X, DPLCS.CODE_START_Y + i * DPLCS.CODE_LINE_HEIGHT, 0); - this.cmd("SetForegroundColor", this.codeID[i][j], DPLCS.CODE_STANDARD_COLOR); - if (j > 0) - { - this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); - } - } - - - } - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -DPLCS.prototype.addControls = function() -{ - this.controls = []; - addLabelToAlgorithmBar("S1:"); - this.S1Field = this.addControlToAlgorithmBar("Text", ""); - this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); - this.controls.push(this.S1Field); - - addLabelToAlgorithmBar("S2:"); - this.S2Field = this.addControlToAlgorithmBar("Text", ""); - this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); - this.controls.push(this.S2Field); - - this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); - this.recursiveButton.onclick = this.recursiveCallback.bind(this); - this.controls.push(this.recursiveButton); - - this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); - this.tableButton.onclick = this.tableCallback.bind(this); - this.controls.push(this.tableButton); - - this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); - this.memoizedButton.onclick = this.memoizedCallback.bind(this); - this.controls.push(this.memoizedButton); - -} - - - -DPLCS.prototype.buildTable = function(S1, S2) -{ - var x = S1.length; - var y = S2.length; - this.tableID = new Array(x+1); - this.tableVals = new Array(x + 1); - this.tableXPos = new Array(x + 1); - this.tableYPos = new Array(x + 1); - - var i, j; - var sequence1ID = new Array(x); - var sequence2ID = new Array(y); - - this.S1TableID = new Array(x); - for (i = 0; i <=x; i++) - { - if (i > 0) - { - this.S1TableID[i-1] = this.nextIndex++; - this.cmd("CreateLabel", this.S1TableID[i-1], S1.charAt(i-1),DPLCS.TABLE_START_X + i*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 2 * DPLCS.TABLE_ELEM_HEIGHT); - this.oldIDs.push(this.S1TableID[i-1]); - } - var index = this.nextIndex++; - this.oldIDs.push(index); - this.cmd("CreateLabel", index, i - 1,DPLCS.TABLE_START_X + i*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 1 * DPLCS.TABLE_ELEM_HEIGHT); - this.cmd("SetForegroundColor", index, "#0000FF"); - - } - - - this.S2TableID = new Array(y); - for (i = 0; i <=y; i++) - { - if (i > 0) - { - this.S2TableID[i-1] = this.nextIndex++; - this.cmd("CreateLabel", this.S2TableID[i-1], S2.charAt(i-1),DPLCS.TABLE_START_X - 2 * DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y + i * DPLCS.TABLE_ELEM_HEIGHT); - this.oldIDs.push(this.S2TableID[i-1]); - } - var index = this.nextIndex++; - this.oldIDs.push(index); - this.cmd("CreateLabel", index, i - 1, DPLCS.TABLE_START_X - 1 * DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y + i * DPLCS.TABLE_ELEM_HEIGHT); - this.cmd("SetForegroundColor", index, "#0000FF"); - } - - - for (i = 0; i <= x; i++) - { - this.tableID[i] = new Array(y+1); - this.tableVals[i] =new Array(y+1); - this.tableXPos[i] = new Array(y+1); - this.tableYPos[i] = new Array(y+1); - - for (j = 0; j <= y; j++) - { - this.tableID[i][j] = this.nextIndex++; - this.tableVals[i][j] = -1; - this.oldIDs.push(this.tableID[i][j]); - - this.tableXPos[i][j] =DPLCS.TABLE_START_X + i * DPLCS.TABLE_ELEM_WIDTH; - this.tableYPos[i][j] = DPLCS.TABLE_START_Y + j * DPLCS.TABLE_ELEM_HEIGHT; - - this.cmd("CreateRectangle", this.tableID[i][j], - "", - DPLCS.TABLE_ELEM_WIDTH, - DPLCS.TABLE_ELEM_HEIGHT, - this.tableXPos[i][j], - this.tableYPos[i][j]); - - } - - } -} - -DPLCS.prototype.clearOldIDs = function() -{ - for (var i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs =[]; - this.nextIndex = this.initialIndex; - -} - - -DPLCS.prototype.reset = function() -{ - this.oldIDs =[]; - this.nextIndex = this.initialIndex; -} - - - -DPLCS.prototype.emptyCallback = function(event) -{ - this.implementAction(this.helpMessage.bind(this), ""); - // TODO: Put up a message to push the appropriate button? - -} - -DPLCS.prototype.recursiveCallback = function(event) -{ - var fibValue; - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.recursiveLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - - -DPLCS.prototype.tableCallback = function(event) -{ - var fibValue; - - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.tableLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - - -DPLCS.prototype.memoizedCallback = function(event) -{ - var fibValue; - - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.memoizedLCS.bind(this), this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - -DPLCS.prototype.helpMessage = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - var messageID = this.nextIndex++; - this.oldIDs.push(messageID); - this.cmd("CreateLabel", messageID, - "Enter two sequences in the text fields.\n" + - "Then press the LCS Recursive, LCS Table, or LCS Memoized button", - DPLCS.RECURSIVE_START_X, DPLCS.RECURSIVE_START_Y, 0); - return this.commands; - - -} - - -DPLCS.prototype.recursiveLCS = function(value) -{ - this.commands = []; - - var sequences=value.split(";"); - - - - this.clearOldIDs(); - - this.currentY = DPLCS.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.LCS(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPLCS.RECURSIVE_START_X, functionCallID); - this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); - return this.commands; -} - - -DPLCS.prototype.LCS = function(S1, S2, x, y, xPos, ID) -{ - var ID2 = this.nextIndex++; - this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); - this.cmd("SetForegroundColor", ID2, "#3333FF"); - this.cmd("AlignRight", ID2, ID); - this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_STANDARD_COLOR); - - if (x == -1 || y == -1) - { - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_HIGHLIGHT_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_HIGHLIGHT_COLOR); - - } - this.cmd("Step"); - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_STANDARD_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_STANDARD_COLOR); - } - this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", ID, 0); - this.cmd("Delete", ID2); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_STANDARD_COLOR); - return 0; - } - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); - - if (S1.charAt(x) == S2.charAt(y)) - { - - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); - - var nextID = this.nextIndex++; - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - var subProb = this.LCS(S1, S2, x-1, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, nextID); - - - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); - - - this.cmd("Delete", nextID); - this.cmd("SetText", ID, subProb + 1); - this.cmd("Delete", ID2); - this.cmd("step"); - this.currentY -= DPLCS.RECURSIVE_DELTA_Y; - return subProb + 1 - } - else - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); - - var subProb1 = this.LCS(S1, S2, x-1, y, xPos + DPLCS.RECURSIVE_DELTA_X, firstID); - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); - - var subProb2 = this.LCS(S1, S2, x, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, secondID); - - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.currentY -= 2*DPLCS.RECURSIVE_DELTA_Y; - var best = Math.max(subProb1, subProb2); - this.cmd("SetText", ID, best); - this.cmd("Delete", ID2); - this.cmd("step"); - return best; - } -} - -DPLCS.prototype.buildLCSFromTable = function(S1, S2) -{ - var currX = this.tableVals.length - 1; - var currY = this.tableVals[0].length - 1; - - var sequence = []; - - var header = this.nextIndex++; - this.oldIDs.push(header); - this.cmd("CreateLabel", header, "Sequence", DPLCS.SEQUENCE_START_X, DPLCS.SEQUENCE_START_Y - 30, 0); - this.cmd("SetForegroundColor", header, "#003300"); - - while (currX > 0 && currY > 0) - { - this.cmd("SetHighlight", this.tableID[currX][currY], 1); - this.cmd("Step"); - this.cmd("SetHighlight", this.S1TableID[currX-1], 1); - this.cmd("SetHighlight", this.S2TableID[currY-1], 1); - this.cmd("Step"); - this.cmd("SetHighlight", this.S1TableID[currX-1], 0); - this.cmd("SetHighlight", this.S2TableID[currY-1], 0); - this.cmd("SetHighlight", this.tableID[currX][currY], 0); - - if (S1.charAt(currX - 1) == S2.charAt(currY - 1)) - { - var nextSequenceID = this.nextIndex++; - this.oldIDs.push(nextSequenceID); - sequence.push(nextSequenceID); - this.cmd("CreateLabel", nextSequenceID, S1.charAt(currX - 1), DPLCS.TABLE_START_X + currX*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 2 * DPLCS.TABLE_ELEM_HEIGHT); - this.cmd("SetForegroundColor", nextSequenceID, "#0000FF"); - - for (var i = sequence.length - 1; i >=0; i--) - { - this.cmd("Move", sequence[i], DPLCS.SEQUENCE_START_X + (sequence.length - 1 - i) * DPLCS.SEQUENCE_DELTA_X, DPLCS.SEQUENCE_START_Y); - } - - currX = currX - 1; - currY = currY - 1; - } - else - { - this.cmd("SetHighlight", this.tableID[currX-1][currY], 1); - this.cmd("SetHighlight", this.tableID[currX][currY - 1], 1); - this.cmd("Step"); - this.cmd("SetHighlight", this.tableID[currX-1][currY], 0); - this.cmd("SetHighlight", this.tableID[currX][currY - 1], 0 ); - - if (this.tableVals[currX-1][currY] > this.tableVals[currX][currY - 1]) - { - currX = currX - 1; - } - else - { - currY = currY - 1; - - } - } - - } - - - -} - - -DPLCS.prototype.tableLCS = function(value) -{ - this.commands = []; - this.clearOldIDs(); - - var sequences=value.split(";"); - - this.buildTable(sequences[0], sequences[1]); - - var moveID = this.nextIndex++; - var x = sequences[0].length; - var y = sequences[1].length; - var i, j; - - for (i = 0; i <= x; i++) - { - this.cmd("SetText", this.tableID[i][0], "0"); - this.tableVals[i][0] = 0; - } - for (i = 0; i <= y; i++) - { - this.cmd("SetText", this.tableID[0][i], "0"); - this.tableVals[0][i] = 0; - } - this.cmd("Step"); - for (j = 0; j < y; j++) - { - for (i = 0; i < x; i++) - { - this.cmd("SetHighlight", this.tableID[i+1][j+1], 1); - this.cmd("SetHighlight", this.S1TableID[i], 1); - this.cmd("SetHighlight", this.S2TableID[j], 1); - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetHighlight", this.S1TableID[i], 0); - this.cmd("SetHighlight", this.S2TableID[j], 0); - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); - if (sequences[0].charAt(i) == sequences[1].charAt(j)) - { - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 1); - this.cmd("Step"); - this.cmd("CreateLabel", moveID, this.tableVals[i][j] + 1, this.tableXPos[i][j], this.tableYPos[i][j]); - this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); - this.cmd("Step"); - this.cmd("Delete", moveID); - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 0); - this.tableVals[i+1][j+1] = this.tableVals[i][j] + 1; - this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); - - this.cmd("SetHighlight", this.tableID[i][j+1], 1); - this.cmd("SetHighlight", this.tableID[i+1][j], 1); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); - - if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) - { - this.cmd("SetHighlight", this.tableID[i+1][j], 0); - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); - - this.tableVals[i+1][j+1] = this.tableVals[i][j+1]; - this.cmd("CreateLabel", moveID, this.tableVals[i][j+1], this.tableXPos[i][j+1], this.tableYPos[i][j+1]); - - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i][j+1], 0); - this.tableVals[i+1][j+1] = this.tableVals[i+1][j]; - this.cmd("CreateLabel", moveID, this.tableVals[i+1][j], this.tableXPos[i+1][j], this.tableYPos[i+1][j]); - } - this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); - this.cmd("Step"); - this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); - this.cmd("Delete", moveID); - if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i][j+1], 0); - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i+1][j], 0); - } - - } - this.cmd("SetHighlight", this.tableID[i+1][j+1], 0); - //this.cmd("Step"); - - } - } - this.buildLCSFromTable(sequences[0], sequences[1]); - return this.commands; -} - - - -DPLCS.prototype.LCSMem = function(S1, S2, x, y, xPos, ID) -{ - var ID2 = this.nextIndex++; - this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); - this.cmd("SetForegroundColor", ID2, "#3333FF"); - this.cmd("AlignRight", ID2, ID); - this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_STANDARD_COLOR); - - if (this.tableVals[x+1][y+1] != -1) - { - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, this.tableVals[x+1][y+1], this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Move", movingLabel, xPos, this.currentY); - this.cmd("SetText", ID, ""); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - this.cmd("SetText", ID, this.tableVals[x+1][y+1]); - this.cmd("Delete", ID2); - this.cmd("Step"); - return this.tableVals[x+1][y+1]; - } - - - if (x == -1 || y == -1) - { - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_HIGHLIGHT_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_HIGHLIGHT_COLOR); - - } - this.cmd("Step"); - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_STANDARD_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_STANDARD_COLOR); - } - this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", ID, 0); - this.cmd("Delete", ID2); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_STANDARD_COLOR); - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel,0, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - this.tableVals[x+1][y+1] = 0; - this.cmd("SetText", this.tableID[x+1][y+1], 0); - - - return 0; - } - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); - - if (S1.charAt(x) == S2.charAt(y)) - { - - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); - - var nextID = this.nextIndex++; - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - var subProb = this.LCSMem(S1, S2, x-1, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, nextID); - - - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); - - - this.cmd("Delete", nextID); - this.cmd("SetText", ID, subProb + 1); - this.cmd("Delete", ID2); - this.cmd("step"); - this.currentY -= DPLCS.RECURSIVE_DELTA_Y; - - // TODO: Animate moving value into table here - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, subProb + 1, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - - this.tableVals[x+1][y+1] = subProb + 1; - this.cmd("SetText", this.tableID[x+1][y+1], subProb + 1); - - return subProb + 1 - } - else - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); - - var subProb1 = this.LCSMem(S1, S2, x-1, y, xPos + DPLCS.RECURSIVE_DELTA_X, firstID); - this.currentY += DPLCS.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); - - var subProb2 = this.LCSMem(S1, S2, x, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, secondID); - - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.currentY -= 2*DPLCS.RECURSIVE_DELTA_Y; - var best = Math.max(subProb1, subProb2); - this.cmd("SetText", ID, best); - this.cmd("Delete", ID2); - - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, best, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - - // TODO: Animate moving value into table here - this.tableVals[x+1][y+1] = best; - this.cmd("SetText", this.tableID[x+1][y+1], best); - - - - this.cmd("step"); - return best; - } -} - - -DPLCS.prototype.memoizedLCS = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - var sequences=value.split(";"); - - this.buildTable(sequences[0], sequences[1]); - - - var functionCallID = this.nextIndex++; - this.currentY = DPLCS.RECURSIVE_START_Y; - - this.oldIDs.push(functionCallID); - - - var final = this.LCSMem(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPLCS.RECURSIVE_START_X, functionCallID); - - this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); - - - this.buildLCSFromTable(sequences[0], sequences[1]); - - return this.commands; -} - -DPLCS.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -DPLCS.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new DPLCS(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function DPLCS(am, w, h) +{ + this.init(am, w, h); + +} +DPLCS.inheritFrom(Algorithm); + +DPLCS.TABLE_ELEM_WIDTH = 40; +DPLCS.TABLE_ELEM_HEIGHT = 30; + +DPLCS.TABLE_START_X = 500; +DPLCS.TABLE_START_Y = 80; + + +DPLCS.TABLE_DIFF_X = 100; + +DPLCS.CODE_START_X = 10; +DPLCS.CODE_START_Y = 10; +DPLCS.CODE_LINE_HEIGHT = 14; + +DPLCS.RECURSIVE_START_X = 20; +DPLCS.RECURSIVE_START_Y = 120; +DPLCS.RECURSIVE_DELTA_Y = 14; +DPLCS.RECURSIVE_DELTA_X = 15; +DPLCS.CODE_HIGHLIGHT_COLOR = "#FF0000"; +DPLCS.CODE_STANDARD_COLOR = "#000000"; +DPLCS.MAX_SEQUENCE_LENGTH = 15; + +DPLCS.TABLE_INDEX_COLOR = "#0000FF" +DPLCS.CODE_RECURSIVE_1_COLOR = "#339933"; +DPLCS.CODE_RECURSIVE_2_COLOR = "#0099FF"; + +DPLCS.SEQUENCE_START_X = 30; +DPLCS.SEQUENCE_START_Y = 180; +DPLCS.SEQUENCE_DELTA_X = 10; + + +DPLCS.MAX_VALUE = 20; + +DPLCS.MESSAGE_ID = 0; + +DPLCS.prototype.init = function(am, w, h) +{ + DPLCS.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = [["def ","LCS(S1, S2, x, y)",":"], + [" if (","(x == -1) ", " or ", "(y == -1)", ")" ], + [" return 0"], + [" else if ", "(S1[x] == S2[y])"], + [" return 1 + ","LCS(S1, S2, x-1, y-1)"], + [" else"], + [" return max(", "LCS(S1, S2, x-1, y)", ",", "LCS(S1, S2, x, y-1)", ")"]]; + + this.codeID = Array(this.code.length); + var i, j; + for (i = 0; i < this.code.length; i++) + { + this.codeID[i] = new Array(this.code[i].length); + for (j = 0; j < this.code[i].length; j++) + { + this.codeID[i][j] = this.nextIndex++; + this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPLCS.CODE_START_X, DPLCS.CODE_START_Y + i * DPLCS.CODE_LINE_HEIGHT, 0); + this.cmd("SetForegroundColor", this.codeID[i][j], DPLCS.CODE_STANDARD_COLOR); + if (j > 0) + { + this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); + } + } + + + } + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +DPLCS.prototype.addControls = function() +{ + this.controls = []; + this.addLabelToAlgorithmBar("S1:"); + this.S1Field = this.addControlToAlgorithmBar("Text", ""); + this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); + this.controls.push(this.S1Field); + + this.addLabelToAlgorithmBar("S2:"); + this.S2Field = this.addControlToAlgorithmBar("Text", ""); + this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPLCS.MAX_SEQUENCE_LENGTH, false); + this.controls.push(this.S2Field); + + this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); + this.recursiveButton.onclick = this.recursiveCallback.bind(this); + this.controls.push(this.recursiveButton); + + this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); + this.tableButton.onclick = this.tableCallback.bind(this); + this.controls.push(this.tableButton); + + this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); + this.memoizedButton.onclick = this.memoizedCallback.bind(this); + this.controls.push(this.memoizedButton); + +} + + + +DPLCS.prototype.buildTable = function(S1, S2) +{ + var x = S1.length; + var y = S2.length; + this.tableID = new Array(x+1); + this.tableVals = new Array(x + 1); + this.tableXPos = new Array(x + 1); + this.tableYPos = new Array(x + 1); + + var i, j; + var sequence1ID = new Array(x); + var sequence2ID = new Array(y); + + this.S1TableID = new Array(x); + for (i = 0; i <=x; i++) + { + if (i > 0) + { + this.S1TableID[i-1] = this.nextIndex++; + this.cmd("CreateLabel", this.S1TableID[i-1], S1.charAt(i-1),DPLCS.TABLE_START_X + i*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 2 * DPLCS.TABLE_ELEM_HEIGHT); + this.oldIDs.push(this.S1TableID[i-1]); + } + var index = this.nextIndex++; + this.oldIDs.push(index); + this.cmd("CreateLabel", index, i - 1,DPLCS.TABLE_START_X + i*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 1 * DPLCS.TABLE_ELEM_HEIGHT); + this.cmd("SetForegroundColor", index, "#0000FF"); + + } + + + this.S2TableID = new Array(y); + for (i = 0; i <=y; i++) + { + if (i > 0) + { + this.S2TableID[i-1] = this.nextIndex++; + this.cmd("CreateLabel", this.S2TableID[i-1], S2.charAt(i-1),DPLCS.TABLE_START_X - 2 * DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y + i * DPLCS.TABLE_ELEM_HEIGHT); + this.oldIDs.push(this.S2TableID[i-1]); + } + var index = this.nextIndex++; + this.oldIDs.push(index); + this.cmd("CreateLabel", index, i - 1, DPLCS.TABLE_START_X - 1 * DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y + i * DPLCS.TABLE_ELEM_HEIGHT); + this.cmd("SetForegroundColor", index, "#0000FF"); + } + + + for (i = 0; i <= x; i++) + { + this.tableID[i] = new Array(y+1); + this.tableVals[i] =new Array(y+1); + this.tableXPos[i] = new Array(y+1); + this.tableYPos[i] = new Array(y+1); + + for (j = 0; j <= y; j++) + { + this.tableID[i][j] = this.nextIndex++; + this.tableVals[i][j] = -1; + this.oldIDs.push(this.tableID[i][j]); + + this.tableXPos[i][j] =DPLCS.TABLE_START_X + i * DPLCS.TABLE_ELEM_WIDTH; + this.tableYPos[i][j] = DPLCS.TABLE_START_Y + j * DPLCS.TABLE_ELEM_HEIGHT; + + this.cmd("CreateRectangle", this.tableID[i][j], + "", + DPLCS.TABLE_ELEM_WIDTH, + DPLCS.TABLE_ELEM_HEIGHT, + this.tableXPos[i][j], + this.tableYPos[i][j]); + + } + + } +} + +DPLCS.prototype.clearOldIDs = function() +{ + for (var i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs =[]; + this.nextIndex = this.initialIndex; + +} + + +DPLCS.prototype.reset = function() +{ + this.oldIDs =[]; + this.nextIndex = this.initialIndex; +} + + + +DPLCS.prototype.emptyCallback = function(event) +{ + this.implementAction(this.helpMessage.bind(this), ""); + // TODO: Put up a message to push the appropriate button? + +} + +DPLCS.prototype.recursiveCallback = function(event) +{ + var fibValue; + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.recursiveLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + + +DPLCS.prototype.tableCallback = function(event) +{ + var fibValue; + + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.tableLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + + +DPLCS.prototype.memoizedCallback = function(event) +{ + var fibValue; + + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.memoizedLCS.bind(this), this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + +DPLCS.prototype.helpMessage = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + var messageID = this.nextIndex++; + this.oldIDs.push(messageID); + this.cmd("CreateLabel", messageID, + "Enter two sequences in the text fields.\n" + + "Then press the LCS Recursive, LCS Table, or LCS Memoized button", + DPLCS.RECURSIVE_START_X, DPLCS.RECURSIVE_START_Y, 0); + return this.commands; + + +} + + +DPLCS.prototype.recursiveLCS = function(value) +{ + this.commands = []; + + var sequences=value.split(";"); + + + + this.clearOldIDs(); + + this.currentY = DPLCS.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.LCS(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPLCS.RECURSIVE_START_X, functionCallID); + this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); + return this.commands; +} + + +DPLCS.prototype.LCS = function(S1, S2, x, y, xPos, ID) +{ + var ID2 = this.nextIndex++; + this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); + this.cmd("SetForegroundColor", ID2, "#3333FF"); + this.cmd("AlignRight", ID2, ID); + this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_STANDARD_COLOR); + + if (x == -1 || y == -1) + { + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_HIGHLIGHT_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_HIGHLIGHT_COLOR); + + } + this.cmd("Step"); + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_STANDARD_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_STANDARD_COLOR); + } + this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", ID, 0); + this.cmd("Delete", ID2); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_STANDARD_COLOR); + return 0; + } + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); + + if (S1.charAt(x) == S2.charAt(y)) + { + + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); + + var nextID = this.nextIndex++; + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + var subProb = this.LCS(S1, S2, x-1, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, nextID); + + + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); + + + this.cmd("Delete", nextID); + this.cmd("SetText", ID, subProb + 1); + this.cmd("Delete", ID2); + this.cmd("step"); + this.currentY -= DPLCS.RECURSIVE_DELTA_Y; + return subProb + 1 + } + else + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); + + var subProb1 = this.LCS(S1, S2, x-1, y, xPos + DPLCS.RECURSIVE_DELTA_X, firstID); + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); + + var subProb2 = this.LCS(S1, S2, x, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, secondID); + + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.currentY -= 2*DPLCS.RECURSIVE_DELTA_Y; + var best = Math.max(subProb1, subProb2); + this.cmd("SetText", ID, best); + this.cmd("Delete", ID2); + this.cmd("step"); + return best; + } +} + +DPLCS.prototype.buildLCSFromTable = function(S1, S2) +{ + var currX = this.tableVals.length - 1; + var currY = this.tableVals[0].length - 1; + + var sequence = []; + + var header = this.nextIndex++; + this.oldIDs.push(header); + this.cmd("CreateLabel", header, "Sequence", DPLCS.SEQUENCE_START_X, DPLCS.SEQUENCE_START_Y - 30, 0); + this.cmd("SetForegroundColor", header, "#003300"); + + while (currX > 0 && currY > 0) + { + this.cmd("SetHighlight", this.tableID[currX][currY], 1); + this.cmd("Step"); + this.cmd("SetHighlight", this.S1TableID[currX-1], 1); + this.cmd("SetHighlight", this.S2TableID[currY-1], 1); + this.cmd("Step"); + this.cmd("SetHighlight", this.S1TableID[currX-1], 0); + this.cmd("SetHighlight", this.S2TableID[currY-1], 0); + this.cmd("SetHighlight", this.tableID[currX][currY], 0); + + if (S1.charAt(currX - 1) == S2.charAt(currY - 1)) + { + var nextSequenceID = this.nextIndex++; + this.oldIDs.push(nextSequenceID); + sequence.push(nextSequenceID); + this.cmd("CreateLabel", nextSequenceID, S1.charAt(currX - 1), DPLCS.TABLE_START_X + currX*DPLCS.TABLE_ELEM_WIDTH, DPLCS.TABLE_START_Y - 2 * DPLCS.TABLE_ELEM_HEIGHT); + this.cmd("SetForegroundColor", nextSequenceID, "#0000FF"); + + for (var i = sequence.length - 1; i >=0; i--) + { + this.cmd("Move", sequence[i], DPLCS.SEQUENCE_START_X + (sequence.length - 1 - i) * DPLCS.SEQUENCE_DELTA_X, DPLCS.SEQUENCE_START_Y); + } + + currX = currX - 1; + currY = currY - 1; + } + else + { + this.cmd("SetHighlight", this.tableID[currX-1][currY], 1); + this.cmd("SetHighlight", this.tableID[currX][currY - 1], 1); + this.cmd("Step"); + this.cmd("SetHighlight", this.tableID[currX-1][currY], 0); + this.cmd("SetHighlight", this.tableID[currX][currY - 1], 0 ); + + if (this.tableVals[currX-1][currY] > this.tableVals[currX][currY - 1]) + { + currX = currX - 1; + } + else + { + currY = currY - 1; + + } + } + + } + + + +} + + +DPLCS.prototype.tableLCS = function(value) +{ + this.commands = []; + this.clearOldIDs(); + + var sequences=value.split(";"); + + this.buildTable(sequences[0], sequences[1]); + + var moveID = this.nextIndex++; + var x = sequences[0].length; + var y = sequences[1].length; + var i, j; + + for (i = 0; i <= x; i++) + { + this.cmd("SetText", this.tableID[i][0], "0"); + this.tableVals[i][0] = 0; + } + for (i = 0; i <= y; i++) + { + this.cmd("SetText", this.tableID[0][i], "0"); + this.tableVals[0][i] = 0; + } + this.cmd("Step"); + for (j = 0; j < y; j++) + { + for (i = 0; i < x; i++) + { + this.cmd("SetHighlight", this.tableID[i+1][j+1], 1); + this.cmd("SetHighlight", this.S1TableID[i], 1); + this.cmd("SetHighlight", this.S2TableID[j], 1); + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetHighlight", this.S1TableID[i], 0); + this.cmd("SetHighlight", this.S2TableID[j], 0); + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); + if (sequences[0].charAt(i) == sequences[1].charAt(j)) + { + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 1); + this.cmd("Step"); + this.cmd("CreateLabel", moveID, this.tableVals[i][j] + 1, this.tableXPos[i][j], this.tableYPos[i][j]); + this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); + this.cmd("Step"); + this.cmd("Delete", moveID); + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 0); + this.tableVals[i+1][j+1] = this.tableVals[i][j] + 1; + this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); + + this.cmd("SetHighlight", this.tableID[i][j+1], 1); + this.cmd("SetHighlight", this.tableID[i+1][j], 1); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); + + if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) + { + this.cmd("SetHighlight", this.tableID[i+1][j], 0); + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); + + this.tableVals[i+1][j+1] = this.tableVals[i][j+1]; + this.cmd("CreateLabel", moveID, this.tableVals[i][j+1], this.tableXPos[i][j+1], this.tableYPos[i][j+1]); + + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i][j+1], 0); + this.tableVals[i+1][j+1] = this.tableVals[i+1][j]; + this.cmd("CreateLabel", moveID, this.tableVals[i+1][j], this.tableXPos[i+1][j], this.tableYPos[i+1][j]); + } + this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); + this.cmd("Step"); + this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); + this.cmd("Delete", moveID); + if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i][j+1], 0); + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i+1][j], 0); + } + + } + this.cmd("SetHighlight", this.tableID[i+1][j+1], 0); + //this.cmd("Step"); + + } + } + this.buildLCSFromTable(sequences[0], sequences[1]); + return this.commands; +} + + + +DPLCS.prototype.LCSMem = function(S1, S2, x, y, xPos, ID) +{ + var ID2 = this.nextIndex++; + this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); + this.cmd("SetForegroundColor", ID2, "#3333FF"); + this.cmd("AlignRight", ID2, ID); + this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPLCS.CODE_STANDARD_COLOR); + + if (this.tableVals[x+1][y+1] != -1) + { + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, this.tableVals[x+1][y+1], this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Move", movingLabel, xPos, this.currentY); + this.cmd("SetText", ID, ""); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + this.cmd("SetText", ID, this.tableVals[x+1][y+1]); + this.cmd("Delete", ID2); + this.cmd("Step"); + return this.tableVals[x+1][y+1]; + } + + + if (x == -1 || y == -1) + { + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_HIGHLIGHT_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_HIGHLIGHT_COLOR); + + } + this.cmd("Step"); + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPLCS.CODE_STANDARD_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPLCS.CODE_STANDARD_COLOR); + } + this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", ID, 0); + this.cmd("Delete", ID2); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPLCS.CODE_STANDARD_COLOR); + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel,0, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + this.tableVals[x+1][y+1] = 0; + this.cmd("SetText", this.tableID[x+1][y+1], 0); + + + return 0; + } + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][1], DPLCS.CODE_STANDARD_COLOR); + + if (S1.charAt(x) == S2.charAt(y)) + { + + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPLCS.CODE_STANDARD_COLOR); + + var nextID = this.nextIndex++; + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + var subProb = this.LCSMem(S1, S2, x-1, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, nextID); + + + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPLCS.CODE_STANDARD_COLOR); + + + this.cmd("Delete", nextID); + this.cmd("SetText", ID, subProb + 1); + this.cmd("Delete", ID2); + this.cmd("step"); + this.currentY -= DPLCS.RECURSIVE_DELTA_Y; + + // TODO: Animate moving value into table here + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, subProb + 1, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + + this.tableVals[x+1][y+1] = subProb + 1; + this.cmd("SetText", this.tableID[x+1][y+1], subProb + 1); + + return subProb + 1 + } + else + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPLCS.CODE_STANDARD_COLOR); + + var subProb1 = this.LCSMem(S1, S2, x-1, y, xPos + DPLCS.RECURSIVE_DELTA_X, firstID); + this.currentY += DPLCS.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][3], DPLCS.CODE_STANDARD_COLOR); + + var subProb2 = this.LCSMem(S1, S2, x, y-1, xPos + DPLCS.RECURSIVE_DELTA_X, secondID); + + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPLCS.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPLCS.CODE_STANDARD_COLOR); + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.currentY -= 2*DPLCS.RECURSIVE_DELTA_Y; + var best = Math.max(subProb1, subProb2); + this.cmd("SetText", ID, best); + this.cmd("Delete", ID2); + + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, best, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + + // TODO: Animate moving value into table here + this.tableVals[x+1][y+1] = best; + this.cmd("SetText", this.tableID[x+1][y+1], best); + + + + this.cmd("step"); + return best; + } +} + + +DPLCS.prototype.memoizedLCS = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + var sequences=value.split(";"); + + this.buildTable(sequences[0], sequences[1]); + + + var functionCallID = this.nextIndex++; + this.currentY = DPLCS.RECURSIVE_START_Y; + + this.oldIDs.push(functionCallID); + + + var final = this.LCSMem(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPLCS.RECURSIVE_START_X, functionCallID); + + this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); + + + this.buildLCSFromTable(sequences[0], sequences[1]); + + return this.commands; +} + +DPLCS.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +DPLCS.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new DPLCS(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/DPMatrixMultiply.js b/AlgorithmLibrary/DPMatrixMultiply.js index f309721..8dba0c0 100644 --- a/AlgorithmLibrary/DPMatrixMultiply.js +++ b/AlgorithmLibrary/DPMatrixMultiply.js @@ -1,764 +1,761 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function DPMatrixMultiply(am, w, h) -{ - this.init(am, w, h); - -} - -DPMatrixMultiply.prototype = new Algorithm(); -DPMatrixMultiply.prototype.constructor = DPMatrixMultiply; -DPMatrixMultiply.superclass = Algorithm.prototype; - -DPMatrixMultiply.TABLE_ELEM_WIDTH = 40; -DPMatrixMultiply.TABLE_ELEM_HEIGHT = 30; - -DPMatrixMultiply.TABLE_START_X = 500; -DPMatrixMultiply.TABLE_START_Y = 80; - - -DPMatrixMultiply.TABLE_DIFF_X = 100; - -DPMatrixMultiply.CODE_START_X = 10; -DPMatrixMultiply.CODE_START_Y = 10; -DPMatrixMultiply.CODE_LINE_HEIGHT = 14; - -DPMatrixMultiply.RECURSIVE_START_X = 20; -DPMatrixMultiply.RECURSIVE_START_Y = 120; -DPMatrixMultiply.RECURSIVE_DELTA_Y = 14; -DPMatrixMultiply.RECURSIVE_DELTA_X = 15; -DPMatrixMultiply.CODE_HIGHLIGHT_COLOR = "#FF0000"; -DPMatrixMultiply.CODE_STANDARD_COLOR = "#000000"; -DPMatrixMultiply.MAX_SEQUENCE_LENGTH = 15; - -DPMatrixMultiply.TABLE_INDEX_COLOR = "#0000FF" -DPMatrixMultiply.CODE_RECURSIVE_1_COLOR = "#339933"; -DPMatrixMultiply.CODE_RECURSIVE_2_COLOR = "#0099FF"; - - - -DPMatrixMultiply.MAX_VALUE = 20; - -DPMatrixMultiply.MESSAGE_ID = 0; - -DPMatrixMultiply.prototype.init = function(am, w, h) -{ - DPMatrixMultiply.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = [["def ","MatrixMultiply(x, y, P)",":"], - [" if (","(x >= y)", ")" ], - [" return 0"], - [" best = -1"], - [" for i in range(x, y)"], - [" left = ", "MatrixMultiply(x, i, P)"], - [" right = ", "MatrixMultiply(i+1, y, P)"], - [" total = left + right + P[x] * P[i+1] * P[y]"], - [" if (", "best == -1", " or ", "best > total", ")"], - [" best = total"], - [" return best"]]; - - this.codeID = Array(this.code.length); - var i, j; - for (i = 0; i < this.code.length; i++) - { - this.codeID[i] = new Array(this.code[i].length); - for (j = 0; j < this.code[i].length; j++) - { - this.codeID[i][j] = this.nextIndex++; - this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPMatrixMultiply.CODE_START_X, DPMatrixMultiply.CODE_START_Y + i * DPMatrixMultiply.CODE_LINE_HEIGHT, 0); - this.cmd("SetForegroundColor", this.codeID[i][j], DPMatrixMultiply.CODE_STANDARD_COLOR); - if (j > 0) - { - this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); - } - } - - - } - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -DPMatrixMultiply.prototype.addControls = function() -{ - this.controls = []; - addLabelToAlgorithmBar("S1:"); - this.S1Field = this.addControlToAlgorithmBar("Text", ""); - this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); - this.controls.push(this.S1Field); - - addLabelToAlgorithmBar("S2:"); - this.S2Field = this.addControlToAlgorithmBar("Text", ""); - this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); - this.controls.push(this.S2Field); - - this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); - this.recursiveButton.onclick = this.recursiveCallback.bind(this); - this.controls.push(this.recursiveButton); - - this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); - this.tableButton.onclick = this.tableCallback.bind(this); - this.controls.push(this.tableButton); - - this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); - this.memoizedButton.onclick = this.memoizedCallback.bind(this); - this.controls.push(this.memoizedButton); - -} - - - -DPMatrixMultiply.prototype.buildTable = function(S1, S2) -{ - var x = S1.length; - var y = S2.length; - this.tableID = new Array(x+1); - this.tableVals = new Array(x + 1); - this.tableXPos = new Array(x + 1); - this.tableYPos = new Array(x + 1); - - var i, j; - var sequence1ID = new Array(x); - var sequence2ID = new Array(y); - - this.S1TableID = new Array(x); - for (i = 0; i <=x; i++) - { - if (i > 0) - { - this.S1TableID[i-1] = this.nextIndex++; - this.cmd("CreateLabel", this.S1TableID[i-1], S1.charAt(i-1),DPMatrixMultiply.TABLE_START_X + i*DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y - 2 * DPMatrixMultiply.TABLE_ELEM_HEIGHT); - this.oldIDs.push(this.S1TableID[i-1]); - } - var index = this.nextIndex++; - this.oldIDs.push(index); - this.cmd("CreateLabel", index, i - 1,DPMatrixMultiply.TABLE_START_X + i*DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y - 1 * DPMatrixMultiply.TABLE_ELEM_HEIGHT); - this.cmd("SetForegroundColor", index, "#0000FF"); - - } - - - this.S2TableID = new Array(y); - for (i = 0; i <=y; i++) - { - if (i > 0) - { - this.S2TableID[i-1] = this.nextIndex++; - this.cmd("CreateLabel", this.S2TableID[i-1], S2.charAt(i-1),DPMatrixMultiply.TABLE_START_X - 2 * DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y + i * DPMatrixMultiply.TABLE_ELEM_HEIGHT); - this.oldIDs.push(this.S2TableID[i-1]); - } - var index = this.nextIndex++; - this.oldIDs.push(index); - this.cmd("CreateLabel", index, i - 1, DPMatrixMultiply.TABLE_START_X - 1 * DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y + i * DPMatrixMultiply.TABLE_ELEM_HEIGHT); - this.cmd("SetForegroundColor", index, "#0000FF"); - } - - - for (i = 0; i <= x; i++) - { - this.tableID[i] = new Array(y+1); - this.tableVals[i] =new Array(y+1); - this.tableXPos[i] = new Array(y+1); - this.tableYPos[i] = new Array(y+1); - - for (j = 0; j <= y; j++) - { - this.tableID[i][j] = this.nextIndex++; - this.tableVals[i][j] = -1; - this.oldIDs.push(this.tableID[i][j]); - - this.tableXPos[i][j] =DPMatrixMultiply.TABLE_START_X + i * DPMatrixMultiply.TABLE_ELEM_WIDTH; - this.tableYPos[i][j] = DPMatrixMultiply.TABLE_START_Y + j * DPMatrixMultiply.TABLE_ELEM_HEIGHT; - - this.cmd("CreateRectangle", this.tableID[i][j], - "", - DPMatrixMultiply.TABLE_ELEM_WIDTH, - DPMatrixMultiply.TABLE_ELEM_HEIGHT, - this.tableXPos[i][j], - this.tableYPos[i][j]); - - } - - } -} - -DPMatrixMultiply.prototype.clearOldIDs = function() -{ - for (var i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs =[]; - this.nextIndex = this.initialIndex; - -} - - -DPMatrixMultiply.prototype.reset = function() -{ - this.oldIDs =[]; - this.nextIndex = this.initialIndex; -} - - - -DPMatrixMultiply.prototype.emptyCallback = function(event) -{ - this.implementAction(this.helpMessage.bind(this), ""); - // TODO: Put up a message to push the appropriate button? - -} - -DPMatrixMultiply.prototype.recursiveCallback = function(event) -{ - var fibValue; - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.recursiveLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - - -DPMatrixMultiply.prototype.tableCallback = function(event) -{ - var fibValue; - - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.tableLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - - -DPMatrixMultiply.prototype.memoizedCallback = function(event) -{ - var fibValue; - - - if (this.S1Field.value != "" && this.S2Field.value != "" ) - { - this.implementAction(this.memoizedLCS.bind(this), this.S1Field.value + ";" + this.S2Field.value); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - -DPMatrixMultiply.prototype.helpMessage = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - var messageID = this.nextIndex++; - this.oldIDs.push(messageID); - this.cmd("CreateLabel", messageID, - "Enter two sequences in the text fields.\n" + - "Then press the LCS Recursive, LCS Table, or LCS Memoized button", - DPMatrixMultiply.RECURSIVE_START_X, DPMatrixMultiply.RECURSIVE_START_Y, 0); - return this.commands; - - -} - - -DPMatrixMultiply.prototype.recursiveLCS = function(value) -{ - this.commands = []; - - var sequences=value.split(";"); - - - - this.clearOldIDs(); - - this.currentY = DPMatrixMultiply.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.LCS(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPMatrixMultiply.RECURSIVE_START_X, functionCallID); - this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); - return this.commands; -} - - -DPMatrixMultiply.prototype.LCS = function(S1, S2, x, y, xPos, ID) -{ - var ID2 = this.nextIndex++; - this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); - this.cmd("SetForegroundColor", ID2, "#3333FF"); - this.cmd("AlignRight", ID2, ID); - this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - if (x == -1 || y == -1) - { - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - - } - this.cmd("Step"); - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - } - this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", ID, 0); - this.cmd("Delete", ID2); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - return 0; - } - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - if (S1.charAt(x) == S2.charAt(y)) - { - - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var nextID = this.nextIndex++; - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - var subProb = this.LCS(S1, S2, x-1, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, nextID); - - - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - - - this.cmd("Delete", nextID); - this.cmd("SetText", ID, subProb + 1); - this.cmd("Delete", ID2); - this.cmd("step"); - this.currentY -= DPMatrixMultiply.RECURSIVE_DELTA_Y; - return subProb + 1 - } - else - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var subProb1 = this.LCS(S1, S2, x-1, y, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, firstID); - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var subProb2 = this.LCS(S1, S2, x, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, secondID); - - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.currentY -= 2*DPMatrixMultiply.RECURSIVE_DELTA_Y; - var best = Math.max(subProb1, subProb2); - this.cmd("SetText", ID, best); - this.cmd("Delete", ID2); - this.cmd("step"); - return best; - } -} - - - - -DPMatrixMultiply.prototype.tableLCS = function(value) -{ - this.commands = []; - this.clearOldIDs(); - - var sequences=value.split(";"); - - this.buildTable(sequences[0], sequences[1]); - - var moveID = this.nextIndex++; - var x = sequences[0].length; - var y = sequences[1].length; - var i, j; - - for (i = 0; i <= x; i++) - { - this.cmd("SetText", this.tableID[i][0], "0"); - this.tableVals[i][0] = 0; - } - for (i = 0; i <= y; i++) - { - this.cmd("SetText", this.tableID[0][i], "0"); - this.tableVals[0][i] = 0; - } - this.cmd("Step"); - for (j = 0; j < y; j++) - { - for (i = 0; i < x; i++) - { - this.cmd("SetHighlight", this.tableID[i+1][j+1], 1); - this.cmd("SetHighlight", this.S1TableID[i], 1); - this.cmd("SetHighlight", this.S2TableID[j], 1); - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetHighlight", this.S1TableID[i], 0); - this.cmd("SetHighlight", this.S2TableID[j], 0); - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - if (sequences[0].charAt(i) == sequences[1].charAt(j)) - { - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 1); - this.cmd("Step"); - this.cmd("CreateLabel", moveID, this.tableVals[i][j] + 1, this.tableXPos[i][j], this.tableYPos[i][j]); - this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); - this.cmd("Step"); - this.cmd("Delete", moveID); - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 0); - this.tableVals[i+1][j+1] = this.tableVals[i][j] + 1; - this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - - this.cmd("SetHighlight", this.tableID[i][j+1], 1); - this.cmd("SetHighlight", this.tableID[i+1][j], 1); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); - - if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) - { - this.cmd("SetHighlight", this.tableID[i+1][j], 0); - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - - this.tableVals[i+1][j+1] = this.tableVals[i][j+1]; - this.cmd("CreateLabel", moveID, this.tableVals[i][j+1], this.tableXPos[i][j+1], this.tableYPos[i][j+1]); - - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i][j+1], 0); - this.tableVals[i+1][j+1] = this.tableVals[i+1][j]; - this.cmd("CreateLabel", moveID, this.tableVals[i+1][j], this.tableXPos[i+1][j], this.tableYPos[i+1][j]); - } - this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); - this.cmd("Step"); - this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); - this.cmd("Delete", moveID); - if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i][j+1], 0); - } - else - { - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i+1][j], 0); - } - - } - this.cmd("SetHighlight", this.tableID[i+1][j+1], 0); - //this.cmd("Step"); - - } - } - return this.commands; -} - - - -DPMatrixMultiply.prototype.LCSMem = function(S1, S2, x, y, xPos, ID) -{ - var ID2 = this.nextIndex++; - this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); - this.cmd("SetForegroundColor", ID2, "#3333FF"); - this.cmd("AlignRight", ID2, ID); - this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - if (this.tableVals[x+1][y+1] != -1) - { - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, this.tableVals[x+1][y+1], this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Move", movingLabel, xPos, this.currentY); - this.cmd("SetText", ID, ""); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - this.cmd("SetText", ID, this.tableVals[x+1][y+1]); - this.cmd("Delete", ID2); - this.cmd("Step"); - return this.tableVals[x+1][y+1]; - } - - - if (x == -1 || y == -1) - { - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - - } - this.cmd("Step"); - if (x == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - } - if (y == -1) - { - this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - } - this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", ID, 0); - this.cmd("Delete", ID2); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel,0, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - this.tableVals[x+1][y+1] = 0; - this.cmd("SetText", this.tableID[x+1][y+1], 0); - - - return 0; - } - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - if (S1.charAt(x) == S2.charAt(y)) - { - - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var nextID = this.nextIndex++; - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - var subProb = this.LCSMem(S1, S2, x-1, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, nextID); - - - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - - - this.cmd("Delete", nextID); - this.cmd("SetText", ID, subProb + 1); - this.cmd("Delete", ID2); - this.cmd("step"); - this.currentY -= DPMatrixMultiply.RECURSIVE_DELTA_Y; - - // TODO: Animate moving value into table here - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, subProb + 1, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - - this.tableVals[x+1][y+1] = subProb + 1; - this.cmd("SetText", this.tableID[x+1][y+1], subProb + 1); - - return subProb + 1 - } - else - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var subProb1 = this.LCSMem(S1, S2, x-1, y, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, firstID); - this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); - - var subProb2 = this.LCSMem(S1, S2, x, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, secondID); - - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.currentY -= 2*DPMatrixMultiply.RECURSIVE_DELTA_Y; - var best = Math.max(subProb1, subProb2); - this.cmd("SetText", ID, best); - this.cmd("Delete", ID2); - - - - var movingLabel = this.nextIndex++; - this.cmd("CreateLabel", movingLabel, best, xPos, this.currentY); - this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); - this.cmd("Step"); - this.cmd("Delete", movingLabel); - - - - // TODO: Animate moving value into table here - this.tableVals[x+1][y+1] = best; - this.cmd("SetText", this.tableID[x+1][y+1], best); - - - - this.cmd("step"); - return best; - } -} - - -DPMatrixMultiply.prototype.memoizedLCS = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - var sequences=value.split(";"); - - this.buildTable(sequences[0], sequences[1]); - - - var functionCallID = this.nextIndex++; - this.currentY = DPMatrixMultiply.RECURSIVE_START_Y; - - this.oldIDs.push(functionCallID); - - - var final = this.LCSMem(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPMatrixMultiply.RECURSIVE_START_X, functionCallID); - - this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); - - return this.commands; -} - -DPMatrixMultiply.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -DPMatrixMultiply.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new DPMatrixMultiply(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function DPMatrixMultiply(am, w, h) +{ + this.init(am, w, h); + +} +DPMatrixMultiply.inheritFrom(Algorithm); + +DPMatrixMultiply.TABLE_ELEM_WIDTH = 40; +DPMatrixMultiply.TABLE_ELEM_HEIGHT = 30; + +DPMatrixMultiply.TABLE_START_X = 500; +DPMatrixMultiply.TABLE_START_Y = 80; + + +DPMatrixMultiply.TABLE_DIFF_X = 100; + +DPMatrixMultiply.CODE_START_X = 10; +DPMatrixMultiply.CODE_START_Y = 10; +DPMatrixMultiply.CODE_LINE_HEIGHT = 14; + +DPMatrixMultiply.RECURSIVE_START_X = 20; +DPMatrixMultiply.RECURSIVE_START_Y = 120; +DPMatrixMultiply.RECURSIVE_DELTA_Y = 14; +DPMatrixMultiply.RECURSIVE_DELTA_X = 15; +DPMatrixMultiply.CODE_HIGHLIGHT_COLOR = "#FF0000"; +DPMatrixMultiply.CODE_STANDARD_COLOR = "#000000"; +DPMatrixMultiply.MAX_SEQUENCE_LENGTH = 15; + +DPMatrixMultiply.TABLE_INDEX_COLOR = "#0000FF" +DPMatrixMultiply.CODE_RECURSIVE_1_COLOR = "#339933"; +DPMatrixMultiply.CODE_RECURSIVE_2_COLOR = "#0099FF"; + + + +DPMatrixMultiply.MAX_VALUE = 20; + +DPMatrixMultiply.MESSAGE_ID = 0; + +DPMatrixMultiply.prototype.init = function(am, w, h) +{ + DPMatrixMultiply.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = [["def ","MatrixMultiply(x, y, P)",":"], + [" if (","(x >= y)", ")" ], + [" return 0"], + [" best = -1"], + [" for i in range(x, y)"], + [" left = ", "MatrixMultiply(x, i, P)"], + [" right = ", "MatrixMultiply(i+1, y, P)"], + [" total = left + right + P[x] * P[i+1] * P[y]"], + [" if (", "best == -1", " or ", "best > total", ")"], + [" best = total"], + [" return best"]]; + + this.codeID = Array(this.code.length); + var i, j; + for (i = 0; i < this.code.length; i++) + { + this.codeID[i] = new Array(this.code[i].length); + for (j = 0; j < this.code[i].length; j++) + { + this.codeID[i][j] = this.nextIndex++; + this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPMatrixMultiply.CODE_START_X, DPMatrixMultiply.CODE_START_Y + i * DPMatrixMultiply.CODE_LINE_HEIGHT, 0); + this.cmd("SetForegroundColor", this.codeID[i][j], DPMatrixMultiply.CODE_STANDARD_COLOR); + if (j > 0) + { + this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); + } + } + + + } + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +DPMatrixMultiply.prototype.addControls = function() +{ + this.controls = []; + this.addLabelToAlgorithmBar("S1:"); + this.S1Field = this.addControlToAlgorithmBar("Text", ""); + this.S1Field.onkeydown = this.returnSubmit(this.S1Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); + this.controls.push(this.S1Field); + + this.addLabelToAlgorithmBar("S2:"); + this.S2Field = this.addControlToAlgorithmBar("Text", ""); + this.S2Field.onkeydown = this.returnSubmit(this.S2Field, this.emptyCallback.bind(this), DPMatrixMultiply.MAX_SEQUENCE_LENGTH, false); + this.controls.push(this.S2Field); + + this.recursiveButton = this.addControlToAlgorithmBar("Button", "LCS Recursive"); + this.recursiveButton.onclick = this.recursiveCallback.bind(this); + this.controls.push(this.recursiveButton); + + this.tableButton = this.addControlToAlgorithmBar("Button", "LCS Table"); + this.tableButton.onclick = this.tableCallback.bind(this); + this.controls.push(this.tableButton); + + this.memoizedButton = this.addControlToAlgorithmBar("Button", "LCS Memoized"); + this.memoizedButton.onclick = this.memoizedCallback.bind(this); + this.controls.push(this.memoizedButton); + +} + + + +DPMatrixMultiply.prototype.buildTable = function(S1, S2) +{ + var x = S1.length; + var y = S2.length; + this.tableID = new Array(x+1); + this.tableVals = new Array(x + 1); + this.tableXPos = new Array(x + 1); + this.tableYPos = new Array(x + 1); + + var i, j; + var sequence1ID = new Array(x); + var sequence2ID = new Array(y); + + this.S1TableID = new Array(x); + for (i = 0; i <=x; i++) + { + if (i > 0) + { + this.S1TableID[i-1] = this.nextIndex++; + this.cmd("CreateLabel", this.S1TableID[i-1], S1.charAt(i-1),DPMatrixMultiply.TABLE_START_X + i*DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y - 2 * DPMatrixMultiply.TABLE_ELEM_HEIGHT); + this.oldIDs.push(this.S1TableID[i-1]); + } + var index = this.nextIndex++; + this.oldIDs.push(index); + this.cmd("CreateLabel", index, i - 1,DPMatrixMultiply.TABLE_START_X + i*DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y - 1 * DPMatrixMultiply.TABLE_ELEM_HEIGHT); + this.cmd("SetForegroundColor", index, "#0000FF"); + + } + + + this.S2TableID = new Array(y); + for (i = 0; i <=y; i++) + { + if (i > 0) + { + this.S2TableID[i-1] = this.nextIndex++; + this.cmd("CreateLabel", this.S2TableID[i-1], S2.charAt(i-1),DPMatrixMultiply.TABLE_START_X - 2 * DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y + i * DPMatrixMultiply.TABLE_ELEM_HEIGHT); + this.oldIDs.push(this.S2TableID[i-1]); + } + var index = this.nextIndex++; + this.oldIDs.push(index); + this.cmd("CreateLabel", index, i - 1, DPMatrixMultiply.TABLE_START_X - 1 * DPMatrixMultiply.TABLE_ELEM_WIDTH, DPMatrixMultiply.TABLE_START_Y + i * DPMatrixMultiply.TABLE_ELEM_HEIGHT); + this.cmd("SetForegroundColor", index, "#0000FF"); + } + + + for (i = 0; i <= x; i++) + { + this.tableID[i] = new Array(y+1); + this.tableVals[i] =new Array(y+1); + this.tableXPos[i] = new Array(y+1); + this.tableYPos[i] = new Array(y+1); + + for (j = 0; j <= y; j++) + { + this.tableID[i][j] = this.nextIndex++; + this.tableVals[i][j] = -1; + this.oldIDs.push(this.tableID[i][j]); + + this.tableXPos[i][j] =DPMatrixMultiply.TABLE_START_X + i * DPMatrixMultiply.TABLE_ELEM_WIDTH; + this.tableYPos[i][j] = DPMatrixMultiply.TABLE_START_Y + j * DPMatrixMultiply.TABLE_ELEM_HEIGHT; + + this.cmd("CreateRectangle", this.tableID[i][j], + "", + DPMatrixMultiply.TABLE_ELEM_WIDTH, + DPMatrixMultiply.TABLE_ELEM_HEIGHT, + this.tableXPos[i][j], + this.tableYPos[i][j]); + + } + + } +} + +DPMatrixMultiply.prototype.clearOldIDs = function() +{ + for (var i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs =[]; + this.nextIndex = this.initialIndex; + +} + + +DPMatrixMultiply.prototype.reset = function() +{ + this.oldIDs =[]; + this.nextIndex = this.initialIndex; +} + + + +DPMatrixMultiply.prototype.emptyCallback = function(event) +{ + this.implementAction(this.helpMessage.bind(this), ""); + // TODO: Put up a message to push the appropriate button? + +} + +DPMatrixMultiply.prototype.recursiveCallback = function(event) +{ + var fibValue; + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.recursiveLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + + +DPMatrixMultiply.prototype.tableCallback = function(event) +{ + var fibValue; + + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.tableLCS.bind(this),this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + + +DPMatrixMultiply.prototype.memoizedCallback = function(event) +{ + var fibValue; + + + if (this.S1Field.value != "" && this.S2Field.value != "" ) + { + this.implementAction(this.memoizedLCS.bind(this), this.S1Field.value + ";" + this.S2Field.value); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + +DPMatrixMultiply.prototype.helpMessage = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + var messageID = this.nextIndex++; + this.oldIDs.push(messageID); + this.cmd("CreateLabel", messageID, + "Enter two sequences in the text fields.\n" + + "Then press the LCS Recursive, LCS Table, or LCS Memoized button", + DPMatrixMultiply.RECURSIVE_START_X, DPMatrixMultiply.RECURSIVE_START_Y, 0); + return this.commands; + + +} + + +DPMatrixMultiply.prototype.recursiveLCS = function(value) +{ + this.commands = []; + + var sequences=value.split(";"); + + + + this.clearOldIDs(); + + this.currentY = DPMatrixMultiply.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.LCS(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPMatrixMultiply.RECURSIVE_START_X, functionCallID); + this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); + return this.commands; +} + + +DPMatrixMultiply.prototype.LCS = function(S1, S2, x, y, xPos, ID) +{ + var ID2 = this.nextIndex++; + this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); + this.cmd("SetForegroundColor", ID2, "#3333FF"); + this.cmd("AlignRight", ID2, ID); + this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + if (x == -1 || y == -1) + { + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + + } + this.cmd("Step"); + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + } + this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", ID, 0); + this.cmd("Delete", ID2); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + return 0; + } + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + if (S1.charAt(x) == S2.charAt(y)) + { + + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var nextID = this.nextIndex++; + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + var subProb = this.LCS(S1, S2, x-1, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, nextID); + + + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + + + this.cmd("Delete", nextID); + this.cmd("SetText", ID, subProb + 1); + this.cmd("Delete", ID2); + this.cmd("step"); + this.currentY -= DPMatrixMultiply.RECURSIVE_DELTA_Y; + return subProb + 1 + } + else + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var subProb1 = this.LCS(S1, S2, x-1, y, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, firstID); + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var subProb2 = this.LCS(S1, S2, x, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, secondID); + + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.currentY -= 2*DPMatrixMultiply.RECURSIVE_DELTA_Y; + var best = Math.max(subProb1, subProb2); + this.cmd("SetText", ID, best); + this.cmd("Delete", ID2); + this.cmd("step"); + return best; + } +} + + + + +DPMatrixMultiply.prototype.tableLCS = function(value) +{ + this.commands = []; + this.clearOldIDs(); + + var sequences=value.split(";"); + + this.buildTable(sequences[0], sequences[1]); + + var moveID = this.nextIndex++; + var x = sequences[0].length; + var y = sequences[1].length; + var i, j; + + for (i = 0; i <= x; i++) + { + this.cmd("SetText", this.tableID[i][0], "0"); + this.tableVals[i][0] = 0; + } + for (i = 0; i <= y; i++) + { + this.cmd("SetText", this.tableID[0][i], "0"); + this.tableVals[0][i] = 0; + } + this.cmd("Step"); + for (j = 0; j < y; j++) + { + for (i = 0; i < x; i++) + { + this.cmd("SetHighlight", this.tableID[i+1][j+1], 1); + this.cmd("SetHighlight", this.S1TableID[i], 1); + this.cmd("SetHighlight", this.S2TableID[j], 1); + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetHighlight", this.S1TableID[i], 0); + this.cmd("SetHighlight", this.S2TableID[j], 0); + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + if (sequences[0].charAt(i) == sequences[1].charAt(j)) + { + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 1); + this.cmd("Step"); + this.cmd("CreateLabel", moveID, this.tableVals[i][j] + 1, this.tableXPos[i][j], this.tableYPos[i][j]); + this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); + this.cmd("Step"); + this.cmd("Delete", moveID); + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i+1-1][j+1-1], 0); + this.tableVals[i+1][j+1] = this.tableVals[i][j] + 1; + this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + + this.cmd("SetHighlight", this.tableID[i][j+1], 1); + this.cmd("SetHighlight", this.tableID[i+1][j], 1); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); + + if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) + { + this.cmd("SetHighlight", this.tableID[i+1][j], 0); + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + + this.tableVals[i+1][j+1] = this.tableVals[i][j+1]; + this.cmd("CreateLabel", moveID, this.tableVals[i][j+1], this.tableXPos[i][j+1], this.tableYPos[i][j+1]); + + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i][j+1], 0); + this.tableVals[i+1][j+1] = this.tableVals[i+1][j]; + this.cmd("CreateLabel", moveID, this.tableVals[i+1][j], this.tableXPos[i+1][j], this.tableYPos[i+1][j]); + } + this.cmd("Move", moveID, this.tableXPos[i+1][j+1], this.tableYPos[i+1][j+1]); + this.cmd("Step"); + this.cmd("SetText", this.tableID[i+1][j+1], this.tableVals[i+1][j+1]); + this.cmd("Delete", moveID); + if (this.tableVals[i][j+1] > this.tableVals[i+1][j]) + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i][j+1], 0); + } + else + { + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i+1][j], 0); + } + + } + this.cmd("SetHighlight", this.tableID[i+1][j+1], 0); + //this.cmd("Step"); + + } + } + return this.commands; +} + + + +DPMatrixMultiply.prototype.LCSMem = function(S1, S2, x, y, xPos, ID) +{ + var ID2 = this.nextIndex++; + this.cmd("CreateLabel", ID, "LCS(" + S1 + ", " + S2 + ", " + String(x) + ", "+ String(y) + ")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID2, " [LCS(" + S1.substring(0,x + 1)+ "," + S2.substring(0,y + 1) + ")]"); + this.cmd("SetForegroundColor", ID2, "#3333FF"); + this.cmd("AlignRight", ID2, ID); + this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + if (this.tableVals[x+1][y+1] != -1) + { + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, this.tableVals[x+1][y+1], this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Move", movingLabel, xPos, this.currentY); + this.cmd("SetText", ID, ""); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + this.cmd("SetText", ID, this.tableVals[x+1][y+1]); + this.cmd("Delete", ID2); + this.cmd("Step"); + return this.tableVals[x+1][y+1]; + } + + + if (x == -1 || y == -1) + { + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + + } + this.cmd("Step"); + if (x == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + } + if (y == -1) + { + this.cmd("SetForegroundColor", this.codeID[1][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + } + this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", ID, 0); + this.cmd("Delete", ID2); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel,0, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + this.tableVals[x+1][y+1] = 0; + this.cmd("SetText", this.tableID[x+1][y+1], 0); + + + return 0; + } + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + if (S1.charAt(x) == S2.charAt(y)) + { + + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var nextID = this.nextIndex++; + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + var subProb = this.LCSMem(S1, S2, x-1, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, nextID); + + + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + + + this.cmd("Delete", nextID); + this.cmd("SetText", ID, subProb + 1); + this.cmd("Delete", ID2); + this.cmd("step"); + this.currentY -= DPMatrixMultiply.RECURSIVE_DELTA_Y; + + // TODO: Animate moving value into table here + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, subProb + 1, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + + this.tableVals[x+1][y+1] = subProb + 1; + this.cmd("SetText", this.tableID[x+1][y+1], subProb + 1); + + return subProb + 1 + } + else + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var subProb1 = this.LCSMem(S1, S2, x-1, y, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, firstID); + this.currentY += DPMatrixMultiply.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][3], DPMatrixMultiply.CODE_STANDARD_COLOR); + + var subProb2 = this.LCSMem(S1, S2, x, y-1, xPos + DPMatrixMultiply.RECURSIVE_DELTA_X, secondID); + + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][2], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][4], DPMatrixMultiply.CODE_STANDARD_COLOR); + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.currentY -= 2*DPMatrixMultiply.RECURSIVE_DELTA_Y; + var best = Math.max(subProb1, subProb2); + this.cmd("SetText", ID, best); + this.cmd("Delete", ID2); + + + + var movingLabel = this.nextIndex++; + this.cmd("CreateLabel", movingLabel, best, xPos, this.currentY); + this.cmd("Move", movingLabel, this.tableXPos[x+1][y+1], this.tableYPos[x+1][y+1]); + this.cmd("Step"); + this.cmd("Delete", movingLabel); + + + + // TODO: Animate moving value into table here + this.tableVals[x+1][y+1] = best; + this.cmd("SetText", this.tableID[x+1][y+1], best); + + + + this.cmd("step"); + return best; + } +} + + +DPMatrixMultiply.prototype.memoizedLCS = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + var sequences=value.split(";"); + + this.buildTable(sequences[0], sequences[1]); + + + var functionCallID = this.nextIndex++; + this.currentY = DPMatrixMultiply.RECURSIVE_START_Y; + + this.oldIDs.push(functionCallID); + + + var final = this.LCSMem(sequences[0], sequences[1], sequences[0].length - 1, sequences[1].length - 1, DPMatrixMultiply.RECURSIVE_START_X, functionCallID); + + this.cmd("SetText", functionCallID, "LCS(" + sequences[0] + ", " + sequences[1] + ", " + String(sequences[0].length - 1) + ", " + String(sequences[1].length - 1) + ") = " + String(final)); + + return this.commands; +} + +DPMatrixMultiply.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +DPMatrixMultiply.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new DPMatrixMultiply(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/DijkstraPrim.js b/AlgorithmLibrary/DijkstraPrim.js index d98bb14..417bf0d 100644 --- a/AlgorithmLibrary/DijkstraPrim.js +++ b/AlgorithmLibrary/DijkstraPrim.js @@ -41,17 +41,17 @@ var HIGHLIGHT_CIRCLE_COLOR = "#000000"; function DijkstraPrim(am, runningDijkstra, w, h) { - this.init(am, runningDijkstra, w, h); - + this.runningDijkstra = runningDijkstra; + + // call superclass' constructor, which calls init + DijkstraPrim.superclass.constructor.call(this, am, w, h); } -DijkstraPrim.prototype = new Graph(); -DijkstraPrim.prototype.constructor = DijkstraPrim; -DijkstraPrim.superclass = Graph.prototype; +DijkstraPrim.inheritFrom(Graph); DijkstraPrim.prototype.addControls = function() { - addLabelToAlgorithmBar("Start Vertex: "); + this.addLabelToAlgorithmBar("Start Vertex: "); this.startField = this.addControlToAlgorithmBar("Text", ""); this.startField.onkeydown = this.returnSubmit(this.startField, this.startCallback.bind(this), 2, true); this.startField.size = 2 @@ -72,7 +72,6 @@ DijkstraPrim.prototype.addControls = function() DijkstraPrim.prototype.init = function(am, runningDijkstra, w, h) { - this.runningDijkstra = runningDijkstra; this.showEdgeCosts = true; DijkstraPrim.superclass.init.call(this, am, w, h, false, false); // TODO: add no edge label flag to this? // Setup called in base class init function diff --git a/AlgorithmLibrary/DisjointSet.js b/AlgorithmLibrary/DisjointSet.js index 6988495..0dabfd3 100644 --- a/AlgorithmLibrary/DisjointSet.js +++ b/AlgorithmLibrary/DisjointSet.js @@ -49,9 +49,7 @@ function DisjointSet(am, w, h) } -DisjointSet.prototype = new Algorithm(); -DisjointSet.prototype.constructor = DisjointSet; -DisjointSet.superclass = Algorithm.prototype; +DisjointSet.inheritFrom(Algorithm); DisjointSet.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/EventTest.js b/AlgorithmLibrary/EventTest.js index 81c3250..d00fa7a 100644 --- a/AlgorithmLibrary/EventTest.js +++ b/AlgorithmLibrary/EventTest.js @@ -125,11 +125,11 @@ EventListener.prototype.fireEvent = function(kind, event) function Source() { - + // call superclass' constructor + Source.superclass.constructor.call(this); } +Source.inheritFrom(EventListener); -Source.prototype = new EventListener(); -Source.prototype.constructor = Source; Source.prototype.testFire = function() { this.fireEvent("test","testcontents"); diff --git a/AlgorithmLibrary/FibonacciHeap.js b/AlgorithmLibrary/FibonacciHeap.js index a053b25..3c55952 100644 --- a/AlgorithmLibrary/FibonacciHeap.js +++ b/AlgorithmLibrary/FibonacciHeap.js @@ -59,9 +59,7 @@ function FibonacciHeap(am, w, h) } -FibonacciHeap.prototype = new Algorithm(); -FibonacciHeap.prototype.constructor = FibonacciHeap; -FibonacciHeap.superclass = Algorithm.prototype; +FibonacciHeap.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/Floyd.js b/AlgorithmLibrary/Floyd.js index 522fd18..d1d4d19 100644 --- a/AlgorithmLibrary/Floyd.js +++ b/AlgorithmLibrary/Floyd.js @@ -28,9 +28,12 @@ function Floyd(am, w, h) { - this.init(am, w, h); + // call superclass' constructor, which calls init + Floyd.superclass.constructor.call(this, am, w, h); } +Floyd.inheritFrom(Graph); + Floyd.SMALL_COST_TABLE_WIDTH = 30; Floyd.SMALL_COST_TABLE_HEIGHT = 30; @@ -73,10 +76,6 @@ Floyd.LARGE_NODE_3_Y_POS = 500; Floyd.LARGE_MESSAGE_X = 300; Floyd.LARGE_MESSAGE_Y = 450; -Floyd.prototype = new Graph(); -Floyd.prototype.constructor = Floyd; -Floyd.superclass = Graph.prototype; - Floyd.prototype.addControls = function() { diff --git a/AlgorithmLibrary/Graph.js b/AlgorithmLibrary/Graph.js index 71f57b0..8e68118 100644 --- a/AlgorithmLibrary/Graph.js +++ b/AlgorithmLibrary/Graph.js @@ -29,16 +29,14 @@ function Graph(am, w, h, dir, dag) { - if (am == undefined) - { - return; - } + // this shouldn't happen if subclassing is done properly + if (!am) + throw "this shouldn't happen"; + this.init(am, w, h, dir,dag); } -Graph.prototype = new Algorithm(); -Graph.prototype.constructor = Graph; -Graph.superclass = Algorithm.prototype; +Graph.inheritFrom(Algorithm); var LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, false, false, false, false, false, true, false, false, false], [true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false], diff --git a/AlgorithmLibrary/Hash.js b/AlgorithmLibrary/Hash.js index 807b09b..bdda260 100644 --- a/AlgorithmLibrary/Hash.js +++ b/AlgorithmLibrary/Hash.js @@ -27,16 +27,13 @@ function Hash(am, w, h) { - if (am == undefined) - { - return; - } + // this shouldn't happen if subclassing is done properly + if (!am) + throw "this shouldn't happen"; + this.init(am, w, h); } - -Hash.prototype = new Algorithm(); -Hash.prototype.constructor = Hash; -Hash.superclass = Algorithm.prototype; +Hash.inheritFrom(Algorithm); var MAX_HASH_LENGTH = 10; diff --git a/AlgorithmLibrary/Heap.js b/AlgorithmLibrary/Heap.js index 3f5e5a4..531bf90 100644 --- a/AlgorithmLibrary/Heap.js +++ b/AlgorithmLibrary/Heap.js @@ -30,10 +30,7 @@ function Heap(am) this.init(am); } - -Heap.prototype = new Algorithm(); -Heap.prototype.constructor = Heap; -Heap.superclass = Algorithm.prototype; +Heap.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/HeapSort.js b/AlgorithmLibrary/HeapSort.js index a799d7a..c4dbe59 100644 --- a/AlgorithmLibrary/HeapSort.js +++ b/AlgorithmLibrary/HeapSort.js @@ -30,10 +30,7 @@ function HeapSort(am) this.init(am); } - -HeapSort.prototype = new Algorithm(); -HeapSort.prototype.constructor = HeapSort; -HeapSort.superclass = Algorithm.prototype; +HeapSort.inheritFrom(Algorithm); diff --git a/AlgorithmLibrary/Huffman.js b/AlgorithmLibrary/Huffman.js index deecd78..b629f2d 100644 --- a/AlgorithmLibrary/Huffman.js +++ b/AlgorithmLibrary/Huffman.js @@ -49,10 +49,7 @@ function Huffman(am, w, h) { this.init(am, w, h); } - -Huffman.prototype = new Algorithm(); -Huffman.prototype.constructor = Huffman; -Huffman.superclass = Algorithm.prototype; +Huffman.inheritFrom(Algorithm); Huffman.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/Kruskal.js b/AlgorithmLibrary/Kruskal.js index 491c797..a84b288 100644 --- a/AlgorithmLibrary/Kruskal.js +++ b/AlgorithmLibrary/Kruskal.js @@ -28,9 +28,13 @@ function Kruskal(am, w, h) { - this.init(am, w, h); + // call superclass' constructor, which calls init + Kruskal.superclass.constructor.call(this, am, w, h); } +Kruskal.inheritFrom(Graph); + + Kruskal.HIGHLIGHT_CIRCLE_COLOR = "#000000"; @@ -60,10 +64,6 @@ Kruskal.HIGHLIGHT_CIRCLE_COLOR = "#000000"; Kruskal.HIGHLIGHT_CIRCLE_COLOR_2 = "#FF0000"; -Kruskal.prototype = new Graph(); -Kruskal.prototype.constructor = Kruskal; -Kruskal.superclass = Graph.prototype; - Kruskal.prototype.addControls = function() { diff --git a/AlgorithmLibrary/LeftistHeap.js b/AlgorithmLibrary/LeftistHeap.js index a9298df..80e1dab 100644 --- a/AlgorithmLibrary/LeftistHeap.js +++ b/AlgorithmLibrary/LeftistHeap.js @@ -32,9 +32,7 @@ function LeftistHeap(am, w, h) } -LeftistHeap.prototype = new Algorithm(); -LeftistHeap.prototype.constructor = LeftistHeap; -LeftistHeap.superclass = Algorithm.prototype; +LeftistHeap.inheritFrom(Algorithm); LeftistHeap.LINK_COLOR = "#007700"; LeftistHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; diff --git a/AlgorithmLibrary/MyAlgorithm.js b/AlgorithmLibrary/MyAlgorithm.js index f363c4b..1da5453 100644 --- a/AlgorithmLibrary/MyAlgorithm.js +++ b/AlgorithmLibrary/MyAlgorithm.js @@ -30,10 +30,7 @@ function MyAlgorithm(am, w, h) { this.init(am, w, h); } - -MyAlgorithm.prototype = new Algorithm(); -MyAlgorithm.prototype.constructor = MyAlgorithm; -MyAlgorithm.superclass = Algorithm.prototype; +MyAlgorithm.inheritFrom(Algorithm); MyAlgorithm.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/OpenHash.js b/AlgorithmLibrary/OpenHash.js index 881454e..ee4c883 100644 --- a/AlgorithmLibrary/OpenHash.js +++ b/AlgorithmLibrary/OpenHash.js @@ -28,9 +28,10 @@ function OpenHash(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + OpenHash.superclass.constructor.call(this, am, w, h); } +OpenHash.inheritFrom(Hash); var POINTER_ARRAY_ELEM_WIDTH = 70; @@ -54,9 +55,6 @@ var INDEX_COLOR = "#0000FF"; -OpenHash.prototype = new Hash(); -OpenHash.prototype.constructor = OpenHash; -OpenHash.superclass = Hash.prototype; OpenHash.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/QueueArray.js b/AlgorithmLibrary/QueueArray.js index 90748f0..84ba27b 100644 --- a/AlgorithmLibrary/QueueArray.js +++ b/AlgorithmLibrary/QueueArray.js @@ -58,9 +58,7 @@ function QueueArray(am, w, h) } -QueueArray.prototype = new Algorithm(); -QueueArray.prototype.constructor = QueueArray; -QueueArray.superclass = Algorithm.prototype; +QueueArray.inheritFrom(Algorithm); QueueArray.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/QueueLL.js b/AlgorithmLibrary/QueueLL.js index 54688a4..0e86b98 100644 --- a/AlgorithmLibrary/QueueLL.js +++ b/AlgorithmLibrary/QueueLL.js @@ -62,9 +62,7 @@ function QueueLL(am, w, h) } -QueueLL.prototype = new Algorithm(); -QueueLL.prototype.constructor = QueueLL; -QueueLL.superclass = Algorithm.prototype; +QueueLL.inheritFrom(Algorithm); QueueLL.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/RadixSort.js b/AlgorithmLibrary/RadixSort.js index 6096c4e..7b210fe 100644 --- a/AlgorithmLibrary/RadixSort.js +++ b/AlgorithmLibrary/RadixSort.js @@ -51,9 +51,7 @@ var MAX_DATA_VALUE = 999; -RadixSort.prototype = new Algorithm(); -RadixSort.prototype.constructor = RadixSort; -RadixSort.superclass = Algorithm.prototype; +RadixSort.inheritFrom(Algorithm); RadixSort.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/RadixTree.js b/AlgorithmLibrary/RadixTree.js index e39d1a4..21a61c6 100644 --- a/AlgorithmLibrary/RadixTree.js +++ b/AlgorithmLibrary/RadixTree.js @@ -52,10 +52,7 @@ function RadixTree(am, w, h) { this.init(am, w, h); } - -RadixTree.prototype = new Algorithm(); -RadixTree.prototype.constructor = RadixTree; -RadixTree.superclass = Algorithm.prototype; +RadixTree.inheritFrom(Algorithm); RadixTree.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/RecFact.js b/AlgorithmLibrary/RecFact.js index 207c0b0..fb44732 100644 --- a/AlgorithmLibrary/RecFact.js +++ b/AlgorithmLibrary/RecFact.js @@ -28,13 +28,10 @@ function RecFact(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + RecFact.superclass.constructor.call(this, am, w, h); } - -RecFact.prototype = new Recursive(); -RecFact.prototype.constructor = RecFact; -RecFact.superclass = Recursive.prototype; +RecFact.inheritFrom(Recursive); RecFact.MAX_VALUE = 20; diff --git a/AlgorithmLibrary/RecQueens.js b/AlgorithmLibrary/RecQueens.js index f1b858e..5733f59 100644 --- a/AlgorithmLibrary/RecQueens.js +++ b/AlgorithmLibrary/RecQueens.js @@ -1,453 +1,451 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function Queens(am, w, h) -{ - this.init(am, w, h); - -} - -Queens.prototype = new Recursive(); -Queens.prototype.constructor = Queens; -Queens.superclass = Recursive.prototype; - -Queens.CALC_QUEENS_ACTIVATION_FIELDS = [" size ", " board "]; -Queens.QUEENS_ACTIVATION_FIELDS = [" board ", " current ", " size ", " i ", " done "]; -Queens.CHECK_ACTIVATION_FIELDS = [" board ", " current ", " i "]; - -Queens.CODE = [["def ","calcQueens(size)",":"], - [" board = ", "[-1] * size"], - [ " return ","queens(board, 0, size)"], - [" "], - ["def ","queens(board, current, size)",":"], - [" if ", "(current == size):"], - [" return true"], - [" else:"], - [" for i in range(size):"], - [" board[current] = i"], - [" if (","noConflicts(board, current)",":"], - [" done"," = ", "queens(board, current + 1, size)"], - [" if (done):"], - [" return true"], - [" return false"], - [" "], - ["def ","noConflicts(board, current)",":"], - [" for i in range(current):"], - [" if ","(board[i] == board[current])",":"], - [" return false"], - [" if ","(current - i == abs(board[current] = board[i]))",":"], - [" return false"], - [" return true"]]; - - -Queens.RECURSIVE_DELTA_Y_CALC_QUEEN = Queens.CALC_QUEENS_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; -Queens.RECURSIVE_DELTA_Y_QUEEN = Queens.QUEENS_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; -Queens.RECURSIVE_DELTA_Y_CHECK = Queens.CHECK_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; - - -Queens.ACTIVATION_RECORT_START_X = 450; -Queens.ACTIVATION_RECORT_START_Y = 20; - -Queens.INTERNAL_BOARD_START_X = 600; -Queens.INTERNAL_BOARD_START_Y = 100; -Queens.INTERNAL_BOARD_WIDTH = 20; -Queens.INTERNAL_BOARD_HEIGHT = 20; - -Queens.LOGICAL_BOARD_START_X = Queens.INTERNAL_BOARD_START_X; -Queens.LOGICAL_BOARD_START_Y = Queens.INTERNAL_BOARD_START_Y + Queens.INTERNAL_BOARD_HEIGHT * 1.5; -Queens.LOGICAL_BOARD_WIDTH = Queens.INTERNAL_BOARD_WIDTH; -Queens.LOGICAL_BOARD_HEIGHT = Queens.INTERNAL_BOARD_HEIGHT; -Queens.ACTIVATION_RECORD_SPACING = 400; - - -Queens.INDEX_COLOR = "#0000FF"; - -Queens.prototype.init = function(am, w, h) -{ - Queens.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = Queens.CODE; - - - this.addCodeToCanvas(this.code); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -Queens.prototype.addControls = function() -{ - this.controls = []; - addLabelToAlgorithmBar("Board size: (1-8)"); - - this.sizeField = this.addControlToAlgorithmBar("Text", ""); - this.sizeField.onkeydown = this.returnSubmit(this.sizeField, this.queensCallback.bind(this), 2, true); - this.controls.push(this.sizeField); - - this.queensButton = this.addControlToAlgorithmBar("Button", "Queens"); - this.queensButton.onclick = this.queensCallback.bind(this); - this.controls.push(this.queensButton); - -} - - - - -Queens.prototype.queensCallback = function(event) -{ - var queensValue; - - if (this.sizeField.value != "") - { - var queenSize = parseInt(this.sizeField.value); - queenSize = Math.min(queenSize, 8); - this.sizeField.value = String(queenSize); - this.implementAction(this.doQueens.bind(this),queenSize); - } -} - - - - -Queens.prototype.doQueens = function(size) -{ - this.commands = []; - - this.clearOldIDs(); - - - this.boardData = new Array(size); - this.boardInternalID = new Array(size); - this.boardLogicalID = new Array(size); - this.boardInternalIndexID = new Array(size); - - - this.currentY = Queens.ACTIVATION_RECORT_START_Y; - this.currentX = Queens.ACTIVATION_RECORT_START_X; - this.activationLeft = true; - - - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); - var activationRec = this.createActivation("calcQueens", Queens.CALC_QUEENS_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); - this.currentY += Queens.RECURSIVE_DELTA_Y_CALC_QUEEN; - - this.cmd("SetText", activationRec.fieldIDs[0], size); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); - - - for (var i = 0; i < size; i++) - { - this.boardInternalID[i] = this.nextIndex++; - this.oldIDs.push(this.boardInternalID[i]) - this.cmd("CreateRectangle", this.boardInternalID[i], - "-1", - Queens.INTERNAL_BOARD_WIDTH, - Queens.INTERNAL_BOARD_HEIGHT, - Queens.INTERNAL_BOARD_START_X + i * Queens.INTERNAL_BOARD_WIDTH, - Queens.INTERNAL_BOARD_START_Y); - - this.boardInternalIndexID[i] = this.nextIndex++; - this.oldIDs.push(this.boardInternalIndexID[i]); - this.cmd("CreateLabel", this.boardInternalIndexID[i], i,Queens.INTERNAL_BOARD_START_X + i * Queens.INTERNAL_BOARD_WIDTH, - Queens.INTERNAL_BOARD_START_Y - Queens.INTERNAL_BOARD_HEIGHT); - this.cmd("SetForegroundColor", this.boardInternalIndexID[i], Queens.INDEX_COLOR); - - this.boardLogicalID[i] = new Array(size); - for (var j = 0; j < size; j++) - { - this.boardLogicalID[i][j] = this.nextIndex++; - this.oldIDs.push(this.boardLogicalID[i][j]); - - this.cmd("CreateRectangle", this.boardLogicalID[i][j], - "", - Queens.LOGICAL_BOARD_WIDTH, - Queens.LOGICAL_BOARD_HEIGHT, - Queens.LOGICAL_BOARD_START_X + j * Queens.LOGICAL_BOARD_WIDTH, - Queens.LOGICAL_BOARD_START_Y + i * Queens.LOGICAL_BOARD_HEIGHT); - - - } - } - this.cmd("Connect", activationRec.fieldIDs[1], this.boardInternalID[0]); - this.cmd("Step"); - - this.cmd("SetForegroundColor", this.codeID[1][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[2][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][1], Recursive.CODE_STANDARD_COLOR); - - - - - board = new Array(size); - this.queens(board, 0, size); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.deleteActivation(activationRec); - - - return this.commands; -} - - -Queens.prototype.queens = function(board, current, size) -{ - var oldX = this.currentX; - var oldY = this.currentY; - var oldLeft = this.activationLeft; - var activationRec = this.createActivation("queens", Queens.QUEENS_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); - - this.cmd("SetText", activationRec.fieldIDs[1], current); - this.cmd("SetText", activationRec.fieldIDs[2], size); - if (this.activationLeft) - { - this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[0]); - } - else - { - this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[size-1]); - } - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); - - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); - - - this.currentY += Queens.RECURSIVE_DELTA_Y_QUEEN; - if (this.currentY + Queens.RECURSIVE_DELTA_Y_QUEEN > this.canvasHeight) - { - this.currentY = Queens.ACTIVATION_RECORT_START_Y; - this.currentX += Queens.ACTIVATION_RECORD_SPACING; - this.activationLeft = false; - } - - if (current == size) - { - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); - - this.deleteActivation(activationRec); - this.currentX = oldX; - this.currentY = oldY; - this.activationLeft = oldLeft; - this.cmd("CreateLabel", this.nextIndex, "Return Value = true", this.currentX, this.currentY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - - return true; - } - - var i; - for (i = 0; i < size; i++) - { - this.cmd("SetTextColor", this.codeID[8][0], Recursive.CODE_HIGHLIGHT_COLOR); - board[current] = i; - this.cmd("SetText", activationRec.fieldIDs[3], i); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[8][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[9][0], Recursive.CODE_HIGHLIGHT_COLOR); - - - this.cmd("SetText", this.boardLogicalID[i][current], "Q"); - this.cmd("SetText", this.boardInternalID[current], i); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[9][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_STANDARD_COLOR); - - var moveLegal = this.legal(board,current); - this.cmd("SetTextColor", this.codeID[10][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("Delete",this.nextIndex); - this.cmd("SetTextColor", this.codeID[10][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_STANDARD_COLOR); - - - - - if (moveLegal) - { - this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_STANDARD_COLOR); - var done = this.queens(board, current+1, size); - this.cmd("SetTextColor", this.codeID[11][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.codeID[11][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", activationRec.fieldIDs[4], done); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.cmd("SetTextColor", this.codeID[11][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[11][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.codeID[12][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[12][0], Recursive.CODE_STANDARD_COLOR); - - if (done) - { - this.cmd("SetTextColor", this.codeID[13][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[13][0], Recursive.CODE_STANDARD_COLOR); - - this.deleteActivation(activationRec); - this.currentX = oldX; - this.currentY = oldY; - this.activationLeft = oldLeft; - this.cmd("CreateLabel", this.nextIndex, "Return Value = true", this.currentX, this.currentY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - - return true; - } - } - this.cmd("SetText", this.boardLogicalID[i][current], ""); - - - } - this.cmd("SetTextColor", this.codeID[14][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.codeID[14][0], Recursive.CODE_STANDARD_COLOR); - this.deleteActivation(activationRec); - this.currentX = oldX; - this.currentY = oldY; - this.activationLeft = oldLeft; - this.cmd("CreateLabel", this.nextIndex, "Return Value = false", this.currentX, this.currentY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - - return false; -} - - -Queens.prototype.legal = function(board, current) -{ - var activationRec = this.createActivation("noConflicts", Queens.CHECK_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); - this.cmd("SetText", activationRec.fieldIDs[1], current); - if (this.activationLeft) - { - this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[0]); - } - else - { - this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[this.boardInternalID.length - 1]); - } - this.cmd("SetForegroundColor", this.codeID[16][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[16][1], Recursive.CODE_STANDARD_COLOR); - - - var i; - var OK = true; - if (current == 0) - { - this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_STANDARD_COLOR); - } - for (i = 0; i < current; i++) - { - this.cmd("SetText", activationRec.fieldIDs[2], i); - this.cmd("SetTextColor", activationRec.fieldIDs[2], Recursive.CODE_HIGHLIGHT_COLOR) - this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", activationRec.fieldIDs[2], Recursive.CODE_STANDARD_COLOR) - this.cmd("SetForegroundColor", this.codeID[18][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[18][1], Recursive.CODE_STANDARD_COLOR); - - if (board[i] == board[current]) - { - this.cmd("SetForegroundColor", this.codeID[19][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[19][0], Recursive.CODE_STANDARD_COLOR); - OK = false; - break; - } - this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_HIGHLIGHT_COLOR); - - this.cmd("SetForegroundColor", this.codeID[20][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[20][1], Recursive.CODE_STANDARD_COLOR); - - if (current - i == Math.abs(board[current] - board[i])) - { - this.cmd("SetForegroundColor", this.codeID[21][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[21][0], Recursive.CODE_STANDARD_COLOR); - - OK = false; - break; - } - - } - if (OK) - { - this.cmd("SetForegroundColor", this.codeID[22][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[22][0], Recursive.CODE_STANDARD_COLOR); - } - this.cmd("CreateLabel", this.nextIndex, "Return Value = " + String(OK), this.currentX, this.currentY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - this.deleteActivation(activationRec); - - return OK; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new Queens(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function Queens(am, w, h) +{ + // call superclass' constructor, which calls init + Queens.superclass.constructor.call(this, am, w, h); +} + +Queens.inheritFrom(Recursive); + +Queens.CALC_QUEENS_ACTIVATION_FIELDS = [" size ", " board "]; +Queens.QUEENS_ACTIVATION_FIELDS = [" board ", " current ", " size ", " i ", " done "]; +Queens.CHECK_ACTIVATION_FIELDS = [" board ", " current ", " i "]; + +Queens.CODE = [["def ","calcQueens(size)",":"], + [" board = ", "[-1] * size"], + [ " return ","queens(board, 0, size)"], + [" "], + ["def ","queens(board, current, size)",":"], + [" if ", "(current == size):"], + [" return true"], + [" else:"], + [" for i in range(size):"], + [" board[current] = i"], + [" if (","noConflicts(board, current)",":"], + [" done"," = ", "queens(board, current + 1, size)"], + [" if (done):"], + [" return true"], + [" return false"], + [" "], + ["def ","noConflicts(board, current)",":"], + [" for i in range(current):"], + [" if ","(board[i] == board[current])",":"], + [" return false"], + [" if ","(current - i == abs(board[current] = board[i]))",":"], + [" return false"], + [" return true"]]; + + +Queens.RECURSIVE_DELTA_Y_CALC_QUEEN = Queens.CALC_QUEENS_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; +Queens.RECURSIVE_DELTA_Y_QUEEN = Queens.QUEENS_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; +Queens.RECURSIVE_DELTA_Y_CHECK = Queens.CHECK_ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; + + +Queens.ACTIVATION_RECORT_START_X = 450; +Queens.ACTIVATION_RECORT_START_Y = 20; + +Queens.INTERNAL_BOARD_START_X = 600; +Queens.INTERNAL_BOARD_START_Y = 100; +Queens.INTERNAL_BOARD_WIDTH = 20; +Queens.INTERNAL_BOARD_HEIGHT = 20; + +Queens.LOGICAL_BOARD_START_X = Queens.INTERNAL_BOARD_START_X; +Queens.LOGICAL_BOARD_START_Y = Queens.INTERNAL_BOARD_START_Y + Queens.INTERNAL_BOARD_HEIGHT * 1.5; +Queens.LOGICAL_BOARD_WIDTH = Queens.INTERNAL_BOARD_WIDTH; +Queens.LOGICAL_BOARD_HEIGHT = Queens.INTERNAL_BOARD_HEIGHT; +Queens.ACTIVATION_RECORD_SPACING = 400; + + +Queens.INDEX_COLOR = "#0000FF"; + +Queens.prototype.init = function(am, w, h) +{ + Queens.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = Queens.CODE; + + + this.addCodeToCanvas(this.code); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +Queens.prototype.addControls = function() +{ + this.controls = []; + this.addLabelToAlgorithmBar("Board size: (1-8)"); + + this.sizeField = this.addControlToAlgorithmBar("Text", ""); + this.sizeField.onkeydown = this.returnSubmit(this.sizeField, this.queensCallback.bind(this), 2, true); + this.controls.push(this.sizeField); + + this.queensButton = this.addControlToAlgorithmBar("Button", "Queens"); + this.queensButton.onclick = this.queensCallback.bind(this); + this.controls.push(this.queensButton); + +} + + + + +Queens.prototype.queensCallback = function(event) +{ + var queensValue; + + if (this.sizeField.value != "") + { + var queenSize = parseInt(this.sizeField.value); + queenSize = Math.min(queenSize, 8); + this.sizeField.value = String(queenSize); + this.implementAction(this.doQueens.bind(this),queenSize); + } +} + + + + +Queens.prototype.doQueens = function(size) +{ + this.commands = []; + + this.clearOldIDs(); + + + this.boardData = new Array(size); + this.boardInternalID = new Array(size); + this.boardLogicalID = new Array(size); + this.boardInternalIndexID = new Array(size); + + + this.currentY = Queens.ACTIVATION_RECORT_START_Y; + this.currentX = Queens.ACTIVATION_RECORT_START_X; + this.activationLeft = true; + + + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); + var activationRec = this.createActivation("calcQueens", Queens.CALC_QUEENS_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); + this.currentY += Queens.RECURSIVE_DELTA_Y_CALC_QUEEN; + + this.cmd("SetText", activationRec.fieldIDs[0], size); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); + + + for (var i = 0; i < size; i++) + { + this.boardInternalID[i] = this.nextIndex++; + this.oldIDs.push(this.boardInternalID[i]) + this.cmd("CreateRectangle", this.boardInternalID[i], + "-1", + Queens.INTERNAL_BOARD_WIDTH, + Queens.INTERNAL_BOARD_HEIGHT, + Queens.INTERNAL_BOARD_START_X + i * Queens.INTERNAL_BOARD_WIDTH, + Queens.INTERNAL_BOARD_START_Y); + + this.boardInternalIndexID[i] = this.nextIndex++; + this.oldIDs.push(this.boardInternalIndexID[i]); + this.cmd("CreateLabel", this.boardInternalIndexID[i], i,Queens.INTERNAL_BOARD_START_X + i * Queens.INTERNAL_BOARD_WIDTH, + Queens.INTERNAL_BOARD_START_Y - Queens.INTERNAL_BOARD_HEIGHT); + this.cmd("SetForegroundColor", this.boardInternalIndexID[i], Queens.INDEX_COLOR); + + this.boardLogicalID[i] = new Array(size); + for (var j = 0; j < size; j++) + { + this.boardLogicalID[i][j] = this.nextIndex++; + this.oldIDs.push(this.boardLogicalID[i][j]); + + this.cmd("CreateRectangle", this.boardLogicalID[i][j], + "", + Queens.LOGICAL_BOARD_WIDTH, + Queens.LOGICAL_BOARD_HEIGHT, + Queens.LOGICAL_BOARD_START_X + j * Queens.LOGICAL_BOARD_WIDTH, + Queens.LOGICAL_BOARD_START_Y + i * Queens.LOGICAL_BOARD_HEIGHT); + + + } + } + this.cmd("Connect", activationRec.fieldIDs[1], this.boardInternalID[0]); + this.cmd("Step"); + + this.cmd("SetForegroundColor", this.codeID[1][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[2][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][1], Recursive.CODE_STANDARD_COLOR); + + + + + board = new Array(size); + this.queens(board, 0, size); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.deleteActivation(activationRec); + + + return this.commands; +} + + +Queens.prototype.queens = function(board, current, size) +{ + var oldX = this.currentX; + var oldY = this.currentY; + var oldLeft = this.activationLeft; + var activationRec = this.createActivation("queens", Queens.QUEENS_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); + + this.cmd("SetText", activationRec.fieldIDs[1], current); + this.cmd("SetText", activationRec.fieldIDs[2], size); + if (this.activationLeft) + { + this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[0]); + } + else + { + this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[size-1]); + } + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); + + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); + + + this.currentY += Queens.RECURSIVE_DELTA_Y_QUEEN; + if (this.currentY + Queens.RECURSIVE_DELTA_Y_QUEEN > this.canvasHeight) + { + this.currentY = Queens.ACTIVATION_RECORT_START_Y; + this.currentX += Queens.ACTIVATION_RECORD_SPACING; + this.activationLeft = false; + } + + if (current == size) + { + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); + + this.deleteActivation(activationRec); + this.currentX = oldX; + this.currentY = oldY; + this.activationLeft = oldLeft; + this.cmd("CreateLabel", this.nextIndex, "Return Value = true", this.currentX, this.currentY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + + return true; + } + + var i; + for (i = 0; i < size; i++) + { + this.cmd("SetTextColor", this.codeID[8][0], Recursive.CODE_HIGHLIGHT_COLOR); + board[current] = i; + this.cmd("SetText", activationRec.fieldIDs[3], i); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[8][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[9][0], Recursive.CODE_HIGHLIGHT_COLOR); + + + this.cmd("SetText", this.boardLogicalID[i][current], "Q"); + this.cmd("SetText", this.boardInternalID[current], i); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[9][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_STANDARD_COLOR); + + var moveLegal = this.legal(board,current); + this.cmd("SetTextColor", this.codeID[10][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("Delete",this.nextIndex); + this.cmd("SetTextColor", this.codeID[10][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[10][1], Recursive.CODE_STANDARD_COLOR); + + + + + if (moveLegal) + { + this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_STANDARD_COLOR); + var done = this.queens(board, current+1, size); + this.cmd("SetTextColor", this.codeID[11][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.codeID[11][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", activationRec.fieldIDs[4], done); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.cmd("SetTextColor", this.codeID[11][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[11][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[11][2], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.codeID[12][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[12][0], Recursive.CODE_STANDARD_COLOR); + + if (done) + { + this.cmd("SetTextColor", this.codeID[13][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[13][0], Recursive.CODE_STANDARD_COLOR); + + this.deleteActivation(activationRec); + this.currentX = oldX; + this.currentY = oldY; + this.activationLeft = oldLeft; + this.cmd("CreateLabel", this.nextIndex, "Return Value = true", this.currentX, this.currentY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + + return true; + } + } + this.cmd("SetText", this.boardLogicalID[i][current], ""); + + + } + this.cmd("SetTextColor", this.codeID[14][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.codeID[14][0], Recursive.CODE_STANDARD_COLOR); + this.deleteActivation(activationRec); + this.currentX = oldX; + this.currentY = oldY; + this.activationLeft = oldLeft; + this.cmd("CreateLabel", this.nextIndex, "Return Value = false", this.currentX, this.currentY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + + return false; +} + + +Queens.prototype.legal = function(board, current) +{ + var activationRec = this.createActivation("noConflicts", Queens.CHECK_ACTIVATION_FIELDS, this.currentX, this.currentY, this.activationLeft); + this.cmd("SetText", activationRec.fieldIDs[1], current); + if (this.activationLeft) + { + this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[0]); + } + else + { + this.cmd("Connect", activationRec.fieldIDs[0], this.boardInternalID[this.boardInternalID.length - 1]); + } + this.cmd("SetForegroundColor", this.codeID[16][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[16][1], Recursive.CODE_STANDARD_COLOR); + + + var i; + var OK = true; + if (current == 0) + { + this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_STANDARD_COLOR); + } + for (i = 0; i < current; i++) + { + this.cmd("SetText", activationRec.fieldIDs[2], i); + this.cmd("SetTextColor", activationRec.fieldIDs[2], Recursive.CODE_HIGHLIGHT_COLOR) + this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetForegroundColor", this.codeID[17][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", activationRec.fieldIDs[2], Recursive.CODE_STANDARD_COLOR) + this.cmd("SetForegroundColor", this.codeID[18][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[18][1], Recursive.CODE_STANDARD_COLOR); + + if (board[i] == board[current]) + { + this.cmd("SetForegroundColor", this.codeID[19][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[19][0], Recursive.CODE_STANDARD_COLOR); + OK = false; + break; + } + this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_HIGHLIGHT_COLOR); + + this.cmd("SetForegroundColor", this.codeID[20][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetTextColor", this.boardLogicalID[board[current]][current], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.boardLogicalID[board[i]][i], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[20][1], Recursive.CODE_STANDARD_COLOR); + + if (current - i == Math.abs(board[current] - board[i])) + { + this.cmd("SetForegroundColor", this.codeID[21][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[21][0], Recursive.CODE_STANDARD_COLOR); + + OK = false; + break; + } + + } + if (OK) + { + this.cmd("SetForegroundColor", this.codeID[22][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[22][0], Recursive.CODE_STANDARD_COLOR); + } + this.cmd("CreateLabel", this.nextIndex, "Return Value = " + String(OK), this.currentX, this.currentY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + this.deleteActivation(activationRec); + + return OK; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new Queens(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/RecReverse.js b/AlgorithmLibrary/RecReverse.js index 89a9c6d..098452f 100644 --- a/AlgorithmLibrary/RecReverse.js +++ b/AlgorithmLibrary/RecReverse.js @@ -28,13 +28,10 @@ function Reverse(am, w, h) { - this.init(am, w, h); - + // call superclass' constructor, which calls init + Reverse.superclass.constructor.call(this, am, w, h); } - -Reverse.prototype = new Recursive(); -Reverse.prototype.constructor = Reverse; -Reverse.superclass = Recursive.prototype; +Reverse.inheritFrom(Recursive); Reverse.ACTIVATION_FIELDS = ["word ", "subProblem ", "subSolution ", "solution "]; diff --git a/AlgorithmLibrary/Recursive.js b/AlgorithmLibrary/Recursive.js index 906380e..f6d8627 100644 --- a/AlgorithmLibrary/Recursive.js +++ b/AlgorithmLibrary/Recursive.js @@ -28,14 +28,13 @@ function Recursive(am, w, h) { - if (am != undefined) - this.init(am, w, h); - -} + // this shouldn't happen if subclassing is done properly + if (!am) + throw "this shouldn't happen"; -Recursive.prototype = new Algorithm(); -Recursive.prototype.constructor = Recursive; -Recursive.superclass = Algorithm.prototype; + this.init(am, w, h); +} +Recursive.inheritFrom(Algorithm); Recursive.CODE_START_X = 10; diff --git a/AlgorithmLibrary/RedBlack.js b/AlgorithmLibrary/RedBlack.js index e38c488..044a558 100644 --- a/AlgorithmLibrary/RedBlack.js +++ b/AlgorithmLibrary/RedBlack.js @@ -29,10 +29,7 @@ function RedBlack(am, w, h) this.init(am, w, h); } - -RedBlack.prototype = new Algorithm(); -RedBlack.prototype.constructor = RedBlack; -RedBlack.superclass = Algorithm.prototype; +RedBlack.inheritFrom(Algorithm); RedBlack.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/RotateScale2D.js b/AlgorithmLibrary/RotateScale2D.js index f86be6f..0ed54b0 100644 --- a/AlgorithmLibrary/RotateScale2D.js +++ b/AlgorithmLibrary/RotateScale2D.js @@ -1,996 +1,994 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function RotateScale2D(am, w, h) -{ - this.init(am, w, h); -} - - -RotateScale2D.prototype = new Algorithm(); -RotateScale2D.prototype.constructor = RotateScale2D; -RotateScale2D.superclass = Algorithm.prototype; - -RotateScale2D.XAxisYPos = 300; -RotateScale2D.XAxisStart = 100; -RotateScale2D.XAxisEnd = 700; - - -RotateScale2D.MATRIX_START_X = 10; -RotateScale2D.MATRIX_START_Y = 10; -RotateScale2D.MATRIX_MULTIPLY_SPACING = 10; -RotateScale2D.EQUALS_SPACING = 30; - - - -RotateScale2D.YAxisXPos = 400; -RotateScale2D.YAxisStart = 100; -RotateScale2D.YAxisEnd = 500; - -RotateScale2D.MATRIX_ELEM_WIDTH = 50; -RotateScale2D.MATRIX_ELEM_HEIGHT = 20; - -RotateScale2D.OBJECTS = [ - [[100, 100], [-100, 100], [-100,-100], [100, -100]], // Square - [[10, 100], [-10, 100], [-10,-100], [100, -100], [100, -80], [10,-80]], // L - [[0, 141], [-134, 44], [-83, -114 ], [83, -114], [134,44]], // Pentagon - [[0, 141], [-35,48],[-134, 44], [-57, -19], [-83, -114 ], [0, -60],[83,-114], [57, -19], [134,44], [35, 48]], // Star - ] - - -RotateScale2D.AXIS_COLOR = "#0000FF" -RotateScale2D.VERTEX_FOREGORUND_COLOR = "#000000"; -RotateScale2D.VERTEX_BACKGROUND_COLOR = RotateScale2D.VERTEX_FOREGORUND_COLOR; -RotateScale2D.EDGE_COLOR = "#000000"; - - - -RotateScale2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; -RotateScale2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateScale2D.VERTEX_FOREGORUND_COLOR; -RotateScale2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; - - - - -RotateScale2D.VECTOR_COLOR = "#FF0000"; - -RotateScale2D.VERTEX_WIDTH = 3; -RotateScale2D.VERTEX_HEIGHT = RotateScale2D.VERTEX_WIDTH; - -RotateScale2D.prototype.init = function(am, w, h) -{ - var sc = RotateScale2D.superclass.init.call(this, am, w, h); - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.addControls(); - this.currentShape = 0; - - this.commands = []; - this.nextIndex = 0; - - this.setupAxis(); - - this.savedNextIndex = this.nextIndex; - this.setupObject(); - this.setupObjectGraphic(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); - - -} - -RotateScale2D.prototype.setupAxis = function() -{ - this.xAxisLeft = this.nextIndex++; - this.xAxisRight = this.nextIndex++; - this.yAxisTop = this.nextIndex++; - this.yAxisBottom = this.nextIndex++; - - this.xAxisLabel = this.nextIndex++; - this.yAxisLabel = this.nextIndex++; - - this.originID = this.nextIndex++; - - this.cmd("CreateRectangle", this.originID, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.XAxisYPos); - - - this.cmd("CreateRectangle", this.xAxisLeft, "", 0, 0, RotateScale2D.XAxisStart, RotateScale2D.XAxisYPos); - this.cmd("SetAlpha", this.xAxisLeft, 0); - this.cmd("CreateRectangle", this.xAxisRight, "", 0, 0, RotateScale2D.XAxisEnd, RotateScale2D.XAxisYPos); - this.cmd("SetAlpha", this.xAxisRight, 0); - this.cmd("Connect", this.xAxisLeft, this.xAxisRight, RotateScale2D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.xAxisRight, this.xAxisLeft, RotateScale2D.AXIS_COLOR, 0, 1, ""); - - - this.cmd("CreateRectangle", this.yAxisTop, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.YAxisStart); - this.cmd("SetAlpha", this.yAxisTop, 0); - this.cmd("CreateRectangle", this.yAxisBottom, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.YAxisEnd); - this.cmd("SetAlpha", this.yAxisBottom, 0); - this.cmd("Connect", this.yAxisTop, this.yAxisBottom, RotateScale2D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.yAxisBottom, this.yAxisTop, RotateScale2D.AXIS_COLOR, 0, 1, ""); - if (this.posYUp) - { - this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisStart + 10); - } - else - { - this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisEnd - 10); - } - this.cmd("CreateLabel", this.xAxisLabel, "+x", RotateScale2D.XAxisEnd - 10, RotateScale2D.XAxisYPos - 10); - this.cmd("SetForegroundColor", this.yAxisLabel, RotateScale2D.AXIS_COLOR); - this.cmd("SetForegroundColor", this.xAxisLabel, RotateScale2D.AXIS_COLOR); -} - - -RotateScale2D.prototype.setupObject = function() -{ - this.objectVertexPosition = RotateScale2D.OBJECTS[this.currentShape].slice(0); -} - - -RotateScale2D.prototype.worldToScreenSpace = function(point) -{ - var transformedPoint = new Array(2); - transformedPoint[0] = point[0] + RotateScale2D.YAxisXPos; - if (this.posYUp) - { - transformedPoint[1] = RotateScale2D.XAxisYPos - point[1]; - } - else - { - transformedPoint[1] = RotateScale2D.XAxisYPos + point[1]; - - } - return transformedPoint; -} - - - -RotateScale2D.prototype.moveObjectToNewPosition = function() -{ - var i; - for (i = 0; i < this.objectVertexID.length; i++) - { - var point = this.worldToScreenSpace(this.objectVertexPosition[i]); - this.cmd("Move", this.objectVertexID[i], point[0], point[1]); - } - -} - - -RotateScale2D.prototype.setupObjectGraphic = function() -{ - this.objectVertexID = new Array(this.objectVertexPosition.length); - var i; - for (i = 0; i < this.objectVertexPosition.length; i++) - { - this.objectVertexID[i] = this.nextIndex++; - var point = this.worldToScreenSpace(this.objectVertexPosition[i]); - - this.cmd("CreateRectangle", this.objectVertexID[i], "", RotateScale2D.VERTEX_WIDTH, RotateScale2D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", this.objectVertexID[i], RotateScale2D.VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", this.objectVertexID[i], RotateScale2D.VERTEX_BACKGROUND_COLOR); - } - for (i = 1; i < this.objectVertexID.length; i++) - { - this.cmd("Connect", this.objectVertexID[i-1], this.objectVertexID[i], RotateScale2D.EDGE_COLOR, 0, 0, ""); - } - this.cmd("Connect", this.objectVertexID[this.objectVertexID.length - 1], this.objectVertexID[0], RotateScale2D.EDGE_COLOR, 0, 0, ""); -} - -RotateScale2D.prototype.addControls = function() -{ - this.controls = []; - - addLabelToAlgorithmBar("Rotation Angle"); - - this.rotationField = this.addControlToAlgorithmBar("Text", ""); - this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.rotationField); - - addLabelToAlgorithmBar("Scale X"); - - this.scaleXField = this.addControlToAlgorithmBar("Text", ""); - this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.scaleXField); - - - addLabelToAlgorithmBar("Scale Y"); - - this.scaleYField = this.addControlToAlgorithmBar("Text", ""); - this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.scaleYField); - - - var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); - transformButton.onclick = this.transformCallback.bind(this); - - this.controls.push(transformButton); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", - "Column Major", - ], - "RankType"); - this.rowMajorButton = radioButtonList[0]; - this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); - this.controls.push(this.rowMajorButton); - - this.colMajorButton = radioButtonList[1]; - this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); - this.controls.push(this.colMajorButton); - - this.rowMajorButton.checked = this.rowMajor; - this.colMajorButton.checked = !this.rowMajor; - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", - "+y Down", - ], - "yAxisDirection"); - this.posYUpButton = radioButtonList[0]; - this.posYUpButton.onclick = this.changePosYCallback.bind(this, true); - this.controls.push(this.posYUpButton); - - this.posYDownButton = radioButtonList[1]; - this.posYDownButton.onclick = this.changePosYCallback.bind(this, false); - this.controls.push(this.posYDownButton); - - this.posYUpButton.checked = this.posYUp; - this.posYDownButton.checked = !this.posYUp; - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rotate, then scale", - "Scale, then rotate", - ], - "RotateFirst"); - this.rotateScaleButton = radioButtonList[0]; - this.rotateScaleButton.onclick = this.rotateScaleOrderCallback.bind(this, true); - this.controls.push(this.rotateScaleButton); - - this.scaleRotateButton = radioButtonList[1]; - this.scaleRotateButton.onclick = this.rotateScaleOrderCallback.bind(this, false); - this.controls.push(this.scaleRotateButton); - - this.rotateScaleButton.checked = this.rotateFirst; - this.scaleRotateButton.checked = !this.rotateFirst; - - var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); - changeShapeButton.onclick = this.changeShapeCallback.bind(this); - - this.controls.push(changeShapeButton); - -} - - - - - - -RotateScale2D.prototype.reset = function() -{ - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.currentShape = 0; - this.rowMajorButton.checked = this.rowMajor; - this.posYUpButton.checked = this.posYUp; - this.rotateScaleButton.checked = this.rotateFirst; - - this.nextIndex = this.savedNextIndex; - this.setupObject(); - this.setupObjectGraphic(); -} - - -RotateScale2D.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -RotateScale2D.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -RotateScale2D.prototype.changePosYCallback = function(posYUp) -{ - if (this.posYUp != posYUp) - { - this.implementAction(this.changePosY.bind(this), posYUp); - } -} - -RotateScale2D.prototype.changePosY = function(posYUp) -{ - this.commands = new Array(); - this.posYUp= posYUp; - if (this.posYUpButton.checked != this.posYUp) - { - this.posYUpButton.checked = this.posYUp; - } - if (this.posYDownButton.checked == this.posYUp) - { - this.posYDownButton.checked = !this.posYUp; - } - if (this.posYUp) - { - this.cmd("Move", this.yAxisLabel, RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisStart + 10); - } - else - { - this.cmd("Move", this.yAxisLabel, RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisEnd - 10); - - } - - this.moveObjectToNewPosition(); - - - - - // Move +y on axis up/down - return this.commands; -} - - - -RotateScale2D.prototype.changeRowColMajorCallback = function(rowMajor) -{ - if (this.rowMajor != rowMajor) - { - this.implementAction(this.changeRowCol.bind(this), rowMajor); - } -} - -RotateScale2D.prototype.changeRowCol = function(rowMajor) -{ - this.commands = new Array(); - this.rowMajor= rowMajor; - if (this.rowMajorButton.checked != this.rowMajor) - { - this.rowMajorButton.checked = this.rowMajor; - } - if (this.colMajorButton.checked == this.rowMajor) - { - this.colMajorButton.checked = !this.rowMajor; - } - return this.commands; -} - - -RotateScale2D.prototype.fixNumber = function(value, defaultVal) -{ - if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) - { - value = defaultVal; - } - else - { - value = String(parseFloat(value)); - } - return value -} - -RotateScale2D.prototype.transformCallback = function() -{ - - - this.rotationField.value = this.fixNumber(this.rotationField.value, "0"); - this.scaleXField.value = this.fixNumber(this.scaleXField.value, "1"); - this.scaleYField.value = this.fixNumber(this.scaleYField.value, "1"); - this.implementAction(this.transform.bind(this), this.rotationField.value + ";" + this.scaleXField.value + ";" + this.scaleYField.value); - -} - - -RotateScale2D.prototype.changeShapeCallback = function() -{ - this.implementAction(this.changeShape.bind(this), 0); -} - -RotateScale2D.prototype.changeShape = function() -{ - this.commands = []; - var i; - for (i = 0; i < this.objectVertexID.length; i++) - { - this.cmd("Delete", this.objectVertexID[i]); - } - this.currentShape++; - if (this.currentShape >= RotateScale2D.OBJECTS.length) - { - this.currentShape = 0; - } - this.setupObject(); - this.setupObjectGraphic(); - return this.commands; -} - -RotateScale2D.prototype.rotateScaleOrderCallback = function(rotateFirst) -{ - if (this.rotateFirst != rotateFirst) - { - this.implementAction(this.rotateScaleOrder.bind(this), rotateFirst); - } -} - - -RotateScale2D.prototype.rotateScaleOrder = function(rotateFirst) -{ - this.commands = new Array(); - this.rotateFirst= rotateFirst; - if (this.rotateScaleButton.checked != this.rotateFirst) - { - this.rotateScaleButton.checked = this.rotateFirst; - } - if (this.scaleRotateButton.checked == this.rotateFirst) - { - this.scaleRotateButton.checked = !this.rotateFirst; - } - return this.commands; -} - - -function toRadians(degrees) -{ - return (degrees * 2 * Math.PI) / 360.0; -} - -RotateScale2D.prototype.transform = function(input) -{ - var oldNextIndex = this.nextIndex; - this.commands = []; - var inputs = input.split(";"); - var rotateDegree = toRadians(parseFloat(inputs[0])); - var scaleX = parseFloat(inputs[1]); - var scaleY = parseFloat(inputs[2]); - - var xpos = RotateScale2D.MATRIX_START_X; - var ypos = RotateScale2D.MATRIX_START_Y; - if (!this.rowMajor) - { - xpos += 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING; - } - - var xy; - if (this.rowMajor) - { - xy = this.createMatrix([["x", "y"]], xpos, ypos); - xpos += xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING; - - } - - var matrixData; - if (this.rotateFirst) - { - if (this.rowMajor) - { - matrixData = [["cos \u0398", "sin \u0398"], ["-sin \u0398", "cos \u0398"]] - } - else - { - matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; - } - - } - else - { - if (this.rowMajor) - { - matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; - } - else - { - matrixData = [["cos \u0398", "-sin \u0398"], ["sin \u0398", "cos \u0398"]] - - } - } - - - var firstMat = this.createMatrix(matrixData, xpos, ypos); - - xpos += firstMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING; - - - if (this.rotateFirst) - { - if (this.rowMajor) - { - matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; - } - else - { - matrixData = [["cos \u0398", "-sin \u0398"], ["sin \u0398", "cos \u0398"]] - - } - } - else - { - if (this.rowMajor) - { - matrixData = [["cos \u0398", "sin \u0398"], ["-sin \u0398", "cos \u0398"]] - } - else - { - matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; - } - } - - var secondMat = this.createMatrix(matrixData,xpos, ypos); - xpos += secondMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH; - - if (!this.rowMajor) - { - xpos += RotateScale2D.MATRIX_MULTIPLY_SPACING; - xy = this.createMatrix([["x"], ["y"]], xpos, ypos); - xpos += xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH; - } - - this.cmd("Step"); - - var rotMat, scaleMat - if ((this.rotateFirst && this.rowMajor) || (!this.rotateFirst && !this.rowMajor)) - { - rotMat = firstMat; - scaleMat = secondMat; - } - else - { - rotMat = secondMat; - scaleMat = firstMat; - - } - - if (this.rowMajor) - { - rotMat.data = [["cos " + inputs[0], "sin " + inputs[0]],["-sin " +inputs[0], "cos " + inputs[0]]]; - } - else - { - rotMat.data = [["cos " + inputs[0], "-sin " + inputs[0]],["sin " +inputs[0], "cos " + inputs[0]]]; - } - this.resetMatrixLabels(rotMat); - - scaleMat.data = [[scaleX, 0],[0, scaleY]]; - this.resetMatrixLabels(scaleMat); - - this.cmd("Step"); - - if (this.rowMajor) - { - rotMat.data = [[Math.cos(rotateDegree), Math.sin(rotateDegree)],[-Math.sin(rotateDegree), Math.cos(rotateDegree)]]; - } - else - { - rotMat.data = [[Math.cos(rotateDegree), -Math.sin(rotateDegree)],[Math.sin(rotateDegree), Math.cos(rotateDegree)]]; - } - this.resetMatrixLabels(rotMat); - this.cmd("Step"); - this.setMatrixAlpha(xy, 0.3); - - - var equalID = this.nextIndex++; - var equaXlPos; - if (this.rowMajor) - { - equalXPos = xpos + RotateScale2D.EQUALS_SPACING / 2; - } - else - { - equalXPos = RotateScale2D.MATRIX_START_X + 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING / 2; - } - - this.cmd("CreateLabel", equalID, "=", equalXPos, ypos + rotMat.data.length / 2 * RotateScale2D.MATRIX_ELEM_HEIGHT); - - xpos += RotateScale2D.EQUALS_SPACING; - - - var paren1 = this.nextIndex++ - var paren2 = this.nextIndex++ - var paren3 = this.nextIndex++ - var paren4 = this.nextIndex++ - - var parenX; - parenX = 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_START_X + RotateScale2D.MATRIX_MULTIPLY_SPACING - 2; - if (!this.rowMajor) - { - parenX += RotateScale2D.EQUALS_SPACING - RotateScale2D.MATRIX_MULTIPLY_SPACING; - } - - this.cmd("CreateRectangle", paren1, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y, "center","center"); - this.cmd("CreateRectangle", paren2, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, "center","center"); - this.cmd("Connect", paren1, paren2, "#000000", 0.2, 0, ""); - - parenX = 6*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_START_X + 2*RotateScale2D.MATRIX_MULTIPLY_SPACING + 2; - if (!this.rowMajor) - { - parenX += RotateScale2D.EQUALS_SPACING - RotateScale2D.MATRIX_MULTIPLY_SPACING; - } - - this.cmd("CreateRectangle", paren3, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y, "center","center"); - this.cmd("CreateRectangle", paren4, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y+ 2*RotateScale2D.MATRIX_ELEM_HEIGHT, "center","center"); - - this.cmd("Connect", paren3, paren4, "#000000", -0.2, 0 ,""); - - this.cmd("Step"); - var tmpMat; - if (this.rowMajor) - { - tmpMat = this.createMatrix([["",""],["",""]],xpos, ypos); - } - else - { - tmpMat = this.createMatrix([["",""],["",""]],RotateScale2D.MATRIX_START_X, RotateScale2D.MATRIX_START_Y); - } - var explainID = this.nextIndex++; - if (this.rowMajor) - { - this.cmd("CreateLabel", explainID, "", 6*RotateScale2D.MATRIX_ELEM_WIDTH + 2*RotateScale2D.MATRIX_MULTIPLY_SPACING + - RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); - } - else - { - this.cmd("CreateLabel", explainID, "", RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); - } - this.cmd("Step"); - this.multiplyMatrix(firstMat, secondMat, tmpMat, explainID); - - - this.deleteMatrix(firstMat); - this.deleteMatrix(secondMat); - this.cmd("Delete", paren1); - this.cmd("Delete", paren2); - this.cmd("Delete", paren3); - this.cmd("Delete", paren4); - this.cmd("Delete", equalID); - - if (this.rowMajor) - { - this.moveMatrix(tmpMat, xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING + RotateScale2D.MATRIX_START_X, - RotateScale2D.MATRIX_START_Y); - xpos = (RotateScale2D.MATRIX_START_X + xy.data[0].length*RotateScale2D.MATRIX_ELEM_WIDTH + - RotateScale2D.MATRIX_MULTIPLY_SPACING + tmpMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH); - this.cmd("SetPosition", explainID, 4*RotateScale2D.MATRIX_ELEM_WIDTH + 1*RotateScale2D.MATRIX_MULTIPLY_SPACING + - RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); - - } - else - { - this.moveMatrix(tmpMat, RotateScale2D.MATRIX_START_X + 4*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_MULTIPLY_SPACING, - RotateScale2D.MATRIX_START_Y); - xpos = (RotateScale2D.MATRIX_START_X + 7*RotateScale2D.MATRIX_ELEM_WIDTH + - 2 * RotateScale2D.MATRIX_MULTIPLY_SPACING + RotateScale2D.EQUALS_SPACING); - - this.cmd("SetPosition", explainID, 7*RotateScale2D.MATRIX_ELEM_WIDTH + 2 * RotateScale2D.EQUALS_SPACING + 3*RotateScale2D.MATRIX_MULTIPLY_SPACING, RotateScale2D.MATRIX_START_Y + 10 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT); - - } - this.setMatrixAlpha(xy, 1); - this.cmd("Step"); - - - var i; - var output; - - - var transformedObjectID = new Array(this.objectVertexID.length); - - for (i = 0; i < this.objectVertexID.length; i++) - { - this.cmd("Connect", this.originID, this.objectVertexID[i], RotateScale2D.VECTOR_COLOR, 0, 1, ""); - if (this.rowMajor) - { - xy.data = [this.objectVertexPosition[i].slice(0)]; - } - else - { - xy.data[0][0] = this.objectVertexPosition[i][0]; - xy.data[1][0] = this.objectVertexPosition[i][1]; - } - this.resetMatrixLabels(xy); - this.cmd("Step"); - this.cmd("CreateLabel", equalID, "=", xpos + RotateScale2D.EQUALS_SPACING / 2, ypos + tmpMat.data.length / 2 * RotateScale2D.MATRIX_ELEM_HEIGHT); - if (this.rowMajor) - { - output = this.createMatrix([["",""]], xpos + RotateScale2D.EQUALS_SPACING, ypos) - this.multiplyMatrix(xy, tmpMat, output, explainID); - } - else - { - output = this.createMatrix([[""],[""]], xpos + RotateScale2D.EQUALS_SPACING, ypos) - this.multiplyMatrix(tmpMat, xy, output, explainID); - } - - - transformedObjectID[i] = this.nextIndex++; - var point; - if (this.rowMajor) - { - point = this.worldToScreenSpace(output.data[0]); - } - else - { - point = this.worldToScreenSpace([output.data[0][0], output.data[1][0]]); - } - - this.cmd("CreateRectangle", transformedObjectID[i], "", RotateScale2D.VERTEX_WIDTH, RotateScale2D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", transformedObjectID[i], RotateScale2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", transformedObjectID[i], RotateScale2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); - this.cmd("Connect", this.originID, transformedObjectID[i], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); - this.cmd("Step"); - this.cmd("Disconnect", this.originID, transformedObjectID[i]); - - if (i > 0) - { - this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - - } - - this.cmd("Disconnect", this.originID, this.objectVertexID[i]); - if (this.rowMajor) - { - this.objectVertexPosition[i] = output.data[0]; - } - else - { - this.objectVertexPosition[i][0] = output.data[0][0]; - this.objectVertexPosition[i][1] = output.data[1][0]; - } - this.cmd("Delete", equalID); - this.deleteMatrix(output); - - } - this.cmd("Step"); - - this.cmd("Connect", transformedObjectID[0], transformedObjectID[transformedObjectID.length-1], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - - this.cmd("Step","B"); - this.moveObjectToNewPosition(); - this.cmd("Step","C"); - - for (i = 0; i < transformedObjectID.length; i++) - { - this.cmd("Delete", transformedObjectID[i]); - } - - - this.deleteMatrix(xy); - this.deleteMatrix(tmpMat); - this.cmd("Delete", explainID); - - this.nextIndex = oldNextIndex - - return this.commands; -} - - -RotateScale2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) -{ - var i; - var j; - var explainText = ""; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat2.data[0].length; j++) - { - var explainText = ""; - var value = 0; - for (k = 0; k < mat2.data.length; k++) - { - this.cmd("SetHighlight", mat1.dataID[i][k], 1); - this.cmd("SetHighlight", mat2.dataID[k][j], 1); - if (explainText != "") - { - explainText = explainText + " + "; - } - value = value + mat1.data[i][k] * mat2.data[k][j]; - explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); - this.cmd("SetText", explainID, explainText); - this.cmd("Step"); - this.cmd("SetHighlight", mat1.dataID[i][k], 0); - this.cmd("SetHighlight", mat2.dataID[k][j], 0); - } - value = this.standardize(value); - explainText += " = " + String(value); - this.cmd("SetText", explainID, explainText); - mat3.data[i][j] = value; - this.cmd("SetText", mat3.dataID[i][j], value); - this.cmd("Step"); - } - } - this.cmd("SetText", explainID, ""); - - -} - -RotateScale2D.prototype.standardize = function(lab) -{ - var newLab = Math.round(lab * 1000) / 1000; - if (isNaN(newLab)) - { - return lab; - } - else - { - return newLab; - } -} - - -RotateScale2D.prototype.resetMatrixLabels = function(mat) -{ - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - mat.data[i][j] = this.standardize(mat.data[i][j]); - this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); - } - } -} - - - -RotateScale2D.prototype.moveMatrix = function(mat, x, y) -{ - var height = mat.data.length; - var width = 0; - - var i, j; - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - } - - - this.cmd("Move", mat.leftBrack1, x, y); - this.cmd("Move", mat.leftBrack2, x, y); - this.cmd("Move", mat.leftBrack3, x, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT); - - this.cmd("Move", mat.rightBrack1, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack2, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack3, x+ width * RotateScale2D.MATRIX_ELEM_WIDTH, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Move", mat.dataID[i][j], - x + j*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateScale2D.MATRIX_ELEM_HEIGHT + RotateScale2D.MATRIX_ELEM_HEIGHT / 2); - } - } -} - -RotateScale2D.prototype.deleteMatrix = function(mat) -{ - this.cmd("Delete",mat.leftBrack1); - this.cmd("Delete",mat.leftBrack2); - this.cmd("Delete",mat.leftBrack3); - this.cmd("Delete",mat.rightBrack1); - this.cmd("Delete",mat.rightBrack2); - this.cmd("Delete",mat.rightBrack3); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Delete", mat.dataID[i][j]); - } - } -} - -RotateScale2D.prototype.setMatrixAlpha = function(mat, alpha) -{ - this.cmd("SetAlpha",mat.leftBrack1, alpha); - this.cmd("SetAlpha",mat.leftBrack2, alpha); - this.cmd("SetAlpha",mat.leftBrack3, alpha); - this.cmd("SetAlpha",mat.rightBrack1, alpha); - this.cmd("SetAlpha",mat.rightBrack2, alpha); - this.cmd("SetAlpha",mat.rightBrack3, alpha); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("SetAlpha", mat.dataID[i][j], alpha); - } - } -} - - -RotateScale2D.prototype.createMatrix = function(contents, x, y) -{ - var mat = new Matrix(contents, x, y); - mat.leftBrack1 = this.nextIndex++; - mat.leftBrack2 = this.nextIndex++; - mat.leftBrack3 = this.nextIndex++; - mat.rightBrack1 = this.nextIndex++; - mat.rightBrack2 = this.nextIndex++; - mat.rightBrack3 = this.nextIndex++; - - var height = mat.data.length; - var width = 0; - - var i, j; - mat.dataID = new Array(mat.data.length); - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - mat.dataID[i] = new Array(mat.data[i].length); - for (j = 0; j < mat.data[i].length; j++) - { - mat.dataID[i][j] = this.nextIndex++; - } - } - - this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); - this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateScale2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); - this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT , "left","center"); - - this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y, "right","center"); - this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateScale2D.MATRIX_ELEM_HEIGHT, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y, "center","top"); - this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateScale2D.MATRIX_ELEM_WIDTH, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT , "right","center"); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], - x + j*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateScale2D.MATRIX_ELEM_HEIGHT + RotateScale2D.MATRIX_ELEM_HEIGHT / 2); - } - } - return mat; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new RotateScale2D(animManag, canvas.width, canvas.height); -} - -function Matrix(contents, x, y) -{ - this.data = contents; - this.x = x; - this.y = y; -} - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function RotateScale2D(am, w, h) +{ + this.init(am, w, h); +} + + +RotateScale2D.inheritFrom(Algorithm); + +RotateScale2D.XAxisYPos = 300; +RotateScale2D.XAxisStart = 100; +RotateScale2D.XAxisEnd = 700; + + +RotateScale2D.MATRIX_START_X = 10; +RotateScale2D.MATRIX_START_Y = 10; +RotateScale2D.MATRIX_MULTIPLY_SPACING = 10; +RotateScale2D.EQUALS_SPACING = 30; + + + +RotateScale2D.YAxisXPos = 400; +RotateScale2D.YAxisStart = 100; +RotateScale2D.YAxisEnd = 500; + +RotateScale2D.MATRIX_ELEM_WIDTH = 50; +RotateScale2D.MATRIX_ELEM_HEIGHT = 20; + +RotateScale2D.OBJECTS = [ + [[100, 100], [-100, 100], [-100,-100], [100, -100]], // Square + [[10, 100], [-10, 100], [-10,-100], [100, -100], [100, -80], [10,-80]], // L + [[0, 141], [-134, 44], [-83, -114 ], [83, -114], [134,44]], // Pentagon + [[0, 141], [-35,48],[-134, 44], [-57, -19], [-83, -114 ], [0, -60],[83,-114], [57, -19], [134,44], [35, 48]], // Star + ] + + +RotateScale2D.AXIS_COLOR = "#0000FF" +RotateScale2D.VERTEX_FOREGORUND_COLOR = "#000000"; +RotateScale2D.VERTEX_BACKGROUND_COLOR = RotateScale2D.VERTEX_FOREGORUND_COLOR; +RotateScale2D.EDGE_COLOR = "#000000"; + + + +RotateScale2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; +RotateScale2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateScale2D.VERTEX_FOREGORUND_COLOR; +RotateScale2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; + + + + +RotateScale2D.VECTOR_COLOR = "#FF0000"; + +RotateScale2D.VERTEX_WIDTH = 3; +RotateScale2D.VERTEX_HEIGHT = RotateScale2D.VERTEX_WIDTH; + +RotateScale2D.prototype.init = function(am, w, h) +{ + var sc = RotateScale2D.superclass.init.call(this, am, w, h); + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.addControls(); + this.currentShape = 0; + + this.commands = []; + this.nextIndex = 0; + + this.setupAxis(); + + this.savedNextIndex = this.nextIndex; + this.setupObject(); + this.setupObjectGraphic(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); + + +} + +RotateScale2D.prototype.setupAxis = function() +{ + this.xAxisLeft = this.nextIndex++; + this.xAxisRight = this.nextIndex++; + this.yAxisTop = this.nextIndex++; + this.yAxisBottom = this.nextIndex++; + + this.xAxisLabel = this.nextIndex++; + this.yAxisLabel = this.nextIndex++; + + this.originID = this.nextIndex++; + + this.cmd("CreateRectangle", this.originID, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.XAxisYPos); + + + this.cmd("CreateRectangle", this.xAxisLeft, "", 0, 0, RotateScale2D.XAxisStart, RotateScale2D.XAxisYPos); + this.cmd("SetAlpha", this.xAxisLeft, 0); + this.cmd("CreateRectangle", this.xAxisRight, "", 0, 0, RotateScale2D.XAxisEnd, RotateScale2D.XAxisYPos); + this.cmd("SetAlpha", this.xAxisRight, 0); + this.cmd("Connect", this.xAxisLeft, this.xAxisRight, RotateScale2D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.xAxisRight, this.xAxisLeft, RotateScale2D.AXIS_COLOR, 0, 1, ""); + + + this.cmd("CreateRectangle", this.yAxisTop, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.YAxisStart); + this.cmd("SetAlpha", this.yAxisTop, 0); + this.cmd("CreateRectangle", this.yAxisBottom, "", 0, 0, RotateScale2D.YAxisXPos, RotateScale2D.YAxisEnd); + this.cmd("SetAlpha", this.yAxisBottom, 0); + this.cmd("Connect", this.yAxisTop, this.yAxisBottom, RotateScale2D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.yAxisBottom, this.yAxisTop, RotateScale2D.AXIS_COLOR, 0, 1, ""); + if (this.posYUp) + { + this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisStart + 10); + } + else + { + this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisEnd - 10); + } + this.cmd("CreateLabel", this.xAxisLabel, "+x", RotateScale2D.XAxisEnd - 10, RotateScale2D.XAxisYPos - 10); + this.cmd("SetForegroundColor", this.yAxisLabel, RotateScale2D.AXIS_COLOR); + this.cmd("SetForegroundColor", this.xAxisLabel, RotateScale2D.AXIS_COLOR); +} + + +RotateScale2D.prototype.setupObject = function() +{ + this.objectVertexPosition = RotateScale2D.OBJECTS[this.currentShape].slice(0); +} + + +RotateScale2D.prototype.worldToScreenSpace = function(point) +{ + var transformedPoint = new Array(2); + transformedPoint[0] = point[0] + RotateScale2D.YAxisXPos; + if (this.posYUp) + { + transformedPoint[1] = RotateScale2D.XAxisYPos - point[1]; + } + else + { + transformedPoint[1] = RotateScale2D.XAxisYPos + point[1]; + + } + return transformedPoint; +} + + + +RotateScale2D.prototype.moveObjectToNewPosition = function() +{ + var i; + for (i = 0; i < this.objectVertexID.length; i++) + { + var point = this.worldToScreenSpace(this.objectVertexPosition[i]); + this.cmd("Move", this.objectVertexID[i], point[0], point[1]); + } + +} + + +RotateScale2D.prototype.setupObjectGraphic = function() +{ + this.objectVertexID = new Array(this.objectVertexPosition.length); + var i; + for (i = 0; i < this.objectVertexPosition.length; i++) + { + this.objectVertexID[i] = this.nextIndex++; + var point = this.worldToScreenSpace(this.objectVertexPosition[i]); + + this.cmd("CreateRectangle", this.objectVertexID[i], "", RotateScale2D.VERTEX_WIDTH, RotateScale2D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", this.objectVertexID[i], RotateScale2D.VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", this.objectVertexID[i], RotateScale2D.VERTEX_BACKGROUND_COLOR); + } + for (i = 1; i < this.objectVertexID.length; i++) + { + this.cmd("Connect", this.objectVertexID[i-1], this.objectVertexID[i], RotateScale2D.EDGE_COLOR, 0, 0, ""); + } + this.cmd("Connect", this.objectVertexID[this.objectVertexID.length - 1], this.objectVertexID[0], RotateScale2D.EDGE_COLOR, 0, 0, ""); +} + +RotateScale2D.prototype.addControls = function() +{ + this.controls = []; + + this.addLabelToAlgorithmBar("Rotation Angle"); + + this.rotationField = this.addControlToAlgorithmBar("Text", ""); + this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.rotationField); + + this.addLabelToAlgorithmBar("Scale X"); + + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); + this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.scaleXField); + + + this.addLabelToAlgorithmBar("Scale Y"); + + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); + this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.scaleYField); + + + var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); + transformButton.onclick = this.transformCallback.bind(this); + + this.controls.push(transformButton); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", + "Column Major", + ], + "RankType"); + this.rowMajorButton = radioButtonList[0]; + this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); + this.controls.push(this.rowMajorButton); + + this.colMajorButton = radioButtonList[1]; + this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); + this.controls.push(this.colMajorButton); + + this.rowMajorButton.checked = this.rowMajor; + this.colMajorButton.checked = !this.rowMajor; + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", + "+y Down", + ], + "yAxisDirection"); + this.posYUpButton = radioButtonList[0]; + this.posYUpButton.onclick = this.changePosYCallback.bind(this, true); + this.controls.push(this.posYUpButton); + + this.posYDownButton = radioButtonList[1]; + this.posYDownButton.onclick = this.changePosYCallback.bind(this, false); + this.controls.push(this.posYDownButton); + + this.posYUpButton.checked = this.posYUp; + this.posYDownButton.checked = !this.posYUp; + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rotate, then scale", + "Scale, then rotate", + ], + "RotateFirst"); + this.rotateScaleButton = radioButtonList[0]; + this.rotateScaleButton.onclick = this.rotateScaleOrderCallback.bind(this, true); + this.controls.push(this.rotateScaleButton); + + this.scaleRotateButton = radioButtonList[1]; + this.scaleRotateButton.onclick = this.rotateScaleOrderCallback.bind(this, false); + this.controls.push(this.scaleRotateButton); + + this.rotateScaleButton.checked = this.rotateFirst; + this.scaleRotateButton.checked = !this.rotateFirst; + + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); + changeShapeButton.onclick = this.changeShapeCallback.bind(this); + + this.controls.push(changeShapeButton); + +} + + + + + + +RotateScale2D.prototype.reset = function() +{ + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.currentShape = 0; + this.rowMajorButton.checked = this.rowMajor; + this.posYUpButton.checked = this.posYUp; + this.rotateScaleButton.checked = this.rotateFirst; + + this.nextIndex = this.savedNextIndex; + this.setupObject(); + this.setupObjectGraphic(); +} + + +RotateScale2D.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +RotateScale2D.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +RotateScale2D.prototype.changePosYCallback = function(posYUp) +{ + if (this.posYUp != posYUp) + { + this.implementAction(this.changePosY.bind(this), posYUp); + } +} + +RotateScale2D.prototype.changePosY = function(posYUp) +{ + this.commands = new Array(); + this.posYUp= posYUp; + if (this.posYUpButton.checked != this.posYUp) + { + this.posYUpButton.checked = this.posYUp; + } + if (this.posYDownButton.checked == this.posYUp) + { + this.posYDownButton.checked = !this.posYUp; + } + if (this.posYUp) + { + this.cmd("Move", this.yAxisLabel, RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisStart + 10); + } + else + { + this.cmd("Move", this.yAxisLabel, RotateScale2D.YAxisXPos + 10, RotateScale2D.YAxisEnd - 10); + + } + + this.moveObjectToNewPosition(); + + + + + // Move +y on axis up/down + return this.commands; +} + + + +RotateScale2D.prototype.changeRowColMajorCallback = function(rowMajor) +{ + if (this.rowMajor != rowMajor) + { + this.implementAction(this.changeRowCol.bind(this), rowMajor); + } +} + +RotateScale2D.prototype.changeRowCol = function(rowMajor) +{ + this.commands = new Array(); + this.rowMajor= rowMajor; + if (this.rowMajorButton.checked != this.rowMajor) + { + this.rowMajorButton.checked = this.rowMajor; + } + if (this.colMajorButton.checked == this.rowMajor) + { + this.colMajorButton.checked = !this.rowMajor; + } + return this.commands; +} + + +RotateScale2D.prototype.fixNumber = function(value, defaultVal) +{ + if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) + { + value = defaultVal; + } + else + { + value = String(parseFloat(value)); + } + return value +} + +RotateScale2D.prototype.transformCallback = function() +{ + + + this.rotationField.value = this.fixNumber(this.rotationField.value, "0"); + this.scaleXField.value = this.fixNumber(this.scaleXField.value, "1"); + this.scaleYField.value = this.fixNumber(this.scaleYField.value, "1"); + this.implementAction(this.transform.bind(this), this.rotationField.value + ";" + this.scaleXField.value + ";" + this.scaleYField.value); + +} + + +RotateScale2D.prototype.changeShapeCallback = function() +{ + this.implementAction(this.changeShape.bind(this), 0); +} + +RotateScale2D.prototype.changeShape = function() +{ + this.commands = []; + var i; + for (i = 0; i < this.objectVertexID.length; i++) + { + this.cmd("Delete", this.objectVertexID[i]); + } + this.currentShape++; + if (this.currentShape >= RotateScale2D.OBJECTS.length) + { + this.currentShape = 0; + } + this.setupObject(); + this.setupObjectGraphic(); + return this.commands; +} + +RotateScale2D.prototype.rotateScaleOrderCallback = function(rotateFirst) +{ + if (this.rotateFirst != rotateFirst) + { + this.implementAction(this.rotateScaleOrder.bind(this), rotateFirst); + } +} + + +RotateScale2D.prototype.rotateScaleOrder = function(rotateFirst) +{ + this.commands = new Array(); + this.rotateFirst= rotateFirst; + if (this.rotateScaleButton.checked != this.rotateFirst) + { + this.rotateScaleButton.checked = this.rotateFirst; + } + if (this.scaleRotateButton.checked == this.rotateFirst) + { + this.scaleRotateButton.checked = !this.rotateFirst; + } + return this.commands; +} + + +function toRadians(degrees) +{ + return (degrees * 2 * Math.PI) / 360.0; +} + +RotateScale2D.prototype.transform = function(input) +{ + var oldNextIndex = this.nextIndex; + this.commands = []; + var inputs = input.split(";"); + var rotateDegree = toRadians(parseFloat(inputs[0])); + var scaleX = parseFloat(inputs[1]); + var scaleY = parseFloat(inputs[2]); + + var xpos = RotateScale2D.MATRIX_START_X; + var ypos = RotateScale2D.MATRIX_START_Y; + if (!this.rowMajor) + { + xpos += 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING; + } + + var xy; + if (this.rowMajor) + { + xy = this.createMatrix([["x", "y"]], xpos, ypos); + xpos += xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING; + + } + + var matrixData; + if (this.rotateFirst) + { + if (this.rowMajor) + { + matrixData = [["cos \u0398", "sin \u0398"], ["-sin \u0398", "cos \u0398"]] + } + else + { + matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; + } + + } + else + { + if (this.rowMajor) + { + matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; + } + else + { + matrixData = [["cos \u0398", "-sin \u0398"], ["sin \u0398", "cos \u0398"]] + + } + } + + + var firstMat = this.createMatrix(matrixData, xpos, ypos); + + xpos += firstMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING; + + + if (this.rotateFirst) + { + if (this.rowMajor) + { + matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; + } + else + { + matrixData = [["cos \u0398", "-sin \u0398"], ["sin \u0398", "cos \u0398"]] + + } + } + else + { + if (this.rowMajor) + { + matrixData = [["cos \u0398", "sin \u0398"], ["-sin \u0398", "cos \u0398"]] + } + else + { + matrixData = [["ScaleX", "0"], ["0", "ScaleY"]]; + } + } + + var secondMat = this.createMatrix(matrixData,xpos, ypos); + xpos += secondMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH; + + if (!this.rowMajor) + { + xpos += RotateScale2D.MATRIX_MULTIPLY_SPACING; + xy = this.createMatrix([["x"], ["y"]], xpos, ypos); + xpos += xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH; + } + + this.cmd("Step"); + + var rotMat, scaleMat + if ((this.rotateFirst && this.rowMajor) || (!this.rotateFirst && !this.rowMajor)) + { + rotMat = firstMat; + scaleMat = secondMat; + } + else + { + rotMat = secondMat; + scaleMat = firstMat; + + } + + if (this.rowMajor) + { + rotMat.data = [["cos " + inputs[0], "sin " + inputs[0]],["-sin " +inputs[0], "cos " + inputs[0]]]; + } + else + { + rotMat.data = [["cos " + inputs[0], "-sin " + inputs[0]],["sin " +inputs[0], "cos " + inputs[0]]]; + } + this.resetMatrixLabels(rotMat); + + scaleMat.data = [[scaleX, 0],[0, scaleY]]; + this.resetMatrixLabels(scaleMat); + + this.cmd("Step"); + + if (this.rowMajor) + { + rotMat.data = [[Math.cos(rotateDegree), Math.sin(rotateDegree)],[-Math.sin(rotateDegree), Math.cos(rotateDegree)]]; + } + else + { + rotMat.data = [[Math.cos(rotateDegree), -Math.sin(rotateDegree)],[Math.sin(rotateDegree), Math.cos(rotateDegree)]]; + } + this.resetMatrixLabels(rotMat); + this.cmd("Step"); + this.setMatrixAlpha(xy, 0.3); + + + var equalID = this.nextIndex++; + var equaXlPos; + if (this.rowMajor) + { + equalXPos = xpos + RotateScale2D.EQUALS_SPACING / 2; + } + else + { + equalXPos = RotateScale2D.MATRIX_START_X + 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING / 2; + } + + this.cmd("CreateLabel", equalID, "=", equalXPos, ypos + rotMat.data.length / 2 * RotateScale2D.MATRIX_ELEM_HEIGHT); + + xpos += RotateScale2D.EQUALS_SPACING; + + + var paren1 = this.nextIndex++ + var paren2 = this.nextIndex++ + var paren3 = this.nextIndex++ + var paren4 = this.nextIndex++ + + var parenX; + parenX = 2 * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_START_X + RotateScale2D.MATRIX_MULTIPLY_SPACING - 2; + if (!this.rowMajor) + { + parenX += RotateScale2D.EQUALS_SPACING - RotateScale2D.MATRIX_MULTIPLY_SPACING; + } + + this.cmd("CreateRectangle", paren1, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y, "center","center"); + this.cmd("CreateRectangle", paren2, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, "center","center"); + this.cmd("Connect", paren1, paren2, "#000000", 0.2, 0, ""); + + parenX = 6*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_START_X + 2*RotateScale2D.MATRIX_MULTIPLY_SPACING + 2; + if (!this.rowMajor) + { + parenX += RotateScale2D.EQUALS_SPACING - RotateScale2D.MATRIX_MULTIPLY_SPACING; + } + + this.cmd("CreateRectangle", paren3, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y, "center","center"); + this.cmd("CreateRectangle", paren4, "", 0, 0, parenX, RotateScale2D.MATRIX_START_Y+ 2*RotateScale2D.MATRIX_ELEM_HEIGHT, "center","center"); + + this.cmd("Connect", paren3, paren4, "#000000", -0.2, 0 ,""); + + this.cmd("Step"); + var tmpMat; + if (this.rowMajor) + { + tmpMat = this.createMatrix([["",""],["",""]],xpos, ypos); + } + else + { + tmpMat = this.createMatrix([["",""],["",""]],RotateScale2D.MATRIX_START_X, RotateScale2D.MATRIX_START_Y); + } + var explainID = this.nextIndex++; + if (this.rowMajor) + { + this.cmd("CreateLabel", explainID, "", 6*RotateScale2D.MATRIX_ELEM_WIDTH + 2*RotateScale2D.MATRIX_MULTIPLY_SPACING + + RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); + } + else + { + this.cmd("CreateLabel", explainID, "", RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); + } + this.cmd("Step"); + this.multiplyMatrix(firstMat, secondMat, tmpMat, explainID); + + + this.deleteMatrix(firstMat); + this.deleteMatrix(secondMat); + this.cmd("Delete", paren1); + this.cmd("Delete", paren2); + this.cmd("Delete", paren3); + this.cmd("Delete", paren4); + this.cmd("Delete", equalID); + + if (this.rowMajor) + { + this.moveMatrix(tmpMat, xy.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_MULTIPLY_SPACING + RotateScale2D.MATRIX_START_X, + RotateScale2D.MATRIX_START_Y); + xpos = (RotateScale2D.MATRIX_START_X + xy.data[0].length*RotateScale2D.MATRIX_ELEM_WIDTH + + RotateScale2D.MATRIX_MULTIPLY_SPACING + tmpMat.data[0].length * RotateScale2D.MATRIX_ELEM_WIDTH); + this.cmd("SetPosition", explainID, 4*RotateScale2D.MATRIX_ELEM_WIDTH + 1*RotateScale2D.MATRIX_MULTIPLY_SPACING + + RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_START_X, 20 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT, 0); + + } + else + { + this.moveMatrix(tmpMat, RotateScale2D.MATRIX_START_X + 4*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.EQUALS_SPACING + RotateScale2D.MATRIX_MULTIPLY_SPACING, + RotateScale2D.MATRIX_START_Y); + xpos = (RotateScale2D.MATRIX_START_X + 7*RotateScale2D.MATRIX_ELEM_WIDTH + + 2 * RotateScale2D.MATRIX_MULTIPLY_SPACING + RotateScale2D.EQUALS_SPACING); + + this.cmd("SetPosition", explainID, 7*RotateScale2D.MATRIX_ELEM_WIDTH + 2 * RotateScale2D.EQUALS_SPACING + 3*RotateScale2D.MATRIX_MULTIPLY_SPACING, RotateScale2D.MATRIX_START_Y + 10 + 2*RotateScale2D.MATRIX_ELEM_HEIGHT); + + } + this.setMatrixAlpha(xy, 1); + this.cmd("Step"); + + + var i; + var output; + + + var transformedObjectID = new Array(this.objectVertexID.length); + + for (i = 0; i < this.objectVertexID.length; i++) + { + this.cmd("Connect", this.originID, this.objectVertexID[i], RotateScale2D.VECTOR_COLOR, 0, 1, ""); + if (this.rowMajor) + { + xy.data = [this.objectVertexPosition[i].slice(0)]; + } + else + { + xy.data[0][0] = this.objectVertexPosition[i][0]; + xy.data[1][0] = this.objectVertexPosition[i][1]; + } + this.resetMatrixLabels(xy); + this.cmd("Step"); + this.cmd("CreateLabel", equalID, "=", xpos + RotateScale2D.EQUALS_SPACING / 2, ypos + tmpMat.data.length / 2 * RotateScale2D.MATRIX_ELEM_HEIGHT); + if (this.rowMajor) + { + output = this.createMatrix([["",""]], xpos + RotateScale2D.EQUALS_SPACING, ypos) + this.multiplyMatrix(xy, tmpMat, output, explainID); + } + else + { + output = this.createMatrix([[""],[""]], xpos + RotateScale2D.EQUALS_SPACING, ypos) + this.multiplyMatrix(tmpMat, xy, output, explainID); + } + + + transformedObjectID[i] = this.nextIndex++; + var point; + if (this.rowMajor) + { + point = this.worldToScreenSpace(output.data[0]); + } + else + { + point = this.worldToScreenSpace([output.data[0][0], output.data[1][0]]); + } + + this.cmd("CreateRectangle", transformedObjectID[i], "", RotateScale2D.VERTEX_WIDTH, RotateScale2D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", transformedObjectID[i], RotateScale2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", transformedObjectID[i], RotateScale2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); + this.cmd("Connect", this.originID, transformedObjectID[i], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); + this.cmd("Step"); + this.cmd("Disconnect", this.originID, transformedObjectID[i]); + + if (i > 0) + { + this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + + } + + this.cmd("Disconnect", this.originID, this.objectVertexID[i]); + if (this.rowMajor) + { + this.objectVertexPosition[i] = output.data[0]; + } + else + { + this.objectVertexPosition[i][0] = output.data[0][0]; + this.objectVertexPosition[i][1] = output.data[1][0]; + } + this.cmd("Delete", equalID); + this.deleteMatrix(output); + + } + this.cmd("Step"); + + this.cmd("Connect", transformedObjectID[0], transformedObjectID[transformedObjectID.length-1], RotateScale2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + + this.cmd("Step","B"); + this.moveObjectToNewPosition(); + this.cmd("Step","C"); + + for (i = 0; i < transformedObjectID.length; i++) + { + this.cmd("Delete", transformedObjectID[i]); + } + + + this.deleteMatrix(xy); + this.deleteMatrix(tmpMat); + this.cmd("Delete", explainID); + + this.nextIndex = oldNextIndex + + return this.commands; +} + + +RotateScale2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) +{ + var i; + var j; + var explainText = ""; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat2.data[0].length; j++) + { + var explainText = ""; + var value = 0; + for (k = 0; k < mat2.data.length; k++) + { + this.cmd("SetHighlight", mat1.dataID[i][k], 1); + this.cmd("SetHighlight", mat2.dataID[k][j], 1); + if (explainText != "") + { + explainText = explainText + " + "; + } + value = value + mat1.data[i][k] * mat2.data[k][j]; + explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); + this.cmd("SetText", explainID, explainText); + this.cmd("Step"); + this.cmd("SetHighlight", mat1.dataID[i][k], 0); + this.cmd("SetHighlight", mat2.dataID[k][j], 0); + } + value = this.standardize(value); + explainText += " = " + String(value); + this.cmd("SetText", explainID, explainText); + mat3.data[i][j] = value; + this.cmd("SetText", mat3.dataID[i][j], value); + this.cmd("Step"); + } + } + this.cmd("SetText", explainID, ""); + + +} + +RotateScale2D.prototype.standardize = function(lab) +{ + var newLab = Math.round(lab * 1000) / 1000; + if (isNaN(newLab)) + { + return lab; + } + else + { + return newLab; + } +} + + +RotateScale2D.prototype.resetMatrixLabels = function(mat) +{ + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + mat.data[i][j] = this.standardize(mat.data[i][j]); + this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); + } + } +} + + + +RotateScale2D.prototype.moveMatrix = function(mat, x, y) +{ + var height = mat.data.length; + var width = 0; + + var i, j; + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + } + + + this.cmd("Move", mat.leftBrack1, x, y); + this.cmd("Move", mat.leftBrack2, x, y); + this.cmd("Move", mat.leftBrack3, x, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT); + + this.cmd("Move", mat.rightBrack1, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack2, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack3, x+ width * RotateScale2D.MATRIX_ELEM_WIDTH, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Move", mat.dataID[i][j], + x + j*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateScale2D.MATRIX_ELEM_HEIGHT + RotateScale2D.MATRIX_ELEM_HEIGHT / 2); + } + } +} + +RotateScale2D.prototype.deleteMatrix = function(mat) +{ + this.cmd("Delete",mat.leftBrack1); + this.cmd("Delete",mat.leftBrack2); + this.cmd("Delete",mat.leftBrack3); + this.cmd("Delete",mat.rightBrack1); + this.cmd("Delete",mat.rightBrack2); + this.cmd("Delete",mat.rightBrack3); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Delete", mat.dataID[i][j]); + } + } +} + +RotateScale2D.prototype.setMatrixAlpha = function(mat, alpha) +{ + this.cmd("SetAlpha",mat.leftBrack1, alpha); + this.cmd("SetAlpha",mat.leftBrack2, alpha); + this.cmd("SetAlpha",mat.leftBrack3, alpha); + this.cmd("SetAlpha",mat.rightBrack1, alpha); + this.cmd("SetAlpha",mat.rightBrack2, alpha); + this.cmd("SetAlpha",mat.rightBrack3, alpha); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("SetAlpha", mat.dataID[i][j], alpha); + } + } +} + + +RotateScale2D.prototype.createMatrix = function(contents, x, y) +{ + var mat = new Matrix(contents, x, y); + mat.leftBrack1 = this.nextIndex++; + mat.leftBrack2 = this.nextIndex++; + mat.leftBrack3 = this.nextIndex++; + mat.rightBrack1 = this.nextIndex++; + mat.rightBrack2 = this.nextIndex++; + mat.rightBrack3 = this.nextIndex++; + + var height = mat.data.length; + var width = 0; + + var i, j; + mat.dataID = new Array(mat.data.length); + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + mat.dataID[i] = new Array(mat.data[i].length); + for (j = 0; j < mat.data[i].length; j++) + { + mat.dataID[i][j] = this.nextIndex++; + } + } + + this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); + this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateScale2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); + this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT , "left","center"); + + this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y, "right","center"); + this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateScale2D.MATRIX_ELEM_HEIGHT, x + width * RotateScale2D.MATRIX_ELEM_WIDTH, y, "center","top"); + this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateScale2D.MATRIX_ELEM_WIDTH, y + height * RotateScale2D.MATRIX_ELEM_HEIGHT , "right","center"); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], + x + j*RotateScale2D.MATRIX_ELEM_WIDTH + RotateScale2D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateScale2D.MATRIX_ELEM_HEIGHT + RotateScale2D.MATRIX_ELEM_HEIGHT / 2); + } + } + return mat; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new RotateScale2D(animManag, canvas.width, canvas.height); +} + +function Matrix(contents, x, y) +{ + this.data = contents; + this.x = x; + this.y = y; +} + diff --git a/AlgorithmLibrary/RotateScale3D.js b/AlgorithmLibrary/RotateScale3D.js index 61fdc18..60ee1fe 100644 --- a/AlgorithmLibrary/RotateScale3D.js +++ b/AlgorithmLibrary/RotateScale3D.js @@ -1,1155 +1,1153 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function RotateScale3D(am, w, h) -{ - this.init(am, w, h); -} - - -RotateScale3D.prototype = new Algorithm(); -RotateScale3D.prototype.constructor = RotateScale3D; -RotateScale3D.superclass = Algorithm.prototype; - -RotateScale3D.XAxisYPos = 300; -RotateScale3D.XAxisStart = 100; -RotateScale3D.XAxisEnd = 700; - - -RotateScale3D.MATRIX_START_X = 10; -RotateScale3D.MATRIX_START_Y = 10; -RotateScale3D.MATRIX_MULTIPLY_SPACING = 10; -RotateScale3D.EQUALS_SPACING = 30; - -RotateScale3D.AXIS_SIZE = 200; - -RotateScale3D.AXIS_ALPHA = 0.7; - -RotateScale3D.YAxisXPos = 400; -RotateScale3D.YAxisStart = 100; -RotateScale3D.YAxisEnd = 500; - -RotateScale3D.MATRIX_ELEM_WIDTH = 50; -RotateScale3D.MATRIX_ELEM_HEIGHT = 20; - -RotateScale3D.OBJECTS = [ - [[100, 100, 100], [-100, 100,100], [-100,-100,100], [100, -100, 100], - [100, -100, -100], [100, 100, -100], [-100, 100,-100], [-100,-100,-100] - ], // Cube - - [[10, 10, 100], [-10, 10, 100], [-10, 10, -100], [100, 10, -100], [100, 10, -80], [10, 10, -80], - [10, -10, -80],[10, -10, 100], [-10, -10, 100], [-10, -10, -100], [100, -10, -100], [100, -10, -80], - - - ], // L - [[0, 0, 141], [-134, 0, 44], [-83, 0, -114 ], [83, 0, -114], [134, 0, 44]], // Pentagon - [[0, 0, 141], [-35,0, 48],[-134, 0, 44], [-57, 0, -19], [-83, 0, -114 ], [0, 0, -60],[83, 0, -114], [57, 0, -19], [134, 0, 44], [35, 0, 48]] // Star - ]; - -RotateScale3D.EXTRA_CONNECTIONS = [ - [[3, 0], [5,0], [6,1], [7,2], [4,7]], // Cube - [[5, 0], [6, 11], [0,7], [1,8], [2,9],[3,10],[4,11]], // L - [[4,0]], // Pentagon - [[9, 0]] //Star - ] - - -RotateScale3D.CAMERA_Z_ROT = toRadians(-10); -RotateScale3D.CAMERA_X_ROT = toRadians(10); - -RotateScale3D.CAMERA_TRANS_ANGLE = toRadians(30); -RotateScale3D.L = 0.5; - - -RotateScale3D.CAMERA_TRANSFORM = [[1, 0, 0], - [RotateScale3D.L * Math.cos(RotateScale3D.CAMERA_TRANS_ANGLE), 0, RotateScale3D.L * Math.sin(RotateScale3D.CAMERA_TRANS_ANGLE)], - [0, 0, 1]]; - - -RotateScale3D.CAMERA_TRANSFORM2 = [[Math.cos(RotateScale3D.CAMERA_Z_ROT), Math.sin(RotateScale3D.CAMERA_Z_ROT), 0], - [-Math.sin(RotateScale3D.CAMERA_Z_ROT), Math.cos(RotateScale3D.CAMERA_Z_ROT), 0], - [0, 0, 1]]; - -RotateScale3D.CAMERA_TRANSFORM1 = [[1, 0, 0], - [0, Math.cos(RotateScale3D.CAMERA_X_ROT), Math.sin(RotateScale3D.CAMERA_X_ROT)], - [0, -Math.sin(RotateScale3D.CAMERA_X_ROT), Math.cos(RotateScale3D.CAMERA_X_ROT)] - ]; - - - -RotateScale3D.AXIS_COLOR = "#0000FF" -RotateScale3D.VERTEX_FOREGORUND_COLOR = "#000000"; -RotateScale3D.VERTEX_BACKGROUND_COLOR = RotateScale3D.VERTEX_FOREGORUND_COLOR; -RotateScale3D.EDGE_COLOR = "#000000"; - - - -RotateScale3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; -RotateScale3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateScale3D.VERTEX_FOREGORUND_COLOR; -RotateScale3D.TRANSFORMED_EDGE_COLOR = "#66FF66"; - - - - -RotateScale3D.VECTOR_COLOR = "#FF0000"; - -RotateScale3D.VERTEX_WIDTH = 3; -RotateScale3D.VERTEX_HEIGHT = RotateScale3D.VERTEX_WIDTH; - -RotateScale3D.prototype.init = function(am, w, h) -{ - var sc = RotateScale3D.superclass.init.call(this, am, w, h); - this.cameraTransform = RotateScale3D.CAMERA_TRANSFORM; -// this.cameraTransform = this.multiply(RotateScale3D.CAMERA_TRANSFORM1, RotateScale3D.CAMERA_TRANSFORM2); - - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.addControls(); - this.currentShape = 0; - - this.commands = []; - this.nextIndex = 0; - - this.setupAxis(); - - this.savedNextIndex = this.nextIndex; - this.setupObject(); - this.setupObjectGraphic(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); - - -} - -RotateScale3D.prototype.setupAxis = function() -{ - this.xAxisMinID = this.nextIndex++; - this.xAxisMaxID = this.nextIndex++; - this.yAxisMinID = this.nextIndex++; - this.yAxisMaxID = this.nextIndex++; - - this.zAxisMinID = this.nextIndex++; - this.zAxisMaxID = this.nextIndex++; - - - this.xAxisLabel = this.nextIndex++; - this.yAxisLabel = this.nextIndex++; - this.zAxisLabel = this.nextIndex++; - var point; - - - this.originID = this.nextIndex++; - - point = this.worldToScreenSpace([0, 0, 0]); - - this.cmd("CreateRectangle", this.originID, "", 0, 0, point[0], point[1]); - - point = this.worldToScreenSpace([-RotateScale3D.AXIS_SIZE, 0, 0]); - this.cmd("CreateRectangle", this.xAxisMinID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.xAxisMinID, 0); - - point = this.worldToScreenSpace([RotateScale3D.AXIS_SIZE, 0, 0]); - this.cmd("CreateRectangle", this.xAxisMaxID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.xAxisMaxID, 0); - - this.cmd("Connect", this.xAxisMinID, this.xAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.xAxisMaxID, this.xAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - this.cmd("SetEdgeAlpha", this.xAxisMaxID, this.xAxisMinID, RotateScale3D.AXIS_ALPHA); - this.cmd("SetEdgeAlpha", this.xAxisMinID, this.xAxisMaxID, RotateScale3D.AXIS_ALPHA); - - point = this.worldToScreenSpace([0,-RotateScale3D.AXIS_SIZE, 0]); - this.cmd("CreateRectangle", this.yAxisMinID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.yAxisMinID, 0); - - point = this.worldToScreenSpace([0,RotateScale3D.AXIS_SIZE, 0]); - this.cmd("CreateRectangle", this.yAxisMaxID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.yAxisMaxID, 0); - - this.cmd("Connect", this.yAxisMinID, this.yAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.yAxisMaxID, this.yAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - this.cmd("SetEdgeAlpha", this.yAxisMaxID, this.yAxisMinID, RotateScale3D.AXIS_ALPHA); - this.cmd("SetEdgeAlpha", this.yAxisMinID, this.yAxisMaxID, RotateScale3D.AXIS_ALPHA); - - - point = this.worldToScreenSpace([0,0, -RotateScale3D.AXIS_SIZE]); - this.cmd("CreateRectangle", this.zAxisMinID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.zAxisMinID, 0); - - point = this.worldToScreenSpace([0, 0, RotateScale3D.AXIS_SIZE]); - this.cmd("CreateRectangle", this.zAxisMaxID, "", 0, 0, point[0], point[1]); - this.cmd("SetAlpha", this.zAxisMaxID, 0); - - this.cmd("Connect", this.zAxisMinID, this.zAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.zAxisMaxID, this.zAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); - - this.cmd("SetEdgeAlpha", this.zAxisMaxID, this.zAxisMinID, RotateScale3D.AXIS_ALPHA); - this.cmd("SetEdgeAlpha", this.zAxisMinID, this.zAxisMaxID, RotateScale3D.AXIS_ALPHA); - - - point = this.worldToScreenSpace([RotateScale3D.AXIS_SIZE, 0, -10]); - this.cmd("CreateLabel", this.xAxisLabel, "+x", point[0], point[1]); - - point = this.worldToScreenSpace([+10, RotateScale3D.AXIS_SIZE, 0]); - this.cmd("CreateLabel", this.yAxisLabel, "+y", point[0], point[1]); - - point = this.worldToScreenSpace([+10, 0, RotateScale3D.AXIS_SIZE]); - this.cmd("CreateLabel", this.zAxisLabel, "+z", point[0], point[1]); - - this.cmd("SetForegroundColor", this.yAxisLabel, RotateScale3D.AXIS_COLOR); - this.cmd("SetForegroundColor", this.xAxisLabel, RotateScale3D.AXIS_COLOR); - this.cmd("SetForegroundColor", this.zAxisLabel, RotateScale3D.AXIS_COLOR); -} - - -RotateScale3D.prototype.setupObject = function() -{ - this.objectVertexPosition = RotateScale3D.OBJECTS[this.currentShape].slice(0); - this.extraConnections = RotateScale3D.EXTRA_CONNECTIONS[this.currentShape].slice(0); -} - - -RotateScale3D.prototype.worldToScreenSpace = function(point) -{ - var transformedPoint = this.multiply([point], this.cameraTransform)[0]; - var worldSpace = new Array(2); - worldSpace[0] = transformedPoint[0] + RotateScale3D.YAxisXPos; - worldSpace[1] = RotateScale3D.XAxisYPos - transformedPoint[2]; - - return worldSpace; -} - - - -RotateScale3D.prototype.moveObjectToNewPosition = function() -{ - var i; - for (i = 0; i < this.objectVertexID.length; i++) - { - var point = this.worldToScreenSpace(this.objectVertexPosition[i]); - this.cmd("Move", this.objectVertexID[i], point[0], point[1]); - } - -} - - -RotateScale3D.prototype.setupObjectGraphic = function() -{ - this.objectVertexID = new Array(this.objectVertexPosition.length); - var i; - for (i = 0; i < this.objectVertexPosition.length; i++) - { - this.objectVertexID[i] = this.nextIndex++; - var point = this.worldToScreenSpace(this.objectVertexPosition[i]); - - this.cmd("CreateRectangle", this.objectVertexID[i], "", RotateScale3D.VERTEX_WIDTH, RotateScale3D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", this.objectVertexID[i], RotateScale3D.VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", this.objectVertexID[i], RotateScale3D.VERTEX_BACKGROUND_COLOR); - } - for (i = 1; i < this.objectVertexID.length; i++) - { - this.cmd("Connect", this.objectVertexID[i-1], this.objectVertexID[i], RotateScale3D.EDGE_COLOR, 0, 0, ""); - } - - for (var i = 0; i < this.extraConnections.length; i++) - { - this.cmd("Connect", this.objectVertexID[this.extraConnections[i][0]], this.objectVertexID[this.extraConnections[i][1]], RotateScale3D.EDGE_COLOR, 0, 0, ""); - } - -} - -RotateScale3D.prototype.addControls = function() -{ - this.controls = []; - - addLabelToAlgorithmBar("X Angle"); - - this.rotationFieldX = this.addControlToAlgorithmBar("Text", ""); - this.rotationFieldX.onkeydown = this.returnSubmitFloat(this.rotationFieldX, this.rotateCallback.bind(this), 4, true); - this.controls.push(this.rotationFieldX); - - addLabelToAlgorithmBar("Y Angle"); - - this.rotationFieldY = this.addControlToAlgorithmBar("Text", ""); - this.rotationFieldY.onkeydown = this.returnSubmitFloat(this.rotationFieldY, this.rotateCallback.bind(this), 4, true); - this.controls.push(this.rotationFieldY); - - addLabelToAlgorithmBar("Z Angle"); - - this.rotationFieldZ = this.addControlToAlgorithmBar("Text", ""); - this.rotationFieldZ.onkeydown = this.returnSubmitFloat(this.rotationFieldZ, this.rotateCallback.bind(this), 4, true); - this.controls.push(this.rotationFieldZ); - - - - var rotateButton = this.addControlToAlgorithmBar("Button", "Rotate"); - rotateButton.onclick = this.rotateCallback.bind(this); - - this.controls.push(rotateButton); - - - addLabelToAlgorithmBar("Scale X"); - - this.scaleXField = this.addControlToAlgorithmBar("Text", ""); - this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.scaleCallback.bind(this), 4, true); - this.controls.push(this.scaleXField); - - - addLabelToAlgorithmBar("Scale Y"); - - this.scaleYField = this.addControlToAlgorithmBar("Text", ""); - this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.scaleCallback.bind(this), 4, true); - this.controls.push(this.scaleYField); - - addLabelToAlgorithmBar("Scale Z"); - - this.scaleZField = this.addControlToAlgorithmBar("Text", ""); - this.scaleZField.onkeydown = this.returnSubmitFloat(this.scaleZField, this.scaleCallback.bind(this), 4, true); - this.controls.push(this.scaleZField); - - - - var scaleButton = this.addControlToAlgorithmBar("Button", "Scale"); - scaleButton.onclick = this.scaleCallback.bind(this); - - this.controls.push(scaleButton); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", - "Column Major", - ], - "RankType"); - this.rowMajorButton = radioButtonList[0]; - this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); - this.controls.push(this.rowMajorButton); - - this.colMajorButton = radioButtonList[1]; - this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); - this.controls.push(this.colMajorButton); - - this.rowMajorButton.checked = this.rowMajor; - this.colMajorButton.checked = !this.rowMajor; - - - - var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); - changeShapeButton.onclick = this.changeShapeCallback.bind(this); - - this.controls.push(changeShapeButton); - -} - - - - - - -RotateScale3D.prototype.reset = function() -{ - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.currentShape = 0; - this.rowMajorButton.checked = this.rowMajor; - - this.nextIndex = this.savedNextIndex; - this.setupObject(); - this.setupObjectGraphic(); -} - - -RotateScale3D.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -RotateScale3D.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -RotateScale3D.prototype.changePosYCallback = function(posYUp) -{ - if (this.posYUp != posYUp) - { - this.implementAction(this.changePosY.bind(this), posYUp); - } -} - -RotateScale3D.prototype.changePosY = function(posYUp) -{ - this.commands = new Array(); - this.posYUp= posYUp; - if (this.posYUpButton.checked != this.posYUp) - { - this.posYUpButton.checked = this.posYUp; - } - if (this.posYDownButton.checked == this.posYUp) - { - this.posYDownButton.checked = !this.posYUp; - } - if (this.posYUp) - { - this.cmd("Move", this.yAxisLabel, RotateScale3D.YAxisXPos + 10, RotateScale3D.YAxisStart + 10); - } - else - { - this.cmd("Move", this.yAxisLabel, RotateScale3D.YAxisXPos + 10, RotateScale3D.YAxisEnd - 10); - - } - - this.moveObjectToNewPosition(); - - - - - // Move +y on axis up/down - return this.commands; -} - - - -RotateScale3D.prototype.changeRowColMajorCallback = function(rowMajor) -{ - if (this.rowMajor != rowMajor) - { - this.implementAction(this.changeRowCol.bind(this), rowMajor); - } -} - -RotateScale3D.prototype.changeRowCol = function(rowMajor) -{ - this.commands = new Array(); - this.rowMajor= rowMajor; - if (this.rowMajorButton.checked != this.rowMajor) - { - this.rowMajorButton.checked = this.rowMajor; - } - if (this.colMajorButton.checked == this.rowMajor) - { - this.colMajorButton.checked = !this.rowMajor; - } - return this.commands; -} - - -RotateScale3D.prototype.fixNumber = function(value, defaultVal) -{ - if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) - { - value = defaultVal; - } - else - { - value = String(parseFloat(value)); - } - return value -} - -RotateScale3D.prototype.rotateCallback = function() -{ - - - this.rotationFieldX.value = this.fixNumber(this.rotationFieldX.value, "0"); - this.rotationFieldY.value = this.fixNumber(this.rotationFieldY.value, "0"); - this.rotationFieldZ.value = this.fixNumber(this.rotationFieldZ.value, "0"); - this.implementAction(this.rotate.bind(this), this.rotationFieldZ.value + ";" +this.rotationFieldY.value + ";" +this.rotationFieldX.value); - -} -RotateScale3D.prototype.scaleCallback = function() -{ - - - this.scaleXField.value = this.fixNumber(this.scaleXField.value, "1"); - this.scaleYField.value = this.fixNumber(this.scaleYField.value, "1"); - this.scaleZField.value = this.fixNumber(this.scaleZField.value, "1"); - this.implementAction(this.scale.bind(this), this.scaleXField.value + ";" +this.scaleYField.value + ";" +this.scaleZField.value); - -} - - -RotateScale3D.prototype.changeShapeCallback = function() -{ - this.implementAction(this.changeShape.bind(this), 0); -} - -RotateScale3D.prototype.changeShape = function() -{ - this.commands = []; - var i; - for (i = 0; i < this.objectVertexID.length; i++) - { - this.cmd("Delete", this.objectVertexID[i]); - } - this.currentShape++; - if (this.currentShape >= RotateScale3D.OBJECTS.length) - { - this.currentShape = 0; - } - this.setupObject(); - this.setupObjectGraphic(); - return this.commands; -} - -RotateScale3D.prototype.rotateScaleOrderCallback = function(rotateFirst) -{ - if (this.rotateFirst != rotateFirst) - { - this.implementAction(this.rotateScaleOrder.bind(this), rotateFirst); - } -} - - -RotateScale3D.prototype.rotateScaleOrder = function(rotateFirst) -{ - this.commands = new Array(); - this.rotateFirst= rotateFirst; - if (this.rotateScaleButton.checked != this.rotateFirst) - { - this.rotateScaleButton.checked = this.rotateFirst; - } - if (this.scaleRotateButton.checked == this.rotateFirst) - { - this.scaleRotateButton.checked = !this.rotateFirst; - } - return this.commands; -} - - -function toRadians(degrees) -{ - return (degrees * 2 * Math.PI) / 360.0; -} - -RotateScale3D.prototype.scale = function(input) -{ - var oldNextIndex = this.nextIndex; - this.commands = []; - var inputs = input.split(";"); - var scaleX = parseFloat(inputs[0]); - var scaleY = parseFloat(inputs[1]); - var scaleZ = parseFloat(inputs[2]); - - var xpos = RotateScale3D.MATRIX_START_X; - var ypos = RotateScale3D.MATRIX_START_Y; - - xpos += 3 * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; - - - var transformMatrix = this.createMatrix([[scaleX, 0, 0], - [0, scaleY, 0], - [0, 0, scaleZ]], xpos, ypos); - this.transformPoints(transformMatrix); - this.deleteMatrix(transformMatrix); - return this.commands; - -} - - -RotateScale3D.prototype.transformPoints = function(transformMatrix) -{ - var explainID = this.nextIndex++; - var equalID = this.nextIndex++; - var xyz; - - if (this.rowMajor) - { - xyz = this.createMatrix([["x", "y", "z"]], RotateScale3D.MATRIX_START_X, RotateScale3D.MATRIX_START_Y); - this.cmd("CreateLabel", explainID, "", RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, - RotateScale3D.MATRIX_START_Y + 1.5*RotateScale3D.MATRIX_ELEM_HEIGHT, 0); - this.cmd("CreateLabel", equalID, "=", RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING / 2, - RotateScale3D.MATRIX_START_Y + 0.5*RotateScale3D.MATRIX_ELEM_HEIGHT); - - } - else - { - xyz = this.createMatrix([["x"], ["y"], ["z"]], RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING, - RotateScale3D.MATRIX_START_Y); - this.cmd("CreateLabel", explainID, "", RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, - RotateScale3D.MATRIX_START_Y + 3*RotateScale3D.MATRIX_ELEM_HEIGHT + 2, 0); - this.cmd("CreateLabel", equalID, "=", RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING / 2, - RotateScale3D.MATRIX_START_Y + 1.5*RotateScale3D.MATRIX_ELEM_HEIGHT); - - } - this.cmd("Step"); - - var i; - - var transformedObjectID = new Array(this.objectVertexID.length); - var output; - - for (i = 0; i < this.objectVertexID.length; i++) - { - this.cmd("Connect", this.originID, this.objectVertexID[i], RotateScale3D.VECTOR_COLOR, 0, 1, ""); - if (this.rowMajor) - { - xyz.data = [this.objectVertexPosition[i].slice(0)]; - } - else - { - xyz.data[0][0] = this.objectVertexPosition[i][0]; - xyz.data[1][0] = this.objectVertexPosition[i][1]; - xyz.data[2][0] = this.objectVertexPosition[i][2]; - } - this.resetMatrixLabels(xyz); - this.cmd("Step"); - - - if (this.rowMajor) - { - output = this.createMatrix([["", "", ""]], - RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, - RotateScale3D.MATRIX_START_Y); - this.multiplyMatrix(xyz, transformMatrix, output, explainID); - } - else - { - output = this.createMatrix([[""], [""], [""]], - RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2 * RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, - RotateScale3D.MATRIX_START_Y); - - this.multiplyMatrix(transformMatrix, xyz, output, explainID); - } - - - transformedObjectID[i] = this.nextIndex++; - var point; - if (this.rowMajor) - { - point = this.worldToScreenSpace(output.data[0]); - } - else - { - point = this.worldToScreenSpace([output.data[0][0], output.data[1][0], output.data[2][0]]); - } - - this.cmd("CreateRectangle", transformedObjectID[i], "", RotateScale3D.VERTEX_WIDTH, RotateScale3D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", transformedObjectID[i], RotateScale3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", transformedObjectID[i], RotateScale3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); - this.cmd("Connect", this.originID, transformedObjectID[i], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); - this.cmd("Step"); - this.cmd("Disconnect", this.originID, transformedObjectID[i]); - - if (i > 0) - { - this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - - } - for (var j = 0; j < this.extraConnections.length; j++) - { - if ((this.extraConnections[j][0] == i && this.extraConnections[j][1] < i) || - (this.extraConnections[j][1] == i && this.extraConnections[j][0] < i)) - { - this.cmd("Connect", transformedObjectID[this.extraConnections[j][0]], transformedObjectID[this.extraConnections[j][1]], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - } - - } - - this.cmd("Disconnect", this.originID, this.objectVertexID[i]); - if (this.rowMajor) - { - this.objectVertexPosition[i] = output.data[0]; - } - else - { - this.objectVertexPosition[i][0] = output.data[0][0]; - this.objectVertexPosition[i][1] = output.data[1][0]; - } - this.deleteMatrix(output); - - } - this.cmd("Step"); - - this.cmd("Connect", transformedObjectID[0], transformedObjectID[transformedObjectID.length-1], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - - this.cmd("Step","B"); - this.moveObjectToNewPosition(); - this.cmd("Step","C"); - - for (i = 0; i < transformedObjectID.length; i++) - { - this.cmd("Delete", transformedObjectID[i]); - } - - - this.deleteMatrix(xyz); - this.cmd("Delete", explainID); - this.cmd("Delete", equalID); - -} - - -RotateScale3D.prototype.rotate = function(input) -{ - var oldNextIndex = this.nextIndex; - this.commands = []; - var inputs = input.split(";"); - var rotateAngle1 = toRadians(parseFloat(inputs[0])); - var rotateAngle2 = toRadians(parseFloat(inputs[1])); - var rotateAngle3 = toRadians(parseFloat(inputs[2])); - - var xpos = RotateScale3D.MATRIX_START_X; - var ypos = RotateScale3D.MATRIX_START_Y; - - xpos += 3 * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; - - - var matrix1Data; - var matrix2Data; - var matrix3Data; - - matrix1Data = [["cos \u0398z", "sin \u0398z", 0], - ["-sin \u0398z", "cos \u0398z", 0], - [ 0, 0, 1]]; - matrix2Data = [["cos \u0398y", 0, "sin \u0398y"], - [0, 1, 0 ], - ["-sin \u0398y", 0, "cos \u0398y"]]; - - matrix3Data = [[1, 0 , 0], - [0, "cos \u0398x", "sin \u0398x"], - [0, "-sin \u0398x", "cos \u0398x"]]; - if (!this.rowMajor) - { - var tmp = matrix1Data; - matrix1Data = matrix3Data; - matrix3Data = tmp; - } - - var firstMat = this.createMatrix(matrix1Data, xpos, ypos); - xpos += firstMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; - - var secondMat = this.createMatrix(matrix2Data, xpos, ypos); - xpos += secondMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; - - var thirdMat = this.createMatrix(matrix3Data, xpos, ypos); - xpos += secondMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH; - - if (!this.rowMajor) - { - firstMat.transpose(); - secondMat.transpose(); - thirdMat.transpose(); - this.resetMatrixLabels(firstMat); - this.resetMatrixLabels(secondMat); - this.resetMatrixLabels(thirdMat); - - } - - this.cmd("Step"); - - firstMat.data = [["cos " + inputs[0], "sin " +inputs[0], 0], - ["-sin "+ inputs[0], "cos "+ inputs[0], 0], - [ 0, 0, 1]]; - secondMat.data = [["cos " +inputs[1], 0, "sin " +inputs[1]], - [0, 1, 0 ], - ["-sin " +inputs[1], 0, "cos " +inputs[1]]]; - - thirdMat.data = [[1, 0 , 0], - [0, "cos " +inputs[2], "sin " +inputs[2]], - [0, "-sin " +inputs[2], "cos " +inputs[2]]]; - - if (!this.rowMajor) - { - var tmp = firstMat.data; - firstMat.data = thirdMat.data; - thirdMat.data = tmp; - firstMat.transpose(); - secondMat.transpose(); - thirdMat.transpose(); - } - - this.resetMatrixLabels(firstMat); - this.resetMatrixLabels(secondMat); - this.resetMatrixLabels(thirdMat); - - this.cmd("Step"); - - firstMat.data = [[Math.cos(rotateAngle1), Math.sin(rotateAngle1), 0], - [-Math.sin(rotateAngle1), Math.cos(rotateAngle1), 0], - [ 0, 0, 1]]; - secondMat.data = [[Math.cos(rotateAngle2), 0, Math.sin(rotateAngle2)], - [ 0, 1, 0], - [-Math.sin(rotateAngle2), 0, Math.cos(rotateAngle2)]]; - thirdMat.data = [[1, 0, 0], - [0, Math.cos(rotateAngle3), Math.sin(rotateAngle3)], - [0, -Math.sin(rotateAngle3), Math.cos(rotateAngle3)]]; - - if (!this.rowMajor) - { - var tmp = firstMat.data; - firstMat.data = thirdMat.data; - thirdMat.data = tmp; - firstMat.transpose(); - secondMat.transpose(); - thirdMat.transpose(); - } - - this.resetMatrixLabels(firstMat); - this.resetMatrixLabels(secondMat); - this.resetMatrixLabels(thirdMat); - - this.cmd("Step"); - - this.setMatrixAlpha(firstMat, 0.3); - - - var paren1 = this.nextIndex++ - var paren2 = this.nextIndex++ - var paren3 = this.nextIndex++ - var paren4 = this.nextIndex++ - this.cmd("step"); - - var parenX; - parenX = xpos - 6 * RotateScale3D.MATRIX_ELEM_WIDTH - RotateScale3D.MATRIX_MULTIPLY_SPACING - 2; - - this.cmd("CreateRectangle", paren1, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y, "center","center"); - this.cmd("CreateRectangle", paren2, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y + 3*RotateScale3D.MATRIX_ELEM_HEIGHT, "center","center"); - this.cmd("Connect", paren1, paren2, "#000000", 0.2, 0, ""); - - parenX = xpos; - - this.cmd("CreateRectangle", paren3, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y, "center","center"); - this.cmd("CreateRectangle", paren4, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y+ 3*RotateScale3D.MATRIX_ELEM_HEIGHT, "center","center"); - - this.cmd("Connect", paren3, paren4, "#000000", -0.2, 0 ,""); - - this.cmd("Step"); - var tmpMat = this.createMatrix([["","",""], ["","",""],["","",""]], xpos + RotateScale3D.EQUALS_SPACING, ypos); - - var explainID = this.nextIndex++; - this.cmd("CreateLabel", explainID, "", xpos + RotateScale3D.EQUALS_SPACING, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*3 + 5, 0); - - var equalID = this.nextIndex++; - this.cmd("CreateLabel", equalID, "=", xpos + RotateScale3D.EQUALS_SPACING / 2, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*1.5); - this.multiplyMatrix(secondMat, thirdMat, tmpMat, explainID); - - - this.cmd("Step"); - this.deleteMatrix(secondMat); - this.deleteMatrix(thirdMat); - this.cmd("Delete", paren1); - this.cmd("Delete", paren2); - this.cmd("Delete", paren3); - this.cmd("Delete", paren4); - this.cmd("Delete", equalID); - this.cmd("Delete", explainID); - - this.moveMatrix(tmpMat, RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + 2* RotateScale3D.MATRIX_MULTIPLY_SPACING, ypos); - - this.cmd("Step"); - - - this.setMatrixAlpha(firstMat, 1); - xpos = RotateScale3D.MATRIX_START_X + 9 * RotateScale3D.MATRIX_ELEM_WIDTH + 2 * RotateScale3D.MATRIX_MULTIPLY_SPACING; - - var transformMatrix = this.createMatrix([["","",""], ["","",""],["","",""]], xpos + RotateScale3D.EQUALS_SPACING, ypos); - - this.cmd("CreateLabel", explainID, "", xpos + RotateScale3D.EQUALS_SPACING, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*3 + 5, 0); - this.cmd("CreateLabel", equalID, "=", xpos + RotateScale3D.EQUALS_SPACING / 2, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*1.5); - - this.multiplyMatrix(firstMat, tmpMat, transformMatrix, explainID); - - this.deleteMatrix(firstMat); - this.deleteMatrix(tmpMat); - this.cmd("Delete", equalID); - this.cmd("Delete", explainID); - - this.moveMatrix(transformMatrix, RotateScale3D.MATRIX_START_X + 3*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING, ypos); - this.cmd("Step"); - - - this.transformPoints(transformMatrix); - - - - - -// this.nextIndex = oldNextIndex - - - this.deleteMatrix(transformMatrix); - - return this.commands; -} - - -RotateScale3D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) -{ - var i; - var j; - var explainText = ""; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat2.data[0].length; j++) - { - var explainText = ""; - var value = 0; - for (k = 0; k < mat2.data.length; k++) - { - this.cmd("SetHighlight", mat1.dataID[i][k], 1); - this.cmd("SetHighlight", mat2.dataID[k][j], 1); - if (explainText != "") - { - explainText = explainText + " + "; - } - value = value + mat1.data[i][k] * mat2.data[k][j]; - explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); - this.cmd("SetText", explainID, explainText); - this.cmd("Step"); - this.cmd("SetHighlight", mat1.dataID[i][k], 0); - this.cmd("SetHighlight", mat2.dataID[k][j], 0); - } - value = this.standardize(value); - explainText += " = " + String(value); - this.cmd("SetText", explainID, explainText); - mat3.data[i][j] = value; - this.cmd("SetText", mat3.dataID[i][j], value); - this.cmd("Step"); - } - } - this.cmd("SetText", explainID, ""); - - -} - -RotateScale3D.prototype.standardize = function(lab) -{ - var newLab = Math.round(lab * 1000) / 1000; - if (isNaN(newLab)) - { - return lab; - } - else - { - return newLab; - } -} - - -RotateScale3D.prototype.resetMatrixLabels = function(mat) -{ - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - mat.data[i][j] = this.standardize(mat.data[i][j]); - this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); - } - } -} - - - -RotateScale3D.prototype.moveMatrix = function(mat, x, y) -{ - var height = mat.data.length; - var width = 0; - - var i, j; - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - } - - - this.cmd("Move", mat.leftBrack1, x, y); - this.cmd("Move", mat.leftBrack2, x, y); - this.cmd("Move", mat.leftBrack3, x, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT); - - this.cmd("Move", mat.rightBrack1, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack2, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack3, x+ width * RotateScale3D.MATRIX_ELEM_WIDTH, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Move", mat.dataID[i][j], - x + j*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateScale3D.MATRIX_ELEM_HEIGHT + RotateScale3D.MATRIX_ELEM_HEIGHT / 2); - } - } -} - -RotateScale3D.prototype.deleteMatrix = function(mat) -{ - this.cmd("Delete",mat.leftBrack1); - this.cmd("Delete",mat.leftBrack2); - this.cmd("Delete",mat.leftBrack3); - this.cmd("Delete",mat.rightBrack1); - this.cmd("Delete",mat.rightBrack2); - this.cmd("Delete",mat.rightBrack3); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Delete", mat.dataID[i][j]); - } - } -} - -RotateScale3D.prototype.setMatrixAlpha = function(mat, alpha) -{ - this.cmd("SetAlpha",mat.leftBrack1, alpha); - this.cmd("SetAlpha",mat.leftBrack2, alpha); - this.cmd("SetAlpha",mat.leftBrack3, alpha); - this.cmd("SetAlpha",mat.rightBrack1, alpha); - this.cmd("SetAlpha",mat.rightBrack2, alpha); - this.cmd("SetAlpha",mat.rightBrack3, alpha); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("SetAlpha", mat.dataID[i][j], alpha); - } - } -} - - - -// Multiply two (data only!) matrices (not complete matrix object with graphics, just -// the data -RotateScale3D.prototype.multiply = function(lhs, rhs) -{ - var resultMat = new Array(lhs.length); - var i, j, k; - - for (i = 0; i < lhs.length; i++) - { - resultMat[i] = new Array(rhs[0].length); - } - for (i = 0; i < lhs.length; i++) - { - for (j = 0; j < rhs[0].length; j++) - { - var value = 0; - for (k = 0; k < rhs.length; k++) - { - value = value + lhs[i][k] * rhs[k][j]; - } - resultMat[i][j] = value; - } - } - return resultMat; -} - - -RotateScale3D.prototype.createMatrix = function(contents, x, y) -{ - var mat = new Matrix(contents, x, y); - mat.leftBrack1 = this.nextIndex++; - mat.leftBrack2 = this.nextIndex++; - mat.leftBrack3 = this.nextIndex++; - mat.rightBrack1 = this.nextIndex++; - mat.rightBrack2 = this.nextIndex++; - mat.rightBrack3 = this.nextIndex++; - - var height = mat.data.length; - var width = 0; - - var i, j; - mat.dataID = new Array(mat.data.length); - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - mat.dataID[i] = new Array(mat.data[i].length); - for (j = 0; j < mat.data[i].length; j++) - { - mat.dataID[i][j] = this.nextIndex++; - } - } - - this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); - this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateScale3D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); - this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT , "left","center"); - - this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y, "right","center"); - this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateScale3D.MATRIX_ELEM_HEIGHT, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y, "center","top"); - this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateScale3D.MATRIX_ELEM_WIDTH, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT , "right","center"); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], - x + j*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateScale3D.MATRIX_ELEM_HEIGHT + RotateScale3D.MATRIX_ELEM_HEIGHT / 2); - } - } - return mat; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new RotateScale3D(animManag, canvas.width, canvas.height); -} - -function Matrix(contents, x, y) -{ - this.data = contents; - this.x = x; - this.y = y; -} - -Matrix.prototype.transpose = function() -{ - var newData = new Array(this.data[0].length); - var i,j; - for (i = 0; i < this.data[0].length; i++) - { - newData[i] = new Array(this.data.length); - } - for (i = 0; i < this.data.length; i++) - { - for (j = 0; j < this.data[i].length; j++) - { - newData[j][i] = this.data[i][j]; - } - } - this.data = newData; -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function RotateScale3D(am, w, h) +{ + this.init(am, w, h); +} + + +RotateScale3D.inheritFrom(Algorithm); + +RotateScale3D.XAxisYPos = 300; +RotateScale3D.XAxisStart = 100; +RotateScale3D.XAxisEnd = 700; + + +RotateScale3D.MATRIX_START_X = 10; +RotateScale3D.MATRIX_START_Y = 10; +RotateScale3D.MATRIX_MULTIPLY_SPACING = 10; +RotateScale3D.EQUALS_SPACING = 30; + +RotateScale3D.AXIS_SIZE = 200; + +RotateScale3D.AXIS_ALPHA = 0.7; + +RotateScale3D.YAxisXPos = 400; +RotateScale3D.YAxisStart = 100; +RotateScale3D.YAxisEnd = 500; + +RotateScale3D.MATRIX_ELEM_WIDTH = 50; +RotateScale3D.MATRIX_ELEM_HEIGHT = 20; + +RotateScale3D.OBJECTS = [ + [[100, 100, 100], [-100, 100,100], [-100,-100,100], [100, -100, 100], + [100, -100, -100], [100, 100, -100], [-100, 100,-100], [-100,-100,-100] + ], // Cube + + [[10, 10, 100], [-10, 10, 100], [-10, 10, -100], [100, 10, -100], [100, 10, -80], [10, 10, -80], + [10, -10, -80],[10, -10, 100], [-10, -10, 100], [-10, -10, -100], [100, -10, -100], [100, -10, -80], + + + ], // L + [[0, 0, 141], [-134, 0, 44], [-83, 0, -114 ], [83, 0, -114], [134, 0, 44]], // Pentagon + [[0, 0, 141], [-35,0, 48],[-134, 0, 44], [-57, 0, -19], [-83, 0, -114 ], [0, 0, -60],[83, 0, -114], [57, 0, -19], [134, 0, 44], [35, 0, 48]] // Star + ]; + +RotateScale3D.EXTRA_CONNECTIONS = [ + [[3, 0], [5,0], [6,1], [7,2], [4,7]], // Cube + [[5, 0], [6, 11], [0,7], [1,8], [2,9],[3,10],[4,11]], // L + [[4,0]], // Pentagon + [[9, 0]] //Star + ] + + +RotateScale3D.CAMERA_Z_ROT = toRadians(-10); +RotateScale3D.CAMERA_X_ROT = toRadians(10); + +RotateScale3D.CAMERA_TRANS_ANGLE = toRadians(30); +RotateScale3D.L = 0.5; + + +RotateScale3D.CAMERA_TRANSFORM = [[1, 0, 0], + [RotateScale3D.L * Math.cos(RotateScale3D.CAMERA_TRANS_ANGLE), 0, RotateScale3D.L * Math.sin(RotateScale3D.CAMERA_TRANS_ANGLE)], + [0, 0, 1]]; + + +RotateScale3D.CAMERA_TRANSFORM2 = [[Math.cos(RotateScale3D.CAMERA_Z_ROT), Math.sin(RotateScale3D.CAMERA_Z_ROT), 0], + [-Math.sin(RotateScale3D.CAMERA_Z_ROT), Math.cos(RotateScale3D.CAMERA_Z_ROT), 0], + [0, 0, 1]]; + +RotateScale3D.CAMERA_TRANSFORM1 = [[1, 0, 0], + [0, Math.cos(RotateScale3D.CAMERA_X_ROT), Math.sin(RotateScale3D.CAMERA_X_ROT)], + [0, -Math.sin(RotateScale3D.CAMERA_X_ROT), Math.cos(RotateScale3D.CAMERA_X_ROT)] + ]; + + + +RotateScale3D.AXIS_COLOR = "#0000FF" +RotateScale3D.VERTEX_FOREGORUND_COLOR = "#000000"; +RotateScale3D.VERTEX_BACKGROUND_COLOR = RotateScale3D.VERTEX_FOREGORUND_COLOR; +RotateScale3D.EDGE_COLOR = "#000000"; + + + +RotateScale3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; +RotateScale3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateScale3D.VERTEX_FOREGORUND_COLOR; +RotateScale3D.TRANSFORMED_EDGE_COLOR = "#66FF66"; + + + + +RotateScale3D.VECTOR_COLOR = "#FF0000"; + +RotateScale3D.VERTEX_WIDTH = 3; +RotateScale3D.VERTEX_HEIGHT = RotateScale3D.VERTEX_WIDTH; + +RotateScale3D.prototype.init = function(am, w, h) +{ + var sc = RotateScale3D.superclass.init.call(this, am, w, h); + this.cameraTransform = RotateScale3D.CAMERA_TRANSFORM; +// this.cameraTransform = this.multiply(RotateScale3D.CAMERA_TRANSFORM1, RotateScale3D.CAMERA_TRANSFORM2); + + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.addControls(); + this.currentShape = 0; + + this.commands = []; + this.nextIndex = 0; + + this.setupAxis(); + + this.savedNextIndex = this.nextIndex; + this.setupObject(); + this.setupObjectGraphic(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); + + +} + +RotateScale3D.prototype.setupAxis = function() +{ + this.xAxisMinID = this.nextIndex++; + this.xAxisMaxID = this.nextIndex++; + this.yAxisMinID = this.nextIndex++; + this.yAxisMaxID = this.nextIndex++; + + this.zAxisMinID = this.nextIndex++; + this.zAxisMaxID = this.nextIndex++; + + + this.xAxisLabel = this.nextIndex++; + this.yAxisLabel = this.nextIndex++; + this.zAxisLabel = this.nextIndex++; + var point; + + + this.originID = this.nextIndex++; + + point = this.worldToScreenSpace([0, 0, 0]); + + this.cmd("CreateRectangle", this.originID, "", 0, 0, point[0], point[1]); + + point = this.worldToScreenSpace([-RotateScale3D.AXIS_SIZE, 0, 0]); + this.cmd("CreateRectangle", this.xAxisMinID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.xAxisMinID, 0); + + point = this.worldToScreenSpace([RotateScale3D.AXIS_SIZE, 0, 0]); + this.cmd("CreateRectangle", this.xAxisMaxID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.xAxisMaxID, 0); + + this.cmd("Connect", this.xAxisMinID, this.xAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.xAxisMaxID, this.xAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + this.cmd("SetEdgeAlpha", this.xAxisMaxID, this.xAxisMinID, RotateScale3D.AXIS_ALPHA); + this.cmd("SetEdgeAlpha", this.xAxisMinID, this.xAxisMaxID, RotateScale3D.AXIS_ALPHA); + + point = this.worldToScreenSpace([0,-RotateScale3D.AXIS_SIZE, 0]); + this.cmd("CreateRectangle", this.yAxisMinID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.yAxisMinID, 0); + + point = this.worldToScreenSpace([0,RotateScale3D.AXIS_SIZE, 0]); + this.cmd("CreateRectangle", this.yAxisMaxID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.yAxisMaxID, 0); + + this.cmd("Connect", this.yAxisMinID, this.yAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.yAxisMaxID, this.yAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + this.cmd("SetEdgeAlpha", this.yAxisMaxID, this.yAxisMinID, RotateScale3D.AXIS_ALPHA); + this.cmd("SetEdgeAlpha", this.yAxisMinID, this.yAxisMaxID, RotateScale3D.AXIS_ALPHA); + + + point = this.worldToScreenSpace([0,0, -RotateScale3D.AXIS_SIZE]); + this.cmd("CreateRectangle", this.zAxisMinID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.zAxisMinID, 0); + + point = this.worldToScreenSpace([0, 0, RotateScale3D.AXIS_SIZE]); + this.cmd("CreateRectangle", this.zAxisMaxID, "", 0, 0, point[0], point[1]); + this.cmd("SetAlpha", this.zAxisMaxID, 0); + + this.cmd("Connect", this.zAxisMinID, this.zAxisMaxID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.zAxisMaxID, this.zAxisMinID, RotateScale3D.AXIS_COLOR, 0, 1, ""); + + this.cmd("SetEdgeAlpha", this.zAxisMaxID, this.zAxisMinID, RotateScale3D.AXIS_ALPHA); + this.cmd("SetEdgeAlpha", this.zAxisMinID, this.zAxisMaxID, RotateScale3D.AXIS_ALPHA); + + + point = this.worldToScreenSpace([RotateScale3D.AXIS_SIZE, 0, -10]); + this.cmd("CreateLabel", this.xAxisLabel, "+x", point[0], point[1]); + + point = this.worldToScreenSpace([+10, RotateScale3D.AXIS_SIZE, 0]); + this.cmd("CreateLabel", this.yAxisLabel, "+y", point[0], point[1]); + + point = this.worldToScreenSpace([+10, 0, RotateScale3D.AXIS_SIZE]); + this.cmd("CreateLabel", this.zAxisLabel, "+z", point[0], point[1]); + + this.cmd("SetForegroundColor", this.yAxisLabel, RotateScale3D.AXIS_COLOR); + this.cmd("SetForegroundColor", this.xAxisLabel, RotateScale3D.AXIS_COLOR); + this.cmd("SetForegroundColor", this.zAxisLabel, RotateScale3D.AXIS_COLOR); +} + + +RotateScale3D.prototype.setupObject = function() +{ + this.objectVertexPosition = RotateScale3D.OBJECTS[this.currentShape].slice(0); + this.extraConnections = RotateScale3D.EXTRA_CONNECTIONS[this.currentShape].slice(0); +} + + +RotateScale3D.prototype.worldToScreenSpace = function(point) +{ + var transformedPoint = this.multiply([point], this.cameraTransform)[0]; + var worldSpace = new Array(2); + worldSpace[0] = transformedPoint[0] + RotateScale3D.YAxisXPos; + worldSpace[1] = RotateScale3D.XAxisYPos - transformedPoint[2]; + + return worldSpace; +} + + + +RotateScale3D.prototype.moveObjectToNewPosition = function() +{ + var i; + for (i = 0; i < this.objectVertexID.length; i++) + { + var point = this.worldToScreenSpace(this.objectVertexPosition[i]); + this.cmd("Move", this.objectVertexID[i], point[0], point[1]); + } + +} + + +RotateScale3D.prototype.setupObjectGraphic = function() +{ + this.objectVertexID = new Array(this.objectVertexPosition.length); + var i; + for (i = 0; i < this.objectVertexPosition.length; i++) + { + this.objectVertexID[i] = this.nextIndex++; + var point = this.worldToScreenSpace(this.objectVertexPosition[i]); + + this.cmd("CreateRectangle", this.objectVertexID[i], "", RotateScale3D.VERTEX_WIDTH, RotateScale3D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", this.objectVertexID[i], RotateScale3D.VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", this.objectVertexID[i], RotateScale3D.VERTEX_BACKGROUND_COLOR); + } + for (i = 1; i < this.objectVertexID.length; i++) + { + this.cmd("Connect", this.objectVertexID[i-1], this.objectVertexID[i], RotateScale3D.EDGE_COLOR, 0, 0, ""); + } + + for (var i = 0; i < this.extraConnections.length; i++) + { + this.cmd("Connect", this.objectVertexID[this.extraConnections[i][0]], this.objectVertexID[this.extraConnections[i][1]], RotateScale3D.EDGE_COLOR, 0, 0, ""); + } + +} + +RotateScale3D.prototype.addControls = function() +{ + this.controls = []; + + this.addLabelToAlgorithmBar("X Angle"); + + this.rotationFieldX = this.addControlToAlgorithmBar("Text", ""); + this.rotationFieldX.onkeydown = this.returnSubmitFloat(this.rotationFieldX, this.rotateCallback.bind(this), 4, true); + this.controls.push(this.rotationFieldX); + + this.addLabelToAlgorithmBar("Y Angle"); + + this.rotationFieldY = this.addControlToAlgorithmBar("Text", ""); + this.rotationFieldY.onkeydown = this.returnSubmitFloat(this.rotationFieldY, this.rotateCallback.bind(this), 4, true); + this.controls.push(this.rotationFieldY); + + this.addLabelToAlgorithmBar("Z Angle"); + + this.rotationFieldZ = this.addControlToAlgorithmBar("Text", ""); + this.rotationFieldZ.onkeydown = this.returnSubmitFloat(this.rotationFieldZ, this.rotateCallback.bind(this), 4, true); + this.controls.push(this.rotationFieldZ); + + + + var rotateButton = this.addControlToAlgorithmBar("Button", "Rotate"); + rotateButton.onclick = this.rotateCallback.bind(this); + + this.controls.push(rotateButton); + + + this.addLabelToAlgorithmBar("Scale X"); + + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); + this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.scaleCallback.bind(this), 4, true); + this.controls.push(this.scaleXField); + + + this.addLabelToAlgorithmBar("Scale Y"); + + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); + this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.scaleCallback.bind(this), 4, true); + this.controls.push(this.scaleYField); + + this.addLabelToAlgorithmBar("Scale Z"); + + this.scaleZField = this.addControlToAlgorithmBar("Text", ""); + this.scaleZField.onkeydown = this.returnSubmitFloat(this.scaleZField, this.scaleCallback.bind(this), 4, true); + this.controls.push(this.scaleZField); + + + + var scaleButton = this.addControlToAlgorithmBar("Button", "Scale"); + scaleButton.onclick = this.scaleCallback.bind(this); + + this.controls.push(scaleButton); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", + "Column Major", + ], + "RankType"); + this.rowMajorButton = radioButtonList[0]; + this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); + this.controls.push(this.rowMajorButton); + + this.colMajorButton = radioButtonList[1]; + this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); + this.controls.push(this.colMajorButton); + + this.rowMajorButton.checked = this.rowMajor; + this.colMajorButton.checked = !this.rowMajor; + + + + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); + changeShapeButton.onclick = this.changeShapeCallback.bind(this); + + this.controls.push(changeShapeButton); + +} + + + + + + +RotateScale3D.prototype.reset = function() +{ + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.currentShape = 0; + this.rowMajorButton.checked = this.rowMajor; + + this.nextIndex = this.savedNextIndex; + this.setupObject(); + this.setupObjectGraphic(); +} + + +RotateScale3D.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +RotateScale3D.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +RotateScale3D.prototype.changePosYCallback = function(posYUp) +{ + if (this.posYUp != posYUp) + { + this.implementAction(this.changePosY.bind(this), posYUp); + } +} + +RotateScale3D.prototype.changePosY = function(posYUp) +{ + this.commands = new Array(); + this.posYUp= posYUp; + if (this.posYUpButton.checked != this.posYUp) + { + this.posYUpButton.checked = this.posYUp; + } + if (this.posYDownButton.checked == this.posYUp) + { + this.posYDownButton.checked = !this.posYUp; + } + if (this.posYUp) + { + this.cmd("Move", this.yAxisLabel, RotateScale3D.YAxisXPos + 10, RotateScale3D.YAxisStart + 10); + } + else + { + this.cmd("Move", this.yAxisLabel, RotateScale3D.YAxisXPos + 10, RotateScale3D.YAxisEnd - 10); + + } + + this.moveObjectToNewPosition(); + + + + + // Move +y on axis up/down + return this.commands; +} + + + +RotateScale3D.prototype.changeRowColMajorCallback = function(rowMajor) +{ + if (this.rowMajor != rowMajor) + { + this.implementAction(this.changeRowCol.bind(this), rowMajor); + } +} + +RotateScale3D.prototype.changeRowCol = function(rowMajor) +{ + this.commands = new Array(); + this.rowMajor= rowMajor; + if (this.rowMajorButton.checked != this.rowMajor) + { + this.rowMajorButton.checked = this.rowMajor; + } + if (this.colMajorButton.checked == this.rowMajor) + { + this.colMajorButton.checked = !this.rowMajor; + } + return this.commands; +} + + +RotateScale3D.prototype.fixNumber = function(value, defaultVal) +{ + if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) + { + value = defaultVal; + } + else + { + value = String(parseFloat(value)); + } + return value +} + +RotateScale3D.prototype.rotateCallback = function() +{ + + + this.rotationFieldX.value = this.fixNumber(this.rotationFieldX.value, "0"); + this.rotationFieldY.value = this.fixNumber(this.rotationFieldY.value, "0"); + this.rotationFieldZ.value = this.fixNumber(this.rotationFieldZ.value, "0"); + this.implementAction(this.rotate.bind(this), this.rotationFieldZ.value + ";" +this.rotationFieldY.value + ";" +this.rotationFieldX.value); + +} +RotateScale3D.prototype.scaleCallback = function() +{ + + + this.scaleXField.value = this.fixNumber(this.scaleXField.value, "1"); + this.scaleYField.value = this.fixNumber(this.scaleYField.value, "1"); + this.scaleZField.value = this.fixNumber(this.scaleZField.value, "1"); + this.implementAction(this.scale.bind(this), this.scaleXField.value + ";" +this.scaleYField.value + ";" +this.scaleZField.value); + +} + + +RotateScale3D.prototype.changeShapeCallback = function() +{ + this.implementAction(this.changeShape.bind(this), 0); +} + +RotateScale3D.prototype.changeShape = function() +{ + this.commands = []; + var i; + for (i = 0; i < this.objectVertexID.length; i++) + { + this.cmd("Delete", this.objectVertexID[i]); + } + this.currentShape++; + if (this.currentShape >= RotateScale3D.OBJECTS.length) + { + this.currentShape = 0; + } + this.setupObject(); + this.setupObjectGraphic(); + return this.commands; +} + +RotateScale3D.prototype.rotateScaleOrderCallback = function(rotateFirst) +{ + if (this.rotateFirst != rotateFirst) + { + this.implementAction(this.rotateScaleOrder.bind(this), rotateFirst); + } +} + + +RotateScale3D.prototype.rotateScaleOrder = function(rotateFirst) +{ + this.commands = new Array(); + this.rotateFirst= rotateFirst; + if (this.rotateScaleButton.checked != this.rotateFirst) + { + this.rotateScaleButton.checked = this.rotateFirst; + } + if (this.scaleRotateButton.checked == this.rotateFirst) + { + this.scaleRotateButton.checked = !this.rotateFirst; + } + return this.commands; +} + + +function toRadians(degrees) +{ + return (degrees * 2 * Math.PI) / 360.0; +} + +RotateScale3D.prototype.scale = function(input) +{ + var oldNextIndex = this.nextIndex; + this.commands = []; + var inputs = input.split(";"); + var scaleX = parseFloat(inputs[0]); + var scaleY = parseFloat(inputs[1]); + var scaleZ = parseFloat(inputs[2]); + + var xpos = RotateScale3D.MATRIX_START_X; + var ypos = RotateScale3D.MATRIX_START_Y; + + xpos += 3 * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; + + + var transformMatrix = this.createMatrix([[scaleX, 0, 0], + [0, scaleY, 0], + [0, 0, scaleZ]], xpos, ypos); + this.transformPoints(transformMatrix); + this.deleteMatrix(transformMatrix); + return this.commands; + +} + + +RotateScale3D.prototype.transformPoints = function(transformMatrix) +{ + var explainID = this.nextIndex++; + var equalID = this.nextIndex++; + var xyz; + + if (this.rowMajor) + { + xyz = this.createMatrix([["x", "y", "z"]], RotateScale3D.MATRIX_START_X, RotateScale3D.MATRIX_START_Y); + this.cmd("CreateLabel", explainID, "", RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, + RotateScale3D.MATRIX_START_Y + 1.5*RotateScale3D.MATRIX_ELEM_HEIGHT, 0); + this.cmd("CreateLabel", equalID, "=", RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING / 2, + RotateScale3D.MATRIX_START_Y + 0.5*RotateScale3D.MATRIX_ELEM_HEIGHT); + + } + else + { + xyz = this.createMatrix([["x"], ["y"], ["z"]], RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING, + RotateScale3D.MATRIX_START_Y); + this.cmd("CreateLabel", explainID, "", RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, + RotateScale3D.MATRIX_START_Y + 3*RotateScale3D.MATRIX_ELEM_HEIGHT + 2, 0); + this.cmd("CreateLabel", equalID, "=", RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2*RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING / 2, + RotateScale3D.MATRIX_START_Y + 1.5*RotateScale3D.MATRIX_ELEM_HEIGHT); + + } + this.cmd("Step"); + + var i; + + var transformedObjectID = new Array(this.objectVertexID.length); + var output; + + for (i = 0; i < this.objectVertexID.length; i++) + { + this.cmd("Connect", this.originID, this.objectVertexID[i], RotateScale3D.VECTOR_COLOR, 0, 1, ""); + if (this.rowMajor) + { + xyz.data = [this.objectVertexPosition[i].slice(0)]; + } + else + { + xyz.data[0][0] = this.objectVertexPosition[i][0]; + xyz.data[1][0] = this.objectVertexPosition[i][1]; + xyz.data[2][0] = this.objectVertexPosition[i][2]; + } + this.resetMatrixLabels(xyz); + this.cmd("Step"); + + + if (this.rowMajor) + { + output = this.createMatrix([["", "", ""]], + RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, + RotateScale3D.MATRIX_START_Y); + this.multiplyMatrix(xyz, transformMatrix, output, explainID); + } + else + { + output = this.createMatrix([[""], [""], [""]], + RotateScale3D.MATRIX_START_X + 7*RotateScale3D.MATRIX_ELEM_WIDTH + 2 * RotateScale3D.MATRIX_MULTIPLY_SPACING + RotateScale3D.EQUALS_SPACING, + RotateScale3D.MATRIX_START_Y); + + this.multiplyMatrix(transformMatrix, xyz, output, explainID); + } + + + transformedObjectID[i] = this.nextIndex++; + var point; + if (this.rowMajor) + { + point = this.worldToScreenSpace(output.data[0]); + } + else + { + point = this.worldToScreenSpace([output.data[0][0], output.data[1][0], output.data[2][0]]); + } + + this.cmd("CreateRectangle", transformedObjectID[i], "", RotateScale3D.VERTEX_WIDTH, RotateScale3D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", transformedObjectID[i], RotateScale3D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", transformedObjectID[i], RotateScale3D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); + this.cmd("Connect", this.originID, transformedObjectID[i], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); + this.cmd("Step"); + this.cmd("Disconnect", this.originID, transformedObjectID[i]); + + if (i > 0) + { + this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + + } + for (var j = 0; j < this.extraConnections.length; j++) + { + if ((this.extraConnections[j][0] == i && this.extraConnections[j][1] < i) || + (this.extraConnections[j][1] == i && this.extraConnections[j][0] < i)) + { + this.cmd("Connect", transformedObjectID[this.extraConnections[j][0]], transformedObjectID[this.extraConnections[j][1]], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + } + + } + + this.cmd("Disconnect", this.originID, this.objectVertexID[i]); + if (this.rowMajor) + { + this.objectVertexPosition[i] = output.data[0]; + } + else + { + this.objectVertexPosition[i][0] = output.data[0][0]; + this.objectVertexPosition[i][1] = output.data[1][0]; + } + this.deleteMatrix(output); + + } + this.cmd("Step"); + + this.cmd("Connect", transformedObjectID[0], transformedObjectID[transformedObjectID.length-1], RotateScale3D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + + this.cmd("Step","B"); + this.moveObjectToNewPosition(); + this.cmd("Step","C"); + + for (i = 0; i < transformedObjectID.length; i++) + { + this.cmd("Delete", transformedObjectID[i]); + } + + + this.deleteMatrix(xyz); + this.cmd("Delete", explainID); + this.cmd("Delete", equalID); + +} + + +RotateScale3D.prototype.rotate = function(input) +{ + var oldNextIndex = this.nextIndex; + this.commands = []; + var inputs = input.split(";"); + var rotateAngle1 = toRadians(parseFloat(inputs[0])); + var rotateAngle2 = toRadians(parseFloat(inputs[1])); + var rotateAngle3 = toRadians(parseFloat(inputs[2])); + + var xpos = RotateScale3D.MATRIX_START_X; + var ypos = RotateScale3D.MATRIX_START_Y; + + xpos += 3 * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; + + + var matrix1Data; + var matrix2Data; + var matrix3Data; + + matrix1Data = [["cos \u0398z", "sin \u0398z", 0], + ["-sin \u0398z", "cos \u0398z", 0], + [ 0, 0, 1]]; + matrix2Data = [["cos \u0398y", 0, "sin \u0398y"], + [0, 1, 0 ], + ["-sin \u0398y", 0, "cos \u0398y"]]; + + matrix3Data = [[1, 0 , 0], + [0, "cos \u0398x", "sin \u0398x"], + [0, "-sin \u0398x", "cos \u0398x"]]; + if (!this.rowMajor) + { + var tmp = matrix1Data; + matrix1Data = matrix3Data; + matrix3Data = tmp; + } + + var firstMat = this.createMatrix(matrix1Data, xpos, ypos); + xpos += firstMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; + + var secondMat = this.createMatrix(matrix2Data, xpos, ypos); + xpos += secondMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING; + + var thirdMat = this.createMatrix(matrix3Data, xpos, ypos); + xpos += secondMat.data[0].length * RotateScale3D.MATRIX_ELEM_WIDTH; + + if (!this.rowMajor) + { + firstMat.transpose(); + secondMat.transpose(); + thirdMat.transpose(); + this.resetMatrixLabels(firstMat); + this.resetMatrixLabels(secondMat); + this.resetMatrixLabels(thirdMat); + + } + + this.cmd("Step"); + + firstMat.data = [["cos " + inputs[0], "sin " +inputs[0], 0], + ["-sin "+ inputs[0], "cos "+ inputs[0], 0], + [ 0, 0, 1]]; + secondMat.data = [["cos " +inputs[1], 0, "sin " +inputs[1]], + [0, 1, 0 ], + ["-sin " +inputs[1], 0, "cos " +inputs[1]]]; + + thirdMat.data = [[1, 0 , 0], + [0, "cos " +inputs[2], "sin " +inputs[2]], + [0, "-sin " +inputs[2], "cos " +inputs[2]]]; + + if (!this.rowMajor) + { + var tmp = firstMat.data; + firstMat.data = thirdMat.data; + thirdMat.data = tmp; + firstMat.transpose(); + secondMat.transpose(); + thirdMat.transpose(); + } + + this.resetMatrixLabels(firstMat); + this.resetMatrixLabels(secondMat); + this.resetMatrixLabels(thirdMat); + + this.cmd("Step"); + + firstMat.data = [[Math.cos(rotateAngle1), Math.sin(rotateAngle1), 0], + [-Math.sin(rotateAngle1), Math.cos(rotateAngle1), 0], + [ 0, 0, 1]]; + secondMat.data = [[Math.cos(rotateAngle2), 0, Math.sin(rotateAngle2)], + [ 0, 1, 0], + [-Math.sin(rotateAngle2), 0, Math.cos(rotateAngle2)]]; + thirdMat.data = [[1, 0, 0], + [0, Math.cos(rotateAngle3), Math.sin(rotateAngle3)], + [0, -Math.sin(rotateAngle3), Math.cos(rotateAngle3)]]; + + if (!this.rowMajor) + { + var tmp = firstMat.data; + firstMat.data = thirdMat.data; + thirdMat.data = tmp; + firstMat.transpose(); + secondMat.transpose(); + thirdMat.transpose(); + } + + this.resetMatrixLabels(firstMat); + this.resetMatrixLabels(secondMat); + this.resetMatrixLabels(thirdMat); + + this.cmd("Step"); + + this.setMatrixAlpha(firstMat, 0.3); + + + var paren1 = this.nextIndex++ + var paren2 = this.nextIndex++ + var paren3 = this.nextIndex++ + var paren4 = this.nextIndex++ + this.cmd("step"); + + var parenX; + parenX = xpos - 6 * RotateScale3D.MATRIX_ELEM_WIDTH - RotateScale3D.MATRIX_MULTIPLY_SPACING - 2; + + this.cmd("CreateRectangle", paren1, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y, "center","center"); + this.cmd("CreateRectangle", paren2, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y + 3*RotateScale3D.MATRIX_ELEM_HEIGHT, "center","center"); + this.cmd("Connect", paren1, paren2, "#000000", 0.2, 0, ""); + + parenX = xpos; + + this.cmd("CreateRectangle", paren3, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y, "center","center"); + this.cmd("CreateRectangle", paren4, "", 0, 0, parenX, RotateScale3D.MATRIX_START_Y+ 3*RotateScale3D.MATRIX_ELEM_HEIGHT, "center","center"); + + this.cmd("Connect", paren3, paren4, "#000000", -0.2, 0 ,""); + + this.cmd("Step"); + var tmpMat = this.createMatrix([["","",""], ["","",""],["","",""]], xpos + RotateScale3D.EQUALS_SPACING, ypos); + + var explainID = this.nextIndex++; + this.cmd("CreateLabel", explainID, "", xpos + RotateScale3D.EQUALS_SPACING, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*3 + 5, 0); + + var equalID = this.nextIndex++; + this.cmd("CreateLabel", equalID, "=", xpos + RotateScale3D.EQUALS_SPACING / 2, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*1.5); + this.multiplyMatrix(secondMat, thirdMat, tmpMat, explainID); + + + this.cmd("Step"); + this.deleteMatrix(secondMat); + this.deleteMatrix(thirdMat); + this.cmd("Delete", paren1); + this.cmd("Delete", paren2); + this.cmd("Delete", paren3); + this.cmd("Delete", paren4); + this.cmd("Delete", equalID); + this.cmd("Delete", explainID); + + this.moveMatrix(tmpMat, RotateScale3D.MATRIX_START_X + 6*RotateScale3D.MATRIX_ELEM_WIDTH + 2* RotateScale3D.MATRIX_MULTIPLY_SPACING, ypos); + + this.cmd("Step"); + + + this.setMatrixAlpha(firstMat, 1); + xpos = RotateScale3D.MATRIX_START_X + 9 * RotateScale3D.MATRIX_ELEM_WIDTH + 2 * RotateScale3D.MATRIX_MULTIPLY_SPACING; + + var transformMatrix = this.createMatrix([["","",""], ["","",""],["","",""]], xpos + RotateScale3D.EQUALS_SPACING, ypos); + + this.cmd("CreateLabel", explainID, "", xpos + RotateScale3D.EQUALS_SPACING, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*3 + 5, 0); + this.cmd("CreateLabel", equalID, "=", xpos + RotateScale3D.EQUALS_SPACING / 2, ypos + RotateScale3D.MATRIX_ELEM_HEIGHT*1.5); + + this.multiplyMatrix(firstMat, tmpMat, transformMatrix, explainID); + + this.deleteMatrix(firstMat); + this.deleteMatrix(tmpMat); + this.cmd("Delete", equalID); + this.cmd("Delete", explainID); + + this.moveMatrix(transformMatrix, RotateScale3D.MATRIX_START_X + 3*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_MULTIPLY_SPACING, ypos); + this.cmd("Step"); + + + this.transformPoints(transformMatrix); + + + + + +// this.nextIndex = oldNextIndex + + + this.deleteMatrix(transformMatrix); + + return this.commands; +} + + +RotateScale3D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) +{ + var i; + var j; + var explainText = ""; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat2.data[0].length; j++) + { + var explainText = ""; + var value = 0; + for (k = 0; k < mat2.data.length; k++) + { + this.cmd("SetHighlight", mat1.dataID[i][k], 1); + this.cmd("SetHighlight", mat2.dataID[k][j], 1); + if (explainText != "") + { + explainText = explainText + " + "; + } + value = value + mat1.data[i][k] * mat2.data[k][j]; + explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); + this.cmd("SetText", explainID, explainText); + this.cmd("Step"); + this.cmd("SetHighlight", mat1.dataID[i][k], 0); + this.cmd("SetHighlight", mat2.dataID[k][j], 0); + } + value = this.standardize(value); + explainText += " = " + String(value); + this.cmd("SetText", explainID, explainText); + mat3.data[i][j] = value; + this.cmd("SetText", mat3.dataID[i][j], value); + this.cmd("Step"); + } + } + this.cmd("SetText", explainID, ""); + + +} + +RotateScale3D.prototype.standardize = function(lab) +{ + var newLab = Math.round(lab * 1000) / 1000; + if (isNaN(newLab)) + { + return lab; + } + else + { + return newLab; + } +} + + +RotateScale3D.prototype.resetMatrixLabels = function(mat) +{ + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + mat.data[i][j] = this.standardize(mat.data[i][j]); + this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); + } + } +} + + + +RotateScale3D.prototype.moveMatrix = function(mat, x, y) +{ + var height = mat.data.length; + var width = 0; + + var i, j; + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + } + + + this.cmd("Move", mat.leftBrack1, x, y); + this.cmd("Move", mat.leftBrack2, x, y); + this.cmd("Move", mat.leftBrack3, x, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT); + + this.cmd("Move", mat.rightBrack1, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack2, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack3, x+ width * RotateScale3D.MATRIX_ELEM_WIDTH, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Move", mat.dataID[i][j], + x + j*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateScale3D.MATRIX_ELEM_HEIGHT + RotateScale3D.MATRIX_ELEM_HEIGHT / 2); + } + } +} + +RotateScale3D.prototype.deleteMatrix = function(mat) +{ + this.cmd("Delete",mat.leftBrack1); + this.cmd("Delete",mat.leftBrack2); + this.cmd("Delete",mat.leftBrack3); + this.cmd("Delete",mat.rightBrack1); + this.cmd("Delete",mat.rightBrack2); + this.cmd("Delete",mat.rightBrack3); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Delete", mat.dataID[i][j]); + } + } +} + +RotateScale3D.prototype.setMatrixAlpha = function(mat, alpha) +{ + this.cmd("SetAlpha",mat.leftBrack1, alpha); + this.cmd("SetAlpha",mat.leftBrack2, alpha); + this.cmd("SetAlpha",mat.leftBrack3, alpha); + this.cmd("SetAlpha",mat.rightBrack1, alpha); + this.cmd("SetAlpha",mat.rightBrack2, alpha); + this.cmd("SetAlpha",mat.rightBrack3, alpha); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("SetAlpha", mat.dataID[i][j], alpha); + } + } +} + + + +// Multiply two (data only!) matrices (not complete matrix object with graphics, just +// the data +RotateScale3D.prototype.multiply = function(lhs, rhs) +{ + var resultMat = new Array(lhs.length); + var i, j, k; + + for (i = 0; i < lhs.length; i++) + { + resultMat[i] = new Array(rhs[0].length); + } + for (i = 0; i < lhs.length; i++) + { + for (j = 0; j < rhs[0].length; j++) + { + var value = 0; + for (k = 0; k < rhs.length; k++) + { + value = value + lhs[i][k] * rhs[k][j]; + } + resultMat[i][j] = value; + } + } + return resultMat; +} + + +RotateScale3D.prototype.createMatrix = function(contents, x, y) +{ + var mat = new Matrix(contents, x, y); + mat.leftBrack1 = this.nextIndex++; + mat.leftBrack2 = this.nextIndex++; + mat.leftBrack3 = this.nextIndex++; + mat.rightBrack1 = this.nextIndex++; + mat.rightBrack2 = this.nextIndex++; + mat.rightBrack3 = this.nextIndex++; + + var height = mat.data.length; + var width = 0; + + var i, j; + mat.dataID = new Array(mat.data.length); + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + mat.dataID[i] = new Array(mat.data[i].length); + for (j = 0; j < mat.data[i].length; j++) + { + mat.dataID[i][j] = this.nextIndex++; + } + } + + this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); + this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateScale3D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); + this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT , "left","center"); + + this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y, "right","center"); + this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateScale3D.MATRIX_ELEM_HEIGHT, x + width * RotateScale3D.MATRIX_ELEM_WIDTH, y, "center","top"); + this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateScale3D.MATRIX_ELEM_WIDTH, y + height * RotateScale3D.MATRIX_ELEM_HEIGHT , "right","center"); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], + x + j*RotateScale3D.MATRIX_ELEM_WIDTH + RotateScale3D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateScale3D.MATRIX_ELEM_HEIGHT + RotateScale3D.MATRIX_ELEM_HEIGHT / 2); + } + } + return mat; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new RotateScale3D(animManag, canvas.width, canvas.height); +} + +function Matrix(contents, x, y) +{ + this.data = contents; + this.x = x; + this.y = y; +} + +Matrix.prototype.transpose = function() +{ + var newData = new Array(this.data[0].length); + var i,j; + for (i = 0; i < this.data[0].length; i++) + { + newData[i] = new Array(this.data.length); + } + for (i = 0; i < this.data.length; i++) + { + for (j = 0; j < this.data[i].length; j++) + { + newData[j][i] = this.data[i][j]; + } + } + this.data = newData; +} + + + diff --git a/AlgorithmLibrary/RotateTranslate2D.js b/AlgorithmLibrary/RotateTranslate2D.js index 5105131..c35773f 100644 --- a/AlgorithmLibrary/RotateTranslate2D.js +++ b/AlgorithmLibrary/RotateTranslate2D.js @@ -1,956 +1,954 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function RotateTranslate2D(am, w, h) -{ - this.init(am, w, h); -} - - -RotateTranslate2D.prototype = new Algorithm(); -RotateTranslate2D.prototype.constructor = RotateTranslate2D; -RotateTranslate2D.superclass = Algorithm.prototype; - -RotateTranslate2D.XAxisYPos = 300; -RotateTranslate2D.XAxisStart = 100; -RotateTranslate2D.XAxisEnd = 700; - -RotateTranslate2D.MATRIX_ELEM_WIDTH = 50; -RotateTranslate2D.MATRIX_ELEM_HEIGHT = 20; - - -RotateTranslate2D.MATRIX_MULTIPLY_SPACING = 10; -RotateTranslate2D.EQUALS_SPACING = 30; -RotateTranslate2D.MATRIX_START_X = 10 + 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING; -RotateTranslate2D.MATRIX_START_Y = 10; - - - -RotateTranslate2D.YAxisXPos = 400; -RotateTranslate2D.YAxisStart = 100; -RotateTranslate2D.YAxisEnd = 500; - - -RotateTranslate2D.OBJECTS = [ - [[100, 100], [-100, 100], [-100,-100], [100, -100]], // Square - [[10, 100], [-10, 100], [-10,-100], [100, -100], [100, -80], [10,-80]], // L - [[0, 141], [-134, 44], [-83, -114 ], [83, -114], [134,44]], // Pentagon - [[0, 141], [-35,48],[-134, 44], [-57, -19], [-83, -114 ], [0, -60],[83,-114], [57, -19], [134,44], [35, 48]], // Star - ] - - -RotateTranslate2D.AXIS_COLOR = "#9999FF" - -RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; -RotateTranslate2D.LOCAL_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR; -RotateTranslate2D.LOCAL_EDGE_COLOR = "#000000"; - -RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; -RotateTranslate2D.GLOBAL_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR; -RotateTranslate2D.GLOBAL_EDGE_COLOR = "#00FF00"; - - - -RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; -RotateTranslate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR; -RotateTranslate2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; - - - - -RotateTranslate2D.VECTOR_COLOR = "#FF0000"; - -RotateTranslate2D.VERTEX_WIDTH = 3; -RotateTranslate2D.VERTEX_HEIGHT = RotateTranslate2D.VERTEX_WIDTH; - -RotateTranslate2D.prototype.init = function(am, w, h) -{ - var sc = RotateTranslate2D.superclass.init.call(this, am, w, h); - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.addControls(); - this.currentShape = 0; - - this.commands = []; - this.nextIndex = 0; - - this.setupAxis(); - - - this.transformMatrix = this.createMatrix([[1, 0, 0], [ 0, 1, 0], [0, 0, 1]], RotateTranslate2D.MATRIX_START_X, RotateTranslate2D.MATRIX_START_Y); - - this.savedNextIndex = this.nextIndex; - this.setupObject(); - this.setupObjectGraphic(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); - - -} - -RotateTranslate2D.prototype.setupAxis = function() -{ - this.xAxisLeft = this.nextIndex++; - this.xAxisRight = this.nextIndex++; - this.yAxisTop = this.nextIndex++; - this.yAxisBottom = this.nextIndex++; - - this.xAxisLabel = this.nextIndex++; - this.yAxisLabel = this.nextIndex++; - - this.originID = this.nextIndex++; - - this.cmd("CreateRectangle", this.originID, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.XAxisYPos); - - - this.cmd("CreateRectangle", this.xAxisLeft, "", 0, 0, RotateTranslate2D.XAxisStart, RotateTranslate2D.XAxisYPos); - this.cmd("SetAlpha", this.xAxisLeft, 0); - this.cmd("CreateRectangle", this.xAxisRight, "", 0, 0, RotateTranslate2D.XAxisEnd, RotateTranslate2D.XAxisYPos); - this.cmd("SetAlpha", this.xAxisRight, 0); - this.cmd("Connect", this.xAxisLeft, this.xAxisRight, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.xAxisRight, this.xAxisLeft, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); - - - this.cmd("CreateRectangle", this.yAxisTop, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.YAxisStart); - this.cmd("SetAlpha", this.yAxisTop, 0); - this.cmd("CreateRectangle", this.yAxisBottom, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.YAxisEnd); - this.cmd("SetAlpha", this.yAxisBottom, 0); - this.cmd("Connect", this.yAxisTop, this.yAxisBottom, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); - this.cmd("Connect", this.yAxisBottom, this.yAxisTop, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); - if (this.posYUp) - { - this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisStart + 10); - } - else - { - this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisEnd - 10); - } - this.cmd("CreateLabel", this.xAxisLabel, "+x", RotateTranslate2D.XAxisEnd - 10, RotateTranslate2D.XAxisYPos - 10); - this.cmd("SetForegroundColor", this.yAxisLabel, RotateTranslate2D.AXIS_COLOR); - this.cmd("SetForegroundColor", this.xAxisLabel, RotateTranslate2D.AXIS_COLOR); -} - - -RotateTranslate2D.prototype.setupObject = function() -{ - var i = 0; - this.objectVertexLocalPosition = new Array(RotateTranslate2D.OBJECTS[this.currentShape].length); - this.objectVertexWorldPosition = new Array(RotateTranslate2D.OBJECTS[this.currentShape].length); - for (i = 0; i < RotateTranslate2D.OBJECTS[this.currentShape].length; i++) - { - this.objectVertexLocalPosition[i] = RotateTranslate2D.OBJECTS[this.currentShape][i].slice(0) - this.objectVertexWorldPosition[i] = RotateTranslate2D.OBJECTS[this.currentShape][i].slice(0); - - } -} - - -RotateTranslate2D.prototype.worldToScreenSpace = function(point) -{ - var transformedPoint = new Array(2); - transformedPoint[0] = point[0] + RotateTranslate2D.YAxisXPos; - if (this.posYUp) - { - transformedPoint[1] = RotateTranslate2D.XAxisYPos - point[1]; - } - else - { - transformedPoint[1] = RotateTranslate2D.XAxisYPos + point[1]; - - } - return transformedPoint; -} - - - - - - - - -RotateTranslate2D.prototype.setupObjectGraphic = function() -{ - var i; - - this.objectVertexLocalID = new Array(this.objectVertexLocalPosition.length); - this.objectVertexWorldID = new Array(this.objectVertexWorldPosition.length); - for (i= 0; i < this.objectVertexLocalPosition.length; i++) - { - this.objectVertexLocalID[i] = this.nextIndex++; - } - for (i= 0; i < this.objectVertexWorldPosition.length; i++) - { - this.objectVertexWorldID[i] = this.nextIndex++; - } - - - var point = this.worldToScreenSpace(this.objectVertexLocalPosition[0]) - var xLocal = point[0]; - var yLocal = point[1]; - point = this.worldToScreenSpace(this.objectVertexWorldPosition[0]) - var xGlobal = point[0]; - var yGlobal = point[1]; - - for (i = 0; i < this.objectVertexLocalPosition.length; i++) - { - point = this.worldToScreenSpace(this.objectVertexLocalPosition[i]); - - xLocal = Math.min(xLocal, point[0]); - yLocal = Math.max(yLocal, point[1]); - - - this.cmd("CreateRectangle", this.objectVertexLocalID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_VERTEX_BACKGROUND_COLOR); - - - - point = this.worldToScreenSpace(this.objectVertexWorldPosition[i]); - - xGlobal = Math.min(xGlobal, point[0]); - yGlobal = Math.min(yGlobal, point[1]); - - this.cmd("CreateRectangle", this.objectVertexWorldID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_VERTEX_BACKGROUND_COLOR); - - } - for (i = 1; i < this.objectVertexLocalID.length; i++) - { - this.cmd("Connect", this.objectVertexLocalID[i-1], this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_EDGE_COLOR, 0, 0, ""); - this.cmd("Connect", this.objectVertexWorldID[i-1], this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_EDGE_COLOR, 0, 0, ""); - } - this.cmd("Connect", this.objectVertexLocalID[this.objectVertexLocalID.length - 1], this.objectVertexLocalID[0], RotateTranslate2D.LOCAL_EDGE_COLOR, 0, 0, ""); - this.cmd("Connect", this.objectVertexWorldID[this.objectVertexWorldID.length - 1], this.objectVertexWorldID[0], RotateTranslate2D.GLOBAL_EDGE_COLOR, 0, 0, ""); - this.localLabelID = this.nextIndex++; - this.globalLabelID = this.nextIndex++; - - - this.cmd("CreateLabel", this.localLabelID, "Local Space", xLocal, yLocal + 2, 0); - this.cmd("SetForegroundColor", this.localLabelID, RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR); - - labelPos = this.worldToScreenSpace([xGlobal, yGlobal]); - - this.cmd("CreateLabel", this.globalLabelID, "World Space", xGlobal, yGlobal - 12, 0); - this.cmd("SetForegroundColor", this.globalLabelID, RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR); - - - -} - -RotateTranslate2D.prototype.addControls = function() -{ - this.controls = []; - - addLabelToAlgorithmBar("Rotation Angle"); - - this.rotationField = this.addControlToAlgorithmBar("Text", ""); - this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.rotationField); - - addLabelToAlgorithmBar("Translate X"); - - this.scaleXField = this.addControlToAlgorithmBar("Text", ""); - this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.scaleXField); - - - addLabelToAlgorithmBar("Translate Y"); - - this.scaleYField = this.addControlToAlgorithmBar("Text", ""); - this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); - this.controls.push(this.scaleYField); - - - var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); - transformButton.onclick = this.transformCallback.bind(this); - - this.controls.push(transformButton); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", - "Column Major", - ], - "RankType"); - this.rowMajorButton = radioButtonList[0]; - this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); - this.controls.push(this.rowMajorButton); - - this.colMajorButton = radioButtonList[1]; - this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); - this.controls.push(this.colMajorButton); - - this.rowMajorButton.checked = this.rowMajor; - this.colMajorButton.checked = !this.rowMajor; - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", - "+y Down", - ], - "yAxisDirection"); - this.posYUpButton = radioButtonList[0]; - this.posYUpButton.onclick = this.changePosYCallback.bind(this, true); - this.controls.push(this.posYUpButton); - - this.posYDownButton = radioButtonList[1]; - this.posYDownButton.onclick = this.changePosYCallback.bind(this, false); - this.controls.push(this.posYDownButton); - - this.posYUpButton.checked = this.posYUp; - this.posYDownButton.checked = !this.posYUp; - - - var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); - changeShapeButton.onclick = this.changeShapeCallback.bind(this); - - this.controls.push(changeShapeButton); - -} - - - - - - -RotateTranslate2D.prototype.reset = function() -{ - this.rowMajor = true; - this.posYUp = true; - this.rotateFirst = true; - this.currentShape = 0; - this.rowMajorButton.checked = this.rowMajor; - this.posYUpButton.checked = this.posYUp; - this.transformMatrix.data = [[1,0,0],[0,1,0],[0,0,1]]; - this.nextIndex = this.savedNextIndex; - this.setupObject(); - this.setupObjectGraphic(); -} - - -RotateTranslate2D.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -RotateTranslate2D.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -RotateTranslate2D.prototype.changePosYCallback = function(posYUp) -{ - if (this.posYUp != posYUp) - { - this.implementAction(this.changePosY.bind(this), posYUp); - } -} - -RotateTranslate2D.prototype.changePosY = function(posYUp) -{ - this.commands = new Array(); - this.posYUp= posYUp; - if (this.posYUpButton.checked != this.posYUp) - { - this.posYUpButton.checked = this.posYUp; - } - if (this.posYDownButton.checked == this.posYUp) - { - this.posYDownButton.checked = !this.posYUp; - } - if (this.posYUp) - { - this.cmd("Move", this.yAxisLabel, RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisStart + 10); - } - else - { - this.cmd("Move", this.yAxisLabel, RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisEnd - 10); - - } - - this.moveObjectToNewPosition(this.objectVertexLocalPosition, this.objectVertexLocalID, this.localLabelID, false); - this.moveObjectToNewPosition(this.objectVertexWorldPosition, this.objectVertexWorldID, this.globalLabelID, true); - - - return this.commands; -} - - -RotateTranslate2D.prototype.moveObjectToNewPosition = function(objectLocations, objectIDs, labelID, top) -{ - var point = this.worldToScreenSpace(objectLocations[0]) - var labelX = point[0]; - var labelY = point[1]; - - for (var i = 0; i < objectLocations.length; i++) - { - point = this.worldToScreenSpace(objectLocations[i]); - this.cmd("Move", objectIDs[i], point[0], point[1]); - - labelX = Math.min(labelX, point[0]); - if (top) - { - labelY = Math.min(labelY, point[1]); - } - else - { - labelY = Math.max(labelY, point[1]); - - } - } - if (top) - { - this.cmd("Move", labelID, labelX, labelY - 12); - } - else - { - this.cmd("Move", labelID, labelX, labelY + 2); - } -} - -RotateTranslate2D.prototype.changeRowColMajorCallback = function(rowMajor) -{ - if (this.rowMajor != rowMajor) - { - this.implementAction(this.changeRowCol.bind(this), rowMajor); - } -} - -RotateTranslate2D.prototype.changeRowCol = function(rowMajor) -{ - this.commands = new Array(); - this.rowMajor= rowMajor; - if (this.rowMajorButton.checked != this.rowMajor) - { - this.rowMajorButton.checked = this.rowMajor; - } - if (this.colMajorButton.checked == this.rowMajor) - { - this.colMajorButton.checked = !this.rowMajor; - } - - this.transformMatrix.transpose(); - this.resetMatrixLabels(this.transformMatrix); - - - return this.commands; -} - - -RotateTranslate2D.prototype.fixNumber = function(value, defaultVal) -{ - if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) - { - value = defaultVal; - } - else - { - value = String(parseFloat(value)); - } - return value -} - -RotateTranslate2D.prototype.transformCallback = function() -{ - - - this.rotationField.value = this.fixNumber(this.rotationField.value, "0"); - this.scaleXField.value = this.fixNumber(this.scaleXField.value, "0"); - this.scaleYField.value = this.fixNumber(this.scaleYField.value, "0"); - this.implementAction(this.transform.bind(this), this.rotationField.value + ";" + this.scaleXField.value + ";" + this.scaleYField.value); - -} - - -RotateTranslate2D.prototype.changeShapeCallback = function() -{ - this.implementAction(this.changeShape.bind(this), 0); -} - -RotateTranslate2D.prototype.changeShape = function() -{ - this.commands = []; - var i; - for (i = 0; i < this.objectVertexLocalID.length; i++) - { - this.cmd("Delete", this.objectVertexLocalID[i]); - this.cmd("Delete", this.objectVertexWorldID[i]); - } - this.cmd("Delete", this.localLabelID); - this.cmd("Delete", this.globalLabelID); - this.currentShape++; - if (this.currentShape >= RotateTranslate2D.OBJECTS.length) - { - this.currentShape = 0; - } - this.transformMatrix.data = [[1,0,0],[0,1,0],[0,0,1]]; - this.resetMatrixLabels(this.transformMatrix); - this.setupObject(); - this.setupObjectGraphic(); - return this.commands; -} - - -function toRadians(degrees) -{ - return (degrees * 2 * Math.PI) / 360.0; -} - -RotateTranslate2D.prototype.transform = function(input) -{ - this.commands = []; - - var inputs = input.split(";"); - var rotateDegree = parseFloat(inputs[0]); - var deltaX = parseFloat(inputs[1]); - var deltaY = parseFloat(inputs[2]); - var rotateRadians = toRadians(rotateDegree); - - - var deltaMatrix; - if (this.rowMajor) - { - deltaMatrix = this.createMatrix([["cos \u0398", "sin \u0398", 0], ["-sin \u0398", "cos \u0398", 0],["\u0394x", "\u0394y", "1"]], - RotateTranslate2D.MATRIX_START_X +3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING, - RotateTranslate2D.MATRIX_START_Y); - } - else - { - deltaMatrix = this.createMatrix([["cos \u0398", "-sin \u0398", "\u0394x"], ["sin \u0398", "cos \u0398", "\u0394y"],[0, 0, 1]], - RotateTranslate2D.MATRIX_START_X -3 * RotateTranslate2D.MATRIX_ELEM_WIDTH - RotateTranslate2D.MATRIX_MULTIPLY_SPACING, - RotateTranslate2D.MATRIX_START_Y); - } - this.cmd("Step"); - - if (this.rowMajor) - { - deltaMatrix.data = [["cos " + inputs[0], "sin " + inputs[0], 0], ["-sin " + inputs[0], "cos " + inputs[0], 0],["\u0394x", "\u0394y", "1"]] - } - else - { - deltaMatrix.data = [["cos " + inputs[0], "-sin " + inputs[0], "\u0394 x"], ["sin " + inputs[0], "cos " + inputs[0], "\u0394y"],[0, 0, 1]]; - } - this.resetMatrixLabels(deltaMatrix); - this.cmd("Step"); - - if (this.rowMajor) - { - deltaMatrix.data = [[Math.cos(rotateRadians), Math.sin(rotateRadians), 0], [-Math.sin(rotateRadians), Math.cos(rotateRadians), 0],[deltaX, deltaY, 1]] - } - else - { - deltaMatrix.data = [[Math.cos(rotateRadians), -Math.sin(rotateRadians), deltaX], [Math.sin(rotateRadians), Math.cos(rotateRadians), deltaY],[0,0, 1]] - } - this.resetMatrixLabels(deltaMatrix); - this.cmd("Step"); - - var equalLabel = this.nextIndex++; - var resultMatrix; - var explainID = this.nextIndex++; - var resultXPos; - - if (this.rowMajor) - { - resultXPos = RotateTranslate2D.MATRIX_START_X +6 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING; - } - else - { - resultXPos = RotateTranslate2D.MATRIX_START_X +3 * RotateTranslate2D.MATRIX_ELEM_WIDTH; - } - resultMatrix = this.createMatrix([["", "", ""],["", "", ""],["", "", ""]], - resultXPos + RotateTranslate2D.EQUALS_SPACING, - RotateTranslate2D.MATRIX_START_Y); - this.cmd("CreateLabel", equalLabel, "=", resultXPos + RotateTranslate2D.EQUALS_SPACING / 2, - RotateTranslate2D.MATRIX_START_Y + 1.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT); - - this.cmd("CreateLabel", explainID, "", resultXPos + RotateTranslate2D.EQUALS_SPACING, RotateTranslate2D.MATRIX_START_Y + 3 * RotateTranslate2D.MATRIX_ELEM_HEIGHT + 5, 0); - - - this.cmd("Step"); // TODO: Remove this? - if (this.rowMajor) - { - this.multiplyMatrix(this.transformMatrix, deltaMatrix, resultMatrix, explainID); - } - else - { - this.multiplyMatrix(deltaMatrix, this.transformMatrix, resultMatrix, explainID); - } - - this.setMatrixAlpha(this.transformMatrix, 0); - this.transformMatrix.data = resultMatrix.data; - this.resetMatrixLabels(this.transformMatrix); - this.moveMatrix(resultMatrix, RotateTranslate2D.MATRIX_START_X, RotateTranslate2D.MATRIX_START_Y); - this.deleteMatrix(deltaMatrix); - this.cmd("Delete", equalLabel); - this.cmd("SetText", explainID, ""); - this.cmd("Step"); - this.deleteMatrix(resultMatrix); - this.setMatrixAlpha(this.transformMatrix, 1); - var i; - - var transformedObjectID = new Array(this.objectVertexLocalPosition.length); - - var xy; - - if (this.rowMajor) - { - xy = this.createMatrix([["x", "y", 1]], RotateTranslate2D.MATRIX_START_X - 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH - RotateTranslate2D.MATRIX_MULTIPLY_SPACING, - RotateTranslate2D.MATRIX_START_Y); - } - else - { - xy = this.createMatrix([["x"], ["y"], [1]], RotateTranslate2D.MATRIX_START_X + 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING, - RotateTranslate2D.MATRIX_START_Y); - - } - this.cmd("Step"); - var equalX; - var equalY; - - if (this.rowMajor) - { - equalX = RotateTranslate2D.MATRIX_START_X + 3*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.EQUALS_SPACING / 2; - equalY = RotateTranslate2D.MATRIX_START_Y + 0.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT; - this.cmd("SetPosition", explainID, equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y + RotateTranslate2D.MATRIX_ELEM_HEIGHT + 10); - } - else - { - equalX = RotateTranslate2D.MATRIX_START_X + 4*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING + RotateTranslate2D.EQUALS_SPACING / 2; - equalY = RotateTranslate2D.MATRIX_START_Y + 1.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT; - this.cmd("SetPosition", explainID, equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y + 3 * RotateTranslate2D.MATRIX_ELEM_HEIGHT + 10); - } - for (i = 0; i < this.objectVertexLocalPosition.length; i++) - { - this.cmd("Connect", this.originID, this.objectVertexLocalID[i], RotateTranslate2D.VECTOR_COLOR, 0, 1, ""); - if (this.rowMajor) - { - xy.data[0][0] = this.objectVertexLocalPosition[i][0]; - xy.data[0][1] = this.objectVertexLocalPosition[i][1]; - xy.data[0][2] = 1; - } - else - { - xy.data[0][0] = this.objectVertexLocalPosition[i][0]; - xy.data[1][0] = this.objectVertexLocalPosition[i][1]; - xy.data[2][0] = 1; - } - this.resetMatrixLabels(xy); - this.cmd("Step"); - - this.cmd("CreateLabel", equalLabel, "=", equalX, equalY); - if (this.rowMajor) - { - output = this.createMatrix([["","", ""]], equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y); - this.multiplyMatrix(xy, this.transformMatrix, output, explainID); - } - else - { - output = this.createMatrix([[""],[""], [""]], equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y) - this.multiplyMatrix(this.transformMatrix, xy, output, explainID); - } - - transformedObjectID[i] = this.nextIndex++; - var point; - if (this.rowMajor) - { - point = this.worldToScreenSpace([output.data[0][0], output.data[0][1]]); - } - else - { - point = this.worldToScreenSpace([output.data[0][0], output.data[1][0]]); - } - - this.cmd("CreateRectangle", transformedObjectID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); - this.cmd("SetForegroundColor", transformedObjectID[i], RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); - this.cmd("SetBackgroundColor", transformedObjectID[i], RotateTranslate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); - this.cmd("Connect", this.originID, transformedObjectID[i], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); - this.cmd("Step"); - this.cmd("Disconnect", this.originID, transformedObjectID[i]); - - if (i > 0) - { - this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - } - - this.cmd("Disconnect", this.originID, this.objectVertexLocalID[i]); - if (this.rowMajor) - { - this.objectVertexWorldPosition[i][0] = output.data[0][0]; - this.objectVertexWorldPosition[i][1] = output.data[0][1]; - } - else - { - this.objectVertexWorldPosition[i][0] = output.data[0][0]; - this.objectVertexWorldPosition[i][1] = output.data[1][0]; - } - this.cmd("Delete", equalLabel); - this.deleteMatrix(output); - } - this.cmd("Step"); - this.cmd("Connect", transformedObjectID[transformedObjectID.length-1], transformedObjectID[0], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); - - this.cmd("Step","B"); - this.moveObjectToNewPosition(this.objectVertexWorldPosition, this.objectVertexWorldID, this.globalLabelID, true); - this.cmd("Step"); - - for (i = 0; i < transformedObjectID.length; i++) - { - this.cmd("Delete", transformedObjectID[i]); - } - - - this.deleteMatrix(xy); - return this.commands; -} - - -RotateTranslate2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) -{ - var i; - var j; - var explainText = ""; - for (i = 0; i < mat1.data.length; i++) - { - for (j = 0; j < mat2.data[0].length; j++) - { - var explainText = ""; - var value = 0; - for (k = 0; k < mat2.data.length; k++) - { - this.cmd("SetHighlight", mat1.dataID[i][k], 1); - this.cmd("SetHighlight", mat2.dataID[k][j], 1); - if (explainText != "") - { - explainText = explainText + " + "; - } - value = value + mat1.data[i][k] * mat2.data[k][j]; - explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); - this.cmd("SetText", explainID, explainText); - this.cmd("Step"); - this.cmd("SetHighlight", mat1.dataID[i][k], 0); - this.cmd("SetHighlight", mat2.dataID[k][j], 0); - } - value = this.standardize(value); - explainText += " = " + String(value); - this.cmd("SetText", explainID, explainText); - mat3.data[i][j] = value; - this.cmd("SetText", mat3.dataID[i][j], value); - this.cmd("Step"); - } - } - this.cmd("SetText", explainID, ""); - - -} - -RotateTranslate2D.prototype.standardize = function(lab) -{ - var newLab = Math.round(lab * 1000) / 1000; - if (isNaN(newLab)) - { - return lab; - } - else - { - return newLab; - } -} - - -RotateTranslate2D.prototype.resetMatrixLabels = function(mat) -{ - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - mat.data[i][j] = this.standardize(mat.data[i][j]); - this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); - } - } -} - - - -RotateTranslate2D.prototype.moveMatrix = function(mat, x, y) -{ - var height = mat.data.length; - var width = 0; - - var i, j; - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - } - - - this.cmd("Move", mat.leftBrack1, x, y); - this.cmd("Move", mat.leftBrack2, x, y); - this.cmd("Move", mat.leftBrack3, x, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT); - - this.cmd("Move", mat.rightBrack1, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack2, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y); - this.cmd("Move", mat.rightBrack3, x+ width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Move", mat.dataID[i][j], - x + j*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateTranslate2D.MATRIX_ELEM_HEIGHT + RotateTranslate2D.MATRIX_ELEM_HEIGHT / 2); - } - } -} - -RotateTranslate2D.prototype.deleteMatrix = function(mat) -{ - this.cmd("Delete",mat.leftBrack1); - this.cmd("Delete",mat.leftBrack2); - this.cmd("Delete",mat.leftBrack3); - this.cmd("Delete",mat.rightBrack1); - this.cmd("Delete",mat.rightBrack2); - this.cmd("Delete",mat.rightBrack3); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("Delete", mat.dataID[i][j]); - } - } -} - -RotateTranslate2D.prototype.setMatrixAlpha = function(mat, alpha) -{ - this.cmd("SetAlpha",mat.leftBrack1, alpha); - this.cmd("SetAlpha",mat.leftBrack2, alpha); - this.cmd("SetAlpha",mat.leftBrack3, alpha); - this.cmd("SetAlpha",mat.rightBrack1, alpha); - this.cmd("SetAlpha",mat.rightBrack2, alpha); - this.cmd("SetAlpha",mat.rightBrack3, alpha); - var i,j; - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("SetAlpha", mat.dataID[i][j], alpha); - } - } -} - - -RotateTranslate2D.prototype.createMatrix = function(contents, x, y) -{ - var mat = new Matrix(contents, x, y); - mat.leftBrack1 = this.nextIndex++; - mat.leftBrack2 = this.nextIndex++; - mat.leftBrack3 = this.nextIndex++; - mat.rightBrack1 = this.nextIndex++; - mat.rightBrack2 = this.nextIndex++; - mat.rightBrack3 = this.nextIndex++; - - var height = mat.data.length; - var width = 0; - - var i, j; - mat.dataID = new Array(mat.data.length); - for (i = 0; i < mat.data.length; i++) - { - width = Math.max(width, mat.data[i].length); - mat.dataID[i] = new Array(mat.data[i].length); - for (j = 0; j < mat.data[i].length; j++) - { - mat.dataID[i][j] = this.nextIndex++; - } - } - - this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); - this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateTranslate2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); - this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT , "left","center"); - - this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y, "right","center"); - this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateTranslate2D.MATRIX_ELEM_HEIGHT, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y, "center","top"); - this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT , "right","center"); - - for (i = 0; i < mat.data.length; i++) - { - for (j = 0; j < mat.data[i].length; j++) - { - this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], - x + j*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_ELEM_WIDTH / 2, - y + i*RotateTranslate2D.MATRIX_ELEM_HEIGHT + RotateTranslate2D.MATRIX_ELEM_HEIGHT / 2); - } - } - return mat; -} - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new RotateTranslate2D(animManag, canvas.width, canvas.height); -} - -function Matrix(contents, x, y) -{ - this.data = contents; - this.x = x; - this.y = y; -} - -Matrix.prototype.transpose = function() -{ - var newData = new Array(this.data[0].length); - var i,j; - for (i = 0; i < this.data[0].length; i++) - { - newData[i] = new Array(this.data.length); - } - for (i = 0; i < this.data.length; i++) - { - for (j = 0; j < this.data[i].length; j++) - { - newData[j][i] = this.data[i][j]; - } - } - this.data = newData; -} - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function RotateTranslate2D(am, w, h) +{ + this.init(am, w, h); +} + + +RotateTranslate2D.inheritFrom(Algorithm); + +RotateTranslate2D.XAxisYPos = 300; +RotateTranslate2D.XAxisStart = 100; +RotateTranslate2D.XAxisEnd = 700; + +RotateTranslate2D.MATRIX_ELEM_WIDTH = 50; +RotateTranslate2D.MATRIX_ELEM_HEIGHT = 20; + + +RotateTranslate2D.MATRIX_MULTIPLY_SPACING = 10; +RotateTranslate2D.EQUALS_SPACING = 30; +RotateTranslate2D.MATRIX_START_X = 10 + 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING; +RotateTranslate2D.MATRIX_START_Y = 10; + + + +RotateTranslate2D.YAxisXPos = 400; +RotateTranslate2D.YAxisStart = 100; +RotateTranslate2D.YAxisEnd = 500; + + +RotateTranslate2D.OBJECTS = [ + [[100, 100], [-100, 100], [-100,-100], [100, -100]], // Square + [[10, 100], [-10, 100], [-10,-100], [100, -100], [100, -80], [10,-80]], // L + [[0, 141], [-134, 44], [-83, -114 ], [83, -114], [134,44]], // Pentagon + [[0, 141], [-35,48],[-134, 44], [-57, -19], [-83, -114 ], [0, -60],[83,-114], [57, -19], [134,44], [35, 48]], // Star + ] + + +RotateTranslate2D.AXIS_COLOR = "#9999FF" + +RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR = "#000000"; +RotateTranslate2D.LOCAL_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR; +RotateTranslate2D.LOCAL_EDGE_COLOR = "#000000"; + +RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR = "#00FF00"; +RotateTranslate2D.GLOBAL_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR; +RotateTranslate2D.GLOBAL_EDGE_COLOR = "#00FF00"; + + + +RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR = "#66FF66"; +RotateTranslate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR = RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR; +RotateTranslate2D.TRANSFORMED_EDGE_COLOR = "#66FF66"; + + + + +RotateTranslate2D.VECTOR_COLOR = "#FF0000"; + +RotateTranslate2D.VERTEX_WIDTH = 3; +RotateTranslate2D.VERTEX_HEIGHT = RotateTranslate2D.VERTEX_WIDTH; + +RotateTranslate2D.prototype.init = function(am, w, h) +{ + var sc = RotateTranslate2D.superclass.init.call(this, am, w, h); + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.addControls(); + this.currentShape = 0; + + this.commands = []; + this.nextIndex = 0; + + this.setupAxis(); + + + this.transformMatrix = this.createMatrix([[1, 0, 0], [ 0, 1, 0], [0, 0, 1]], RotateTranslate2D.MATRIX_START_X, RotateTranslate2D.MATRIX_START_Y); + + this.savedNextIndex = this.nextIndex; + this.setupObject(); + this.setupObjectGraphic(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); + + +} + +RotateTranslate2D.prototype.setupAxis = function() +{ + this.xAxisLeft = this.nextIndex++; + this.xAxisRight = this.nextIndex++; + this.yAxisTop = this.nextIndex++; + this.yAxisBottom = this.nextIndex++; + + this.xAxisLabel = this.nextIndex++; + this.yAxisLabel = this.nextIndex++; + + this.originID = this.nextIndex++; + + this.cmd("CreateRectangle", this.originID, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.XAxisYPos); + + + this.cmd("CreateRectangle", this.xAxisLeft, "", 0, 0, RotateTranslate2D.XAxisStart, RotateTranslate2D.XAxisYPos); + this.cmd("SetAlpha", this.xAxisLeft, 0); + this.cmd("CreateRectangle", this.xAxisRight, "", 0, 0, RotateTranslate2D.XAxisEnd, RotateTranslate2D.XAxisYPos); + this.cmd("SetAlpha", this.xAxisRight, 0); + this.cmd("Connect", this.xAxisLeft, this.xAxisRight, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.xAxisRight, this.xAxisLeft, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); + + + this.cmd("CreateRectangle", this.yAxisTop, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.YAxisStart); + this.cmd("SetAlpha", this.yAxisTop, 0); + this.cmd("CreateRectangle", this.yAxisBottom, "", 0, 0, RotateTranslate2D.YAxisXPos, RotateTranslate2D.YAxisEnd); + this.cmd("SetAlpha", this.yAxisBottom, 0); + this.cmd("Connect", this.yAxisTop, this.yAxisBottom, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); + this.cmd("Connect", this.yAxisBottom, this.yAxisTop, RotateTranslate2D.AXIS_COLOR, 0, 1, ""); + if (this.posYUp) + { + this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisStart + 10); + } + else + { + this.cmd("CreateLabel", this.yAxisLabel, "+y", RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisEnd - 10); + } + this.cmd("CreateLabel", this.xAxisLabel, "+x", RotateTranslate2D.XAxisEnd - 10, RotateTranslate2D.XAxisYPos - 10); + this.cmd("SetForegroundColor", this.yAxisLabel, RotateTranslate2D.AXIS_COLOR); + this.cmd("SetForegroundColor", this.xAxisLabel, RotateTranslate2D.AXIS_COLOR); +} + + +RotateTranslate2D.prototype.setupObject = function() +{ + var i = 0; + this.objectVertexLocalPosition = new Array(RotateTranslate2D.OBJECTS[this.currentShape].length); + this.objectVertexWorldPosition = new Array(RotateTranslate2D.OBJECTS[this.currentShape].length); + for (i = 0; i < RotateTranslate2D.OBJECTS[this.currentShape].length; i++) + { + this.objectVertexLocalPosition[i] = RotateTranslate2D.OBJECTS[this.currentShape][i].slice(0) + this.objectVertexWorldPosition[i] = RotateTranslate2D.OBJECTS[this.currentShape][i].slice(0); + + } +} + + +RotateTranslate2D.prototype.worldToScreenSpace = function(point) +{ + var transformedPoint = new Array(2); + transformedPoint[0] = point[0] + RotateTranslate2D.YAxisXPos; + if (this.posYUp) + { + transformedPoint[1] = RotateTranslate2D.XAxisYPos - point[1]; + } + else + { + transformedPoint[1] = RotateTranslate2D.XAxisYPos + point[1]; + + } + return transformedPoint; +} + + + + + + + + +RotateTranslate2D.prototype.setupObjectGraphic = function() +{ + var i; + + this.objectVertexLocalID = new Array(this.objectVertexLocalPosition.length); + this.objectVertexWorldID = new Array(this.objectVertexWorldPosition.length); + for (i= 0; i < this.objectVertexLocalPosition.length; i++) + { + this.objectVertexLocalID[i] = this.nextIndex++; + } + for (i= 0; i < this.objectVertexWorldPosition.length; i++) + { + this.objectVertexWorldID[i] = this.nextIndex++; + } + + + var point = this.worldToScreenSpace(this.objectVertexLocalPosition[0]) + var xLocal = point[0]; + var yLocal = point[1]; + point = this.worldToScreenSpace(this.objectVertexWorldPosition[0]) + var xGlobal = point[0]; + var yGlobal = point[1]; + + for (i = 0; i < this.objectVertexLocalPosition.length; i++) + { + point = this.worldToScreenSpace(this.objectVertexLocalPosition[i]); + + xLocal = Math.min(xLocal, point[0]); + yLocal = Math.max(yLocal, point[1]); + + + this.cmd("CreateRectangle", this.objectVertexLocalID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_VERTEX_BACKGROUND_COLOR); + + + + point = this.worldToScreenSpace(this.objectVertexWorldPosition[i]); + + xGlobal = Math.min(xGlobal, point[0]); + yGlobal = Math.min(yGlobal, point[1]); + + this.cmd("CreateRectangle", this.objectVertexWorldID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_VERTEX_BACKGROUND_COLOR); + + } + for (i = 1; i < this.objectVertexLocalID.length; i++) + { + this.cmd("Connect", this.objectVertexLocalID[i-1], this.objectVertexLocalID[i], RotateTranslate2D.LOCAL_EDGE_COLOR, 0, 0, ""); + this.cmd("Connect", this.objectVertexWorldID[i-1], this.objectVertexWorldID[i], RotateTranslate2D.GLOBAL_EDGE_COLOR, 0, 0, ""); + } + this.cmd("Connect", this.objectVertexLocalID[this.objectVertexLocalID.length - 1], this.objectVertexLocalID[0], RotateTranslate2D.LOCAL_EDGE_COLOR, 0, 0, ""); + this.cmd("Connect", this.objectVertexWorldID[this.objectVertexWorldID.length - 1], this.objectVertexWorldID[0], RotateTranslate2D.GLOBAL_EDGE_COLOR, 0, 0, ""); + this.localLabelID = this.nextIndex++; + this.globalLabelID = this.nextIndex++; + + + this.cmd("CreateLabel", this.localLabelID, "Local Space", xLocal, yLocal + 2, 0); + this.cmd("SetForegroundColor", this.localLabelID, RotateTranslate2D.LOCAL_VERTEX_FOREGORUND_COLOR); + + labelPos = this.worldToScreenSpace([xGlobal, yGlobal]); + + this.cmd("CreateLabel", this.globalLabelID, "World Space", xGlobal, yGlobal - 12, 0); + this.cmd("SetForegroundColor", this.globalLabelID, RotateTranslate2D.GLOBAL_VERTEX_FOREGORUND_COLOR); + + + +} + +RotateTranslate2D.prototype.addControls = function() +{ + this.controls = []; + + this.addLabelToAlgorithmBar("Rotation Angle"); + + this.rotationField = this.addControlToAlgorithmBar("Text", ""); + this.rotationField.onkeydown = this.returnSubmitFloat(this.rotationField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.rotationField); + + this.addLabelToAlgorithmBar("Translate X"); + + this.scaleXField = this.addControlToAlgorithmBar("Text", ""); + this.scaleXField.onkeydown = this.returnSubmitFloat(this.scaleXField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.scaleXField); + + + this.addLabelToAlgorithmBar("Translate Y"); + + this.scaleYField = this.addControlToAlgorithmBar("Text", ""); + this.scaleYField.onkeydown = this.returnSubmitFloat(this.scaleYField, this.transformCallback.bind(this), 4, true); + this.controls.push(this.scaleYField); + + + var transformButton = this.addControlToAlgorithmBar("Button", "Transform"); + transformButton.onclick = this.transformCallback.bind(this); + + this.controls.push(transformButton); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Row Major", + "Column Major", + ], + "RankType"); + this.rowMajorButton = radioButtonList[0]; + this.rowMajorButton.onclick = this.changeRowColMajorCallback.bind(this, true); + this.controls.push(this.rowMajorButton); + + this.colMajorButton = radioButtonList[1]; + this.colMajorButton.onclick = this.changeRowColMajorCallback.bind(this, false); + this.controls.push(this.colMajorButton); + + this.rowMajorButton.checked = this.rowMajor; + this.colMajorButton.checked = !this.rowMajor; + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["+y Up", + "+y Down", + ], + "yAxisDirection"); + this.posYUpButton = radioButtonList[0]; + this.posYUpButton.onclick = this.changePosYCallback.bind(this, true); + this.controls.push(this.posYUpButton); + + this.posYDownButton = radioButtonList[1]; + this.posYDownButton.onclick = this.changePosYCallback.bind(this, false); + this.controls.push(this.posYDownButton); + + this.posYUpButton.checked = this.posYUp; + this.posYDownButton.checked = !this.posYUp; + + + var changeShapeButton = this.addControlToAlgorithmBar("Button", "Change Shape"); + changeShapeButton.onclick = this.changeShapeCallback.bind(this); + + this.controls.push(changeShapeButton); + +} + + + + + + +RotateTranslate2D.prototype.reset = function() +{ + this.rowMajor = true; + this.posYUp = true; + this.rotateFirst = true; + this.currentShape = 0; + this.rowMajorButton.checked = this.rowMajor; + this.posYUpButton.checked = this.posYUp; + this.transformMatrix.data = [[1,0,0],[0,1,0],[0,0,1]]; + this.nextIndex = this.savedNextIndex; + this.setupObject(); + this.setupObjectGraphic(); +} + + +RotateTranslate2D.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +RotateTranslate2D.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +RotateTranslate2D.prototype.changePosYCallback = function(posYUp) +{ + if (this.posYUp != posYUp) + { + this.implementAction(this.changePosY.bind(this), posYUp); + } +} + +RotateTranslate2D.prototype.changePosY = function(posYUp) +{ + this.commands = new Array(); + this.posYUp= posYUp; + if (this.posYUpButton.checked != this.posYUp) + { + this.posYUpButton.checked = this.posYUp; + } + if (this.posYDownButton.checked == this.posYUp) + { + this.posYDownButton.checked = !this.posYUp; + } + if (this.posYUp) + { + this.cmd("Move", this.yAxisLabel, RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisStart + 10); + } + else + { + this.cmd("Move", this.yAxisLabel, RotateTranslate2D.YAxisXPos + 10, RotateTranslate2D.YAxisEnd - 10); + + } + + this.moveObjectToNewPosition(this.objectVertexLocalPosition, this.objectVertexLocalID, this.localLabelID, false); + this.moveObjectToNewPosition(this.objectVertexWorldPosition, this.objectVertexWorldID, this.globalLabelID, true); + + + return this.commands; +} + + +RotateTranslate2D.prototype.moveObjectToNewPosition = function(objectLocations, objectIDs, labelID, top) +{ + var point = this.worldToScreenSpace(objectLocations[0]) + var labelX = point[0]; + var labelY = point[1]; + + for (var i = 0; i < objectLocations.length; i++) + { + point = this.worldToScreenSpace(objectLocations[i]); + this.cmd("Move", objectIDs[i], point[0], point[1]); + + labelX = Math.min(labelX, point[0]); + if (top) + { + labelY = Math.min(labelY, point[1]); + } + else + { + labelY = Math.max(labelY, point[1]); + + } + } + if (top) + { + this.cmd("Move", labelID, labelX, labelY - 12); + } + else + { + this.cmd("Move", labelID, labelX, labelY + 2); + } +} + +RotateTranslate2D.prototype.changeRowColMajorCallback = function(rowMajor) +{ + if (this.rowMajor != rowMajor) + { + this.implementAction(this.changeRowCol.bind(this), rowMajor); + } +} + +RotateTranslate2D.prototype.changeRowCol = function(rowMajor) +{ + this.commands = new Array(); + this.rowMajor= rowMajor; + if (this.rowMajorButton.checked != this.rowMajor) + { + this.rowMajorButton.checked = this.rowMajor; + } + if (this.colMajorButton.checked == this.rowMajor) + { + this.colMajorButton.checked = !this.rowMajor; + } + + this.transformMatrix.transpose(); + this.resetMatrixLabels(this.transformMatrix); + + + return this.commands; +} + + +RotateTranslate2D.prototype.fixNumber = function(value, defaultVal) +{ + if (value == "" || value == "-" || value == "." || value == "-." || isNaN(parseFloat(value))) + { + value = defaultVal; + } + else + { + value = String(parseFloat(value)); + } + return value +} + +RotateTranslate2D.prototype.transformCallback = function() +{ + + + this.rotationField.value = this.fixNumber(this.rotationField.value, "0"); + this.scaleXField.value = this.fixNumber(this.scaleXField.value, "0"); + this.scaleYField.value = this.fixNumber(this.scaleYField.value, "0"); + this.implementAction(this.transform.bind(this), this.rotationField.value + ";" + this.scaleXField.value + ";" + this.scaleYField.value); + +} + + +RotateTranslate2D.prototype.changeShapeCallback = function() +{ + this.implementAction(this.changeShape.bind(this), 0); +} + +RotateTranslate2D.prototype.changeShape = function() +{ + this.commands = []; + var i; + for (i = 0; i < this.objectVertexLocalID.length; i++) + { + this.cmd("Delete", this.objectVertexLocalID[i]); + this.cmd("Delete", this.objectVertexWorldID[i]); + } + this.cmd("Delete", this.localLabelID); + this.cmd("Delete", this.globalLabelID); + this.currentShape++; + if (this.currentShape >= RotateTranslate2D.OBJECTS.length) + { + this.currentShape = 0; + } + this.transformMatrix.data = [[1,0,0],[0,1,0],[0,0,1]]; + this.resetMatrixLabels(this.transformMatrix); + this.setupObject(); + this.setupObjectGraphic(); + return this.commands; +} + + +function toRadians(degrees) +{ + return (degrees * 2 * Math.PI) / 360.0; +} + +RotateTranslate2D.prototype.transform = function(input) +{ + this.commands = []; + + var inputs = input.split(";"); + var rotateDegree = parseFloat(inputs[0]); + var deltaX = parseFloat(inputs[1]); + var deltaY = parseFloat(inputs[2]); + var rotateRadians = toRadians(rotateDegree); + + + var deltaMatrix; + if (this.rowMajor) + { + deltaMatrix = this.createMatrix([["cos \u0398", "sin \u0398", 0], ["-sin \u0398", "cos \u0398", 0],["\u0394x", "\u0394y", "1"]], + RotateTranslate2D.MATRIX_START_X +3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING, + RotateTranslate2D.MATRIX_START_Y); + } + else + { + deltaMatrix = this.createMatrix([["cos \u0398", "-sin \u0398", "\u0394x"], ["sin \u0398", "cos \u0398", "\u0394y"],[0, 0, 1]], + RotateTranslate2D.MATRIX_START_X -3 * RotateTranslate2D.MATRIX_ELEM_WIDTH - RotateTranslate2D.MATRIX_MULTIPLY_SPACING, + RotateTranslate2D.MATRIX_START_Y); + } + this.cmd("Step"); + + if (this.rowMajor) + { + deltaMatrix.data = [["cos " + inputs[0], "sin " + inputs[0], 0], ["-sin " + inputs[0], "cos " + inputs[0], 0],["\u0394x", "\u0394y", "1"]] + } + else + { + deltaMatrix.data = [["cos " + inputs[0], "-sin " + inputs[0], "\u0394 x"], ["sin " + inputs[0], "cos " + inputs[0], "\u0394y"],[0, 0, 1]]; + } + this.resetMatrixLabels(deltaMatrix); + this.cmd("Step"); + + if (this.rowMajor) + { + deltaMatrix.data = [[Math.cos(rotateRadians), Math.sin(rotateRadians), 0], [-Math.sin(rotateRadians), Math.cos(rotateRadians), 0],[deltaX, deltaY, 1]] + } + else + { + deltaMatrix.data = [[Math.cos(rotateRadians), -Math.sin(rotateRadians), deltaX], [Math.sin(rotateRadians), Math.cos(rotateRadians), deltaY],[0,0, 1]] + } + this.resetMatrixLabels(deltaMatrix); + this.cmd("Step"); + + var equalLabel = this.nextIndex++; + var resultMatrix; + var explainID = this.nextIndex++; + var resultXPos; + + if (this.rowMajor) + { + resultXPos = RotateTranslate2D.MATRIX_START_X +6 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING; + } + else + { + resultXPos = RotateTranslate2D.MATRIX_START_X +3 * RotateTranslate2D.MATRIX_ELEM_WIDTH; + } + resultMatrix = this.createMatrix([["", "", ""],["", "", ""],["", "", ""]], + resultXPos + RotateTranslate2D.EQUALS_SPACING, + RotateTranslate2D.MATRIX_START_Y); + this.cmd("CreateLabel", equalLabel, "=", resultXPos + RotateTranslate2D.EQUALS_SPACING / 2, + RotateTranslate2D.MATRIX_START_Y + 1.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT); + + this.cmd("CreateLabel", explainID, "", resultXPos + RotateTranslate2D.EQUALS_SPACING, RotateTranslate2D.MATRIX_START_Y + 3 * RotateTranslate2D.MATRIX_ELEM_HEIGHT + 5, 0); + + + this.cmd("Step"); // TODO: Remove this? + if (this.rowMajor) + { + this.multiplyMatrix(this.transformMatrix, deltaMatrix, resultMatrix, explainID); + } + else + { + this.multiplyMatrix(deltaMatrix, this.transformMatrix, resultMatrix, explainID); + } + + this.setMatrixAlpha(this.transformMatrix, 0); + this.transformMatrix.data = resultMatrix.data; + this.resetMatrixLabels(this.transformMatrix); + this.moveMatrix(resultMatrix, RotateTranslate2D.MATRIX_START_X, RotateTranslate2D.MATRIX_START_Y); + this.deleteMatrix(deltaMatrix); + this.cmd("Delete", equalLabel); + this.cmd("SetText", explainID, ""); + this.cmd("Step"); + this.deleteMatrix(resultMatrix); + this.setMatrixAlpha(this.transformMatrix, 1); + var i; + + var transformedObjectID = new Array(this.objectVertexLocalPosition.length); + + var xy; + + if (this.rowMajor) + { + xy = this.createMatrix([["x", "y", 1]], RotateTranslate2D.MATRIX_START_X - 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH - RotateTranslate2D.MATRIX_MULTIPLY_SPACING, + RotateTranslate2D.MATRIX_START_Y); + } + else + { + xy = this.createMatrix([["x"], ["y"], [1]], RotateTranslate2D.MATRIX_START_X + 3 * RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING, + RotateTranslate2D.MATRIX_START_Y); + + } + this.cmd("Step"); + var equalX; + var equalY; + + if (this.rowMajor) + { + equalX = RotateTranslate2D.MATRIX_START_X + 3*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.EQUALS_SPACING / 2; + equalY = RotateTranslate2D.MATRIX_START_Y + 0.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT; + this.cmd("SetPosition", explainID, equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y + RotateTranslate2D.MATRIX_ELEM_HEIGHT + 10); + } + else + { + equalX = RotateTranslate2D.MATRIX_START_X + 4*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_MULTIPLY_SPACING + RotateTranslate2D.EQUALS_SPACING / 2; + equalY = RotateTranslate2D.MATRIX_START_Y + 1.5 * RotateTranslate2D.MATRIX_ELEM_HEIGHT; + this.cmd("SetPosition", explainID, equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y + 3 * RotateTranslate2D.MATRIX_ELEM_HEIGHT + 10); + } + for (i = 0; i < this.objectVertexLocalPosition.length; i++) + { + this.cmd("Connect", this.originID, this.objectVertexLocalID[i], RotateTranslate2D.VECTOR_COLOR, 0, 1, ""); + if (this.rowMajor) + { + xy.data[0][0] = this.objectVertexLocalPosition[i][0]; + xy.data[0][1] = this.objectVertexLocalPosition[i][1]; + xy.data[0][2] = 1; + } + else + { + xy.data[0][0] = this.objectVertexLocalPosition[i][0]; + xy.data[1][0] = this.objectVertexLocalPosition[i][1]; + xy.data[2][0] = 1; + } + this.resetMatrixLabels(xy); + this.cmd("Step"); + + this.cmd("CreateLabel", equalLabel, "=", equalX, equalY); + if (this.rowMajor) + { + output = this.createMatrix([["","", ""]], equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y); + this.multiplyMatrix(xy, this.transformMatrix, output, explainID); + } + else + { + output = this.createMatrix([[""],[""], [""]], equalX + RotateTranslate2D.EQUALS_SPACING / 2, RotateTranslate2D.MATRIX_START_Y) + this.multiplyMatrix(this.transformMatrix, xy, output, explainID); + } + + transformedObjectID[i] = this.nextIndex++; + var point; + if (this.rowMajor) + { + point = this.worldToScreenSpace([output.data[0][0], output.data[0][1]]); + } + else + { + point = this.worldToScreenSpace([output.data[0][0], output.data[1][0]]); + } + + this.cmd("CreateRectangle", transformedObjectID[i], "", RotateTranslate2D.VERTEX_WIDTH, RotateTranslate2D.VERTEX_HEIGHT, point[0], point[1]); + this.cmd("SetForegroundColor", transformedObjectID[i], RotateTranslate2D.TRANSFORMED_VERTEX_FOREGORUND_COLOR); + this.cmd("SetBackgroundColor", transformedObjectID[i], RotateTranslate2D.TRANSFORMED_VERTEX_BACKGROUND_COLOR); + this.cmd("Connect", this.originID, transformedObjectID[i], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 1, ""); + this.cmd("Step"); + this.cmd("Disconnect", this.originID, transformedObjectID[i]); + + if (i > 0) + { + this.cmd("Connect", transformedObjectID[i-1], transformedObjectID[i], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + } + + this.cmd("Disconnect", this.originID, this.objectVertexLocalID[i]); + if (this.rowMajor) + { + this.objectVertexWorldPosition[i][0] = output.data[0][0]; + this.objectVertexWorldPosition[i][1] = output.data[0][1]; + } + else + { + this.objectVertexWorldPosition[i][0] = output.data[0][0]; + this.objectVertexWorldPosition[i][1] = output.data[1][0]; + } + this.cmd("Delete", equalLabel); + this.deleteMatrix(output); + } + this.cmd("Step"); + this.cmd("Connect", transformedObjectID[transformedObjectID.length-1], transformedObjectID[0], RotateTranslate2D.TRANSFORMED_EDGE_COLOR, 0, 0, ""); + + this.cmd("Step","B"); + this.moveObjectToNewPosition(this.objectVertexWorldPosition, this.objectVertexWorldID, this.globalLabelID, true); + this.cmd("Step"); + + for (i = 0; i < transformedObjectID.length; i++) + { + this.cmd("Delete", transformedObjectID[i]); + } + + + this.deleteMatrix(xy); + return this.commands; +} + + +RotateTranslate2D.prototype.multiplyMatrix = function(mat1, mat2, mat3, explainID) +{ + var i; + var j; + var explainText = ""; + for (i = 0; i < mat1.data.length; i++) + { + for (j = 0; j < mat2.data[0].length; j++) + { + var explainText = ""; + var value = 0; + for (k = 0; k < mat2.data.length; k++) + { + this.cmd("SetHighlight", mat1.dataID[i][k], 1); + this.cmd("SetHighlight", mat2.dataID[k][j], 1); + if (explainText != "") + { + explainText = explainText + " + "; + } + value = value + mat1.data[i][k] * mat2.data[k][j]; + explainText = explainText + String(mat1.data[i][k]) + " * " + String(mat2.data[k][j]); + this.cmd("SetText", explainID, explainText); + this.cmd("Step"); + this.cmd("SetHighlight", mat1.dataID[i][k], 0); + this.cmd("SetHighlight", mat2.dataID[k][j], 0); + } + value = this.standardize(value); + explainText += " = " + String(value); + this.cmd("SetText", explainID, explainText); + mat3.data[i][j] = value; + this.cmd("SetText", mat3.dataID[i][j], value); + this.cmd("Step"); + } + } + this.cmd("SetText", explainID, ""); + + +} + +RotateTranslate2D.prototype.standardize = function(lab) +{ + var newLab = Math.round(lab * 1000) / 1000; + if (isNaN(newLab)) + { + return lab; + } + else + { + return newLab; + } +} + + +RotateTranslate2D.prototype.resetMatrixLabels = function(mat) +{ + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + mat.data[i][j] = this.standardize(mat.data[i][j]); + this.cmd("SetText", mat.dataID[i][j], mat.data[i][j]); + } + } +} + + + +RotateTranslate2D.prototype.moveMatrix = function(mat, x, y) +{ + var height = mat.data.length; + var width = 0; + + var i, j; + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + } + + + this.cmd("Move", mat.leftBrack1, x, y); + this.cmd("Move", mat.leftBrack2, x, y); + this.cmd("Move", mat.leftBrack3, x, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT); + + this.cmd("Move", mat.rightBrack1, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack2, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y); + this.cmd("Move", mat.rightBrack3, x+ width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Move", mat.dataID[i][j], + x + j*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateTranslate2D.MATRIX_ELEM_HEIGHT + RotateTranslate2D.MATRIX_ELEM_HEIGHT / 2); + } + } +} + +RotateTranslate2D.prototype.deleteMatrix = function(mat) +{ + this.cmd("Delete",mat.leftBrack1); + this.cmd("Delete",mat.leftBrack2); + this.cmd("Delete",mat.leftBrack3); + this.cmd("Delete",mat.rightBrack1); + this.cmd("Delete",mat.rightBrack2); + this.cmd("Delete",mat.rightBrack3); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("Delete", mat.dataID[i][j]); + } + } +} + +RotateTranslate2D.prototype.setMatrixAlpha = function(mat, alpha) +{ + this.cmd("SetAlpha",mat.leftBrack1, alpha); + this.cmd("SetAlpha",mat.leftBrack2, alpha); + this.cmd("SetAlpha",mat.leftBrack3, alpha); + this.cmd("SetAlpha",mat.rightBrack1, alpha); + this.cmd("SetAlpha",mat.rightBrack2, alpha); + this.cmd("SetAlpha",mat.rightBrack3, alpha); + var i,j; + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("SetAlpha", mat.dataID[i][j], alpha); + } + } +} + + +RotateTranslate2D.prototype.createMatrix = function(contents, x, y) +{ + var mat = new Matrix(contents, x, y); + mat.leftBrack1 = this.nextIndex++; + mat.leftBrack2 = this.nextIndex++; + mat.leftBrack3 = this.nextIndex++; + mat.rightBrack1 = this.nextIndex++; + mat.rightBrack2 = this.nextIndex++; + mat.rightBrack3 = this.nextIndex++; + + var height = mat.data.length; + var width = 0; + + var i, j; + mat.dataID = new Array(mat.data.length); + for (i = 0; i < mat.data.length; i++) + { + width = Math.max(width, mat.data[i].length); + mat.dataID[i] = new Array(mat.data[i].length); + for (j = 0; j < mat.data[i].length; j++) + { + mat.dataID[i][j] = this.nextIndex++; + } + } + + this.cmd("CreateRectangle", mat.leftBrack1, "", 5, 1, x, y, "left","center"); + this.cmd("CreateRectangle", mat.leftBrack2, "", 1, height * RotateTranslate2D.MATRIX_ELEM_HEIGHT, x, y, "center","top"); + this.cmd("CreateRectangle", mat.leftBrack3, "", 5, 1, x, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT , "left","center"); + + this.cmd("CreateRectangle", mat.rightBrack1, "", 5, 1, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y, "right","center"); + this.cmd("CreateRectangle", mat.rightBrack2, "", 1, height * RotateTranslate2D.MATRIX_ELEM_HEIGHT, x + width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y, "center","top"); + this.cmd("CreateRectangle", mat.rightBrack3, "", 5, 1, x+ width * RotateTranslate2D.MATRIX_ELEM_WIDTH, y + height * RotateTranslate2D.MATRIX_ELEM_HEIGHT , "right","center"); + + for (i = 0; i < mat.data.length; i++) + { + for (j = 0; j < mat.data[i].length; j++) + { + this.cmd("CreateLabel", mat.dataID[i][j], mat.data[i][j], + x + j*RotateTranslate2D.MATRIX_ELEM_WIDTH + RotateTranslate2D.MATRIX_ELEM_WIDTH / 2, + y + i*RotateTranslate2D.MATRIX_ELEM_HEIGHT + RotateTranslate2D.MATRIX_ELEM_HEIGHT / 2); + } + } + return mat; +} + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new RotateTranslate2D(animManag, canvas.width, canvas.height); +} + +function Matrix(contents, x, y) +{ + this.data = contents; + this.x = x; + this.y = y; +} + +Matrix.prototype.transpose = function() +{ + var newData = new Array(this.data[0].length); + var i,j; + for (i = 0; i < this.data[0].length; i++) + { + newData[i] = new Array(this.data.length); + } + for (i = 0; i < this.data.length; i++) + { + for (j = 0; j < this.data[i].length; j++) + { + newData[j][i] = this.data[i][j]; + } + } + this.data = newData; +} + + diff --git a/AlgorithmLibrary/Search.js b/AlgorithmLibrary/Search.js index e0c7ca7..2925e0d 100644 --- a/AlgorithmLibrary/Search.js +++ b/AlgorithmLibrary/Search.js @@ -107,9 +107,7 @@ function Search(am, w, h) } -Search.prototype = new Algorithm(); -Search.prototype.constructor = Search; -Search.superclass = Algorithm.prototype; +Search.inheritFrom(Algorithm); Search.LINEAR_CODE = [ ["def ", "linearSearch(listData, value)"], diff --git a/AlgorithmLibrary/SimpleStack.js b/AlgorithmLibrary/SimpleStack.js index 361fd98..191252e 100644 --- a/AlgorithmLibrary/SimpleStack.js +++ b/AlgorithmLibrary/SimpleStack.js @@ -30,10 +30,7 @@ function SimpleStack(am, w, h) { this.init(am, w, h); } - -SimpleStack.prototype = new Algorithm(); -SimpleStack.prototype.constructor = SimpleStack; -SimpleStack.superclass = Algorithm.prototype; +SimpleStack.inheritFrom(Algorithm); SimpleStack.ELEMENT_WIDTH = 30; diff --git a/AlgorithmLibrary/SkewHeap.js b/AlgorithmLibrary/SkewHeap.js index aefe10a..2dc4bbb 100644 --- a/AlgorithmLibrary/SkewHeap.js +++ b/AlgorithmLibrary/SkewHeap.js @@ -32,9 +32,7 @@ function SkewHeap(am, w, h) } -SkewHeap.prototype = new Algorithm(); -SkewHeap.prototype.constructor = SkewHeap; -SkewHeap.superclass = Algorithm.prototype; +SkewHeap.inheritFrom(Algorithm); SkewHeap.LINK_COLOR = "#007700"; SkewHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; diff --git a/AlgorithmLibrary/SplayTree.js b/AlgorithmLibrary/SplayTree.js index ae2eec4..c2462a4 100644 --- a/AlgorithmLibrary/SplayTree.js +++ b/AlgorithmLibrary/SplayTree.js @@ -48,10 +48,7 @@ function SPLAYTREE(am, w, h) { this.init(am, w, h); } - -SPLAYTREE.prototype = new Algorithm(); -SPLAYTREE.prototype.constructor = SPLAYTREE; -SPLAYTREE.superclass = Algorithm.prototype; +SPLAYTREE.inheritFrom(Algorithm); SPLAYTREE.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/StackArray.js b/AlgorithmLibrary/StackArray.js index 18a0afc..50a20bd 100644 --- a/AlgorithmLibrary/StackArray.js +++ b/AlgorithmLibrary/StackArray.js @@ -51,9 +51,7 @@ function StackArray(am, w, h) } -StackArray.prototype = new Algorithm(); -StackArray.prototype.constructor = StackArray; -StackArray.superclass = Algorithm.prototype; +StackArray.inheritFrom(Algorithm); StackArray.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/StackLL.js b/AlgorithmLibrary/StackLL.js index d0d788e..263de92 100644 --- a/AlgorithmLibrary/StackLL.js +++ b/AlgorithmLibrary/StackLL.js @@ -58,9 +58,7 @@ function StackLL(am, w, h) } -StackLL.prototype = new Algorithm(); -StackLL.prototype.constructor = StackLL; -StackLL.superclass = Algorithm.prototype; +StackLL.inheritFrom(Algorithm); StackLL.prototype.init = function(am, w, h) diff --git a/AlgorithmLibrary/TST.js b/AlgorithmLibrary/TST.js index 8aac03d..d37d772 100644 --- a/AlgorithmLibrary/TST.js +++ b/AlgorithmLibrary/TST.js @@ -54,10 +54,7 @@ function Ternary(am, w, h) { this.init(am, w, h); } - -Ternary.prototype = new Algorithm(); -Ternary.prototype.constructor = Ternary; -Ternary.superclass = Algorithm.prototype; +Ternary.inheritFrom(Algorithm); Ternary.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/TestAlgorithmOld.js b/AlgorithmLibrary/TestAlgorithmOld.js index 2efac8f..c929611 100644 --- a/AlgorithmLibrary/TestAlgorithmOld.js +++ b/AlgorithmLibrary/TestAlgorithmOld.js @@ -30,10 +30,7 @@ function TestAlgorithm(am) this.init(am); } - -TestAlgorithm.prototype = new Algorithm(); -TestAlgorithm.prototype.constructor = TestAlgorithm; -TestAlgorithm.superclass = Algorithm.prototype; +TestAlgorithm.inheritFrom(Algorithm); TestAlgorithm.prototype.init = function(am) { diff --git a/AlgorithmLibrary/TopoSortDFS.js b/AlgorithmLibrary/TopoSortDFS.js index 56e6753..6040338 100644 --- a/AlgorithmLibrary/TopoSortDFS.js +++ b/AlgorithmLibrary/TopoSortDFS.js @@ -26,9 +26,13 @@ function TopoSortDFS(am, w, h) { - this.init(am, w, h); + // call superclass' constructor, which calls init + TopoSortDFS.superclass.constructor.call(this, am, w, h); } +TopoSortDFS.inheritFrom(Graph); + + TopoSortDFS.ORDERING_INITIAL_X = 300; TopoSortDFS.ORDERING_INITIAL_Y = 70; @@ -74,10 +78,6 @@ TopoSortDFS.DFS_TREE_COLOR = "#0000FF"; -TopoSortDFS.prototype = new Graph(); -TopoSortDFS.prototype.constructor = TopoSortDFS; -TopoSortDFS.superclass = Graph.prototype; - TopoSortDFS.prototype.addControls = function() { this.startButton = this.addControlToAlgorithmBar("Button", "Do Topological Sort"); diff --git a/AlgorithmLibrary/TopoSortIndegree.js b/AlgorithmLibrary/TopoSortIndegree.js index 204d47c..e42c474 100644 --- a/AlgorithmLibrary/TopoSortIndegree.js +++ b/AlgorithmLibrary/TopoSortIndegree.js @@ -26,9 +26,13 @@ function TopoSortIndegree(am, w, h) { - this.init(am, w, h); + // call superclass' constructor, which calls init + TopoSortIndegree.superclass.constructor.call(this, am, w, h); } +TopoSortIndegree.inheritFrom(Graph); + + TopoSortIndegree.INDEGREE_ARRAY_ELEM_WIDTH = 25; @@ -58,10 +62,6 @@ TopoSortIndegree.HIGHLIGHT_CIRCLE_COLOR = "#000000"; TopoSortIndegree.MESSAGE_COLOR = "#0000FF"; -TopoSortIndegree.prototype = new Graph(); -TopoSortIndegree.prototype.constructor = TopoSortIndegree; -TopoSortIndegree.superclass = Graph.prototype; - TopoSortIndegree.prototype.addControls = function() { this.startButton = this.addControlToAlgorithmBar("Button", "Do Topological Sort"); diff --git a/AlgorithmLibrary/Trie.js b/AlgorithmLibrary/Trie.js index 7c84d6c..3299ea0 100644 --- a/AlgorithmLibrary/Trie.js +++ b/AlgorithmLibrary/Trie.js @@ -53,10 +53,7 @@ function Trie(am, w, h) { this.init(am, w, h); } - -Trie.prototype = new Algorithm(); -Trie.prototype.constructor = Trie; -Trie.superclass = Algorithm.prototype; +Trie.inheritFrom(Algorithm); Trie.prototype.init = function(am, w, h) { diff --git a/AlgorithmLibrary/TrinarySearchTree.js b/AlgorithmLibrary/TrinarySearchTree.js index fedb018..22b27a4 100644 --- a/AlgorithmLibrary/TrinarySearchTree.js +++ b/AlgorithmLibrary/TrinarySearchTree.js @@ -53,10 +53,7 @@ function Ternary(am, w, h) { this.init(am, w, h); } - -Ternary.prototype = new Algorithm(); -Ternary.prototype.constructor = Ternary; -Ternary.superclass = Algorithm.prototype; +Ternary.inheritFrom(Algorithm); Ternary.prototype.init = function(am, w, h) { diff --git a/AnimationLibrary/AnimatedBTreeNode.js b/AnimationLibrary/AnimatedBTreeNode.js index 3be4ae5..b3c1d79 100644 --- a/AnimationLibrary/AnimatedBTreeNode.js +++ b/AnimationLibrary/AnimatedBTreeNode.js @@ -27,14 +27,17 @@ function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor) { - fillColor = (fillColor == undefined)? "#FFFFFF" : fillColor; - edgeColor = (edgeColor == undefined)? "#000000" : edgeColor; - this.init(id, widthPerElem, h, numElems, fillColor, edgeColor); -} + this.objectID = id; + this.widthPerElement = widthPerElem; + this.nodeHeight = h; + this.numLabels = numElems; + this.backgroundColor = (fillColor == undefined)? "#FFFFFF" : fillColor; + this.foregroundColor = (edgeColor == undefined)? "#000000" : edgeColor; -AnimatedBTreeNode.prototype = new AnimatedObject(); -AnimatedBTreeNode.prototype.constructor = AnimatedBTreeNode; -AnimatedBTreeNode.superclass = AnimatedObject.prototype; + // call superclass' constructor, which calls init + AnimatedBTreeNode.superclass.constructor.call(this); +} +AnimatedBTreeNode.inheritFrom(AnimatedObject); AnimatedBTreeNode.MIN_WIDTH = 10; AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; @@ -42,18 +45,8 @@ AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fillColor, edgeColor) { - - var MIN_WIDTH = 10; AnimatedBTreeNode.superclass.init.call(this); - this.objectID = id; - - - this.backgroundColor = fillColor; - this.foregroundColor = edgeColor; - - this.widthPerElement = widthPerElem; - this.nodeHeight = h; - this.numLabels = numElems; + this.labels = new Array(this.numLabels); this.labelColors = new Array(this.numLabels); for (var i = 0; i < this.numLabels; i++) @@ -288,8 +281,7 @@ function UndoDeleteBTreeNode(id, numLab, labelText, x, y, wPerElement, nHeight, this.highlighted = highlighted; } -UndoDeleteBTreeNode.prototype = new UndoBlock(); -UndoDeleteBTreeNode.prototype.constructor = UndoDeleteBTreeNode; +UndoDeleteBTreeNode.inheritFrom(UndoBlock); UndoDeleteBTreeNode.prototype.undoInitialStep = function(world) { diff --git a/AnimationLibrary/AnimatedCircle.js b/AnimationLibrary/AnimatedCircle.js index f1a71d4..36e1c25 100644 --- a/AnimationLibrary/AnimatedCircle.js +++ b/AnimationLibrary/AnimatedCircle.js @@ -27,6 +27,9 @@ var AnimatedCircle = function(objectID, objectLabel) { + // call superclass' constructor + AnimatedCircle.superclass.constructor.call(this); + this.objectID = objectID; this.label = objectLabel; this.radius = 20; @@ -41,9 +44,7 @@ var AnimatedCircle = function(objectID, objectLabel) this.backgroundColor = '#EEFFEE'; */ } - -AnimatedCircle.prototype = new AnimatedObject(); -AnimatedCircle.prototype.constructor = AnimatedCircle; +AnimatedCircle.inheritFrom(AnimatedObject); AnimatedCircle.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint) { @@ -193,8 +194,7 @@ function UndoDeleteCircle(id, lab, x, y, foregroundColor, backgroundColor, l, ra this.radius = radius; } -UndoDeleteCircle.prototype = new UndoBlock(); -UndoDeleteCircle.prototype.constructor = UndoDeleteCircle; +UndoDeleteCircle.inheritFrom(UndoBlock); UndoDeleteCircle.prototype.undoInitialStep = function(world) { diff --git a/AnimationLibrary/AnimatedLabel.js b/AnimationLibrary/AnimatedLabel.js index eb675b8..2198387 100644 --- a/AnimationLibrary/AnimatedLabel.js +++ b/AnimationLibrary/AnimatedLabel.js @@ -26,6 +26,9 @@ function AnimatedLabel(id, val, center, initialWidth, ctx) { + // call superclass' constructor + AnimatedLabel.superclass.constructor.call(this); + this.centering = center; this.label = val; this.highlighted = false; @@ -50,9 +53,7 @@ function AnimatedLabel(id, val, center, initialWidth, ctx) this.centerWidth = -1; this.highlightIndex = -1; } - -AnimatedLabel.prototype = new AnimatedObject(); -AnimatedLabel.prototype.constructor = AnimatedLabel; +AnimatedLabel.inheritFrom(AnimatedObject); AnimatedLabel.prototype.alwaysOnTop = true; @@ -441,8 +442,7 @@ function UndoDeleteLabel(id, lab, x, y, centered, color, l, hli) this.dirty = true; } -UndoDeleteLabel.prototype = new UndoBlock(); -UndoDeleteLabel.prototype.constructor = UndoDeleteLabel; +UndoDeleteLabel.inheritFrom(UndoBlock); UndoDeleteLabel.prototype.undoInitialStep = function(world) { diff --git a/AnimationLibrary/AnimatedLinkedList.js b/AnimationLibrary/AnimatedLinkedList.js index abfa00e..14d4df7 100644 --- a/AnimationLibrary/AnimatedLinkedList.js +++ b/AnimationLibrary/AnimatedLinkedList.js @@ -26,30 +26,30 @@ function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor) { - this.init(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor); -} - -AnimatedLinkedList.prototype = new AnimatedObject(); -AnimatedLinkedList.prototype.constructor = AnimatedLinkedList; -AnimatedLinkedList.superclass = AnimatedObject.prototype; - - -AnimatedLinkedList.prototype.init = function(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor) -{ - - AnimatedLinkedList.superclass.init.call(this); - this.w = wth; this.h = hgt; this.backgroundColor = fillColor; this.foregroundColor = edgeColor; + this.val = val; this.vertical = verticalOrientation; this.linkPositionEnd = linkPosEnd; this.linkPercent = linkPer; this.numLabels = numLab; - + this.objectID = id; + + // call superclass' constructor, which calls init + AnimatedLinkedList.superclass.constructor.call(this); +} + +AnimatedLinkedList.inheritFrom(AnimatedObject); + + +AnimatedLinkedList.prototype.init = function() +{ + AnimatedLinkedList.superclass.init.call(this); + this.labels = []; this.labelPosX = []; this.labelPosY = []; @@ -60,8 +60,6 @@ AnimatedLinkedList.prototype.init = function(id, val, wth, hgt, linkPer, vertica this.maxHeightDiff = 5; this.minHeightDiff = 3; - - for (var i = 0; i < this.numLabels; i++) { this.labels[i] = ""; @@ -70,9 +68,8 @@ AnimatedLinkedList.prototype.init = function(id, val, wth, hgt, linkPer, vertica this.labelColors[i] = this.foregroundColor; } - this.labels[0] = val; + this.labels[0] = this.val; this.highlighted = false; - this.objectID = id; } @@ -454,8 +451,7 @@ function UndoDeleteLinkedList(id, numlab, lab, x, y, w, h, linkper, posEnd, vert this.nullPointer = np; } -UndoDeleteLinkedList.prototype = new UndoBlock(); -UndoDeleteLinkedList.prototype.constructor = UndoDeleteLinkedList; +UndoDeleteLinkedList.inheritFrom(UndoBlock); diff --git a/AnimationLibrary/AnimatedRectangle.js b/AnimationLibrary/AnimatedRectangle.js index e4f890f..a3c9a84 100644 --- a/AnimationLibrary/AnimatedRectangle.js +++ b/AnimationLibrary/AnimatedRectangle.js @@ -28,6 +28,9 @@ AnimatedRectangle = function(id, val, wth, hgt, xJust, yJust, fillColor, edgeColor) { + // call superclass' constructor + AnimatedRectangle.superclass.constructor.call(this); + this.w = wth; this.h = hgt; this.xJustify = xJust; @@ -46,8 +49,7 @@ AnimatedRectangle = function(id, val, wth, hgt, xJust, yJust, fillColor, edgeCo } -AnimatedRectangle.prototype = new AnimatedObject(); -AnimatedRectangle.prototype.constructor = AnimatedRectangle; +AnimatedRectangle.inheritFrom(AnimatedObject); AnimatedRectangle.prototype.setNull = function(np) { @@ -324,8 +326,7 @@ function UndoDeleteRectangle(id, lab, x, y, w, h, xJust, yJust, bgColor, fgColor this.highlighted = highlight; } -UndoDeleteRectangle.prototype = new UndoBlock(); -UndoDeleteRectangle.prototype.constructor = UndoDeleteRectangle; +UndoDeleteRectangle.inheritFrom(UndoBlock); UndoDeleteRectangle.prototype.undoInitialStep = function(world) diff --git a/AnimationLibrary/AnimationMain.js b/AnimationLibrary/AnimationMain.js index 97d3964..be86e2f 100644 --- a/AnimationLibrary/AnimationMain.js +++ b/AnimationLibrary/AnimationMain.js @@ -390,6 +390,8 @@ function initCanvas(canvas, generalControlBar, algorithmControlBar) function AnimationManager(objectManager) { + AnimationManager.superclass.constructor.call(this); + // Holder for all animated objects. // All animation is done by manipulating objects in\ // this container @@ -1298,8 +1300,7 @@ function AnimationManager(objectManager) } -AnimationManager.prototype = new EventListener(); -AnimationManager.prototype.constructor = AnimationManager; +AnimationManager.inheritFrom(EventListener); AnimationManager.prototype.addControlToAnimationBar = function(type,name,containerType) { diff --git a/AnimationLibrary/CustomEvents.js b/AnimationLibrary/CustomEvents.js index c276f42..5aa0bf5 100644 --- a/AnimationLibrary/CustomEvents.js +++ b/AnimationLibrary/CustomEvents.js @@ -25,6 +25,12 @@ // or implied, of the University of San Francisco +Function.prototype.inheritFrom = function(superConstructor) { + this.superclass = superConstructor.prototype; // for calling superclass' constructor/methods + this.prototype = Object.create(this.superclass); // create an object with the needed prototype, but without calling superConstructor + this.prototype.constructor = this; // for instanceof +} + Function.prototype.bind = function() { var _function = this; @@ -128,49 +134,3 @@ EventListener.prototype.fireEvent = function(kind, event) } -/* -function Source() -{ - -} - -Source.prototype = new EventListener(); -Source.prototype.constructor = Source; -Source.prototype.testFire = function() -{ - this.fireEvent("test","testcontents"); - this.fireEvent("test2","test2contents"); -} - - - -function Client(eventSource) -{ - - this.first = function(blah) - { - alert("first:" + blah); - } - - this.second = function(blah) - { - alert("second:" + blah); - } - eventSource.addListener("test", this, this.first); - eventSource.addListener("test", this, this.first); - eventSource.addListener("test", this, this.second); - eventSource.removeListener("test", this, this.first); - - -} - - -function init() -{ - var src = new Source; - var c = new Client(src); - src.testFire(); -} - -*/ - diff --git a/AnimationLibrary/HighlightCircle.js b/AnimationLibrary/HighlightCircle.js index 9034b37..4e0569e 100644 --- a/AnimationLibrary/HighlightCircle.js +++ b/AnimationLibrary/HighlightCircle.js @@ -36,10 +36,11 @@ var HighlightCircle = function(objectID, color, radius) this.x = 0; this.y = 0; this.alpha = 1; -} -HighlightCircle.prototype = new AnimatedObject(); -HighlightCircle.prototype.constructor = HighlightCircle; + // call superclass' constructor + HighlightCircle.superclass.constructor.call(this); +} +HighlightCircle.inheritFrom(AnimatedObject); HighlightCircle.prototype.draw = function(ctx) @@ -71,8 +72,7 @@ function UndoDeleteHighlightCircle(objectID, x, y, circleColor, r, layer, alpha) this.alpha = alpha } -UndoDeleteHighlightCircle.prototype = new UndoBlock(); -UndoDeleteHighlightCircle.prototype.constructor = UndoDeleteHighlightCircle; +UndoDeleteHighlightCircle.inheritFrom(UndoBlock); UndoDeleteHighlightCircle.prototype.undoInitialStep = function(world) { diff --git a/AnimationLibrary/UndoFunctions.js b/AnimationLibrary/UndoFunctions.js index 95b48d9..5019e5a 100644 --- a/AnimationLibrary/UndoFunctions.js +++ b/AnimationLibrary/UndoFunctions.js @@ -56,8 +56,7 @@ function UndoMove(id, fmX, fmy, tx, ty) } -UndoMove.prototype = new UndoBlock(); -UndoMove.prototype.constructor = UndoMove; +UndoMove.inheritFrom(UndoBlock); UndoMove.prototype.addUndoAnimation = function (animationList) { @@ -75,8 +74,7 @@ function UndoCreate(id) this.objectID = id; } -UndoCreate.prototype = new UndoBlock(); -UndoCreate.prototype.constructor = UndoCreate; +UndoCreate.inheritFrom(UndoBlock); UndoCreate.prototype.undoInitialStep = function(world) @@ -94,8 +92,7 @@ function UndoHighlight(id, val) this.highlightValue = val; } -UndoHighlight.prototype = new UndoBlock(); -UndoHighlight.prototype.constructor = UndoHighlight; +UndoHighlight.inheritFrom(UndoBlock); UndoHighlight.prototype.undoInitialStep = function(world) { @@ -113,8 +110,7 @@ function UndoSetHeight(id, val) this.height = val; } -UndoSetHeight.prototype = new UndoBlock(); -UndoSetHeight.prototype.constructor = UndoSetHeight; +UndoSetHeight.inheritFrom(UndoBlock); UndoSetHeight.prototype.undoInitialStep = function(world) { @@ -131,8 +127,7 @@ function UndoSetWidth(id, val) this.width = val; } -UndoSetWidth.prototype = new UndoBlock(); -UndoSetWidth.prototype.constructor = UndoSetWidth; +UndoSetWidth.inheritFrom(UndoBlock); UndoSetWidth.prototype.undoInitialStep = function(world) { @@ -161,8 +156,7 @@ function UndoSetNumElements(obj, newNumElems) } } -UndoSetNumElements.prototype = new UndoBlock(); -UndoSetNumElements.prototype.constructor = UndoSetNumElements; +UndoSetNumElements.inheritFrom(UndoBlock); UndoSetNumElements.prototype.undoInitialStep = function(world) @@ -189,8 +183,7 @@ function UndoSetAlpha(id, alph) this.alphaVal = alph; } -UndoSetAlpha.prototype = new UndoBlock(); -UndoSetAlpha.prototype.constructor = UndoSetAlpha; +UndoSetAlpha.inheritFrom(UndoBlock); UndoSetAlpha.prototype.undoInitialStep = function(world) { @@ -207,8 +200,7 @@ function UndoSetNull(id, nv) this.nullVal = nv; } -UndoSetNull.prototype = new UndoBlock(); -UndoSetNull.prototype.constructor = UndoSetNull; +UndoSetNull.inheritFrom(UndoBlock); UndoSetNull.prototype.undoInitialStep = function(world) { @@ -225,8 +217,7 @@ function UndoSetForegroundColor(id, color) this.color = color; } -UndoSetForegroundColor.prototype = new UndoBlock(); -UndoSetForegroundColor.prototype.constructor = UndoSetForegroundColor; +UndoSetForegroundColor.inheritFrom(UndoBlock); UndoSetForegroundColor.prototype.undoInitialStep = function (world) { @@ -243,8 +234,7 @@ function UndoSetBackgroundColor(id, color) this.color = color; } -UndoSetBackgroundColor.prototype = new UndoBlock(); -UndoSetBackgroundColor.prototype.constructor = UndoSetBackgroundColor; +UndoSetBackgroundColor.inheritFrom(UndoBlock); UndoSetBackgroundColor.prototype.undoInitialStep = function (world) { @@ -263,8 +253,7 @@ function UndoSetHighlightIndex(id, index) this.index = index; } -UndoSetHighlightIndex.prototype = new UndoBlock(); -UndoSetHighlightIndex.prototype.constructor = UndoSetHighlightIndex; +UndoSetHighlightIndex.inheritFrom(UndoBlock); UndoSetHighlightIndex.prototype.undoInitialStep = function (world) { @@ -286,8 +275,7 @@ function UndoSetText(id, str, index) this.labelIndex = index; } -UndoSetText.prototype = new UndoBlock(); -UndoSetText.prototype.constructor = UndoSetText; +UndoSetText.inheritFrom(UndoBlock); UndoSetText.prototype.undoInitialStep = function(world) { @@ -306,8 +294,7 @@ function UndoSetTextColor(id, color, index) this.index = index; } -UndoSetTextColor.prototype = new UndoBlock(); -UndoSetTextColor.prototype.constructor = UndoSetTextColor; +UndoSetTextColor.inheritFrom(UndoBlock); UndoSetTextColor.prototype.undoInitialStep = function(world) { @@ -327,8 +314,7 @@ function UndoHighlightEdge(from, to, val) this.highlightValue = val; } -UndoHighlightEdge.prototype = new UndoBlock(); -UndoHighlightEdge.prototype.constructor = UndoHighlightEdge; +UndoHighlightEdge.inheritFrom(UndoBlock); UndoHighlightEdge.prototype.undoInitialStep = function(world) { @@ -347,8 +333,7 @@ function UndoSetEdgeColor(from, to, oldColor) this.color = oldColor; } -UndoSetEdgeColor.prototype = new UndoBlock(); -UndoSetEdgeColor.prototype.constructor = UndoSetEdgeColor; +UndoSetEdgeColor.inheritFrom(UndoBlock); UndoSetEdgeColor.prototype.undoInitialStep = function(world) { @@ -367,8 +352,7 @@ function UndoSetEdgeAlpha(from, to, oldAplha) this.alpha = oldAplha; } -UndoSetEdgeAlpha.prototype = new UndoBlock(); -UndoSetEdgeAlpha.prototype.constructor = UndoSetEdgeAlpha; +UndoSetEdgeAlpha.inheritFrom(UndoBlock); UndoSetEdgeAlpha.prototype.undoInitialStep = function(world) { @@ -386,8 +370,7 @@ function UndoSetPosition(id, x, y) this.y = y; } -UndoSetPosition.prototype = new UndoBlock(); -UndoSetPosition.prototype.constructor = UndoSetPosition; +UndoSetPosition.inheritFrom(UndoBlock); UndoSetPosition.prototype.undoInitialStep = function(world) diff --git a/BFS.html b/BFS.html index 9501b2e..51a0613 100644 --- a/BFS.html +++ b/BFS.html @@ -13,7 +13,11 @@ - + + diff --git a/source.html b/source.html index 7993de5..b32ffac 100644 --- a/source.html +++ b/source.html @@ -141,10 +141,7 @@

Using Algorithm function

{ this.init(am, w, h); } - -MyAlgorithm.prototype = new Algorithm(); -MyAlgorithm.prototype.constructor = MyAlgorithm; -MyAlgorithm.superclass = Algorithm.prototype; +MyAlgorithm.inheritFrom(Algorithm); @@ -812,10 +809,7 @@

Simple Stack Example

{ this.init(am, w, h); } - -SimpleStack.prototype = new Algorithm(); -SimpleStack.prototype.constructor = SimpleStack; -SimpleStack.superclass = Algorithm.prototype; +SimpleStack.inheritFrom(Algorithm); From 276aed8d20ec74db8b6794774512511f9baba837 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 18:58:02 +0200 Subject: [PATCH 06/25] use LF in the repo Files had mixed LF and CRLF endings, the standard git way is to use LF in the repo, git automatically converts to CRLF on windows. --- AlgorithmLibrary/BinomialQueue.js | 1282 +++++------ AlgorithmLibrary/ChangingCoordinate2D.js | 2 +- AlgorithmLibrary/ChangingCoordinate3D.js | 2 +- AlgorithmLibrary/DPChange.js | 1966 ++++++++-------- AlgorithmLibrary/DPFib.js | 1040 ++++----- AlgorithmLibrary/DPLCS.js | 2 +- AlgorithmLibrary/DPMatrixMultiply.js | 2 +- AlgorithmLibrary/DisjointSet.js | 1386 +++++------ AlgorithmLibrary/FibonacciHeap.js | 1752 +++++++------- AlgorithmLibrary/Graph.js | 1436 ++++++------ AlgorithmLibrary/LeftistHeap.js | 1132 ++++----- AlgorithmLibrary/QueueArray.js | 644 +++--- AlgorithmLibrary/QueueLL.js | 658 +++--- AlgorithmLibrary/RecFact.js | 434 ++-- AlgorithmLibrary/RecQueens.js | 2 +- AlgorithmLibrary/RecReverse.js | 452 ++-- AlgorithmLibrary/Recursive.js | 442 ++-- AlgorithmLibrary/RotateScale2D.js | 2 +- AlgorithmLibrary/RotateScale3D.js | 2 +- AlgorithmLibrary/RotateTranslate2D.js | 2 +- AlgorithmLibrary/Search.js | 1464 ++++++------ AlgorithmLibrary/SkewHeap.js | 1020 ++++----- AlgorithmLibrary/StackArray.js | 600 ++--- AlgorithmLibrary/StackLL.js | 598 ++--- AnimationLibrary/AnimatedBTreeNode.js | 602 ++--- AnimationLibrary/AnimatedCircle.js | 422 ++-- AnimationLibrary/AnimatedLabel.js | 908 ++++---- AnimationLibrary/AnimatedLinkedList.js | 938 ++++---- AnimationLibrary/AnimatedRectangle.js | 682 +++--- AnimationLibrary/AnimationMain.js | 2676 +++++++++++----------- AnimationLibrary/HighlightCircle.js | 174 +- AnimationLibrary/Line.js | 458 ++-- AnimationLibrary/ObjectManager.js | 1716 +++++++------- AnimationLibrary/UndoFunctions.js | 762 +++--- 34 files changed, 12830 insertions(+), 12830 deletions(-) diff --git a/AlgorithmLibrary/BinomialQueue.js b/AlgorithmLibrary/BinomialQueue.js index 8cb7715..50c1294 100644 --- a/AlgorithmLibrary/BinomialQueue.js +++ b/AlgorithmLibrary/BinomialQueue.js @@ -1,641 +1,641 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var LINK_COLOR = "#007700"; -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var MERGE_SEPARATING_LINE_COLOR = "#0000FF"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var DEGREE_OFFSET_X = -20; -var DEGREE_OFFSET_Y = -20; - -var DELETE_LAB_X = 30; -var DELETE_LAB_Y = 50; - - -var NODE_WIDTH = 60; -var NODE_HEIGHT = 70 - -var STARTING_X = 70; -var STARTING_Y = 80; - -var INSERT_X = 30; -var INSERT_Y = 25 - - -function BinomialQueue(am, w, h) -{ - this.init(am, w, h); - -} - -BinomialQueue.inheritFrom(Algorithm); - - - -BinomialQueue.prototype.init = function(am, w, h) -{ - BinomialQueue.superclass.init.call(this, am, w, h); - this.addControls(); - this.treeRoot = null; - this.currentLayer = 1; - this.animationManager.setAllLayers([0,this.currentLayer]); - this.nextIndex = 0; -} - - -BinomialQueue.prototype.addControls = function() -{ - this.controls = []; - this.insertField = this.addControlToAlgorithmBar("Text", ""); - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.controls.push(this.insertField); - - this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); - this.insertButton.onclick = this.insertCallback.bind(this); - this.controls.push(this.insertButton); - - this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); - this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); - this.controls.push(this.removeSmallestButton); - - this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); - this.clearHeapButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearHeapButton); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", - "Internal Representation", - ], - "BQueueRep"); - - radioButtonList[0].onclick = this.representationChangedHandler.bind(this, true); - radioButtonList[1].onclick = this.representationChangedHandler.bind(this, false); - radioButtonList[0].checked = true; - -} - - -BinomialQueue.prototype.representationChangedHandler = function(logicalRep, event) -{ - if (logicalRep) - { - this.animationManager.setAllLayers([0,1]); - this.currentLayer = 1; - } - else - { - this.animationManager.setAllLayers([0,2]); - this.currentLayer = 2; - } -} - - - - -BinomialQueue.prototype.setPositions = function(tree, xPosition, yPosition) -{ - if (tree != null) - { - if (tree.degree == 0) - { - tree.x = xPosition; - tree.y = yPosition; - return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); - } - else if (tree.degree == 1) - { - tree.x = xPosition; - tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); - } - else - { - var treeWidth = Math.pow(2, tree.degree - 1); - tree.x = xPosition + (treeWidth - 1) * NODE_WIDTH; - tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + treeWidth * NODE_WIDTH, yPosition); - } - } - return xPosition; -} - -BinomialQueue.prototype.moveTree = function(tree) -{ - if (tree != null) - { - this.cmd("Move", tree.graphicID, tree.x, tree.y); - this.cmd("Move", tree.internalGraphicID, tree.x, tree.y); - this.cmd("Move", tree.degreeID, tree.x + DEGREE_OFFSET_X, tree.y + DEGREE_OFFSET_Y); - - this.moveTree(tree.leftChild); - this.moveTree(tree.rightSib); - } -} - - -BinomialQueue.prototype.insertCallback = function(event) -{ - var insertedValue; - - insertedValue = this.normalizeNumber(this.insertField.value, 4); - if (insertedValue != "") - { - this.insertField.value = ""; - this.implementAction(this.insertElement.bind(this),insertedValue); - } -} - -BinomialQueue.prototype.clearCallback = function(event) -{ - this.clear(); -} - -BinomialQueue.prototype.clear = function() -{ - this.commands = new Array(); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.actionHistory = new Array(); -} - - -BinomialQueue.prototype.reset = function() -{ - this.treeRoot = null; - this.nextIndex = 0; -} - -BinomialQueue.prototype.removeSmallestCallback = function(event) -{ - this.implementAction(this.removeSmallest.bind(this),""); -} - - - -BinomialQueue.prototype.removeSmallest = function(dummy) -{ - this.commands = new Array(); - - if (this.treeRoot != null) - { - var tmp; - var prev; - var smallest = this.treeRoot; - - this.cmd("SetHighlight", smallest.graphicID, 1); - this.cmd("SetHighlight", smallest.internalGraphicID, 1); - - for (tmp = this.treeRoot.rightSib; tmp != null; tmp = tmp.rightSib) - { - this.cmd("SetHighlight", tmp.graphicID, 1); - this.cmd("SetHighlight", tmp.internalGraphicID, 1); - this.cmd("Step"); - if (tmp.data < smallest.data) - { - this.cmd("SetHighlight", smallest.graphicID, 0); - this.cmd("SetHighlight", smallest.internalGraphicID, 0); - smallest = tmp; - } - else - { - this.cmd("SetHighlight", tmp.graphicID, 0); - this.cmd("SetHighlight", tmp.internalGraphicID, 0); - } - } - - if (smallest == this.treeRoot) { - this.treeRoot = this.treeRoot.rightSib; - prev = null; - } - else - { - for (prev = this.treeRoot; prev.rightSib != smallest; prev = prev.rightSib) ; - prev.rightSib = prev.rightSib.rightSib; - - } - var moveLabel = this.nextIndex++; - this.cmd("SetText", smallest.graphicID, ""); - this.cmd("SetText", smallest.internalGraphicID, ""); - this.cmd("CreateLabel", moveLabel, smallest.data, smallest.x, smallest.y); - this.cmd("Move", moveLabel, DELETE_LAB_X, DELETE_LAB_Y); - this.cmd("Step"); - if (prev != null && prev.rightSib != null) - { - this.cmd("Connect", prev.internalGraphicID, - prev.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - } - this.cmd("Delete", smallest.graphicID); - this.cmd("Delete", smallest.internalGraphicID); - this.cmd("Delete", smallest.degreeID); - - this.secondaryTreeRoot = this.reverse(smallest.leftChild); - for (tmp = this.secondaryTreeRoot; tmp != null; tmp = tmp.rightSib) - tmp.parent = null; - this.merge(); - this.cmd("Delete", moveLabel); - } - return this.commands; -} - -BinomialQueue.prototype.reverse = function(tree) -{ - var newTree = null; - var tmp; - while (tree != null) - { - if (tree.rightSib != null) - { - this.cmd("Disconnect", tree.internalGraphicID, tree.rightSib.internalGraphicID); - this.cmd("Connect", tree.rightSib.internalGraphicID, - tree.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - tmp = tree; - tree = tree.rightSib; - tmp.rightSib = newTree; - tmp.parent=null; - newTree = tmp; - } - return newTree; -} - - -BinomialQueue.prototype.insertElement = function(insertedValue) -{ - this.commands = new Array(); - - var insertNode = new BinomialNode(insertedValue, this.nextIndex++, INSERT_X, INSERT_Y); - insertNode.internalGraphicID = this.nextIndex++; - insertNode.degreeID= this.nextIndex++; - this.cmd("CreateCircle", insertNode.graphicID, insertedValue, INSERT_X, INSERT_Y); - this.cmd("SetForegroundColor", insertNode.graphicID, FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.graphicID, BACKGROUND_COLOR); - this.cmd("SetLayer", insertNode.graphicID, 1); - this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, INSERT_X, INSERT_Y); - this.cmd("SetForegroundColor", insertNode.internalGraphicID, FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.internalGraphicID, BACKGROUND_COLOR); - this.cmd("SetLayer", insertNode.internalGraphicID, 2); - this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + DEGREE_OFFSET_X, insertNode.y + DEGREE_OFFSET_Y); - this.cmd("SetTextColor", insertNode.degreeID, "#0000FF"); - this.cmd("SetLayer", insertNode.degreeID, 2); - this.cmd("Step"); - - if (this.treeRoot == null) - { - this.treeRoot = insertNode; - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.moveTree(this.treeRoot); - } - else - { - this.secondaryTreeRoot = insertNode; - this.merge(); - } - - return this.commands; -} - - -BinomialQueue.prototype.merge = function() -{ - if (this.treeRoot != null) - { - var leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); - this.moveTree(this.secondaryTreeRoot); - this.moveTree(this.treeRoot); - var lineID = this.nextIndex++; - this.cmd("CreateRectangle", lineID, "", 0, 200, leftSize, 50,"left","top"); - this.cmd("SetForegroundColor", lineID, MERGE_SEPARATING_LINE_COLOR); - this.cmd("SetLayer", lineID, 0); - this.cmd("Step"); - } - else - { - this.treeRoot = this.secondaryTreeRoot; - this.secondaryTreeRoot = null; - this.setPositions(this.treeRoot, NODE_WIDTH, STARTING_Y); - this.moveTree(this.treeRoot); - return; - } - while (this.secondaryTreeRoot != null) - { - var tmp = this.secondaryTreeRoot; - this.secondaryTreeRoot = this.secondaryTreeRoot.rightSib; - if (this.secondaryTreeRoot != null) - { - this.cmd("Disconnect", tmp.internalGraphicID, this.secondaryTreeRoot.internalGraphicID); - } - if (tmp.degree <= this.treeRoot.degree) - { - tmp.rightSib = this.treeRoot; - this.treeRoot = tmp; - this.cmd("Connect", this.treeRoot.internalGraphicID, - this.treeRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - else - { - var tmp2 = this.treeRoot; - while (tmp2.rightSib != null && tmp2.rightSib.degree < tmp.degree) - { - tmp2 = tmp2. rightSib; - } - if (tmp2.rightSib != null) - { - this.cmd("Disconnect", tmp2.internalGraphicID, tmp2.rightSib.internalGraphicID); - this.cmd("Connect", tmp.internalGraphicID, - tmp2.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - tmp.rightSib= tmp2.rightSib; - tmp2.rightSib = tmp; - this.cmd("Connect", tmp2.internalGraphicID, - tmp.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); - this.moveTree(this.secondaryTreeRoot); - this.moveTree(this.treeRoot); - this.cmd("Move", lineID, leftSize, 50); - this.cmd("Step"); - } - this.cmd("Delete", lineID); - this.combineNodes(); -} - - -BinomialQueue.prototype.combineNodes = function() -{ - var tmp; - var tmp2; - while ((this.treeRoot != null && this.treeRoot.rightSib != null && this.treeRoot.degree == this.treeRoot.rightSib.degree) && - (this.treeRoot.rightSib.rightSib == null || this.treeRoot.rightSib.degree != this.treeRoot.rightSib.rightSib.degree)) - { - this.cmd("Disconnect", this.treeRoot.internalGraphicID, this.treeRoot.rightSib.internalGraphicID); - if (this.treeRoot.rightSib.rightSib != null) - { - this.cmd("Disconnect", this.treeRoot.rightSib.internalGraphicID, this.treeRoot.rightSib.rightSib.internalGraphicID); - } - if (this.treeRoot.data < this.treeRoot.rightSib.data) - { - tmp = this.treeRoot.rightSib; - this.treeRoot.rightSib = tmp.rightSib; - tmp.rightSib = this.treeRoot.leftChild; - this.treeRoot.leftChild = tmp; - tmp.parent = this.treeRoot; - } - else - { - tmp = this.treeRoot; - this.treeRoot = this.treeRoot.rightSib; - tmp.rightSib = this.treeRoot.leftChild; - this.treeRoot.leftChild = tmp; - tmp.parent = this.treeRoot; - } - this.cmd("Connect", this.treeRoot.graphicID, - this.treeRoot.leftChild.graphicID, - FOREGROUND_COLOR, - 0, // Curve - 0, // Directed - ""); // Label - - - this.cmd("Connect", this.treeRoot.internalGraphicID, - this.treeRoot.leftChild.internalGraphicID, - FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, - this.treeRoot.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - if (this.treeRoot.leftChild.rightSib != null) - { - this.cmd("Disconnect", this.treeRoot.internalGraphicID, this.treeRoot.leftChild.rightSib.internalGraphicID); - this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, - this.treeRoot.leftChild.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - if (this.treeRoot.rightSib != null) - { - this.cmd("Connect", this.treeRoot.internalGraphicID, - this.treeRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - - this.treeRoot.degree++; - - this.cmd("SetText", this.treeRoot.degreeID, this.treeRoot.degree); - - - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.moveTree(this.treeRoot); - this.cmd("Step"); - } - - tmp2 = this.treeRoot; - while (tmp2 != null && tmp2.rightSib != null && tmp2.rightSib.rightSib != null) - { - if (tmp2.rightSib.degree != tmp2.rightSib.rightSib.degree) - { - tmp2 = tmp2.rightSib; - } else if ((tmp2.rightSib.rightSib.rightSib != null) && - (tmp2.rightSib.rightSib.degree == tmp2.rightSib.rightSib.rightSib.degree)) - { - tmp2 = tmp2.rightSib; - } - else - { - this.cmd("Disconnect", tmp2.rightSib.internalGraphicID, tmp2.rightSib.rightSib.internalGraphicID); - this.cmd("Disconnect", tmp2.internalGraphicID, tmp2.rightSib.internalGraphicID); - if (tmp2.rightSib.rightSib.rightSib != null) - { - this.cmd("Disconnect", tmp2.rightSib.rightSib.internalGraphicID, tmp2.rightSib.rightSib.rightSib.internalGraphicID); - } - - var tempRoot; - if (tmp2.rightSib.data < tmp2.rightSib.rightSib.data) - { - tmp = tmp2.rightSib.rightSib; - tmp2.rightSib.rightSib = tmp.rightSib; - - tmp.rightSib = tmp2.rightSib.leftChild; - tmp2.rightSib.leftChild = tmp; - tmp.parent = tmp2.rightSib; - tmp2.rightSib.degree++; - this.cmd("SetText", tmp2.rightSib.degreeID, tmp2.rightSib.degree); - tempRoot = tmp2.rightSib; - - } - else - { - tmp = tmp2.rightSib; - tmp2.rightSib = tmp2.rightSib.rightSib; - tmp.rightSib = tmp2.rightSib.leftChild; - tmp2.rightSib.leftChild = tmp; - tmp.parent = tmp2.rightSib; - tmp2.rightSib.degree++; - this.cmd("SetText", tmp2.rightSib.degreeID, tmp2.rightSib.degree); - tempRoot = tmp2.rightSib; - } - this.cmd("Connect", tempRoot.graphicID, - tempRoot.leftChild.graphicID, - FOREGROUND_COLOR, - 0, // Curve - 0, // Directed - ""); // Label - - this.cmd("Connect", tempRoot.internalGraphicID, - tempRoot.leftChild.internalGraphicID, - FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", tempRoot.leftChild.internalGraphicID, - tempRoot.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", tmp2.internalGraphicID, - tempRoot.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - if (tempRoot.leftChild.rightSib != null) - { - this.cmd("Disconnect",tempRoot.internalGraphicID, tempRoot.leftChild.rightSib.internalGraphicID); - this.cmd("Connect",tempRoot.leftChild.internalGraphicID, - tempRoot.leftChild.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label); - } - if (tempRoot.rightSib != null) - { - this.cmd("Connect",tempRoot.internalGraphicID, - tempRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label); - } - - - - - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.moveTree(this.treeRoot); - this.cmd("Step"); - } - } -} - - -BinomialQueue.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -BinomialQueue.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new BinomialQueue(animManag, canvas.width, canvas.height); -} - - - - -function BinomialNode(val, id, initialX, initialY) -{ - this.data = val; - this.x = initialX; - this.y = initialY; - this.graphicID = id; - this.degree = 0; - this.leftChild = null; - this.rightSib = null; - this.parent = null; - this.internalGraphicID = -1; - this.degreeID = -1; -} - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var LINK_COLOR = "#007700"; +var HIGHLIGHT_CIRCLE_COLOR = "#007700"; +var MERGE_SEPARATING_LINE_COLOR = "#0000FF"; +var FOREGROUND_COLOR = "#007700"; +var BACKGROUND_COLOR = "#EEFFEE"; +var DEGREE_OFFSET_X = -20; +var DEGREE_OFFSET_Y = -20; + +var DELETE_LAB_X = 30; +var DELETE_LAB_Y = 50; + + +var NODE_WIDTH = 60; +var NODE_HEIGHT = 70 + +var STARTING_X = 70; +var STARTING_Y = 80; + +var INSERT_X = 30; +var INSERT_Y = 25 + + +function BinomialQueue(am, w, h) +{ + this.init(am, w, h); + +} + +BinomialQueue.inheritFrom(Algorithm); + + + +BinomialQueue.prototype.init = function(am, w, h) +{ + BinomialQueue.superclass.init.call(this, am, w, h); + this.addControls(); + this.treeRoot = null; + this.currentLayer = 1; + this.animationManager.setAllLayers([0,this.currentLayer]); + this.nextIndex = 0; +} + + +BinomialQueue.prototype.addControls = function() +{ + this.controls = []; + this.insertField = this.addControlToAlgorithmBar("Text", ""); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); + this.controls.push(this.insertField); + + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); + this.insertButton.onclick = this.insertCallback.bind(this); + this.controls.push(this.insertButton); + + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); + this.controls.push(this.removeSmallestButton); + + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearHeapButton); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", + "Internal Representation", + ], + "BQueueRep"); + + radioButtonList[0].onclick = this.representationChangedHandler.bind(this, true); + radioButtonList[1].onclick = this.representationChangedHandler.bind(this, false); + radioButtonList[0].checked = true; + +} + + +BinomialQueue.prototype.representationChangedHandler = function(logicalRep, event) +{ + if (logicalRep) + { + this.animationManager.setAllLayers([0,1]); + this.currentLayer = 1; + } + else + { + this.animationManager.setAllLayers([0,2]); + this.currentLayer = 2; + } +} + + + + +BinomialQueue.prototype.setPositions = function(tree, xPosition, yPosition) +{ + if (tree != null) + { + if (tree.degree == 0) + { + tree.x = xPosition; + tree.y = yPosition; + return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); + } + else if (tree.degree == 1) + { + tree.x = xPosition; + tree.y = yPosition; + this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); + } + else + { + var treeWidth = Math.pow(2, tree.degree - 1); + tree.x = xPosition + (treeWidth - 1) * NODE_WIDTH; + tree.y = yPosition; + this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + treeWidth * NODE_WIDTH, yPosition); + } + } + return xPosition; +} + +BinomialQueue.prototype.moveTree = function(tree) +{ + if (tree != null) + { + this.cmd("Move", tree.graphicID, tree.x, tree.y); + this.cmd("Move", tree.internalGraphicID, tree.x, tree.y); + this.cmd("Move", tree.degreeID, tree.x + DEGREE_OFFSET_X, tree.y + DEGREE_OFFSET_Y); + + this.moveTree(tree.leftChild); + this.moveTree(tree.rightSib); + } +} + + +BinomialQueue.prototype.insertCallback = function(event) +{ + var insertedValue; + + insertedValue = this.normalizeNumber(this.insertField.value, 4); + if (insertedValue != "") + { + this.insertField.value = ""; + this.implementAction(this.insertElement.bind(this),insertedValue); + } +} + +BinomialQueue.prototype.clearCallback = function(event) +{ + this.clear(); +} + +BinomialQueue.prototype.clear = function() +{ + this.commands = new Array(); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.actionHistory = new Array(); +} + + +BinomialQueue.prototype.reset = function() +{ + this.treeRoot = null; + this.nextIndex = 0; +} + +BinomialQueue.prototype.removeSmallestCallback = function(event) +{ + this.implementAction(this.removeSmallest.bind(this),""); +} + + + +BinomialQueue.prototype.removeSmallest = function(dummy) +{ + this.commands = new Array(); + + if (this.treeRoot != null) + { + var tmp; + var prev; + var smallest = this.treeRoot; + + this.cmd("SetHighlight", smallest.graphicID, 1); + this.cmd("SetHighlight", smallest.internalGraphicID, 1); + + for (tmp = this.treeRoot.rightSib; tmp != null; tmp = tmp.rightSib) + { + this.cmd("SetHighlight", tmp.graphicID, 1); + this.cmd("SetHighlight", tmp.internalGraphicID, 1); + this.cmd("Step"); + if (tmp.data < smallest.data) + { + this.cmd("SetHighlight", smallest.graphicID, 0); + this.cmd("SetHighlight", smallest.internalGraphicID, 0); + smallest = tmp; + } + else + { + this.cmd("SetHighlight", tmp.graphicID, 0); + this.cmd("SetHighlight", tmp.internalGraphicID, 0); + } + } + + if (smallest == this.treeRoot) { + this.treeRoot = this.treeRoot.rightSib; + prev = null; + } + else + { + for (prev = this.treeRoot; prev.rightSib != smallest; prev = prev.rightSib) ; + prev.rightSib = prev.rightSib.rightSib; + + } + var moveLabel = this.nextIndex++; + this.cmd("SetText", smallest.graphicID, ""); + this.cmd("SetText", smallest.internalGraphicID, ""); + this.cmd("CreateLabel", moveLabel, smallest.data, smallest.x, smallest.y); + this.cmd("Move", moveLabel, DELETE_LAB_X, DELETE_LAB_Y); + this.cmd("Step"); + if (prev != null && prev.rightSib != null) + { + this.cmd("Connect", prev.internalGraphicID, + prev.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + } + this.cmd("Delete", smallest.graphicID); + this.cmd("Delete", smallest.internalGraphicID); + this.cmd("Delete", smallest.degreeID); + + this.secondaryTreeRoot = this.reverse(smallest.leftChild); + for (tmp = this.secondaryTreeRoot; tmp != null; tmp = tmp.rightSib) + tmp.parent = null; + this.merge(); + this.cmd("Delete", moveLabel); + } + return this.commands; +} + +BinomialQueue.prototype.reverse = function(tree) +{ + var newTree = null; + var tmp; + while (tree != null) + { + if (tree.rightSib != null) + { + this.cmd("Disconnect", tree.internalGraphicID, tree.rightSib.internalGraphicID); + this.cmd("Connect", tree.rightSib.internalGraphicID, + tree.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + tmp = tree; + tree = tree.rightSib; + tmp.rightSib = newTree; + tmp.parent=null; + newTree = tmp; + } + return newTree; +} + + +BinomialQueue.prototype.insertElement = function(insertedValue) +{ + this.commands = new Array(); + + var insertNode = new BinomialNode(insertedValue, this.nextIndex++, INSERT_X, INSERT_Y); + insertNode.internalGraphicID = this.nextIndex++; + insertNode.degreeID= this.nextIndex++; + this.cmd("CreateCircle", insertNode.graphicID, insertedValue, INSERT_X, INSERT_Y); + this.cmd("SetForegroundColor", insertNode.graphicID, FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.graphicID, BACKGROUND_COLOR); + this.cmd("SetLayer", insertNode.graphicID, 1); + this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, INSERT_X, INSERT_Y); + this.cmd("SetForegroundColor", insertNode.internalGraphicID, FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.internalGraphicID, BACKGROUND_COLOR); + this.cmd("SetLayer", insertNode.internalGraphicID, 2); + this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + DEGREE_OFFSET_X, insertNode.y + DEGREE_OFFSET_Y); + this.cmd("SetTextColor", insertNode.degreeID, "#0000FF"); + this.cmd("SetLayer", insertNode.degreeID, 2); + this.cmd("Step"); + + if (this.treeRoot == null) + { + this.treeRoot = insertNode; + this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.moveTree(this.treeRoot); + } + else + { + this.secondaryTreeRoot = insertNode; + this.merge(); + } + + return this.commands; +} + + +BinomialQueue.prototype.merge = function() +{ + if (this.treeRoot != null) + { + var leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); + this.moveTree(this.secondaryTreeRoot); + this.moveTree(this.treeRoot); + var lineID = this.nextIndex++; + this.cmd("CreateRectangle", lineID, "", 0, 200, leftSize, 50,"left","top"); + this.cmd("SetForegroundColor", lineID, MERGE_SEPARATING_LINE_COLOR); + this.cmd("SetLayer", lineID, 0); + this.cmd("Step"); + } + else + { + this.treeRoot = this.secondaryTreeRoot; + this.secondaryTreeRoot = null; + this.setPositions(this.treeRoot, NODE_WIDTH, STARTING_Y); + this.moveTree(this.treeRoot); + return; + } + while (this.secondaryTreeRoot != null) + { + var tmp = this.secondaryTreeRoot; + this.secondaryTreeRoot = this.secondaryTreeRoot.rightSib; + if (this.secondaryTreeRoot != null) + { + this.cmd("Disconnect", tmp.internalGraphicID, this.secondaryTreeRoot.internalGraphicID); + } + if (tmp.degree <= this.treeRoot.degree) + { + tmp.rightSib = this.treeRoot; + this.treeRoot = tmp; + this.cmd("Connect", this.treeRoot.internalGraphicID, + this.treeRoot.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + else + { + var tmp2 = this.treeRoot; + while (tmp2.rightSib != null && tmp2.rightSib.degree < tmp.degree) + { + tmp2 = tmp2. rightSib; + } + if (tmp2.rightSib != null) + { + this.cmd("Disconnect", tmp2.internalGraphicID, tmp2.rightSib.internalGraphicID); + this.cmd("Connect", tmp.internalGraphicID, + tmp2.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + tmp.rightSib= tmp2.rightSib; + tmp2.rightSib = tmp; + this.cmd("Connect", tmp2.internalGraphicID, + tmp.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); + this.moveTree(this.secondaryTreeRoot); + this.moveTree(this.treeRoot); + this.cmd("Move", lineID, leftSize, 50); + this.cmd("Step"); + } + this.cmd("Delete", lineID); + this.combineNodes(); +} + + +BinomialQueue.prototype.combineNodes = function() +{ + var tmp; + var tmp2; + while ((this.treeRoot != null && this.treeRoot.rightSib != null && this.treeRoot.degree == this.treeRoot.rightSib.degree) && + (this.treeRoot.rightSib.rightSib == null || this.treeRoot.rightSib.degree != this.treeRoot.rightSib.rightSib.degree)) + { + this.cmd("Disconnect", this.treeRoot.internalGraphicID, this.treeRoot.rightSib.internalGraphicID); + if (this.treeRoot.rightSib.rightSib != null) + { + this.cmd("Disconnect", this.treeRoot.rightSib.internalGraphicID, this.treeRoot.rightSib.rightSib.internalGraphicID); + } + if (this.treeRoot.data < this.treeRoot.rightSib.data) + { + tmp = this.treeRoot.rightSib; + this.treeRoot.rightSib = tmp.rightSib; + tmp.rightSib = this.treeRoot.leftChild; + this.treeRoot.leftChild = tmp; + tmp.parent = this.treeRoot; + } + else + { + tmp = this.treeRoot; + this.treeRoot = this.treeRoot.rightSib; + tmp.rightSib = this.treeRoot.leftChild; + this.treeRoot.leftChild = tmp; + tmp.parent = this.treeRoot; + } + this.cmd("Connect", this.treeRoot.graphicID, + this.treeRoot.leftChild.graphicID, + FOREGROUND_COLOR, + 0, // Curve + 0, // Directed + ""); // Label + + + this.cmd("Connect", this.treeRoot.internalGraphicID, + this.treeRoot.leftChild.internalGraphicID, + FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, + this.treeRoot.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + if (this.treeRoot.leftChild.rightSib != null) + { + this.cmd("Disconnect", this.treeRoot.internalGraphicID, this.treeRoot.leftChild.rightSib.internalGraphicID); + this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, + this.treeRoot.leftChild.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + if (this.treeRoot.rightSib != null) + { + this.cmd("Connect", this.treeRoot.internalGraphicID, + this.treeRoot.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + + this.treeRoot.degree++; + + this.cmd("SetText", this.treeRoot.degreeID, this.treeRoot.degree); + + + this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.moveTree(this.treeRoot); + this.cmd("Step"); + } + + tmp2 = this.treeRoot; + while (tmp2 != null && tmp2.rightSib != null && tmp2.rightSib.rightSib != null) + { + if (tmp2.rightSib.degree != tmp2.rightSib.rightSib.degree) + { + tmp2 = tmp2.rightSib; + } else if ((tmp2.rightSib.rightSib.rightSib != null) && + (tmp2.rightSib.rightSib.degree == tmp2.rightSib.rightSib.rightSib.degree)) + { + tmp2 = tmp2.rightSib; + } + else + { + this.cmd("Disconnect", tmp2.rightSib.internalGraphicID, tmp2.rightSib.rightSib.internalGraphicID); + this.cmd("Disconnect", tmp2.internalGraphicID, tmp2.rightSib.internalGraphicID); + if (tmp2.rightSib.rightSib.rightSib != null) + { + this.cmd("Disconnect", tmp2.rightSib.rightSib.internalGraphicID, tmp2.rightSib.rightSib.rightSib.internalGraphicID); + } + + var tempRoot; + if (tmp2.rightSib.data < tmp2.rightSib.rightSib.data) + { + tmp = tmp2.rightSib.rightSib; + tmp2.rightSib.rightSib = tmp.rightSib; + + tmp.rightSib = tmp2.rightSib.leftChild; + tmp2.rightSib.leftChild = tmp; + tmp.parent = tmp2.rightSib; + tmp2.rightSib.degree++; + this.cmd("SetText", tmp2.rightSib.degreeID, tmp2.rightSib.degree); + tempRoot = tmp2.rightSib; + + } + else + { + tmp = tmp2.rightSib; + tmp2.rightSib = tmp2.rightSib.rightSib; + tmp.rightSib = tmp2.rightSib.leftChild; + tmp2.rightSib.leftChild = tmp; + tmp.parent = tmp2.rightSib; + tmp2.rightSib.degree++; + this.cmd("SetText", tmp2.rightSib.degreeID, tmp2.rightSib.degree); + tempRoot = tmp2.rightSib; + } + this.cmd("Connect", tempRoot.graphicID, + tempRoot.leftChild.graphicID, + FOREGROUND_COLOR, + 0, // Curve + 0, // Directed + ""); // Label + + this.cmd("Connect", tempRoot.internalGraphicID, + tempRoot.leftChild.internalGraphicID, + FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", tempRoot.leftChild.internalGraphicID, + tempRoot.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", tmp2.internalGraphicID, + tempRoot.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + if (tempRoot.leftChild.rightSib != null) + { + this.cmd("Disconnect",tempRoot.internalGraphicID, tempRoot.leftChild.rightSib.internalGraphicID); + this.cmd("Connect",tempRoot.leftChild.internalGraphicID, + tempRoot.leftChild.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label); + } + if (tempRoot.rightSib != null) + { + this.cmd("Connect",tempRoot.internalGraphicID, + tempRoot.rightSib.internalGraphicID, + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label); + } + + + + + this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.moveTree(this.treeRoot); + this.cmd("Step"); + } + } +} + + +BinomialQueue.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +BinomialQueue.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new BinomialQueue(animManag, canvas.width, canvas.height); +} + + + + +function BinomialNode(val, id, initialX, initialY) +{ + this.data = val; + this.x = initialX; + this.y = initialY; + this.graphicID = id; + this.degree = 0; + this.leftChild = null; + this.rightSib = null; + this.parent = null; + this.internalGraphicID = -1; + this.degreeID = -1; +} + + diff --git a/AlgorithmLibrary/ChangingCoordinate2D.js b/AlgorithmLibrary/ChangingCoordinate2D.js index 6794e24..5581433 100644 --- a/AlgorithmLibrary/ChangingCoordinate2D.js +++ b/AlgorithmLibrary/ChangingCoordinate2D.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/ChangingCoordinate3D.js b/AlgorithmLibrary/ChangingCoordinate3D.js index 93cc6cb..3945850 100644 --- a/AlgorithmLibrary/ChangingCoordinate3D.js +++ b/AlgorithmLibrary/ChangingCoordinate3D.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/DPChange.js b/AlgorithmLibrary/DPChange.js index 272ba12..8791a12 100644 --- a/AlgorithmLibrary/DPChange.js +++ b/AlgorithmLibrary/DPChange.js @@ -1,983 +1,983 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function DPChange(am, w, h) -{ - this.init(am, w, h); - -} - -DPChange.inheritFrom(Algorithm); - -DPChange.TABLE_ELEM_WIDTH = 30; -DPChange.TABLE_ELEM_HEIGHT = 30; - -DPChange.TABLE_START_X = 500; -DPChange.TABLE_START_Y = 50; -DPChange.TABLE_DIFF_X = 70; - -DPChange.CODE_START_X = 10; -DPChange.CODE_START_Y = 10; -DPChange.CODE_LINE_HEIGHT = 14; - - -DPChange.GREEDY_START_X = 100; -DPChange.GREEDY_START_Y = 150; -DPChange.RECURSIVE_START_X = 220; -DPChange.RECURSIVE_START_Y = 10; -DPChange.RECURSIVE_DELTA_Y = 14; -DPChange.RECURSIVE_DELTA_X = 8; -DPChange.CODE_HIGHLIGHT_COLOR = "#FF0000"; -DPChange.CODE_STANDARD_COLOR = "#000000"; - -DPChange.TABLE_INDEX_COLOR = "#0000FF" -DPChange.CODE_RECURSIVE_1_COLOR = "#339933"; -DPChange.CODE_RECURSIVE_2_COLOR = "#0099FF"; - -DPChange.DPCode = [["def ","change(n, coinArray)",":"], - [" if ","(n == 0) "], - [" return 0"], - [" best = -1"], - [" for coin in coinArray:"], - [" if ","(coin <= n)",":"], - [" nextTry = ","change(n - coin, coinArray)"], - [" if (", "best < 0", " or ", "best > nextTry + 1", ")"], - [" best = nextTry + 1"], - [" return best"]]; - - -DPChange.GREEDYCode = [["def ","changeGreedy(n, coinArray)",":"], - [" coinsRequired = 0"], - [" for coin in reversed(coinArray): "], - [" while ", "(n <= coin)"], - [" n = n - coin"], - [" coinsRequired = coinsRequired + 1"], - [" return coinsRequired"]]; - - -DPChange.COINS = [[1, 5, 10, 25], - [1, 4, 6, 10]]; - - -DPChange.MAX_VALUE = 30; - -DPChange.MESSAGE_ID = 0; - - -DPChange.prototype.setCode = function(codeArray) -{ - this.code = codeArray; - this.codeID = Array(this.code.length); - var i, j; - for (i = 0; i < this.code.length; i++) - { - this.codeID[i] = new Array(this.code[i].length); - for (j = 0; j < this.code[i].length; j++) - { - this.codeID[i][j] = this.nextIndex++; - this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPChange.CODE_START_X, DPChange.CODE_START_Y + i * DPChange.CODE_LINE_HEIGHT, 0); - this.cmd("SetForegroundColor", this.codeID[i][j], DPChange.CODE_STANDARD_COLOR); - if (j > 0) - { - this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); - } - } - } -} - - -DPChange.prototype.deleteCode = function() -{ - var i,j - for (i = 0; i < this.codeID.length; i++) - { - for (j = 0; j < this.codeID[i].length; j++) - { - this.cmd("Delete", this.codeID[i][j]); - } - } - this.codeID = []; -} - -DPChange.prototype.setCodeAlpha = function(codeArray, alpha) -{ - var i, j - for (i = 0; i < codeArray.length; i++) - { - var foo = 3; - foo = codeArray[i]; - for (j = 0; j < codeArray[i].length; j++) - { - this.cmd("SetAlpha", codeArray[i][j], alpha); - } - } -} - - - -DPChange.prototype.init = function(am, w, h) -{ - DPChange.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - // HACK!! - this.setCode(DPChange.GREEDYCode); - this.greedyCodeID = this.codeID; - this.setCodeAlpha(this.greedyCodeID, 0); - /// - this.setCode(DPChange.DPCode); - this.usingDPCode = true; - - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -DPChange.prototype.addControls = function() -{ - this.controls = []; - this.fibField = this.addControlToAlgorithmBar("Text", ""); - this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); - this.controls.push(this.fibField); - - this.recursiveButton = this.addControlToAlgorithmBar("Button", "Change Recursive"); - this.recursiveButton.onclick = this.recursiveCallback.bind(this); - this.controls.push(this.recursiveButton); - - this.tableButton = this.addControlToAlgorithmBar("Button", "Change Table"); - this.tableButton.onclick = this.tableCallback.bind(this); - this.controls.push(this.tableButton); - - this.memoizedButton = this.addControlToAlgorithmBar("Button", "Change Memoized"); - this.memoizedButton.onclick = this.memoizedCallback.bind(this); - this.controls.push(this.memoizedButton); - - - this.greedyButton = this.addControlToAlgorithmBar("Button", "Change Greedy"); - this.greedyButton.onclick = this.greedyCallback.bind(this); - this.controls.push(this.greedyButton); - - - - - var coinLabels = []; - var i, j; - for (i = 0; i < DPChange.COINS.length; i++) - { - var nextLabel = "Coins: [" + DPChange.COINS[i][0]; - for (j = 1; j < DPChange.COINS[i].length; j++) - { - nextLabel = nextLabel + ", " + DPChange.COINS[i][j]; - } - nextLabel = nextLabel + "]"; - coinLabels.push(nextLabel); - } - - this.coinTypeButtons = this.addRadioButtonGroupToAlgorithmBar(coinLabels, "CoinType"); - - for (i = 0; i < this.coinTypeButtons.length; i++) - { - this.coinTypeButtons[i].onclick = this.coinTypeChangedCallback.bind(this, i); - this.controls.push(this.coinTypeButtons[i]); - } - - this.coinTypeButtons[0].checked = true; - this.coinIndex = 0; -} - - - -DPChange.prototype.coinTypeChangedCallback = function(coinIndex) -{ - this.implementAction(this.coinTypeChanged.bind(this), coinIndex); -} - - -DPChange.prototype.coinTypeChanged = function(coinIndex) -{ - this.commands = []; - this.coinIndex = coinIndex; - this.coinTypeButtons[coinIndex].checked = true; - this.clearOldIDs(); - - return this.commands; -} - - - - - -DPChange.prototype.greedyCallback = function(value) -{ - - if (this.fibField.value != "") - { - this.implementAction(this.implementGreedy.bind(this),parseInt(this.fibField.value)); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - - -DPChange.prototype.implementGreedy = function(value) -{ - this.commands = []; - this.clearOldIDs(); - var initialValue = value; - if (this.usingDPCode) - { - this.setCodeAlpha(this.greedyCodeID, 1); - this.setCodeAlpha(this.codeID, 0); - this.usingDPCode = false; - } - - var currX = DPChange.GREEDY_START_X; - var currY = DPChange.GREEDY_START_Y + 2.5 * DPChange.TABLE_ELEM_HEIGHT; - - var messageID = this.nextIndex++; - this.oldIDs.push(messageID); - - var valueRemainingID = this.nextIndex++; - this.oldIDs.push(valueRemainingID); - - this.cmd("CreateRectangle", valueRemainingID, value, DPChange.TABLE_ELEM_WIDTH, - DPChange.TABLE_ELEM_HEIGHT, - DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y); - - var tempLabel = this.nextIndex++; - this.oldIDs.push(tempLabel); - this.cmd("CreateLabel", tempLabel, "Amount remaining:",0, 0); - this.cmd("AlignLeft", tempLabel, valueRemainingID); - - var requiredCoinsID = this.nextIndex++; - this.oldIDs.push(requiredCoinsID); - - this.cmd("CreateRectangle", requiredCoinsID, value, DPChange.TABLE_ELEM_WIDTH, - DPChange.TABLE_ELEM_HEIGHT, - DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y + DPChange.TABLE_ELEM_HEIGHT); - - tempLabel = this.nextIndex++; - this.oldIDs.push(tempLabel); - this.cmd("CreateLabel", tempLabel, "Required Coins:",0, 0); - this.cmd("AlignLeft", tempLabel, requiredCoinsID); - - - var requiredCoins = 0; - var i; - for (i = DPChange.COINS[this.coinIndex].length - 1; i >=0; i--) - { - while (value >= DPChange.COINS[this.coinIndex][i]) - { - requiredCoins = requiredCoins + 1; - value = value - DPChange.COINS[this.coinIndex][i]; - this.cmd("SetText", valueRemainingID, value); - this.cmd("SetText", requiredCoinsID, requiredCoins); - var moveIndex = this.nextIndex++; - this.oldIDs.push(moveIndex); - this.cmd("CreateLabel", moveIndex, DPChange.COINS[this.coinIndex][i], DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y); - this.cmd("Move", moveIndex, currX, currY); - currX += DPChange.TABLE_ELEM_WIDTH; - this.cmd("Step"); - } - - } - - this.cmd("CreateLabel", messageID, - "changeGreedy(" + String(initialValue)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(requiredCoins), - DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y, 0); - - return this.commands; -} - - - - -DPChange.prototype.buildTable = function(maxVal) -{ - - this.tableID = new Array(2); - this.tableVals = new Array(2); - this.tableXPos = new Array(2); - this.tableYPos = new Array(2); - var i; - for (i = 0; i < 2; i++) - { - this.tableID[i] = new Array(maxVal + 1); - this.tableVals[i] = new Array(maxVal + 1); - this.tableXPos[i] = new Array(maxVal + 1); - this.tableYPos[i] = new Array(maxVal + 1); - } - - var j; - var indexID; - var xPos; - var yPos; - var table_rows = Math.floor((this.canvasHeight - DPChange.TABLE_ELEM_HEIGHT - DPChange.TABLE_START_Y) / DPChange.TABLE_ELEM_HEIGHT); - var table_cols = Math.ceil((maxVal + 1) / table_rows); - - var header1ID = this.nextIndex++; - this.oldIDs.push(header1ID); - - this.cmd("CreateLabel", header1ID, "# of Coins Required", DPChange.TABLE_START_X, DPChange.TABLE_START_Y - 30); - - - var header2ID = this.nextIndex++; - this.oldIDs.push(header2ID); - - this.cmd("CreateLabel", header2ID, "Coins to Use", DPChange.TABLE_START_X + table_cols*DPChange.TABLE_DIFF_X + 1.5*DPChange.TABLE_DIFF_X, DPChange.TABLE_START_Y - 30); - - - - for (i = 0; i <= maxVal; i++) - { - yPos = i % table_rows * DPChange.TABLE_ELEM_HEIGHT + DPChange.TABLE_START_Y; - xPos = Math.floor(i / table_rows) * DPChange.TABLE_DIFF_X + DPChange.TABLE_START_X; - - for (j = 0; j < 2; j++) - { - - this.tableID[j][i] = this.nextIndex++; - this.tableVals[j][i] = -1; - this.oldIDs.push(this.tableID[j][i]); - - - this.tableXPos[j][i] = xPos; - this.tableYPos[j][i] = yPos; - - this.cmd("CreateRectangle", this.tableID[j][i], - "", - DPChange.TABLE_ELEM_WIDTH, - DPChange.TABLE_ELEM_HEIGHT, - xPos, - yPos); - indexID = this.nextIndex++; - this.oldIDs.push(indexID); - this.cmd("CreateLabel", indexID, i, xPos - DPChange.TABLE_ELEM_WIDTH, yPos); - this.cmd("SetForegroundColor", indexID, DPChange.TABLE_INDEX_COLOR); - - xPos = xPos + table_cols * DPChange.TABLE_DIFF_X + 1.5*DPChange.TABLE_DIFF_X; - } - - - - } -} - -DPChange.prototype.clearOldIDs = function() -{ - for (var i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs =[]; - this.nextIndex = this.initialIndex; - -} - - -DPChange.prototype.reset = function() -{ - this.oldIDs =[]; - this.coinIndex = 0; - this.usingDPCode = true; - this.coinTypeButtons[0].checked = true; - this.nextIndex = this.initialIndex; -} - - - -DPChange.prototype.emptyCallback = function(event) -{ - this.implementAction(this.helpMessage.bind(this), ""); - // TODO: Put up a message to push the appropriate button? - -} - -DPChange.prototype.displayCoinsUsed = function() -{ - var currValue = this.tableVals[1].length - 1; - var currX = 30; - var currY = 200; - - var moveID; - moveID = this.nextIndex++; - - while (currValue > 0) - { - moveID = this.nextIndex++; - this.oldIDs.push(moveID); - this.cmd("CreateLabel", moveID, this.tableVals[1][currValue], this.tableXPos[1][currValue], this.tableYPos[1][currValue]); - this.cmd("Move", moveID, currX, currY); - this.cmd("Step"); - currX += 20; - currValue = currValue - this.tableVals[1][currValue]; - } -} - -DPChange.prototype.recursiveCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var fibValue = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE - 5); - this.fibField.value = String(fibValue); - this.implementAction(this.recursiveChange.bind(this),fibValue); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - - -DPChange.prototype.tableCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var fibValue = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE); - this.fibField.value = String(fibValue); - this.implementAction(this.tableChange.bind(this),fibValue); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - - -DPChange.prototype.memoizedCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var changeVal = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE); - this.fibField.value = String(changeVal); - this.implementAction(this.memoizedChange.bind(this),changeVal); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - -DPChange.prototype.helpMessage = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - var messageID = this.nextIndex++; - this.oldIDs.push(messageID); - this.cmd("CreateLabel", messageID, - "Enter a value between 0 and " + String(DPChange.MAX_VALUE) + " in the text field.\n" + - "Then press the Change Recursive, Change Table, Change Memoized, or Change Greedy button", - DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y, 0); - return this.commands; - - -} - - -DPChange.prototype.recursiveChange = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - if (!this.usingDPCode) - { - this.setCodeAlpha(this.greedyCodeID, 0); - this.setCodeAlpha(this.codeID, 1); - this.usingDPCode = true; - } - - this.currentY = DPChange.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.change(value, DPChange.RECURSIVE_START_X, functionCallID); - this.cmd("SetText", functionCallID, "change(" + String(value)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(final[0])); - return this.commands; -} - - -DPChange.prototype.change = function(value, xPos, ID) -{ - var coins = DPChange.COINS[this.coinIndex]; - this.cmd("CreateLabel", ID, "change(" + String(value)+ ", [" +String(coins) +"])", xPos, this.currentY, 0); - this.currentY += DPChange.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); - // return 1; - if (value > 0) - { - this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_STANDARD_COLOR); - - var i; - var best = -1; - var nextID = this.nextIndex++; - var nextID2 = this.nextIndex++; - var recID = nextID; - var bestList; - for (i = 0; i < coins.length; i++) - { - this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_STANDARD_COLOR); - if (value >= coins[i]) - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_STANDARD_COLOR); - var nextTry = this.change(value - coins[i], xPos + DPChange.RECURSIVE_DELTA_X, recID); - // TODO: SOMEHTING ELSE HERE - if (best == -1) - { - this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_STANDARD_COLOR); - best = nextTry[0] + 1; - bestList = nextTry[1]; - bestList.push(coins[i]); - this.currentY += DPChange.RECURSIVE_DELTA_Y; - recID = nextID2; - } - else if (best > nextTry[0] + 1) - { - this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_STANDARD_COLOR); - best = nextTry[0] + 1; - bestList = nextTry[1]; - bestList.push(coins[i]);; - this.cmd("Delete", recID); - this.cmd("SetText", nextID, String(best) + " ([" + String(bestList) + "])"); - this.cmd("SetPosition", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); - this.cmd("Move", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY - DPChange.RECURSIVE_DELTA_Y); - this.cmd("Step"); - } - else - { - this.cmd("Delete", recID); - } - } - else - { - break; - } - } - this.cmd("Delete", nextID); - this.cmd("SetText", ID, String(best) + " ([" + String(bestList) + "])"); - this.cmd("SetPosition", ID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); - this.cmd("Move", ID, xPos, this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y); - - - this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; - - this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("Step"); - return [best, bestList]; - } - else - { - this.cmd("SetText", ID, "0"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); - - this.currentY -= DPChange.RECURSIVE_DELTA_Y; - return [0, []]; - } - - - -} - - - - -DPChange.prototype.tableChange = function(value) -{ - this.commands = []; - this.clearOldIDs(); - if (!this.usingDPCode) - { - this.setCodeAlpha(this.greedyCodeID, 0); - this.setCodeAlpha(this.codeID, 1); - this.usingDPCode = true; - } - - this.buildTable(value); - coins = DPChange.COINS[this.coinIndex]; - var i; - for (i = 0; i <= value && i <= 0; i++) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.tableID[0][i], 1); - this.cmd("SetText", this.tableID[0][i], 0); - this.tableVals[0][i] = 0; - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[0][i], 0); - } - for (i = 1; i <= value; i++) - { - this.tableVals[0][i] = -1; - var j; - for (j = 0; j < coins.length; j++) - { - if (coins[j] <= i) - { - this.cmd("SetHighlight", this.tableID[0][i-coins[j]], 1); - this.cmd("SetHighlight", this.tableID[0][i], 1); - this.cmd("Step"); - if (this.tableVals[0][i] == -1 || this.tableVals[0][i] > this.tableVals[0][i - coins[j]] + 1) - { - this.tableVals[0][i] = this.tableVals[0][i- coins[j]] + 1; - this.cmd("SetText", this.tableID[0][i], this.tableVals[0][i]); - this.cmd("SetHighlight", this.tableID[1][i], 1); - this.cmd("SetText", this.tableID[1][i], coins[j]); - this.tableVals[1][i] = coins[j]; - this.cmd("Step") - this.cmd("SetHighlight", this.tableID[1][i], 0); - } - this.cmd("SetHighlight", this.tableID[0][i-coins[j]], 0); - this.cmd("SetHighlight", this.tableID[0][i], 0); - } - } - } - - var finalID = this.nextIndex++; - this.oldIDs.push(finalID); - this.cmd("CreateLabel", finalID, this.tableVals[0][value], this.tableXPos[0][value] - 5, this.tableYPos[0][value] - 5, 0); - this.cmd("Move", finalID, DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y); - this.cmd("Step"); - this.cmd("SetText", finalID, "change(" + String(value) + ") = " + String(this.tableVals[0][value])); - - this.displayCoinsUsed(); - - return this.commands; - - -} - - - -DPChange.prototype.fibMem = function(value, xPos, ID) -{ - this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); - this.cmd("SetHighlight", this.tableID[value], 1); - // TODO: Add an extra pause here? - this.cmd("Step"); - if (this.tableVals[value] >= 0) - { - this.cmd("Delete", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); - this.cmd("Move", ID, xPos, this.currentY); - this.cmd("Step") - this.cmd("SetHighlight", this.tableID[value], 0); - return this.tableVals[value]; - } - this.cmd("SetHighlight", this.tableID[value], 0); - this.currentY += DPChange.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); - if (value > 1) - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_STANDARD_COLOR); - var firstValue = this.fibMem(value-1, xPos + DPChange.RECURSIVE_DELTA_X, firstID); - this.currentY += DPChange.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_STANDARD_COLOR); - var secondValue = this.fibMem(value-2, xPos + DPChange.RECURSIVE_DELTA_X, secondID); - - - this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", firstID, DPChange.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_RECURSIVE_2_COLOR); - this.cmd("SetForegroundColor", secondID, DPChange.CODE_RECURSIVE_2_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_STANDARD_COLOR); - - - - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.cmd("SetText", ID, firstValue + secondValue); - this.cmd("Step"); - this.tableVals[value] = firstValue + secondValue; - this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; - this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos+5, this.currentY + 5); - this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.cmd("SetText", this.tableID[value], this.tableVals[value]); - return firstValue + secondValue; - } - else - { - this.cmd("SetText", ID, "1"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); - this.tableVals[value] = 1; - this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos + 5, this.currentY + 5); - this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.cmd("SetText", this.tableID[value], this.tableVals[value]); - - this.currentY -= DPChange.RECURSIVE_DELTA_Y; - return 1; - } - -} - -DPChange.prototype.memoizedChange = function(value) -{ - this.commands = []; - - if (!this.usingDPCode) - { - this.setCodeAlpha(this.greedyCodeID, 0); - this.setCodeAlpha(this.codeID, 1); - this.usingDPCode = true; - } - - - this.clearOldIDs(); - this.buildTable(value); - - this.currentY = DPChange.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.changeMem(value, DPChange.RECURSIVE_START_X, functionCallID); - this.cmd("SetText", functionCallID, "change(" + String(value)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(final[0])); - return this.commands; - - this.currentY = DPChange.RECURSIVE_START_Y; - - return this.commands; -} - - - -DPChange.prototype.changeMem = function(value, xPos, ID) -{ - var coins = DPChange.COINS[this.coinIndex]; - this.cmd("CreateLabel", ID, "change(" + String(value)+ ", [" +String(coins) +"])", xPos, this.currentY, 0); - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.tableID[0][value], 1); - this.cmd("Step"); - if (this.tableVals[0][value] >= 0) - { - this.cmd("Delete", ID); - this.cmd("CreateLabel", ID, this.tableVals[0][value], this.tableXPos[0][value] - 5, this.tableYPos[0][value] - 5, 0); - this.cmd("Move", ID, xPos, this.currentY); - this.cmd("Step") - this.cmd("SetHighlight", this.tableID[0][value], 0); - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); - return [this.tableVals[0][value], []]; - } - this.cmd("SetHighlight", this.tableID[0][value], 0); - this.currentY += DPChange.RECURSIVE_DELTA_Y; - - - - this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); - // return 1; - if (value > 0) - { - this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_STANDARD_COLOR); - - var i; - var best = -1; - var nextID = this.nextIndex++; - var nextID2 = this.nextIndex++; - var recID = nextID; - var bestList; - for (i = 0; i < coins.length; i++) - { - this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_STANDARD_COLOR); - if (value >= coins[i]) - { - this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_STANDARD_COLOR); - var nextTry = this.changeMem(value - coins[i], xPos + DPChange.RECURSIVE_DELTA_X, recID); - // TODO: SOMEHTING ELSE HERE - if (best == -1) - { - this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_STANDARD_COLOR); - best = nextTry[0] + 1; - bestList = nextTry[1]; - bestList.push(coins[i]);; - this.currentY += DPChange.RECURSIVE_DELTA_Y; - recID = nextID2; - } - else if (best > nextTry[0] + 1) - { - this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_STANDARD_COLOR); - best = nextTry[0] + 1; - bestList = nextTry[1]; - bestList.push(coins[i]);; - this.cmd("Delete", recID); - this.cmd("SetText", nextID, String(best)); - this.cmd("SetPosition", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); - this.cmd("Move", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY - DPChange.RECURSIVE_DELTA_Y); - this.cmd("Step"); - } - else - { - this.cmd("Step"); - this.cmd("Delete", recID); - } - } - else - { - break; - } - } - this.cmd("Delete", nextID); - this.cmd("SetText", ID, String(best)); - this.cmd("SetText", this.tableID[0][value], best); - this.cmd("SetText", this.tableID[1][value], bestList[0]); - this.tableVals[0][value] = best; - this.tableVals[1][value] = bestList[0]; - - this.cmd("SetPosition", ID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); - this.cmd("Move", ID, xPos, this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y); - - - this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; - - this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("Step"); - return [best, bestList]; - } - else - { - this.cmd("SetText", ID, "0"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); - this.cmd("SetText", this.tableID[0][value], 0); - - this.currentY -= DPChange.RECURSIVE_DELTA_Y; - return [0, []]; - } - - - -} - - - -DPChange.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -DPChange.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new DPChange(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function DPChange(am, w, h) +{ + this.init(am, w, h); + +} + +DPChange.inheritFrom(Algorithm); + +DPChange.TABLE_ELEM_WIDTH = 30; +DPChange.TABLE_ELEM_HEIGHT = 30; + +DPChange.TABLE_START_X = 500; +DPChange.TABLE_START_Y = 50; +DPChange.TABLE_DIFF_X = 70; + +DPChange.CODE_START_X = 10; +DPChange.CODE_START_Y = 10; +DPChange.CODE_LINE_HEIGHT = 14; + + +DPChange.GREEDY_START_X = 100; +DPChange.GREEDY_START_Y = 150; +DPChange.RECURSIVE_START_X = 220; +DPChange.RECURSIVE_START_Y = 10; +DPChange.RECURSIVE_DELTA_Y = 14; +DPChange.RECURSIVE_DELTA_X = 8; +DPChange.CODE_HIGHLIGHT_COLOR = "#FF0000"; +DPChange.CODE_STANDARD_COLOR = "#000000"; + +DPChange.TABLE_INDEX_COLOR = "#0000FF" +DPChange.CODE_RECURSIVE_1_COLOR = "#339933"; +DPChange.CODE_RECURSIVE_2_COLOR = "#0099FF"; + +DPChange.DPCode = [["def ","change(n, coinArray)",":"], + [" if ","(n == 0) "], + [" return 0"], + [" best = -1"], + [" for coin in coinArray:"], + [" if ","(coin <= n)",":"], + [" nextTry = ","change(n - coin, coinArray)"], + [" if (", "best < 0", " or ", "best > nextTry + 1", ")"], + [" best = nextTry + 1"], + [" return best"]]; + + +DPChange.GREEDYCode = [["def ","changeGreedy(n, coinArray)",":"], + [" coinsRequired = 0"], + [" for coin in reversed(coinArray): "], + [" while ", "(n <= coin)"], + [" n = n - coin"], + [" coinsRequired = coinsRequired + 1"], + [" return coinsRequired"]]; + + +DPChange.COINS = [[1, 5, 10, 25], + [1, 4, 6, 10]]; + + +DPChange.MAX_VALUE = 30; + +DPChange.MESSAGE_ID = 0; + + +DPChange.prototype.setCode = function(codeArray) +{ + this.code = codeArray; + this.codeID = Array(this.code.length); + var i, j; + for (i = 0; i < this.code.length; i++) + { + this.codeID[i] = new Array(this.code[i].length); + for (j = 0; j < this.code[i].length; j++) + { + this.codeID[i][j] = this.nextIndex++; + this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPChange.CODE_START_X, DPChange.CODE_START_Y + i * DPChange.CODE_LINE_HEIGHT, 0); + this.cmd("SetForegroundColor", this.codeID[i][j], DPChange.CODE_STANDARD_COLOR); + if (j > 0) + { + this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); + } + } + } +} + + +DPChange.prototype.deleteCode = function() +{ + var i,j + for (i = 0; i < this.codeID.length; i++) + { + for (j = 0; j < this.codeID[i].length; j++) + { + this.cmd("Delete", this.codeID[i][j]); + } + } + this.codeID = []; +} + +DPChange.prototype.setCodeAlpha = function(codeArray, alpha) +{ + var i, j + for (i = 0; i < codeArray.length; i++) + { + var foo = 3; + foo = codeArray[i]; + for (j = 0; j < codeArray[i].length; j++) + { + this.cmd("SetAlpha", codeArray[i][j], alpha); + } + } +} + + + +DPChange.prototype.init = function(am, w, h) +{ + DPChange.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + // HACK!! + this.setCode(DPChange.GREEDYCode); + this.greedyCodeID = this.codeID; + this.setCodeAlpha(this.greedyCodeID, 0); + /// + this.setCode(DPChange.DPCode); + this.usingDPCode = true; + + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +DPChange.prototype.addControls = function() +{ + this.controls = []; + this.fibField = this.addControlToAlgorithmBar("Text", ""); + this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); + this.controls.push(this.fibField); + + this.recursiveButton = this.addControlToAlgorithmBar("Button", "Change Recursive"); + this.recursiveButton.onclick = this.recursiveCallback.bind(this); + this.controls.push(this.recursiveButton); + + this.tableButton = this.addControlToAlgorithmBar("Button", "Change Table"); + this.tableButton.onclick = this.tableCallback.bind(this); + this.controls.push(this.tableButton); + + this.memoizedButton = this.addControlToAlgorithmBar("Button", "Change Memoized"); + this.memoizedButton.onclick = this.memoizedCallback.bind(this); + this.controls.push(this.memoizedButton); + + + this.greedyButton = this.addControlToAlgorithmBar("Button", "Change Greedy"); + this.greedyButton.onclick = this.greedyCallback.bind(this); + this.controls.push(this.greedyButton); + + + + + var coinLabels = []; + var i, j; + for (i = 0; i < DPChange.COINS.length; i++) + { + var nextLabel = "Coins: [" + DPChange.COINS[i][0]; + for (j = 1; j < DPChange.COINS[i].length; j++) + { + nextLabel = nextLabel + ", " + DPChange.COINS[i][j]; + } + nextLabel = nextLabel + "]"; + coinLabels.push(nextLabel); + } + + this.coinTypeButtons = this.addRadioButtonGroupToAlgorithmBar(coinLabels, "CoinType"); + + for (i = 0; i < this.coinTypeButtons.length; i++) + { + this.coinTypeButtons[i].onclick = this.coinTypeChangedCallback.bind(this, i); + this.controls.push(this.coinTypeButtons[i]); + } + + this.coinTypeButtons[0].checked = true; + this.coinIndex = 0; +} + + + +DPChange.prototype.coinTypeChangedCallback = function(coinIndex) +{ + this.implementAction(this.coinTypeChanged.bind(this), coinIndex); +} + + +DPChange.prototype.coinTypeChanged = function(coinIndex) +{ + this.commands = []; + this.coinIndex = coinIndex; + this.coinTypeButtons[coinIndex].checked = true; + this.clearOldIDs(); + + return this.commands; +} + + + + + +DPChange.prototype.greedyCallback = function(value) +{ + + if (this.fibField.value != "") + { + this.implementAction(this.implementGreedy.bind(this),parseInt(this.fibField.value)); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + + +DPChange.prototype.implementGreedy = function(value) +{ + this.commands = []; + this.clearOldIDs(); + var initialValue = value; + if (this.usingDPCode) + { + this.setCodeAlpha(this.greedyCodeID, 1); + this.setCodeAlpha(this.codeID, 0); + this.usingDPCode = false; + } + + var currX = DPChange.GREEDY_START_X; + var currY = DPChange.GREEDY_START_Y + 2.5 * DPChange.TABLE_ELEM_HEIGHT; + + var messageID = this.nextIndex++; + this.oldIDs.push(messageID); + + var valueRemainingID = this.nextIndex++; + this.oldIDs.push(valueRemainingID); + + this.cmd("CreateRectangle", valueRemainingID, value, DPChange.TABLE_ELEM_WIDTH, + DPChange.TABLE_ELEM_HEIGHT, + DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y); + + var tempLabel = this.nextIndex++; + this.oldIDs.push(tempLabel); + this.cmd("CreateLabel", tempLabel, "Amount remaining:",0, 0); + this.cmd("AlignLeft", tempLabel, valueRemainingID); + + var requiredCoinsID = this.nextIndex++; + this.oldIDs.push(requiredCoinsID); + + this.cmd("CreateRectangle", requiredCoinsID, value, DPChange.TABLE_ELEM_WIDTH, + DPChange.TABLE_ELEM_HEIGHT, + DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y + DPChange.TABLE_ELEM_HEIGHT); + + tempLabel = this.nextIndex++; + this.oldIDs.push(tempLabel); + this.cmd("CreateLabel", tempLabel, "Required Coins:",0, 0); + this.cmd("AlignLeft", tempLabel, requiredCoinsID); + + + var requiredCoins = 0; + var i; + for (i = DPChange.COINS[this.coinIndex].length - 1; i >=0; i--) + { + while (value >= DPChange.COINS[this.coinIndex][i]) + { + requiredCoins = requiredCoins + 1; + value = value - DPChange.COINS[this.coinIndex][i]; + this.cmd("SetText", valueRemainingID, value); + this.cmd("SetText", requiredCoinsID, requiredCoins); + var moveIndex = this.nextIndex++; + this.oldIDs.push(moveIndex); + this.cmd("CreateLabel", moveIndex, DPChange.COINS[this.coinIndex][i], DPChange.GREEDY_START_X, DPChange.GREEDY_START_Y); + this.cmd("Move", moveIndex, currX, currY); + currX += DPChange.TABLE_ELEM_WIDTH; + this.cmd("Step"); + } + + } + + this.cmd("CreateLabel", messageID, + "changeGreedy(" + String(initialValue)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(requiredCoins), + DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y, 0); + + return this.commands; +} + + + + +DPChange.prototype.buildTable = function(maxVal) +{ + + this.tableID = new Array(2); + this.tableVals = new Array(2); + this.tableXPos = new Array(2); + this.tableYPos = new Array(2); + var i; + for (i = 0; i < 2; i++) + { + this.tableID[i] = new Array(maxVal + 1); + this.tableVals[i] = new Array(maxVal + 1); + this.tableXPos[i] = new Array(maxVal + 1); + this.tableYPos[i] = new Array(maxVal + 1); + } + + var j; + var indexID; + var xPos; + var yPos; + var table_rows = Math.floor((this.canvasHeight - DPChange.TABLE_ELEM_HEIGHT - DPChange.TABLE_START_Y) / DPChange.TABLE_ELEM_HEIGHT); + var table_cols = Math.ceil((maxVal + 1) / table_rows); + + var header1ID = this.nextIndex++; + this.oldIDs.push(header1ID); + + this.cmd("CreateLabel", header1ID, "# of Coins Required", DPChange.TABLE_START_X, DPChange.TABLE_START_Y - 30); + + + var header2ID = this.nextIndex++; + this.oldIDs.push(header2ID); + + this.cmd("CreateLabel", header2ID, "Coins to Use", DPChange.TABLE_START_X + table_cols*DPChange.TABLE_DIFF_X + 1.5*DPChange.TABLE_DIFF_X, DPChange.TABLE_START_Y - 30); + + + + for (i = 0; i <= maxVal; i++) + { + yPos = i % table_rows * DPChange.TABLE_ELEM_HEIGHT + DPChange.TABLE_START_Y; + xPos = Math.floor(i / table_rows) * DPChange.TABLE_DIFF_X + DPChange.TABLE_START_X; + + for (j = 0; j < 2; j++) + { + + this.tableID[j][i] = this.nextIndex++; + this.tableVals[j][i] = -1; + this.oldIDs.push(this.tableID[j][i]); + + + this.tableXPos[j][i] = xPos; + this.tableYPos[j][i] = yPos; + + this.cmd("CreateRectangle", this.tableID[j][i], + "", + DPChange.TABLE_ELEM_WIDTH, + DPChange.TABLE_ELEM_HEIGHT, + xPos, + yPos); + indexID = this.nextIndex++; + this.oldIDs.push(indexID); + this.cmd("CreateLabel", indexID, i, xPos - DPChange.TABLE_ELEM_WIDTH, yPos); + this.cmd("SetForegroundColor", indexID, DPChange.TABLE_INDEX_COLOR); + + xPos = xPos + table_cols * DPChange.TABLE_DIFF_X + 1.5*DPChange.TABLE_DIFF_X; + } + + + + } +} + +DPChange.prototype.clearOldIDs = function() +{ + for (var i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs =[]; + this.nextIndex = this.initialIndex; + +} + + +DPChange.prototype.reset = function() +{ + this.oldIDs =[]; + this.coinIndex = 0; + this.usingDPCode = true; + this.coinTypeButtons[0].checked = true; + this.nextIndex = this.initialIndex; +} + + + +DPChange.prototype.emptyCallback = function(event) +{ + this.implementAction(this.helpMessage.bind(this), ""); + // TODO: Put up a message to push the appropriate button? + +} + +DPChange.prototype.displayCoinsUsed = function() +{ + var currValue = this.tableVals[1].length - 1; + var currX = 30; + var currY = 200; + + var moveID; + moveID = this.nextIndex++; + + while (currValue > 0) + { + moveID = this.nextIndex++; + this.oldIDs.push(moveID); + this.cmd("CreateLabel", moveID, this.tableVals[1][currValue], this.tableXPos[1][currValue], this.tableYPos[1][currValue]); + this.cmd("Move", moveID, currX, currY); + this.cmd("Step"); + currX += 20; + currValue = currValue - this.tableVals[1][currValue]; + } +} + +DPChange.prototype.recursiveCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var fibValue = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE - 5); + this.fibField.value = String(fibValue); + this.implementAction(this.recursiveChange.bind(this),fibValue); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + + +DPChange.prototype.tableCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var fibValue = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE); + this.fibField.value = String(fibValue); + this.implementAction(this.tableChange.bind(this),fibValue); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + + +DPChange.prototype.memoizedCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var changeVal = Math.min(parseInt(this.fibField.value), DPChange.MAX_VALUE); + this.fibField.value = String(changeVal); + this.implementAction(this.memoizedChange.bind(this),changeVal); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + +DPChange.prototype.helpMessage = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + var messageID = this.nextIndex++; + this.oldIDs.push(messageID); + this.cmd("CreateLabel", messageID, + "Enter a value between 0 and " + String(DPChange.MAX_VALUE) + " in the text field.\n" + + "Then press the Change Recursive, Change Table, Change Memoized, or Change Greedy button", + DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y, 0); + return this.commands; + + +} + + +DPChange.prototype.recursiveChange = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + if (!this.usingDPCode) + { + this.setCodeAlpha(this.greedyCodeID, 0); + this.setCodeAlpha(this.codeID, 1); + this.usingDPCode = true; + } + + this.currentY = DPChange.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.change(value, DPChange.RECURSIVE_START_X, functionCallID); + this.cmd("SetText", functionCallID, "change(" + String(value)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(final[0])); + return this.commands; +} + + +DPChange.prototype.change = function(value, xPos, ID) +{ + var coins = DPChange.COINS[this.coinIndex]; + this.cmd("CreateLabel", ID, "change(" + String(value)+ ", [" +String(coins) +"])", xPos, this.currentY, 0); + this.currentY += DPChange.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); + // return 1; + if (value > 0) + { + this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_STANDARD_COLOR); + + var i; + var best = -1; + var nextID = this.nextIndex++; + var nextID2 = this.nextIndex++; + var recID = nextID; + var bestList; + for (i = 0; i < coins.length; i++) + { + this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_STANDARD_COLOR); + if (value >= coins[i]) + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_STANDARD_COLOR); + var nextTry = this.change(value - coins[i], xPos + DPChange.RECURSIVE_DELTA_X, recID); + // TODO: SOMEHTING ELSE HERE + if (best == -1) + { + this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_STANDARD_COLOR); + best = nextTry[0] + 1; + bestList = nextTry[1]; + bestList.push(coins[i]); + this.currentY += DPChange.RECURSIVE_DELTA_Y; + recID = nextID2; + } + else if (best > nextTry[0] + 1) + { + this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_STANDARD_COLOR); + best = nextTry[0] + 1; + bestList = nextTry[1]; + bestList.push(coins[i]);; + this.cmd("Delete", recID); + this.cmd("SetText", nextID, String(best) + " ([" + String(bestList) + "])"); + this.cmd("SetPosition", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); + this.cmd("Move", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY - DPChange.RECURSIVE_DELTA_Y); + this.cmd("Step"); + } + else + { + this.cmd("Delete", recID); + } + } + else + { + break; + } + } + this.cmd("Delete", nextID); + this.cmd("SetText", ID, String(best) + " ([" + String(bestList) + "])"); + this.cmd("SetPosition", ID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); + this.cmd("Move", ID, xPos, this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y); + + + this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; + + this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("Step"); + return [best, bestList]; + } + else + { + this.cmd("SetText", ID, "0"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); + + this.currentY -= DPChange.RECURSIVE_DELTA_Y; + return [0, []]; + } + + + +} + + + + +DPChange.prototype.tableChange = function(value) +{ + this.commands = []; + this.clearOldIDs(); + if (!this.usingDPCode) + { + this.setCodeAlpha(this.greedyCodeID, 0); + this.setCodeAlpha(this.codeID, 1); + this.usingDPCode = true; + } + + this.buildTable(value); + coins = DPChange.COINS[this.coinIndex]; + var i; + for (i = 0; i <= value && i <= 0; i++) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.tableID[0][i], 1); + this.cmd("SetText", this.tableID[0][i], 0); + this.tableVals[0][i] = 0; + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[0][i], 0); + } + for (i = 1; i <= value; i++) + { + this.tableVals[0][i] = -1; + var j; + for (j = 0; j < coins.length; j++) + { + if (coins[j] <= i) + { + this.cmd("SetHighlight", this.tableID[0][i-coins[j]], 1); + this.cmd("SetHighlight", this.tableID[0][i], 1); + this.cmd("Step"); + if (this.tableVals[0][i] == -1 || this.tableVals[0][i] > this.tableVals[0][i - coins[j]] + 1) + { + this.tableVals[0][i] = this.tableVals[0][i- coins[j]] + 1; + this.cmd("SetText", this.tableID[0][i], this.tableVals[0][i]); + this.cmd("SetHighlight", this.tableID[1][i], 1); + this.cmd("SetText", this.tableID[1][i], coins[j]); + this.tableVals[1][i] = coins[j]; + this.cmd("Step") + this.cmd("SetHighlight", this.tableID[1][i], 0); + } + this.cmd("SetHighlight", this.tableID[0][i-coins[j]], 0); + this.cmd("SetHighlight", this.tableID[0][i], 0); + } + } + } + + var finalID = this.nextIndex++; + this.oldIDs.push(finalID); + this.cmd("CreateLabel", finalID, this.tableVals[0][value], this.tableXPos[0][value] - 5, this.tableYPos[0][value] - 5, 0); + this.cmd("Move", finalID, DPChange.RECURSIVE_START_X, DPChange.RECURSIVE_START_Y); + this.cmd("Step"); + this.cmd("SetText", finalID, "change(" + String(value) + ") = " + String(this.tableVals[0][value])); + + this.displayCoinsUsed(); + + return this.commands; + + +} + + + +DPChange.prototype.fibMem = function(value, xPos, ID) +{ + this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); + this.cmd("SetHighlight", this.tableID[value], 1); + // TODO: Add an extra pause here? + this.cmd("Step"); + if (this.tableVals[value] >= 0) + { + this.cmd("Delete", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); + this.cmd("Move", ID, xPos, this.currentY); + this.cmd("Step") + this.cmd("SetHighlight", this.tableID[value], 0); + return this.tableVals[value]; + } + this.cmd("SetHighlight", this.tableID[value], 0); + this.currentY += DPChange.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); + if (value > 1) + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_STANDARD_COLOR); + var firstValue = this.fibMem(value-1, xPos + DPChange.RECURSIVE_DELTA_X, firstID); + this.currentY += DPChange.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_STANDARD_COLOR); + var secondValue = this.fibMem(value-2, xPos + DPChange.RECURSIVE_DELTA_X, secondID); + + + this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", firstID, DPChange.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_RECURSIVE_2_COLOR); + this.cmd("SetForegroundColor", secondID, DPChange.CODE_RECURSIVE_2_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPChange.CODE_STANDARD_COLOR); + + + + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.cmd("SetText", ID, firstValue + secondValue); + this.cmd("Step"); + this.tableVals[value] = firstValue + secondValue; + this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; + this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos+5, this.currentY + 5); + this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.cmd("SetText", this.tableID[value], this.tableVals[value]); + return firstValue + secondValue; + } + else + { + this.cmd("SetText", ID, "1"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); + this.tableVals[value] = 1; + this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos + 5, this.currentY + 5); + this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.cmd("SetText", this.tableID[value], this.tableVals[value]); + + this.currentY -= DPChange.RECURSIVE_DELTA_Y; + return 1; + } + +} + +DPChange.prototype.memoizedChange = function(value) +{ + this.commands = []; + + if (!this.usingDPCode) + { + this.setCodeAlpha(this.greedyCodeID, 0); + this.setCodeAlpha(this.codeID, 1); + this.usingDPCode = true; + } + + + this.clearOldIDs(); + this.buildTable(value); + + this.currentY = DPChange.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.changeMem(value, DPChange.RECURSIVE_START_X, functionCallID); + this.cmd("SetText", functionCallID, "change(" + String(value)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(final[0])); + return this.commands; + + this.currentY = DPChange.RECURSIVE_START_Y; + + return this.commands; +} + + + +DPChange.prototype.changeMem = function(value, xPos, ID) +{ + var coins = DPChange.COINS[this.coinIndex]; + this.cmd("CreateLabel", ID, "change(" + String(value)+ ", [" +String(coins) +"])", xPos, this.currentY, 0); + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.tableID[0][value], 1); + this.cmd("Step"); + if (this.tableVals[0][value] >= 0) + { + this.cmd("Delete", ID); + this.cmd("CreateLabel", ID, this.tableVals[0][value], this.tableXPos[0][value] - 5, this.tableYPos[0][value] - 5, 0); + this.cmd("Move", ID, xPos, this.currentY); + this.cmd("Step") + this.cmd("SetHighlight", this.tableID[0][value], 0); + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); + return [this.tableVals[0][value], []]; + } + this.cmd("SetHighlight", this.tableID[0][value], 0); + this.currentY += DPChange.RECURSIVE_DELTA_Y; + + + + this.cmd("SetForegroundColor", this.codeID[0][1], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPChange.CODE_STANDARD_COLOR); + // return 1; + if (value > 0) + { + this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[3][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], DPChange.CODE_STANDARD_COLOR); + + var i; + var best = -1; + var nextID = this.nextIndex++; + var nextID2 = this.nextIndex++; + var recID = nextID; + var bestList; + for (i = 0; i < coins.length; i++) + { + this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][1], DPChange.CODE_STANDARD_COLOR); + if (value >= coins[i]) + { + this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][1], DPChange.CODE_STANDARD_COLOR); + var nextTry = this.changeMem(value - coins[i], xPos + DPChange.RECURSIVE_DELTA_X, recID); + // TODO: SOMEHTING ELSE HERE + if (best == -1) + { + this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[7][1], DPChange.CODE_STANDARD_COLOR); + best = nextTry[0] + 1; + bestList = nextTry[1]; + bestList.push(coins[i]);; + this.currentY += DPChange.RECURSIVE_DELTA_Y; + recID = nextID2; + } + else if (best > nextTry[0] + 1) + { + this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[7][2], DPChange.CODE_STANDARD_COLOR); + best = nextTry[0] + 1; + bestList = nextTry[1]; + bestList.push(coins[i]);; + this.cmd("Delete", recID); + this.cmd("SetText", nextID, String(best)); + this.cmd("SetPosition", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); + this.cmd("Move", nextID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY - DPChange.RECURSIVE_DELTA_Y); + this.cmd("Step"); + } + else + { + this.cmd("Step"); + this.cmd("Delete", recID); + } + } + else + { + break; + } + } + this.cmd("Delete", nextID); + this.cmd("SetText", ID, String(best)); + this.cmd("SetText", this.tableID[0][value], best); + this.cmd("SetText", this.tableID[1][value], bestList[0]); + this.tableVals[0][value] = best; + this.tableVals[1][value] = bestList[0]; + + this.cmd("SetPosition", ID, xPos + DPChange.RECURSIVE_DELTA_X, this.currentY); + this.cmd("Move", ID, xPos, this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y); + + + this.currentY = this.currentY - 2 * DPChange.RECURSIVE_DELTA_Y; + + this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[9][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("Step"); + return [best, bestList]; + } + else + { + this.cmd("SetText", ID, "0"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPChange.CODE_STANDARD_COLOR); + this.cmd("SetText", this.tableID[0][value], 0); + + this.currentY -= DPChange.RECURSIVE_DELTA_Y; + return [0, []]; + } + + + +} + + + +DPChange.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +DPChange.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new DPChange(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/DPFib.js b/AlgorithmLibrary/DPFib.js index 97fe96a..d8f3f12 100644 --- a/AlgorithmLibrary/DPFib.js +++ b/AlgorithmLibrary/DPFib.js @@ -1,520 +1,520 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function DPFib(am, w, h) -{ - this.init(am, w, h); - -} - -DPFib.inheritFrom(Algorithm); - -DPFib.TABLE_ELEM_WIDTH = 40; -DPFib.TABLE_ELEM_HEIGHT = 30; - -DPFib.TABLE_START_X = 500; -DPFib.TABLE_START_Y = 40; -DPFib.TABLE_DIFF_X = 100; - -DPFib.CODE_START_X = 10; -DPFib.CODE_START_Y = 10; -DPFib.CODE_LINE_HEIGHT = 14; - -DPFib.RECURSIVE_START_X = 20; -DPFib.RECURSIVE_START_Y = 120; -DPFib.RECURSIVE_DELTA_Y = 14; -DPFib.RECURSIVE_DELTA_X = 15; -DPFib.CODE_HIGHLIGHT_COLOR = "#FF0000"; -DPFib.CODE_STANDARD_COLOR = "#000000"; - -DPFib.TABLE_INDEX_COLOR = "#0000FF" -DPFib.CODE_RECURSIVE_1_COLOR = "#339933"; -DPFib.CODE_RECURSIVE_2_COLOR = "#0099FF"; - - - -DPFib.MAX_VALUE = 20; - -DPFib.MESSAGE_ID = 0; - -DPFib.prototype.init = function(am, w, h) -{ - DPFib.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = [["def ","fib(n)",":"], - [" if ","(n <= 1) "], - [" return 1"], - [" else"], - [" return ", "fib(n-1)", " + ", "fib(n-2)"]]; - - this.codeID = Array(this.code.length); - var i, j; - for (i = 0; i < this.code.length; i++) - { - this.codeID[i] = new Array(this.code[i].length); - for (j = 0; j < this.code[i].length; j++) - { - this.codeID[i][j] = this.nextIndex++; - this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPFib.CODE_START_X, DPFib.CODE_START_Y + i * DPFib.CODE_LINE_HEIGHT, 0); - this.cmd("SetForegroundColor", this.codeID[i][j], DPFib.CODE_STANDARD_COLOR); - if (j > 0) - { - this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); - } - } - - - } - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -DPFib.prototype.addControls = function() -{ - this.controls = []; - this.fibField = this.addControlToAlgorithmBar("Text", ""); - this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); - this.controls.push(this.fibField); - - this.recursiveButton = this.addControlToAlgorithmBar("Button", "Fibonacci Recursive"); - this.recursiveButton.onclick = this.recursiveCallback.bind(this); - this.controls.push(this.recursiveButton); - - this.tableButton = this.addControlToAlgorithmBar("Button", "Fibonacci Table"); - this.tableButton.onclick = this.tableCallback.bind(this); - this.controls.push(this.tableButton); - - this.memoizedButton = this.addControlToAlgorithmBar("Button", "Fibonacci Memoized"); - this.memoizedButton.onclick = this.memoizedCallback.bind(this); - this.controls.push(this.memoizedButton); - -} - - - -DPFib.prototype.buildTable = function(maxVal) -{ - this.tableID = new Array(maxVal + 1); - this.tableVals = new Array(maxVal + 1); - this.tableXPos = new Array(maxVal + 1); - this.tableYPos = new Array(maxVal + 1); - var i; - var indexID; - var xPos; - var yPos; - var table_rows = Math.floor((this.canvasHeight - DPFib.TABLE_ELEM_HEIGHT - DPFib.TABLE_START_Y) / DPFib.TABLE_ELEM_HEIGHT); - - for (i = 0; i <= maxVal; i++) - { - this.tableID[i] = this.nextIndex++; - this.tableVals[i] = -1; - this.oldIDs.push(this.tableID[i]); - - yPos = i % table_rows * DPFib.TABLE_ELEM_HEIGHT + DPFib.TABLE_START_Y; - xPos = Math.floor(i / table_rows) * DPFib.TABLE_DIFF_X + DPFib.TABLE_START_X; - - this.tableXPos[i] = xPos; - this.tableYPos[i] = yPos; - - this.cmd("CreateRectangle", this.tableID[i], - "", - DPFib.TABLE_ELEM_WIDTH, - DPFib.TABLE_ELEM_HEIGHT, - xPos, - yPos); - indexID = this.nextIndex++; - this.oldIDs.push(indexID); - this.cmd("CreateLabel", indexID, i, xPos - DPFib.TABLE_ELEM_WIDTH, yPos); - this.cmd("SetForegroundColor", indexID, DPFib.TABLE_INDEX_COLOR); - } -} - -DPFib.prototype.clearOldIDs = function() -{ - for (var i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs =[]; - this.nextIndex = this.initialIndex; - -} - - -DPFib.prototype.reset = function() -{ - this.oldIDs =[]; - this.nextIndex = this.initialIndex; -} - - - -DPFib.prototype.emptyCallback = function(event) -{ - this.implementAction(this.helpMessage.bind(this), ""); - // TODO: Put up a message to push the appropriate button? - -} - -DPFib.prototype.recursiveCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); - this.fibField.value = String(fibValue); - this.implementAction(this.recursiveFib.bind(this),fibValue); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - - -DPFib.prototype.tableCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); - this.fibField.value = String(fibValue); - this.implementAction(this.tableFib.bind(this),fibValue); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } - -} - - -DPFib.prototype.memoizedCallback = function(event) -{ - var fibValue; - - if (this.fibField.value != "") - { - var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); - this.fibField.value = String(fibValue); - this.implementAction(this.memoizedFib.bind(this),fibValue); - } - else - { - this.implementAction(this.helpMessage.bind(this), ""); - } -} - -DPFib.prototype.helpMessage = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - var messageID = this.nextIndex++; - this.oldIDs.push(messageID); - this.cmd("CreateLabel", messageID, - "Enter a value betweeen 0 and " + String(DPFib.MAX_VALUE) + " in the text field.\n" + - "Then press the Fibonacci Recursive, Fibonacci Table, or Fibonacci Memoized button", - DPFib.RECURSIVE_START_X, DPFib.RECURSIVE_START_Y, 0); - return this.commands; - - -} - - -DPFib.prototype.recursiveFib = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - this.currentY = DPFib.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.fib(value, DPFib.RECURSIVE_START_X, functionCallID); - this.cmd("SetText", functionCallID, "fib(" + String(value) + ") = " + String(final)); - return this.commands; -} - - -DPFib.prototype.fib = function(value, xPos, ID) -{ - this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); - this.currentY += DPFib.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); - if (value > 1) - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); - var firstValue = this.fib(value-1, xPos + DPFib.RECURSIVE_DELTA_X, firstID); - this.currentY += DPFib.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); - var secondValue = this.fib(value-2, xPos + DPFib.RECURSIVE_DELTA_X, secondID); - - - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", firstID, DPFib.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_RECURSIVE_2_COLOR); - this.cmd("SetForegroundColor", secondID, DPFib.CODE_RECURSIVE_2_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); - - - - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.cmd("SetText", ID, firstValue + secondValue); - this.cmd("Step"); - this.currentY = this.currentY - 2 * DPFib.RECURSIVE_DELTA_Y; - return firstValue + secondValue; - } - else - { - this.cmd("SetText", ID, "1"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); - - this.currentY -= DPFib.RECURSIVE_DELTA_Y; - return 1; - } - - - -} - - - - -DPFib.prototype.tableFib = function(value) -{ - this.commands = []; - this.clearOldIDs(); - this.buildTable(value); - var i; - for (i = 0; i <= value && i <= 1; i++) - { - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.tableID[i], 1); - this.cmd("SetText", this.tableID[i], 1); - this.tableVals[i] = 1; - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i], 0); - } - for (i = 2; i <= value; i++) - { - this.cmd("SetHighlight", this.tableID[i-1], 1) - this.cmd("SetHighlight", this.tableID[i-2], 1) - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.tableVals[i] = this.tableVals[i-1] + this.tableVals[i-2]; - this.cmd("SetText", this.tableID[i], this.tableVals[i]); - this.cmd("SetTextColor", this.tableID[i], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetTextColor", this.tableID[i], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.tableID[i-1], 0) - this.cmd("SetHighlight", this.tableID[i-2], 0) - - - } - - var finalID = this.nextIndex++; - this.oldIDs.push(finalID); - this.cmd("CreateLabel", finalID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); - this.cmd("Move", finalID, DPFib.RECURSIVE_START_X, DPFib.RECURSIVE_START_Y); - this.cmd("Step"); - this.cmd("SetText", finalID, "fib(" + String(value) + ") = " + String(this.tableVals[value])); - - return this.commands; - - -} - - - -DPFib.prototype.fibMem = function(value, xPos, ID) -{ - this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); - this.cmd("SetHighlight", this.tableID[value], 1); - // TODO: Add an extra pause here? - this.cmd("Step"); - if (this.tableVals[value] >= 0) - { - this.cmd("Delete", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); - this.cmd("CreateLabel", ID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); - this.cmd("Move", ID, xPos, this.currentY); - this.cmd("Step") - this.cmd("SetHighlight", this.tableID[value], 0); - return this.tableVals[value]; - } - this.cmd("SetHighlight", this.tableID[value], 0); - this.currentY += DPFib.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); - if (value > 1) - { - var firstID = this.nextIndex++; - var secondID = this.nextIndex++; - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); - var firstValue = this.fibMem(value-1, xPos + DPFib.RECURSIVE_DELTA_X, firstID); - this.currentY += DPFib.RECURSIVE_DELTA_Y; - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); - var secondValue = this.fibMem(value-2, xPos + DPFib.RECURSIVE_DELTA_X, secondID); - - - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", firstID, DPFib.CODE_RECURSIVE_1_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_RECURSIVE_2_COLOR); - this.cmd("SetForegroundColor", secondID, DPFib.CODE_RECURSIVE_2_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); - - - - this.cmd("Delete", firstID); - this.cmd("Delete", secondID); - this.cmd("SetText", ID, firstValue + secondValue); - this.cmd("Step"); - this.tableVals[value] = firstValue + secondValue; - this.currentY = this.currentY - 2 * DPFib.RECURSIVE_DELTA_Y; - this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos+5, this.currentY + 5); - this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.cmd("SetText", this.tableID[value], this.tableVals[value]); - return firstValue + secondValue; - } - else - { - this.cmd("SetText", ID, "1"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); - this.tableVals[value] = 1; - this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos + 5, this.currentY + 5); - this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); - this.cmd("Step"); - this.cmd("Delete", this.nextIndex); - this.cmd("SetText", this.tableID[value], this.tableVals[value]); - - this.currentY -= DPFib.RECURSIVE_DELTA_Y; - return 1; - } - -} - -DPFib.prototype.memoizedFib = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - this.buildTable(value); - - this.currentY = DPFib.RECURSIVE_START_Y; - - var functionCallID = this.nextIndex++; - this.oldIDs.push(functionCallID); - var final = this.fibMem(value, DPFib.RECURSIVE_START_X, functionCallID); - - this.cmd("SetText", functionCallID, "fib(" + String(value) + ") = " + String(final)); - return this.commands; -} - -DPFib.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -DPFib.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new DPFib(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function DPFib(am, w, h) +{ + this.init(am, w, h); + +} + +DPFib.inheritFrom(Algorithm); + +DPFib.TABLE_ELEM_WIDTH = 40; +DPFib.TABLE_ELEM_HEIGHT = 30; + +DPFib.TABLE_START_X = 500; +DPFib.TABLE_START_Y = 40; +DPFib.TABLE_DIFF_X = 100; + +DPFib.CODE_START_X = 10; +DPFib.CODE_START_Y = 10; +DPFib.CODE_LINE_HEIGHT = 14; + +DPFib.RECURSIVE_START_X = 20; +DPFib.RECURSIVE_START_Y = 120; +DPFib.RECURSIVE_DELTA_Y = 14; +DPFib.RECURSIVE_DELTA_X = 15; +DPFib.CODE_HIGHLIGHT_COLOR = "#FF0000"; +DPFib.CODE_STANDARD_COLOR = "#000000"; + +DPFib.TABLE_INDEX_COLOR = "#0000FF" +DPFib.CODE_RECURSIVE_1_COLOR = "#339933"; +DPFib.CODE_RECURSIVE_2_COLOR = "#0099FF"; + + + +DPFib.MAX_VALUE = 20; + +DPFib.MESSAGE_ID = 0; + +DPFib.prototype.init = function(am, w, h) +{ + DPFib.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = [["def ","fib(n)",":"], + [" if ","(n <= 1) "], + [" return 1"], + [" else"], + [" return ", "fib(n-1)", " + ", "fib(n-2)"]]; + + this.codeID = Array(this.code.length); + var i, j; + for (i = 0; i < this.code.length; i++) + { + this.codeID[i] = new Array(this.code[i].length); + for (j = 0; j < this.code[i].length; j++) + { + this.codeID[i][j] = this.nextIndex++; + this.cmd("CreateLabel", this.codeID[i][j], this.code[i][j], DPFib.CODE_START_X, DPFib.CODE_START_Y + i * DPFib.CODE_LINE_HEIGHT, 0); + this.cmd("SetForegroundColor", this.codeID[i][j], DPFib.CODE_STANDARD_COLOR); + if (j > 0) + { + this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); + } + } + + + } + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +DPFib.prototype.addControls = function() +{ + this.controls = []; + this.fibField = this.addControlToAlgorithmBar("Text", ""); + this.fibField.onkeydown = this.returnSubmit(this.fibField, this.emptyCallback.bind(this), 2, true); + this.controls.push(this.fibField); + + this.recursiveButton = this.addControlToAlgorithmBar("Button", "Fibonacci Recursive"); + this.recursiveButton.onclick = this.recursiveCallback.bind(this); + this.controls.push(this.recursiveButton); + + this.tableButton = this.addControlToAlgorithmBar("Button", "Fibonacci Table"); + this.tableButton.onclick = this.tableCallback.bind(this); + this.controls.push(this.tableButton); + + this.memoizedButton = this.addControlToAlgorithmBar("Button", "Fibonacci Memoized"); + this.memoizedButton.onclick = this.memoizedCallback.bind(this); + this.controls.push(this.memoizedButton); + +} + + + +DPFib.prototype.buildTable = function(maxVal) +{ + this.tableID = new Array(maxVal + 1); + this.tableVals = new Array(maxVal + 1); + this.tableXPos = new Array(maxVal + 1); + this.tableYPos = new Array(maxVal + 1); + var i; + var indexID; + var xPos; + var yPos; + var table_rows = Math.floor((this.canvasHeight - DPFib.TABLE_ELEM_HEIGHT - DPFib.TABLE_START_Y) / DPFib.TABLE_ELEM_HEIGHT); + + for (i = 0; i <= maxVal; i++) + { + this.tableID[i] = this.nextIndex++; + this.tableVals[i] = -1; + this.oldIDs.push(this.tableID[i]); + + yPos = i % table_rows * DPFib.TABLE_ELEM_HEIGHT + DPFib.TABLE_START_Y; + xPos = Math.floor(i / table_rows) * DPFib.TABLE_DIFF_X + DPFib.TABLE_START_X; + + this.tableXPos[i] = xPos; + this.tableYPos[i] = yPos; + + this.cmd("CreateRectangle", this.tableID[i], + "", + DPFib.TABLE_ELEM_WIDTH, + DPFib.TABLE_ELEM_HEIGHT, + xPos, + yPos); + indexID = this.nextIndex++; + this.oldIDs.push(indexID); + this.cmd("CreateLabel", indexID, i, xPos - DPFib.TABLE_ELEM_WIDTH, yPos); + this.cmd("SetForegroundColor", indexID, DPFib.TABLE_INDEX_COLOR); + } +} + +DPFib.prototype.clearOldIDs = function() +{ + for (var i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs =[]; + this.nextIndex = this.initialIndex; + +} + + +DPFib.prototype.reset = function() +{ + this.oldIDs =[]; + this.nextIndex = this.initialIndex; +} + + + +DPFib.prototype.emptyCallback = function(event) +{ + this.implementAction(this.helpMessage.bind(this), ""); + // TODO: Put up a message to push the appropriate button? + +} + +DPFib.prototype.recursiveCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); + this.fibField.value = String(fibValue); + this.implementAction(this.recursiveFib.bind(this),fibValue); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + + +DPFib.prototype.tableCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); + this.fibField.value = String(fibValue); + this.implementAction(this.tableFib.bind(this),fibValue); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } + +} + + +DPFib.prototype.memoizedCallback = function(event) +{ + var fibValue; + + if (this.fibField.value != "") + { + var fibValue = Math.min(parseInt(this.fibField.value), DPFib.MAX_VALUE); + this.fibField.value = String(fibValue); + this.implementAction(this.memoizedFib.bind(this),fibValue); + } + else + { + this.implementAction(this.helpMessage.bind(this), ""); + } +} + +DPFib.prototype.helpMessage = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + var messageID = this.nextIndex++; + this.oldIDs.push(messageID); + this.cmd("CreateLabel", messageID, + "Enter a value betweeen 0 and " + String(DPFib.MAX_VALUE) + " in the text field.\n" + + "Then press the Fibonacci Recursive, Fibonacci Table, or Fibonacci Memoized button", + DPFib.RECURSIVE_START_X, DPFib.RECURSIVE_START_Y, 0); + return this.commands; + + +} + + +DPFib.prototype.recursiveFib = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + this.currentY = DPFib.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.fib(value, DPFib.RECURSIVE_START_X, functionCallID); + this.cmd("SetText", functionCallID, "fib(" + String(value) + ") = " + String(final)); + return this.commands; +} + + +DPFib.prototype.fib = function(value, xPos, ID) +{ + this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); + this.currentY += DPFib.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); + if (value > 1) + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); + var firstValue = this.fib(value-1, xPos + DPFib.RECURSIVE_DELTA_X, firstID); + this.currentY += DPFib.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); + var secondValue = this.fib(value-2, xPos + DPFib.RECURSIVE_DELTA_X, secondID); + + + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", firstID, DPFib.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_RECURSIVE_2_COLOR); + this.cmd("SetForegroundColor", secondID, DPFib.CODE_RECURSIVE_2_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); + + + + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.cmd("SetText", ID, firstValue + secondValue); + this.cmd("Step"); + this.currentY = this.currentY - 2 * DPFib.RECURSIVE_DELTA_Y; + return firstValue + secondValue; + } + else + { + this.cmd("SetText", ID, "1"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); + + this.currentY -= DPFib.RECURSIVE_DELTA_Y; + return 1; + } + + + +} + + + + +DPFib.prototype.tableFib = function(value) +{ + this.commands = []; + this.clearOldIDs(); + this.buildTable(value); + var i; + for (i = 0; i <= value && i <= 1; i++) + { + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.tableID[i], 1); + this.cmd("SetText", this.tableID[i], 1); + this.tableVals[i] = 1; + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i], 0); + } + for (i = 2; i <= value; i++) + { + this.cmd("SetHighlight", this.tableID[i-1], 1) + this.cmd("SetHighlight", this.tableID[i-2], 1) + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.tableVals[i] = this.tableVals[i-1] + this.tableVals[i-2]; + this.cmd("SetText", this.tableID[i], this.tableVals[i]); + this.cmd("SetTextColor", this.tableID[i], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetTextColor", this.tableID[i], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.tableID[i-1], 0) + this.cmd("SetHighlight", this.tableID[i-2], 0) + + + } + + var finalID = this.nextIndex++; + this.oldIDs.push(finalID); + this.cmd("CreateLabel", finalID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); + this.cmd("Move", finalID, DPFib.RECURSIVE_START_X, DPFib.RECURSIVE_START_Y); + this.cmd("Step"); + this.cmd("SetText", finalID, "fib(" + String(value) + ") = " + String(this.tableVals[value])); + + return this.commands; + + +} + + + +DPFib.prototype.fibMem = function(value, xPos, ID) +{ + this.cmd("CreateLabel", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); + this.cmd("SetHighlight", this.tableID[value], 1); + // TODO: Add an extra pause here? + this.cmd("Step"); + if (this.tableVals[value] >= 0) + { + this.cmd("Delete", ID, "fib(" + String(value)+")", xPos, this.currentY, 0); + this.cmd("CreateLabel", ID, this.tableVals[value], this.tableXPos[value] - 5, this.tableYPos[value] - 5, 0); + this.cmd("Move", ID, xPos, this.currentY); + this.cmd("Step") + this.cmd("SetHighlight", this.tableID[value], 0); + return this.tableVals[value]; + } + this.cmd("SetHighlight", this.tableID[value], 0); + this.currentY += DPFib.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], DPFib.CODE_STANDARD_COLOR); + if (value > 1) + { + var firstID = this.nextIndex++; + var secondID = this.nextIndex++; + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); + var firstValue = this.fibMem(value-1, xPos + DPFib.RECURSIVE_DELTA_X, firstID); + this.currentY += DPFib.RECURSIVE_DELTA_Y; + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); + var secondValue = this.fibMem(value-2, xPos + DPFib.RECURSIVE_DELTA_X, secondID); + + + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", firstID, DPFib.CODE_RECURSIVE_1_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_RECURSIVE_2_COLOR); + this.cmd("SetForegroundColor", secondID, DPFib.CODE_RECURSIVE_2_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][2], DPFib.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][3], DPFib.CODE_STANDARD_COLOR); + + + + this.cmd("Delete", firstID); + this.cmd("Delete", secondID); + this.cmd("SetText", ID, firstValue + secondValue); + this.cmd("Step"); + this.tableVals[value] = firstValue + secondValue; + this.currentY = this.currentY - 2 * DPFib.RECURSIVE_DELTA_Y; + this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos+5, this.currentY + 5); + this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.cmd("SetText", this.tableID[value], this.tableVals[value]); + return firstValue + secondValue; + } + else + { + this.cmd("SetText", ID, "1"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], DPFib.CODE_STANDARD_COLOR); + this.tableVals[value] = 1; + this.cmd("CreateLabel", this.nextIndex, this.tableVals[value], xPos + 5, this.currentY + 5); + this.cmd("Move", this.nextIndex, this.tableXPos[value], this.tableYPos[value], this.currentY); + this.cmd("Step"); + this.cmd("Delete", this.nextIndex); + this.cmd("SetText", this.tableID[value], this.tableVals[value]); + + this.currentY -= DPFib.RECURSIVE_DELTA_Y; + return 1; + } + +} + +DPFib.prototype.memoizedFib = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + this.buildTable(value); + + this.currentY = DPFib.RECURSIVE_START_Y; + + var functionCallID = this.nextIndex++; + this.oldIDs.push(functionCallID); + var final = this.fibMem(value, DPFib.RECURSIVE_START_X, functionCallID); + + this.cmd("SetText", functionCallID, "fib(" + String(value) + ") = " + String(final)); + return this.commands; +} + +DPFib.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +DPFib.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new DPFib(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/DPLCS.js b/AlgorithmLibrary/DPLCS.js index bf8f252..0404980 100644 --- a/AlgorithmLibrary/DPLCS.js +++ b/AlgorithmLibrary/DPLCS.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/DPMatrixMultiply.js b/AlgorithmLibrary/DPMatrixMultiply.js index 8dba0c0..08496bc 100644 --- a/AlgorithmLibrary/DPMatrixMultiply.js +++ b/AlgorithmLibrary/DPMatrixMultiply.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/DisjointSet.js b/AlgorithmLibrary/DisjointSet.js index 0dabfd3..a6a5cc1 100644 --- a/AlgorithmLibrary/DisjointSet.js +++ b/AlgorithmLibrary/DisjointSet.js @@ -1,693 +1,693 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var ARRAY_START_X = 50; -var ARRAY_WIDTH = 30; -var ARRAY_HEIGHT = 30; - -var TREE_START_X = 50; -var TREE_ELEM_WIDTH = 50; -var TREE_ELEM_HEIGHT = 50; - -var SIZE = 16; - -var LINK_COLOR = "#007700" -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var PRINT_COLOR = FOREGROUND_COLOR; - -function DisjointSet(am, w, h) -{ - this.array_start_y = h - 2 * ARRAY_HEIGHT; - this.tree_start_y = this.array_start_y - 50; - this.init(am); - -} - -DisjointSet.inheritFrom(Algorithm); - -DisjointSet.prototype.init = function(am, w, h) -{ - var sc = DisjointSet.superclass.init.call(this, am, w, h); - this.addControls(); - - this.commands = []; - this.nextIndex = 0; - this.highlight1ID = this.nextIndex++; - this.highlight2ID = this.nextIndex++; - - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - this.treeID = new Array(SIZE); - this.setData = new Array(SIZE); - this.treeY = new Array(SIZE); - this.treeIndexToLocation = new Array(SIZE); - this.locationToTreeIndex = new Array(SIZE); - this.heights = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - this.treeIndexToLocation[i] = i; - this.locationToTreeIndex[i] = i; - this.arrayID[i]= this.nextIndex++; - this.arrayLabelID[i]= this.nextIndex++; - this.treeID[i] = this.nextIndex++; - this.setData[i] = -1; - this.treeY[i] = this.tree_start_y; - this.heights[i] = 0; - } - - this.pathCompression = false; - this.unionByRank = false; - this.rankAsHeight = false; - this.setup(); -} - -DisjointSet.prototype.addControls = function() -{ - this.controls = []; - - - this.findField = this.addControlToAlgorithmBar("Text", ""); - this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4, true); - this.controls.push(this.findField); - - var findButton = this.addControlToAlgorithmBar("Button", "Find"); - findButton.onclick = this.findCallback.bind(this); - - this.controls.push(findButton); - - - this.unionField1 = this.addControlToAlgorithmBar("Text", ""); - this.unionField1.onkeydown = this.returnSubmit(this.unionField1, this.unionCallback.bind(this), 4, true); - - this.controls.push(this.unionField1); - - - this.unionField2 = this.addControlToAlgorithmBar("Text", ""); - this.unionField2.onkeydown = this.returnSubmit(this.unionField2, this.unionCallback.bind(this), 4, true); - - this.unionButton = this.addControlToAlgorithmBar("Button", "Union"); - this.unionButton.onclick = this.unionCallback.bind(this); - - this.controls.push(this.unionField2); - - this.pathCompressionBox = this.addCheckboxToAlgorithmBar("Path Compression"); - this.pathCompressionBox.onclick = this.pathCompressionChangeCallback.bind(this); - - this.controls.push(this.pathCompressionBox); - - this.unionByRankBox = this.addCheckboxToAlgorithmBar("Union By Rank"); - this.unionByRankBox.onclick = this.unionByRankChangeCallback.bind(this); - - this.controls.push(this.unionByRankBox); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rank = # of nodes", - "Rank = estimated height", - ], - "RankType"); - this.rankNumberOfNodesButton = radioButtonList[0]; - this.rankNumberOfNodesButton.onclick = this.rankTypeChangedCallback.bind(this, false); - this.controls.push(this.rankNumberOfNodesButton); - - - this.rankEstimatedHeightButton = radioButtonList[1]; - this.rankEstimatedHeightButton.onclick = this.rankTypeChangedCallback.bind(this, true); - this.controls.push(this.rankEstimatedHeightButton); - - this.rankNumberOfNodesButton.checked = !this.rankAsHeight; - this.rankEstimatedHeightButton.checked = this.rankAsHeight; - -} - - - - - - -DisjointSet.prototype.setup = function() -{ - this.commands = new Array(); - - for (var i = 0; i < SIZE; i++) - { - this.cmd("CreateRectangle", this.arrayID[i], this.setData[i], ARRAY_WIDTH, ARRAY_HEIGHT, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y); - this.cmd("CreateLabel",this.arrayLabelID[i], i, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y + ARRAY_HEIGHT); - this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); - - this.cmd("CreateCircle", this.treeID[i], i, TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); - this.cmd("SetForegroundColor", this.treeID[i], FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.treeID[i], BACKGROUND_COLOR); - - } - - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - -} - - -DisjointSet.prototype.reset = function() -{ - for (var i = 0; i < SIZE; i++) - { - this.setData[i] = -1; - } - this.pathCompression = false; - this.unionByRank = false; - this.rankAsHeight = false; - this.pathCompressionBox.selected = this.pathCompression; - this.unionByRankBox.selected = this.unionByRank; - this.rankNumberOfNodesButton.checked = !this.rankAsHeight; - this.rankEstimatedHeightButton.checked = this.rankAsHeight; - -} - - -DisjointSet.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -DisjointSet.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - - -DisjointSet.prototype.rankTypeChangedCallback = function(rankAsHeight, event) -{ - if (this.rankAsHeight != rankAsHeight) - { - this.implementAction(this.changeRankType.bind(this), rankAsHeight); - } -} - - - -DisjointSet.prototype.pathCompressionChangeCallback = function(event) -{ - if (this.pathCompression != this.pathCompressionBox.checked) - { - this.implementAction(this.changePathCompression.bind(this), this.pathCompressionBox.checked); - } -} - -DisjointSet.prototype.unionByRankChangeCallback = function(event) -{ - if (this.unionByRank != this.unionByRankBox.checked) - { - this.implementAction(this.changeUnionByRank.bind(this), this.unionByRankBox.checked); - } -} - -DisjointSet.prototype.changeRankType = function(newValue) -{ - this.commands = new Array(); - this.rankAsHeight = newValue - if (this.rankNumberOfNodesButton.checked == this.rankAsHeight) - { - this.rankNumberOfNodesButton.checked = !this.rankAsHeight; - } - if (this.rankEstimatedHeightButton.checked != this.rankAsHeight) - { - this.rankEstimatedHeightButton.checked = this.rankAsHeight; - } - // When we change union by rank, we can either create a blank slate using clearAll, - // or we can rebuild the root values to what they shoue be given the current state of - // the tree. - // clearAll(); - this.rebuildRootValues(); - return this.commands; - - -} - - -DisjointSet.prototype.changeUnionByRank = function(newValue) -{ - this.commands = new Array(); - this.unionByRank = newValue; - if (this.unionByRankBox.selected != this.unionByRank) - { - this.unionByRankBox.selected = this.unionByRank; - } - // When we change union by rank, we can either create a blank slate using clearAll, - // or we can rebuild the root values to what they shoue be given the current state of - // the tree. - // clearAll(); - this.rebuildRootValues(); - return this.commands; - -} - - -DisjointSet.prototype.changePathCompression = function(newValue) -{ - this.commands = new Array(); - this.cmd("Step"); - this.pathCompression = newValue; - if (this.pathCompressionBox.selected != this.pathCompression) - { - this.pathCompressionBox.selected = this.pathCompression; - } - this.rebuildRootValues(); - // clearAll(); - return this.commands; - -} - -DisjointSet.prototype.findCallback = function(event) -{ - var findValue; - - findValue = this.findField.value; - if (findValue != "" && parseInt(findValue) < SIZE) - { - this.findField.value.value = ""; - this.implementAction(this.findElement.bind(this), findValue); - } -} - -DisjointSet.prototype.clearCallback = function(event) -{ - this.implementAction(this.clearData.bind(this), ""); -} - -DisjointSet.prototype.clearData = function(ignored) -{ - this.commands = new Array(); - clearAll(); - return this.commands; -} - - -DisjointSet.prototype.getSizes = function() -{ - var sizes = new Array(SIZE); - - for (var i = 0; i < SIZE; i++) - { - sizes[i] = 1; - } - var changed = true; - while (changed) - { - changed = false; - for (i = 0; i < SIZE; i++) - { - if (sizes[i] > 0 && this.setData[i] >= 0) - { - sizes[this.setData[i]] += sizes[i]; - sizes[i] = 0; - changed = true; - } - } - } - return sizes; -} - -DisjointSet.prototype.rebuildRootValues = function() -{ - var changed = false; - - if (this.unionByRank) - { - if (!this.rankAsHeight) - { - var sizes = this.getSizes(); - } - for (var i = 0; i < SIZE; i++) - { - if (this.setData[i] < 0) - { - if (this.rankAsHeight) - { - this.setData[i] = 0 - this.heights[i] - 1; - } - else - { - this.setData[i] = - sizes[i]; - } - } - } - } - else - { - for (i = 0; i < SIZE; i++) - { - if (this.setData[i] < 0) - { - this.setData[i] = -1; - } - } - } - for (i = 0; i < SIZE; i++) - { - this.cmd("SetText", this.arrayID[i], this.setData[i]); - } - -} - -DisjointSet.prototype.unionCallback = function(event) -{ - var union1; - var union2; - - union1 = this.unionField1.value; - union2 = this.unionField2.value; - - - if ( union1 != "" && parseInt(union1) < SIZE && - union2 != "" && parseInt(union2) < SIZE) - { - this.unionField1.value = ""; - this.unionField2.value = ""; - this.implementAction(this.doUnion.bind(this), union1 + ";" + union2); - } -} - - -DisjointSet.prototype.clearAll = function() -{ - for (var i = 0; i < SIZE; i++) - { - if (this.setData[i] >= 0) - { - this.cmd("Disconnect", this.treeID[i], this.treeID[this.setData[i]]); - } - this.setData[i] = -1; - this.cmd("SetText", this.arrayID[i], this.setData[i]); - this.treeIndexToLocation[i] = i; - this.locationToTreeIndex[i] = i; - this.treeY[i] = this.tree_start_y; - this.cmd("SetPosition", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); - } - - -} - - -DisjointSet.prototype.findElement = function(findValue) -{ - this.commands = new Array(); - - - var found = this.doFind(parseInt(findValue)); - - if (this.pathCompression) - { - var changed = this.adjustHeights(); - if (changed) - { - this.animateNewPositions(); - } - } - return this.commands; -} - - - -DisjointSet.prototype.doFind = function(elem) -{ - this.cmd("SetHighlight", this.treeID[elem], 1); - this.cmd("SetHighlight", this.arrayID[elem], 1); - this.cmd("Step"); - this.cmd("SetHighlight", this.treeID[elem], 0); - this.cmd("SetHighlight", this.arrayID[elem], 0); - if (this.setData[elem] >= 0) - { - var treeRoot = this.doFind(this.setData[elem]); - if (this.pathCompression) - { - if (this.setData[elem] != treeRoot) - { - this.cmd("Disconnect", this.treeID[elem], this.treeID[this.setData[elem]]); - this.setData[elem] = treeRoot; - this.cmd("SetText", this.arrayID[elem], this.setData[elem]); - this.cmd("Connect", this.treeID[elem], - this.treeID[treeRoot], - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - } - return treeRoot; - } - else - { - return elem; - } - -} - - -DisjointSet.prototype.findRoot = function (elem) -{ - while (this.setData[elem] >= 0) - elem = this.setData[elem]; - return elem; -} - - - -// After linking two trees, move them next to each other. -DisjointSet.prototype.adjustXPos = function(pos1, pos2) -{ - - var left1 = this.treeIndexToLocation[pos1]; - while (left1 > 0 && this.findRoot(this.locationToTreeIndex[left1 - 1]) == pos1) - { - left1--; - } - var right1 = this.treeIndexToLocation[pos1]; - while (right1 < SIZE - 1 && this.findRoot(this.locationToTreeIndex[right1 + 1]) == pos1) - { - right1++; - } - var left2 = this.treeIndexToLocation[pos2]; - while (left2 > 0 && this.findRoot(this.locationToTreeIndex[left2-1]) == pos2) - { - left2--; - } - var right2 = this.treeIndexToLocation[pos2]; - while (right2 < SIZE - 1 && this.findRoot(this.locationToTreeIndex[right2 + 1]) == pos2) - { - right2++; - } - if (right1 == left2-1) - { - return false; - } - - var tmpLocationToTreeIndex = new Array(SIZE); - var nextInsertIndex = 0; - for (var i = 0; i <= right1; i++) - { - tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; - } - for (i = left2; i <= right2; i++) - { - tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; - } - for (i = right1+1; i < left2; i++) - { - tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; - } - for (i = right2+1; i < SIZE; i++) - { - tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; - } - for (i = 0; i < SIZE; i++) - { - this.locationToTreeIndex[i] = tmpLocationToTreeIndex[i]; - } - for (i = 0; i < SIZE; i++) - { - this.treeIndexToLocation[this.locationToTreeIndex[i]] = i; - } - return true; -} - -DisjointSet.prototype.doUnion = function(value) -{ - this.commands = new Array(); - var args = value.split(";"); - var arg1 = this.doFind(parseInt(args[0])); - - this.cmd("CreateHighlightCircle", this.highlight1ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg1] * TREE_ELEM_WIDTH, this.treeY[arg1]); - - - var arg2 = this.doFind(parseInt(args[1])); - this.cmd("CreateHighlightCircle", this.highlight2ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg2] * TREE_ELEM_WIDTH, this.treeY[arg2]); - - - if (arg1 == arg2) - { - this.cmd("Delete", this.highlight1ID); - this.cmd("Delete", this.highlight2ID); - return this.commands; - } - - var changed; - - if (this.treeIndexToLocation[arg1] < this.treeIndexToLocation[arg2]) - { - changed = this.adjustXPos(arg1, arg2) || changed - } - else - { - changed = this.adjustXPos(arg2, arg1) || changed - } - - - if (this.unionByRank && this.setData[arg1] < this.setData[arg2]) - { - var tmp = arg1; - arg1 = arg2; - arg2 = tmp; - } - - if (this.unionByRank && this.rankAsHeight) - { - if (this.setData[arg2] == this.setData[arg1]) - { - this.setData[arg2] -= 1; - } - } - else if (this.unionByRank) - { - this.setData[arg2] = this.setData[arg2] + this.setData[arg1]; - } - - this.setData[arg1] = arg2; - - this.cmd("SetText", this.arrayID[arg1], this.setData[arg1]); - this.cmd("SetText", this.arrayID[arg2], this.setData[arg2]); - - this.cmd("Connect", this.treeID[arg1], - this.treeID[arg2], - FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - if (this.adjustHeights()) - { - changed = true; - } - - if (changed) - { - this.cmd("Step"); - this.cmd("Delete", this.highlight1ID); - this.cmd("Delete", this.highlight2ID); - this.animateNewPositions(); - } - else - { - this.cmd("Delete", this.highlight1ID); - this.cmd("Delete", this.highlight2ID); - } - - return this.commands; -} - - -DisjointSet.prototype.adjustHeights = function() -{ - var changed = false; - for (var i = 0; i < SIZE; i++) - { - this.heights[i] = 0; - } - - for (var j = 0; j < SIZE; j++) - { - for (i = 0; i < SIZE; i++) - { - if (this.setData[i] >= 0) - { - this.heights[this.setData[i]] = Math.max(this.heights[this.setData[i]], this.heights[i] + 1); - } - - } - } - for (j = 0; j < SIZE; j++) - { - for (i = 0; i < SIZE; i++) - { - if (this.setData[i] >= 0) - { - this.heights[i] = this.heights[this.setData[i]] - 1; - } - - } - } - for (i = 0; i < SIZE; i++) - { - var newY = this.tree_start_y - this.heights[i] * TREE_ELEM_HEIGHT; - if (this.treeY[i] != newY) - { - this.treeY[i] = newY; - changed = true; - } - } - return changed; -} - - -DisjointSet.prototype.animateNewPositions = function() -{ - for (var i = 0; i < SIZE; i++) - { - this.cmd("Move", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); - } -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new DisjointSet(animManag, canvas.width, canvas.height); -} - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var ARRAY_START_X = 50; +var ARRAY_WIDTH = 30; +var ARRAY_HEIGHT = 30; + +var TREE_START_X = 50; +var TREE_ELEM_WIDTH = 50; +var TREE_ELEM_HEIGHT = 50; + +var SIZE = 16; + +var LINK_COLOR = "#007700" +var HIGHLIGHT_CIRCLE_COLOR = "#007700"; +var FOREGROUND_COLOR = "#007700"; +var BACKGROUND_COLOR = "#EEFFEE"; +var PRINT_COLOR = FOREGROUND_COLOR; + +function DisjointSet(am, w, h) +{ + this.array_start_y = h - 2 * ARRAY_HEIGHT; + this.tree_start_y = this.array_start_y - 50; + this.init(am); + +} + +DisjointSet.inheritFrom(Algorithm); + +DisjointSet.prototype.init = function(am, w, h) +{ + var sc = DisjointSet.superclass.init.call(this, am, w, h); + this.addControls(); + + this.commands = []; + this.nextIndex = 0; + this.highlight1ID = this.nextIndex++; + this.highlight2ID = this.nextIndex++; + + this.arrayID = new Array(SIZE); + this.arrayLabelID = new Array(SIZE); + this.treeID = new Array(SIZE); + this.setData = new Array(SIZE); + this.treeY = new Array(SIZE); + this.treeIndexToLocation = new Array(SIZE); + this.locationToTreeIndex = new Array(SIZE); + this.heights = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + this.treeIndexToLocation[i] = i; + this.locationToTreeIndex[i] = i; + this.arrayID[i]= this.nextIndex++; + this.arrayLabelID[i]= this.nextIndex++; + this.treeID[i] = this.nextIndex++; + this.setData[i] = -1; + this.treeY[i] = this.tree_start_y; + this.heights[i] = 0; + } + + this.pathCompression = false; + this.unionByRank = false; + this.rankAsHeight = false; + this.setup(); +} + +DisjointSet.prototype.addControls = function() +{ + this.controls = []; + + + this.findField = this.addControlToAlgorithmBar("Text", ""); + this.findField.onkeydown = this.returnSubmit(this.findField, this.findCallback.bind(this), 4, true); + this.controls.push(this.findField); + + var findButton = this.addControlToAlgorithmBar("Button", "Find"); + findButton.onclick = this.findCallback.bind(this); + + this.controls.push(findButton); + + + this.unionField1 = this.addControlToAlgorithmBar("Text", ""); + this.unionField1.onkeydown = this.returnSubmit(this.unionField1, this.unionCallback.bind(this), 4, true); + + this.controls.push(this.unionField1); + + + this.unionField2 = this.addControlToAlgorithmBar("Text", ""); + this.unionField2.onkeydown = this.returnSubmit(this.unionField2, this.unionCallback.bind(this), 4, true); + + this.unionButton = this.addControlToAlgorithmBar("Button", "Union"); + this.unionButton.onclick = this.unionCallback.bind(this); + + this.controls.push(this.unionField2); + + this.pathCompressionBox = this.addCheckboxToAlgorithmBar("Path Compression"); + this.pathCompressionBox.onclick = this.pathCompressionChangeCallback.bind(this); + + this.controls.push(this.pathCompressionBox); + + this.unionByRankBox = this.addCheckboxToAlgorithmBar("Union By Rank"); + this.unionByRankBox.onclick = this.unionByRankChangeCallback.bind(this); + + this.controls.push(this.unionByRankBox); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Rank = # of nodes", + "Rank = estimated height", + ], + "RankType"); + this.rankNumberOfNodesButton = radioButtonList[0]; + this.rankNumberOfNodesButton.onclick = this.rankTypeChangedCallback.bind(this, false); + this.controls.push(this.rankNumberOfNodesButton); + + + this.rankEstimatedHeightButton = radioButtonList[1]; + this.rankEstimatedHeightButton.onclick = this.rankTypeChangedCallback.bind(this, true); + this.controls.push(this.rankEstimatedHeightButton); + + this.rankNumberOfNodesButton.checked = !this.rankAsHeight; + this.rankEstimatedHeightButton.checked = this.rankAsHeight; + +} + + + + + + +DisjointSet.prototype.setup = function() +{ + this.commands = new Array(); + + for (var i = 0; i < SIZE; i++) + { + this.cmd("CreateRectangle", this.arrayID[i], this.setData[i], ARRAY_WIDTH, ARRAY_HEIGHT, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y); + this.cmd("CreateLabel",this.arrayLabelID[i], i, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y + ARRAY_HEIGHT); + this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); + + this.cmd("CreateCircle", this.treeID[i], i, TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); + this.cmd("SetForegroundColor", this.treeID[i], FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.treeID[i], BACKGROUND_COLOR); + + } + + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + +} + + +DisjointSet.prototype.reset = function() +{ + for (var i = 0; i < SIZE; i++) + { + this.setData[i] = -1; + } + this.pathCompression = false; + this.unionByRank = false; + this.rankAsHeight = false; + this.pathCompressionBox.selected = this.pathCompression; + this.unionByRankBox.selected = this.unionByRank; + this.rankNumberOfNodesButton.checked = !this.rankAsHeight; + this.rankEstimatedHeightButton.checked = this.rankAsHeight; + +} + + +DisjointSet.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +DisjointSet.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + + +DisjointSet.prototype.rankTypeChangedCallback = function(rankAsHeight, event) +{ + if (this.rankAsHeight != rankAsHeight) + { + this.implementAction(this.changeRankType.bind(this), rankAsHeight); + } +} + + + +DisjointSet.prototype.pathCompressionChangeCallback = function(event) +{ + if (this.pathCompression != this.pathCompressionBox.checked) + { + this.implementAction(this.changePathCompression.bind(this), this.pathCompressionBox.checked); + } +} + +DisjointSet.prototype.unionByRankChangeCallback = function(event) +{ + if (this.unionByRank != this.unionByRankBox.checked) + { + this.implementAction(this.changeUnionByRank.bind(this), this.unionByRankBox.checked); + } +} + +DisjointSet.prototype.changeRankType = function(newValue) +{ + this.commands = new Array(); + this.rankAsHeight = newValue + if (this.rankNumberOfNodesButton.checked == this.rankAsHeight) + { + this.rankNumberOfNodesButton.checked = !this.rankAsHeight; + } + if (this.rankEstimatedHeightButton.checked != this.rankAsHeight) + { + this.rankEstimatedHeightButton.checked = this.rankAsHeight; + } + // When we change union by rank, we can either create a blank slate using clearAll, + // or we can rebuild the root values to what they shoue be given the current state of + // the tree. + // clearAll(); + this.rebuildRootValues(); + return this.commands; + + +} + + +DisjointSet.prototype.changeUnionByRank = function(newValue) +{ + this.commands = new Array(); + this.unionByRank = newValue; + if (this.unionByRankBox.selected != this.unionByRank) + { + this.unionByRankBox.selected = this.unionByRank; + } + // When we change union by rank, we can either create a blank slate using clearAll, + // or we can rebuild the root values to what they shoue be given the current state of + // the tree. + // clearAll(); + this.rebuildRootValues(); + return this.commands; + +} + + +DisjointSet.prototype.changePathCompression = function(newValue) +{ + this.commands = new Array(); + this.cmd("Step"); + this.pathCompression = newValue; + if (this.pathCompressionBox.selected != this.pathCompression) + { + this.pathCompressionBox.selected = this.pathCompression; + } + this.rebuildRootValues(); + // clearAll(); + return this.commands; + +} + +DisjointSet.prototype.findCallback = function(event) +{ + var findValue; + + findValue = this.findField.value; + if (findValue != "" && parseInt(findValue) < SIZE) + { + this.findField.value.value = ""; + this.implementAction(this.findElement.bind(this), findValue); + } +} + +DisjointSet.prototype.clearCallback = function(event) +{ + this.implementAction(this.clearData.bind(this), ""); +} + +DisjointSet.prototype.clearData = function(ignored) +{ + this.commands = new Array(); + clearAll(); + return this.commands; +} + + +DisjointSet.prototype.getSizes = function() +{ + var sizes = new Array(SIZE); + + for (var i = 0; i < SIZE; i++) + { + sizes[i] = 1; + } + var changed = true; + while (changed) + { + changed = false; + for (i = 0; i < SIZE; i++) + { + if (sizes[i] > 0 && this.setData[i] >= 0) + { + sizes[this.setData[i]] += sizes[i]; + sizes[i] = 0; + changed = true; + } + } + } + return sizes; +} + +DisjointSet.prototype.rebuildRootValues = function() +{ + var changed = false; + + if (this.unionByRank) + { + if (!this.rankAsHeight) + { + var sizes = this.getSizes(); + } + for (var i = 0; i < SIZE; i++) + { + if (this.setData[i] < 0) + { + if (this.rankAsHeight) + { + this.setData[i] = 0 - this.heights[i] - 1; + } + else + { + this.setData[i] = - sizes[i]; + } + } + } + } + else + { + for (i = 0; i < SIZE; i++) + { + if (this.setData[i] < 0) + { + this.setData[i] = -1; + } + } + } + for (i = 0; i < SIZE; i++) + { + this.cmd("SetText", this.arrayID[i], this.setData[i]); + } + +} + +DisjointSet.prototype.unionCallback = function(event) +{ + var union1; + var union2; + + union1 = this.unionField1.value; + union2 = this.unionField2.value; + + + if ( union1 != "" && parseInt(union1) < SIZE && + union2 != "" && parseInt(union2) < SIZE) + { + this.unionField1.value = ""; + this.unionField2.value = ""; + this.implementAction(this.doUnion.bind(this), union1 + ";" + union2); + } +} + + +DisjointSet.prototype.clearAll = function() +{ + for (var i = 0; i < SIZE; i++) + { + if (this.setData[i] >= 0) + { + this.cmd("Disconnect", this.treeID[i], this.treeID[this.setData[i]]); + } + this.setData[i] = -1; + this.cmd("SetText", this.arrayID[i], this.setData[i]); + this.treeIndexToLocation[i] = i; + this.locationToTreeIndex[i] = i; + this.treeY[i] = this.tree_start_y; + this.cmd("SetPosition", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); + } + + +} + + +DisjointSet.prototype.findElement = function(findValue) +{ + this.commands = new Array(); + + + var found = this.doFind(parseInt(findValue)); + + if (this.pathCompression) + { + var changed = this.adjustHeights(); + if (changed) + { + this.animateNewPositions(); + } + } + return this.commands; +} + + + +DisjointSet.prototype.doFind = function(elem) +{ + this.cmd("SetHighlight", this.treeID[elem], 1); + this.cmd("SetHighlight", this.arrayID[elem], 1); + this.cmd("Step"); + this.cmd("SetHighlight", this.treeID[elem], 0); + this.cmd("SetHighlight", this.arrayID[elem], 0); + if (this.setData[elem] >= 0) + { + var treeRoot = this.doFind(this.setData[elem]); + if (this.pathCompression) + { + if (this.setData[elem] != treeRoot) + { + this.cmd("Disconnect", this.treeID[elem], this.treeID[this.setData[elem]]); + this.setData[elem] = treeRoot; + this.cmd("SetText", this.arrayID[elem], this.setData[elem]); + this.cmd("Connect", this.treeID[elem], + this.treeID[treeRoot], + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + } + return treeRoot; + } + else + { + return elem; + } + +} + + +DisjointSet.prototype.findRoot = function (elem) +{ + while (this.setData[elem] >= 0) + elem = this.setData[elem]; + return elem; +} + + + +// After linking two trees, move them next to each other. +DisjointSet.prototype.adjustXPos = function(pos1, pos2) +{ + + var left1 = this.treeIndexToLocation[pos1]; + while (left1 > 0 && this.findRoot(this.locationToTreeIndex[left1 - 1]) == pos1) + { + left1--; + } + var right1 = this.treeIndexToLocation[pos1]; + while (right1 < SIZE - 1 && this.findRoot(this.locationToTreeIndex[right1 + 1]) == pos1) + { + right1++; + } + var left2 = this.treeIndexToLocation[pos2]; + while (left2 > 0 && this.findRoot(this.locationToTreeIndex[left2-1]) == pos2) + { + left2--; + } + var right2 = this.treeIndexToLocation[pos2]; + while (right2 < SIZE - 1 && this.findRoot(this.locationToTreeIndex[right2 + 1]) == pos2) + { + right2++; + } + if (right1 == left2-1) + { + return false; + } + + var tmpLocationToTreeIndex = new Array(SIZE); + var nextInsertIndex = 0; + for (var i = 0; i <= right1; i++) + { + tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; + } + for (i = left2; i <= right2; i++) + { + tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; + } + for (i = right1+1; i < left2; i++) + { + tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; + } + for (i = right2+1; i < SIZE; i++) + { + tmpLocationToTreeIndex[nextInsertIndex++] = this.locationToTreeIndex[i]; + } + for (i = 0; i < SIZE; i++) + { + this.locationToTreeIndex[i] = tmpLocationToTreeIndex[i]; + } + for (i = 0; i < SIZE; i++) + { + this.treeIndexToLocation[this.locationToTreeIndex[i]] = i; + } + return true; +} + +DisjointSet.prototype.doUnion = function(value) +{ + this.commands = new Array(); + var args = value.split(";"); + var arg1 = this.doFind(parseInt(args[0])); + + this.cmd("CreateHighlightCircle", this.highlight1ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg1] * TREE_ELEM_WIDTH, this.treeY[arg1]); + + + var arg2 = this.doFind(parseInt(args[1])); + this.cmd("CreateHighlightCircle", this.highlight2ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg2] * TREE_ELEM_WIDTH, this.treeY[arg2]); + + + if (arg1 == arg2) + { + this.cmd("Delete", this.highlight1ID); + this.cmd("Delete", this.highlight2ID); + return this.commands; + } + + var changed; + + if (this.treeIndexToLocation[arg1] < this.treeIndexToLocation[arg2]) + { + changed = this.adjustXPos(arg1, arg2) || changed + } + else + { + changed = this.adjustXPos(arg2, arg1) || changed + } + + + if (this.unionByRank && this.setData[arg1] < this.setData[arg2]) + { + var tmp = arg1; + arg1 = arg2; + arg2 = tmp; + } + + if (this.unionByRank && this.rankAsHeight) + { + if (this.setData[arg2] == this.setData[arg1]) + { + this.setData[arg2] -= 1; + } + } + else if (this.unionByRank) + { + this.setData[arg2] = this.setData[arg2] + this.setData[arg1]; + } + + this.setData[arg1] = arg2; + + this.cmd("SetText", this.arrayID[arg1], this.setData[arg1]); + this.cmd("SetText", this.arrayID[arg2], this.setData[arg2]); + + this.cmd("Connect", this.treeID[arg1], + this.treeID[arg2], + FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + if (this.adjustHeights()) + { + changed = true; + } + + if (changed) + { + this.cmd("Step"); + this.cmd("Delete", this.highlight1ID); + this.cmd("Delete", this.highlight2ID); + this.animateNewPositions(); + } + else + { + this.cmd("Delete", this.highlight1ID); + this.cmd("Delete", this.highlight2ID); + } + + return this.commands; +} + + +DisjointSet.prototype.adjustHeights = function() +{ + var changed = false; + for (var i = 0; i < SIZE; i++) + { + this.heights[i] = 0; + } + + for (var j = 0; j < SIZE; j++) + { + for (i = 0; i < SIZE; i++) + { + if (this.setData[i] >= 0) + { + this.heights[this.setData[i]] = Math.max(this.heights[this.setData[i]], this.heights[i] + 1); + } + + } + } + for (j = 0; j < SIZE; j++) + { + for (i = 0; i < SIZE; i++) + { + if (this.setData[i] >= 0) + { + this.heights[i] = this.heights[this.setData[i]] - 1; + } + + } + } + for (i = 0; i < SIZE; i++) + { + var newY = this.tree_start_y - this.heights[i] * TREE_ELEM_HEIGHT; + if (this.treeY[i] != newY) + { + this.treeY[i] = newY; + changed = true; + } + } + return changed; +} + + +DisjointSet.prototype.animateNewPositions = function() +{ + for (var i = 0; i < SIZE; i++) + { + this.cmd("Move", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); + } +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new DisjointSet(animManag, canvas.width, canvas.height); +} + diff --git a/AlgorithmLibrary/FibonacciHeap.js b/AlgorithmLibrary/FibonacciHeap.js index 3c55952..86cd323 100644 --- a/AlgorithmLibrary/FibonacciHeap.js +++ b/AlgorithmLibrary/FibonacciHeap.js @@ -1,876 +1,876 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -FibonacciHeap.LINK_COLOR = "#007700"; -FibonacciHeap.FOREGROUND_COLOR = "#007700"; -FibonacciHeap.BACKGROUND_COLOR = "#EEFFEE"; -FibonacciHeap.INDEX_COLOR = "#0000FF"; - -FibonacciHeap.DEGREE_OFFSET_X = -20; -FibonacciHeap.DEGREE_OFFSET_Y = -20; - -FibonacciHeap.DELETE_LAB_X = 30; -FibonacciHeap.DELETE_LAB_Y = 50; - -FibonacciHeap.NODE_WIDTH = 60; -FibonacciHeap.NODE_HEIGHT = 70 - -FibonacciHeap.STARTING_X = 70; - -FibonacciHeap.INSERT_X = 30; -FibonacciHeap.INSERT_Y = 25 - -FibonacciHeap.STARTING_Y = 100; -FibonacciHeap.MAX_DEGREE = 7; -FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH = 30; -FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT = 30; -FibonacciHeap.DEGREE_ARRAY_START_X = 500; -FibonacciHeap.INDEGREE_ARRAY_START_Y = 50; - -FibonacciHeap.TMP_PTR_Y = 60; - -function FibonacciHeap(am, w, h) -{ - this.init(am, w, h); - -} - -FibonacciHeap.inheritFrom(Algorithm); - - - -FibonacciHeap.prototype.init = function(am, w, h) -{ - FibonacciHeap.superclass.init.call(this, am, w, h); - this.addControls(); - this.treeRoot = null; - this.currentLayer = 1; - this.animationManager.setAllLayers([0,this.currentLayer]); - this.minID = 0; - this.nextIndex = 1; -} - - -FibonacciHeap.prototype.addControls = function() -{ - this.controls = []; - this.insertField = this.addControlToAlgorithmBar("Text", ""); - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.controls.push(this.insertField); - - this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); - this.insertButton.onclick = this.insertCallback.bind(this); - this.controls.push(this.insertButton); - - this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); - this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); - this.controls.push(this.removeSmallestButton); - - this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); - this.clearHeapButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearHeapButton); - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", - "Internal Representation", - ], - "BQueueRep"); - - radioButtonList[0].onclick = this.representationChangedHandler.bind(this, true); - radioButtonList[1].onclick = this.representationChangedHandler.bind(this, false); - radioButtonList[0].checked = true; - -} - - -FibonacciHeap.prototype.representationChangedHandler = function(logicalRep, event) -{ - if (logicalRep) - { - this.animationManager.setAllLayers([0,1]); - this.currentLayer = 1; - } - else - { - this.animationManager.setAllLayers([0,2]); - this.currentLayer = 2; - } -} - - - - -FibonacciHeap.prototype.setPositions = function(tree, xPosition, yPosition) -{ - if (tree != null) - { - if (tree.degree == 0) - { - tree.x = xPosition; - tree.y = yPosition; - return this.setPositions(tree.rightSib, xPosition + FibonacciHeap.NODE_WIDTH, yPosition); - } - else if (tree.degree == 1) - { - tree.x = xPosition; - tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + FibonacciHeap.NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + FibonacciHeap.NODE_WIDTH, yPosition); - } - else - { - var treeWidth = Math.pow(2, tree.degree - 1); - tree.x = xPosition + (treeWidth - 1) * FibonacciHeap.NODE_WIDTH; - tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + FibonacciHeap.NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + treeWidth * FibonacciHeap.NODE_WIDTH, yPosition); - } - } - return xPosition; -} - -FibonacciHeap.prototype.moveTree = function(tree) -{ - if (tree != null) - { - this.cmd("Move", tree.graphicID, tree.x, tree.y); - this.cmd("Move", tree.internalGraphicID, tree.x, tree.y); - this.cmd("Move", tree.degreeID, tree.x + FibonacciHeap.DEGREE_OFFSET_X, tree.y + FibonacciHeap.DEGREE_OFFSET_Y); - - this.moveTree(tree.leftChild); - this.moveTree(tree.rightSib); - } -} - - -FibonacciHeap.prototype.insertCallback = function(event) -{ - var insertedValue; - - insertedValue = this.normalizeNumber(this.insertField.value, 4); - if (insertedValue != "") - { - this.insertField.value = ""; - this.implementAction(this.insertElement.bind(this),insertedValue); - } -} - -FibonacciHeap.prototype.clearCallback = function(event) -{ - this.implementAction(this.clear.bind(this),""); -} - -FibonacciHeap.prototype.clear = function() -{ - this.commands = new Array(); - - - this.deleteTree(this.treeRoot); - - this.cmd("Delete", this.minID); - this.nextIndex = 1; - this.treeRoot = null; - this.minElement = null; - return this.commands; -} - - -FibonacciHeap.prototype.deleteTree = function(tree) -{ - if (tree != null) - { - this.cmd("Delete", tree.graphicID); - this.cmd("Delete", tree.internalGraphicID); - this.cmd("Delete", tree.degreeID); - this.deleteTree(tree.leftChild); - this.deleteTree(tree.rightSib); - } -} - -FibonacciHeap.prototype.reset = function() -{ - this.treeRoot = null; - this.nextIndex = 1; -} - -FibonacciHeap.prototype.removeSmallestCallback = function(event) -{ - this.implementAction(this.removeSmallest.bind(this),""); -} - - - -FibonacciHeap.prototype.removeSmallest = function(dummy) -{ - this.commands = new Array(); - - if (this.treeRoot != null) - { - var tmp; - var prev; - - - - if (this.minElement == this.treeRoot) { - this.treeRoot = this.treeRoot.rightSib; - prev = null; - } - else - { - for (prev = this.treeRoot; prev.rightSib != this.minElement; prev = prev.rightSib) ; - prev.rightSib = prev.rightSib.rightSib; - - } - var moveLabel = this.nextIndex++; - this.cmd("SetText", this.minElement.graphicID, ""); - this.cmd("SetText", this.minElement.internalGraphicID, ""); - this.cmd("CreateLabel", moveLabel, this.minElement.data, this.minElement.x, this.minElement.y); - this.cmd("Move", moveLabel, FibonacciHeap.DELETE_LAB_X, FibonacciHeap.DELETE_LAB_Y); - this.cmd("Step"); - this.cmd("Delete", this.minID); - var childList = this.minElement.leftChild; - if (this.treeRoot == null) - { - this.cmd("Delete", this.minElement.graphicID); - this.cmd("Delete", this.minElement.internalGraphicID); - this.cmd("Delete", this.minElement.degreeID); - this.treeRoot = childList; - this.minElement = null; - if (this.treeRoot != null) - { - for (tmp = this.treeRoot; tmp != null; tmp = tmp.rightSib) - { - if (this.minElement == null || this.minElement.data > tmp.data) - { - this.minElement = tmp; - - } - } - this.cmd("CreateLabel", this.minID, "Min element", this.minElement.x, FibonacciHeap.TMP_PTR_Y); - this.cmd("Connect", this.minID, - this.minElement.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", this.minID, - this.minElement.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - } - - this.SetAllTreePositions(this.treeRoot, []); - this.MoveAllTrees(this.treeRoot, []); - this.cmd("Delete", moveLabel); - return this.commands; - - - } - else if (childList == null) - { - if (prev != null && prev.rightSib != null) - { - this.cmd("Connect", prev.internalGraphicID, - prev.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", prev.rightSib.internalGraphicID, - prev.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - } - } - else - { - var tmp; - for (tmp = childList; tmp.rightSib != null; tmp = tmp.rightSib) - { - tmp.parent = null; - } - tmp.parent = null; - - // TODO: Add in implementation links - if (prev == null) - { - this.cmd("Connect", tmp.internalGraphicID, - this.treeRoot.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", this.treeRoot.internalGraphicID, - tmp.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - tmp.rightSib = this.treeRoot; - this.treeRoot = childList; - } - else - { - this.cmd("Connect", prev.internalGraphicID, - childList.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", childList.internalGraphicID, - prev.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - if (prev.rightSib != null) - { - this.cmd("Connect", prev.rightSib.internalGraphicID, - tmp.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", tmp.internalGraphicID, - prev.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - } - tmp.rightSib = prev.rightSib; - prev.rightSib = childList; - } - } - this.cmd("Delete", this.minElement.graphicID); - this.cmd("Delete", this.minElement.internalGraphicID); - this.cmd("Delete", this.minElement.degreeID); - - this.SetAllTreePositions(this.treeRoot, []); - this.MoveAllTrees(this.treeRoot, []); - this.fixAfterRemoveMin(); - this.cmd("Delete", moveLabel); - } - return this.commands; -} - - -FibonacciHeap.prototype.insertElement = function(insertedValue) -{ - this.commands = new Array(); - - var insertNode = new BinomialNode(insertedValue, this.nextIndex++, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); - insertNode.internalGraphicID = this.nextIndex++; - insertNode.degreeID= this.nextIndex++; - this.cmd("CreateCircle", insertNode.graphicID, insertedValue, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); - this.cmd("SetForegroundColor", insertNode.graphicID, FibonacciHeap.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.graphicID, FibonacciHeap.BACKGROUND_COLOR); - this.cmd("SetLayer", insertNode.graphicID, 1); - this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); - this.cmd("SetForegroundColor", insertNode.internalGraphicID, FibonacciHeap.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.internalGraphicID, FibonacciHeap.BACKGROUND_COLOR); - this.cmd("SetLayer", insertNode.internalGraphicID, 2); - this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + FibonacciHeap.DEGREE_OFFSET_X, insertNode.y + FibonacciHeap.DEGREE_OFFSET_Y); - this.cmd("SetTextColor", insertNode.degreeID, "#0000FF"); - this.cmd("SetLayer", insertNode.degreeID, 2); - this.cmd("Step"); - - if (this.treeRoot == null) - { - this.treeRoot = insertNode; - this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); - this.moveTree(this.treeRoot); - this.cmd("CreateLabel", this.minID, "Min element", this.treeRoot.x, FibonacciHeap.TMP_PTR_Y); - this.minElement = this.treeRoot; - this.cmd("Connect", this.minID, - this.minElement.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", this.minID, - this.minElement.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - } - else - { - var tmp; - var prev; - - if (this.minElement == this.treeRoot) { - insertNode.rightSib = this.treeRoot; - this.treeRoot = insertNode; - - this.cmd("Connect", this.treeRoot.internalGraphicID, - this.treeRoot.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", this.treeRoot.rightSib.internalGraphicID, - this.treeRoot.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Step"); - this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); - if (this.minElement.data > insertNode.data) - { - this.cmd("Disconnect", this.minID, this.minElement.graphicID); - this.cmd("Disconnect", this.minID, this.minElement.internalGraphicID); - this.minElement = insertNode; - this.cmd("Connect", this.minID, - this.minElement.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", this.minID, - this.minElement.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - } - this.cmd("Move", this.minID, this.minElement.x, FibonacciHeap.TMP_PTR_Y); - this.moveTree(this.treeRoot); - - } - else - { - for (prev = this.treeRoot; prev.rightSib != this.minElement; prev = prev.rightSib) ; - - - this.cmd("Disconnect", prev.internalGraphicID, prev.rightSib.internalGraphicID); - this.cmd("Disconnect", prev.rightSib.internalGraphicID, prev.internalGraphicID); - - insertNode.rightSib = prev.rightSib; - prev.rightSib = insertNode; - - this.cmd("Connect", prev.internalGraphicID, - prev.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", prev.rightSib.internalGraphicID, - prev.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - if (prev.rightSib.rightSib != null) - { - - this.cmd("Connect", prev.rightSib.internalGraphicID, - prev.rightSib.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", prev.rightSib.rightSib.internalGraphicID, - prev.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - } - - - this.cmd("Step"); - this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); - if (this.minElement.data > insertNode.data) - { - this.cmd("Disconnect", this.minID, this.minElement.graphicID); - this.cmd("Disconnect", this.minID, this.minElement.internalGraphicID); - this.minElement = insertNode; - this.cmd("Connect", this.minID, - this.minElement.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", this.minID, - this.minElement.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - this.cmd("Move", this.minID, this.minElement.x, FibonacciHeap.TMP_PTR_Y); - - this.moveTree(this.treeRoot); - - } - - - - - - } - - return this.commands; -} - - - - - -FibonacciHeap.prototype.fixAfterRemoveMin = function() -{ - if (this.treeRoot == null) - return; - var degreeArray = new Array(FibonacciHeap.MAX_DEGREE); - var degreeGraphic = new Array(FibonacciHeap.MAX_DEGREE); - var indexID = new Array(FibonacciHeap.MAX_DEGREE); - var tmpPtrID = this.nextIndex++; - - var i; - for (i = 0 ; i <= FibonacciHeap.MAX_DEGREE; i++) - { - degreeArray[i] = null; - degreeGraphic[i] = this.nextIndex++; - indexID[i] = this.nextIndex++; - this.cmd("CreateRectangle", - degreeGraphic[i], - " ", - FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, - FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT, - FibonacciHeap.DEGREE_ARRAY_START_X + i * FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, - FibonacciHeap.INDEGREE_ARRAY_START_Y); - this.cmd("SetNull", degreeGraphic[i], 1); - this.cmd("CreateLabel", indexID[i], i, FibonacciHeap.DEGREE_ARRAY_START_X + i * FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, - FibonacciHeap.INDEGREE_ARRAY_START_Y - FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT); - this.cmd("SetTextColod", indexID[i], FibonacciHeap.INDEX_COLOR); - } - var tmp = this.treeRoot; - // When remving w/ 1 tree. this.treeRoot == null? - this.cmd("CreateLabel", tmpPtrID, "NextElem", this.treeRoot.x, FibonacciHeap.TMP_PTR_Y); - while (this.treeRoot != null) - { - tmp = this.treeRoot; - this.cmd("Connect", tmpPtrID, - tmp.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", tmpPtrID, - tmp.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - - this.treeRoot = this.treeRoot.rightSib; - if (tmp.rightSib != null) - { - this.cmd("Disconnect", tmp.internalGraphicID, tmp.rightSib.internalGraphicID); - this.cmd("Disconnect", tmp.rightSib.internalGraphicID, tmp.internalGraphicID); - } - - this.cmd("Step"); - tmp.rightSib = null; - while(degreeArray[tmp.degree] != null) - { - this.cmd("SetEdgeHighlight", tmpPtrID, tmp.graphicID, 1); - this.cmd("SetEdgeHighlight", tmpPtrID, tmp.internalGraphicID, 1); - - this.cmd("SetEdgeHighlight", degreeGraphic[tmp.degree], degreeArray[tmp.degree].graphicID, 1); - this.cmd("SetEdgeHighlight", degreeGraphic[tmp.degree], degreeArray[tmp.degree].internalGraphicID, 1); - this.cmd("Step"); - this.cmd("Disconnect", tmpPtrID, tmp.graphicID); - this.cmd("Disconnect", tmpPtrID, tmp.internalGraphicID); - - - - this.cmd("Disconnect", degreeGraphic[tmp.degree], degreeArray[tmp.degree].graphicID); - this.cmd("Disconnect", degreeGraphic[tmp.degree], degreeArray[tmp.degree].internalGraphicID); - this.cmd("SetNull", degreeGraphic[tmp.degree], 1); - var tmp2 = degreeArray[tmp.degree]; - degreeArray[tmp.degree] = null - tmp = this.combineTrees(tmp, tmp2); - this.cmd("Connect", tmpPtrID, - tmp.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", tmpPtrID, - tmp.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.SetAllTreePositions(this.treeRoot, degreeArray, tmp); - this.cmd("Move", tmpPtrID, tmp.x, FibonacciHeap.TMP_PTR_Y); - this.MoveAllTrees(this.treeRoot, degreeArray, tmp); - } - this.cmd("Disconnect", tmpPtrID, tmp.graphicID); - this.cmd("Disconnect", tmpPtrID, tmp.internalGraphicID); - - degreeArray[tmp.degree] = tmp; - this.cmd("SetNull", degreeGraphic[tmp.degree], 0); - this.cmd("Connect", degreeGraphic[tmp.degree], - tmp.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", degreeGraphic[tmp.degree], - tmp.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Step"); - this.SetAllTreePositions(this.treeRoot, degreeArray); - this.MoveAllTrees(this.treeRoot, degreeArray); - } - this.minElement = null; - for (i = FibonacciHeap.MAX_DEGREE; i >= 0; i--) - { - if (degreeArray[i] != null) - { - degreeArray[i].rightSib = this.treeRoot; - if (this.minElement == null || this.minElement.data > degreeArray[i].data) - { - this.minElement = degreeArray[i]; - } - this.treeRoot = degreeArray[i]; - if (this.treeRoot.rightSib != null) - { - this.cmd("Connect", this.treeRoot.internalGraphicID, - this.treeRoot.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", this.treeRoot.rightSib.internalGraphicID, - this.treeRoot.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - } - } - - this.cmd("Delete", degreeGraphic[i]); - this.cmd("Delete", indexID[i]); - - } - if (this.minElement != null) - { - this.cmd("CreateLabel", this.minID,"Min element", this.minElement.x,FibonacciHeap.TMP_PTR_Y); - this.cmd("Connect", this.minID, - this.minElement.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", this.minID, - this.minElement.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 1, // Directed - ""); // Label - } - this.cmd("Delete", tmpPtrID); - -} - -FibonacciHeap.prototype.MoveAllTrees = function(tree, treeList, tree2) -{ - if (tree2 != null && tree2 != undefined) - { - this.moveTree(tree2); - } - if (tree != null) - { - this.moveTree(tree); - } - for (var i = 0; i < treeList.length; i++) - { - if (treeList[i] != null) - { - this.moveTree(treeList[i]); - } - } - this.cmd("Step"); - - -} - - -FibonacciHeap.prototype.SetAllTreePositions = function(tree, treeList, tree2) -{ - var leftSize = FibonacciHeap.STARTING_X; - if (tree2 != null && tree2 != undefined) - { - leftSize = this.setPositions(tree2, leftSize, FibonacciHeap.STARTING_Y); // +FibonacciHeap.NODE_WIDTH; - } - if (tree != null) - { - leftSize = this.setPositions(tree, leftSize, FibonacciHeap.STARTING_Y); // + FibonacciHeap.NODE_WIDTH; - - } - for (var i = 0; i < treeList.length; i++) - { - if (treeList[i] != null) - { - leftSize = this.setPositions(treeList[i], leftSize, FibonacciHeap.STARTING_Y); // + FibonacciHeap.NODE_WIDTH; - } - } -} - -FibonacciHeap.prototype.combineTrees = function(tree1, tree2) -{ - if (tree2.data < tree1.data) - { - var tmp = tree2; - tree2 = tree1; - tree1 = tmp; - } - if (tree1.degree != tree2.degree) - { - return null; - } - tree2.rightSib = tree1.leftChild; - tree2.parent =tree1; - tree1.leftChild = tree2; - tree1.degree++; - - if (tree1.leftChild.rightSib != null) - { - this.cmd("Disconnect", tree1.internalGraphicID, tree1.leftChild.rightSib.internalGraphicID); - this.cmd("Connect", tree1.leftChild.internalGraphicID, - tree1.leftChild.rightSib.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.3, // Curve - 1, // Directed - ""); // Label - this.cmd("Connect", tree1.leftChild.rightSib.internalGraphicID, - tree1.leftChild.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.3, // Curve - 1, // Directed - ""); // Label - } - - this.cmd("Connect", tree1.internalGraphicID, - tree1.leftChild.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.15, // Curve - 1, // Directed - ""); // Label - - this.cmd("Connect", tree1.leftChild.internalGraphicID, - tree1.internalGraphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0.0, // Curve - 1, // Directed - ""); // Label - - this.cmd("SetText", tree1.degreeID, tree1.degree); - this.cmd("Connect", tree1.graphicID, - tree2.graphicID, - FibonacciHeap.FOREGROUND_COLOR, - 0, // Curve - 0, // Directed - ""); // Label - // TODO: Add all the internal links &etc - - return tree1; - -} - -FibonacciHeap.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -FibonacciHeap.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new FibonacciHeap(animManag, canvas.width, canvas.height); -} - - - - -function BinomialNode(val, id, initialX, initialY) -{ - this.data = val; - this.x = initialX; - this.y = initialY; - this.graphicID = id; - this.degree = 0; - this.leftChild = null; - this.rightSib = null; - this.parent = null; - this.internalGraphicID = -1; - this.degreeID = -1; -} - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +FibonacciHeap.LINK_COLOR = "#007700"; +FibonacciHeap.FOREGROUND_COLOR = "#007700"; +FibonacciHeap.BACKGROUND_COLOR = "#EEFFEE"; +FibonacciHeap.INDEX_COLOR = "#0000FF"; + +FibonacciHeap.DEGREE_OFFSET_X = -20; +FibonacciHeap.DEGREE_OFFSET_Y = -20; + +FibonacciHeap.DELETE_LAB_X = 30; +FibonacciHeap.DELETE_LAB_Y = 50; + +FibonacciHeap.NODE_WIDTH = 60; +FibonacciHeap.NODE_HEIGHT = 70 + +FibonacciHeap.STARTING_X = 70; + +FibonacciHeap.INSERT_X = 30; +FibonacciHeap.INSERT_Y = 25 + +FibonacciHeap.STARTING_Y = 100; +FibonacciHeap.MAX_DEGREE = 7; +FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH = 30; +FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT = 30; +FibonacciHeap.DEGREE_ARRAY_START_X = 500; +FibonacciHeap.INDEGREE_ARRAY_START_Y = 50; + +FibonacciHeap.TMP_PTR_Y = 60; + +function FibonacciHeap(am, w, h) +{ + this.init(am, w, h); + +} + +FibonacciHeap.inheritFrom(Algorithm); + + + +FibonacciHeap.prototype.init = function(am, w, h) +{ + FibonacciHeap.superclass.init.call(this, am, w, h); + this.addControls(); + this.treeRoot = null; + this.currentLayer = 1; + this.animationManager.setAllLayers([0,this.currentLayer]); + this.minID = 0; + this.nextIndex = 1; +} + + +FibonacciHeap.prototype.addControls = function() +{ + this.controls = []; + this.insertField = this.addControlToAlgorithmBar("Text", ""); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); + this.controls.push(this.insertField); + + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); + this.insertButton.onclick = this.insertCallback.bind(this); + this.controls.push(this.insertButton); + + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); + this.controls.push(this.removeSmallestButton); + + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearHeapButton); + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", + "Internal Representation", + ], + "BQueueRep"); + + radioButtonList[0].onclick = this.representationChangedHandler.bind(this, true); + radioButtonList[1].onclick = this.representationChangedHandler.bind(this, false); + radioButtonList[0].checked = true; + +} + + +FibonacciHeap.prototype.representationChangedHandler = function(logicalRep, event) +{ + if (logicalRep) + { + this.animationManager.setAllLayers([0,1]); + this.currentLayer = 1; + } + else + { + this.animationManager.setAllLayers([0,2]); + this.currentLayer = 2; + } +} + + + + +FibonacciHeap.prototype.setPositions = function(tree, xPosition, yPosition) +{ + if (tree != null) + { + if (tree.degree == 0) + { + tree.x = xPosition; + tree.y = yPosition; + return this.setPositions(tree.rightSib, xPosition + FibonacciHeap.NODE_WIDTH, yPosition); + } + else if (tree.degree == 1) + { + tree.x = xPosition; + tree.y = yPosition; + this.setPositions(tree.leftChild, xPosition, yPosition + FibonacciHeap.NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + FibonacciHeap.NODE_WIDTH, yPosition); + } + else + { + var treeWidth = Math.pow(2, tree.degree - 1); + tree.x = xPosition + (treeWidth - 1) * FibonacciHeap.NODE_WIDTH; + tree.y = yPosition; + this.setPositions(tree.leftChild, xPosition, yPosition + FibonacciHeap.NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + treeWidth * FibonacciHeap.NODE_WIDTH, yPosition); + } + } + return xPosition; +} + +FibonacciHeap.prototype.moveTree = function(tree) +{ + if (tree != null) + { + this.cmd("Move", tree.graphicID, tree.x, tree.y); + this.cmd("Move", tree.internalGraphicID, tree.x, tree.y); + this.cmd("Move", tree.degreeID, tree.x + FibonacciHeap.DEGREE_OFFSET_X, tree.y + FibonacciHeap.DEGREE_OFFSET_Y); + + this.moveTree(tree.leftChild); + this.moveTree(tree.rightSib); + } +} + + +FibonacciHeap.prototype.insertCallback = function(event) +{ + var insertedValue; + + insertedValue = this.normalizeNumber(this.insertField.value, 4); + if (insertedValue != "") + { + this.insertField.value = ""; + this.implementAction(this.insertElement.bind(this),insertedValue); + } +} + +FibonacciHeap.prototype.clearCallback = function(event) +{ + this.implementAction(this.clear.bind(this),""); +} + +FibonacciHeap.prototype.clear = function() +{ + this.commands = new Array(); + + + this.deleteTree(this.treeRoot); + + this.cmd("Delete", this.minID); + this.nextIndex = 1; + this.treeRoot = null; + this.minElement = null; + return this.commands; +} + + +FibonacciHeap.prototype.deleteTree = function(tree) +{ + if (tree != null) + { + this.cmd("Delete", tree.graphicID); + this.cmd("Delete", tree.internalGraphicID); + this.cmd("Delete", tree.degreeID); + this.deleteTree(tree.leftChild); + this.deleteTree(tree.rightSib); + } +} + +FibonacciHeap.prototype.reset = function() +{ + this.treeRoot = null; + this.nextIndex = 1; +} + +FibonacciHeap.prototype.removeSmallestCallback = function(event) +{ + this.implementAction(this.removeSmallest.bind(this),""); +} + + + +FibonacciHeap.prototype.removeSmallest = function(dummy) +{ + this.commands = new Array(); + + if (this.treeRoot != null) + { + var tmp; + var prev; + + + + if (this.minElement == this.treeRoot) { + this.treeRoot = this.treeRoot.rightSib; + prev = null; + } + else + { + for (prev = this.treeRoot; prev.rightSib != this.minElement; prev = prev.rightSib) ; + prev.rightSib = prev.rightSib.rightSib; + + } + var moveLabel = this.nextIndex++; + this.cmd("SetText", this.minElement.graphicID, ""); + this.cmd("SetText", this.minElement.internalGraphicID, ""); + this.cmd("CreateLabel", moveLabel, this.minElement.data, this.minElement.x, this.minElement.y); + this.cmd("Move", moveLabel, FibonacciHeap.DELETE_LAB_X, FibonacciHeap.DELETE_LAB_Y); + this.cmd("Step"); + this.cmd("Delete", this.minID); + var childList = this.minElement.leftChild; + if (this.treeRoot == null) + { + this.cmd("Delete", this.minElement.graphicID); + this.cmd("Delete", this.minElement.internalGraphicID); + this.cmd("Delete", this.minElement.degreeID); + this.treeRoot = childList; + this.minElement = null; + if (this.treeRoot != null) + { + for (tmp = this.treeRoot; tmp != null; tmp = tmp.rightSib) + { + if (this.minElement == null || this.minElement.data > tmp.data) + { + this.minElement = tmp; + + } + } + this.cmd("CreateLabel", this.minID, "Min element", this.minElement.x, FibonacciHeap.TMP_PTR_Y); + this.cmd("Connect", this.minID, + this.minElement.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", this.minID, + this.minElement.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + } + + this.SetAllTreePositions(this.treeRoot, []); + this.MoveAllTrees(this.treeRoot, []); + this.cmd("Delete", moveLabel); + return this.commands; + + + } + else if (childList == null) + { + if (prev != null && prev.rightSib != null) + { + this.cmd("Connect", prev.internalGraphicID, + prev.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", prev.rightSib.internalGraphicID, + prev.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + } + } + else + { + var tmp; + for (tmp = childList; tmp.rightSib != null; tmp = tmp.rightSib) + { + tmp.parent = null; + } + tmp.parent = null; + + // TODO: Add in implementation links + if (prev == null) + { + this.cmd("Connect", tmp.internalGraphicID, + this.treeRoot.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", this.treeRoot.internalGraphicID, + tmp.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + tmp.rightSib = this.treeRoot; + this.treeRoot = childList; + } + else + { + this.cmd("Connect", prev.internalGraphicID, + childList.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", childList.internalGraphicID, + prev.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + if (prev.rightSib != null) + { + this.cmd("Connect", prev.rightSib.internalGraphicID, + tmp.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", tmp.internalGraphicID, + prev.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + } + tmp.rightSib = prev.rightSib; + prev.rightSib = childList; + } + } + this.cmd("Delete", this.minElement.graphicID); + this.cmd("Delete", this.minElement.internalGraphicID); + this.cmd("Delete", this.minElement.degreeID); + + this.SetAllTreePositions(this.treeRoot, []); + this.MoveAllTrees(this.treeRoot, []); + this.fixAfterRemoveMin(); + this.cmd("Delete", moveLabel); + } + return this.commands; +} + + +FibonacciHeap.prototype.insertElement = function(insertedValue) +{ + this.commands = new Array(); + + var insertNode = new BinomialNode(insertedValue, this.nextIndex++, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); + insertNode.internalGraphicID = this.nextIndex++; + insertNode.degreeID= this.nextIndex++; + this.cmd("CreateCircle", insertNode.graphicID, insertedValue, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); + this.cmd("SetForegroundColor", insertNode.graphicID, FibonacciHeap.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.graphicID, FibonacciHeap.BACKGROUND_COLOR); + this.cmd("SetLayer", insertNode.graphicID, 1); + this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, FibonacciHeap.INSERT_X, FibonacciHeap.INSERT_Y); + this.cmd("SetForegroundColor", insertNode.internalGraphicID, FibonacciHeap.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.internalGraphicID, FibonacciHeap.BACKGROUND_COLOR); + this.cmd("SetLayer", insertNode.internalGraphicID, 2); + this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + FibonacciHeap.DEGREE_OFFSET_X, insertNode.y + FibonacciHeap.DEGREE_OFFSET_Y); + this.cmd("SetTextColor", insertNode.degreeID, "#0000FF"); + this.cmd("SetLayer", insertNode.degreeID, 2); + this.cmd("Step"); + + if (this.treeRoot == null) + { + this.treeRoot = insertNode; + this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); + this.moveTree(this.treeRoot); + this.cmd("CreateLabel", this.minID, "Min element", this.treeRoot.x, FibonacciHeap.TMP_PTR_Y); + this.minElement = this.treeRoot; + this.cmd("Connect", this.minID, + this.minElement.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", this.minID, + this.minElement.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + } + else + { + var tmp; + var prev; + + if (this.minElement == this.treeRoot) { + insertNode.rightSib = this.treeRoot; + this.treeRoot = insertNode; + + this.cmd("Connect", this.treeRoot.internalGraphicID, + this.treeRoot.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", this.treeRoot.rightSib.internalGraphicID, + this.treeRoot.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Step"); + this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); + if (this.minElement.data > insertNode.data) + { + this.cmd("Disconnect", this.minID, this.minElement.graphicID); + this.cmd("Disconnect", this.minID, this.minElement.internalGraphicID); + this.minElement = insertNode; + this.cmd("Connect", this.minID, + this.minElement.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", this.minID, + this.minElement.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + } + this.cmd("Move", this.minID, this.minElement.x, FibonacciHeap.TMP_PTR_Y); + this.moveTree(this.treeRoot); + + } + else + { + for (prev = this.treeRoot; prev.rightSib != this.minElement; prev = prev.rightSib) ; + + + this.cmd("Disconnect", prev.internalGraphicID, prev.rightSib.internalGraphicID); + this.cmd("Disconnect", prev.rightSib.internalGraphicID, prev.internalGraphicID); + + insertNode.rightSib = prev.rightSib; + prev.rightSib = insertNode; + + this.cmd("Connect", prev.internalGraphicID, + prev.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", prev.rightSib.internalGraphicID, + prev.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + if (prev.rightSib.rightSib != null) + { + + this.cmd("Connect", prev.rightSib.internalGraphicID, + prev.rightSib.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", prev.rightSib.rightSib.internalGraphicID, + prev.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + } + + + this.cmd("Step"); + this.setPositions(this.treeRoot, FibonacciHeap.STARTING_X, FibonacciHeap.STARTING_Y); + if (this.minElement.data > insertNode.data) + { + this.cmd("Disconnect", this.minID, this.minElement.graphicID); + this.cmd("Disconnect", this.minID, this.minElement.internalGraphicID); + this.minElement = insertNode; + this.cmd("Connect", this.minID, + this.minElement.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", this.minID, + this.minElement.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + this.cmd("Move", this.minID, this.minElement.x, FibonacciHeap.TMP_PTR_Y); + + this.moveTree(this.treeRoot); + + } + + + + + + } + + return this.commands; +} + + + + + +FibonacciHeap.prototype.fixAfterRemoveMin = function() +{ + if (this.treeRoot == null) + return; + var degreeArray = new Array(FibonacciHeap.MAX_DEGREE); + var degreeGraphic = new Array(FibonacciHeap.MAX_DEGREE); + var indexID = new Array(FibonacciHeap.MAX_DEGREE); + var tmpPtrID = this.nextIndex++; + + var i; + for (i = 0 ; i <= FibonacciHeap.MAX_DEGREE; i++) + { + degreeArray[i] = null; + degreeGraphic[i] = this.nextIndex++; + indexID[i] = this.nextIndex++; + this.cmd("CreateRectangle", + degreeGraphic[i], + " ", + FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, + FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT, + FibonacciHeap.DEGREE_ARRAY_START_X + i * FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, + FibonacciHeap.INDEGREE_ARRAY_START_Y); + this.cmd("SetNull", degreeGraphic[i], 1); + this.cmd("CreateLabel", indexID[i], i, FibonacciHeap.DEGREE_ARRAY_START_X + i * FibonacciHeap.DEGREE_ARRAY_ELEM_WIDTH, + FibonacciHeap.INDEGREE_ARRAY_START_Y - FibonacciHeap.DEGREE_ARRAY_ELEM_HEIGHT); + this.cmd("SetTextColod", indexID[i], FibonacciHeap.INDEX_COLOR); + } + var tmp = this.treeRoot; + // When remving w/ 1 tree. this.treeRoot == null? + this.cmd("CreateLabel", tmpPtrID, "NextElem", this.treeRoot.x, FibonacciHeap.TMP_PTR_Y); + while (this.treeRoot != null) + { + tmp = this.treeRoot; + this.cmd("Connect", tmpPtrID, + tmp.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", tmpPtrID, + tmp.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + + this.treeRoot = this.treeRoot.rightSib; + if (tmp.rightSib != null) + { + this.cmd("Disconnect", tmp.internalGraphicID, tmp.rightSib.internalGraphicID); + this.cmd("Disconnect", tmp.rightSib.internalGraphicID, tmp.internalGraphicID); + } + + this.cmd("Step"); + tmp.rightSib = null; + while(degreeArray[tmp.degree] != null) + { + this.cmd("SetEdgeHighlight", tmpPtrID, tmp.graphicID, 1); + this.cmd("SetEdgeHighlight", tmpPtrID, tmp.internalGraphicID, 1); + + this.cmd("SetEdgeHighlight", degreeGraphic[tmp.degree], degreeArray[tmp.degree].graphicID, 1); + this.cmd("SetEdgeHighlight", degreeGraphic[tmp.degree], degreeArray[tmp.degree].internalGraphicID, 1); + this.cmd("Step"); + this.cmd("Disconnect", tmpPtrID, tmp.graphicID); + this.cmd("Disconnect", tmpPtrID, tmp.internalGraphicID); + + + + this.cmd("Disconnect", degreeGraphic[tmp.degree], degreeArray[tmp.degree].graphicID); + this.cmd("Disconnect", degreeGraphic[tmp.degree], degreeArray[tmp.degree].internalGraphicID); + this.cmd("SetNull", degreeGraphic[tmp.degree], 1); + var tmp2 = degreeArray[tmp.degree]; + degreeArray[tmp.degree] = null + tmp = this.combineTrees(tmp, tmp2); + this.cmd("Connect", tmpPtrID, + tmp.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", tmpPtrID, + tmp.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.SetAllTreePositions(this.treeRoot, degreeArray, tmp); + this.cmd("Move", tmpPtrID, tmp.x, FibonacciHeap.TMP_PTR_Y); + this.MoveAllTrees(this.treeRoot, degreeArray, tmp); + } + this.cmd("Disconnect", tmpPtrID, tmp.graphicID); + this.cmd("Disconnect", tmpPtrID, tmp.internalGraphicID); + + degreeArray[tmp.degree] = tmp; + this.cmd("SetNull", degreeGraphic[tmp.degree], 0); + this.cmd("Connect", degreeGraphic[tmp.degree], + tmp.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", degreeGraphic[tmp.degree], + tmp.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Step"); + this.SetAllTreePositions(this.treeRoot, degreeArray); + this.MoveAllTrees(this.treeRoot, degreeArray); + } + this.minElement = null; + for (i = FibonacciHeap.MAX_DEGREE; i >= 0; i--) + { + if (degreeArray[i] != null) + { + degreeArray[i].rightSib = this.treeRoot; + if (this.minElement == null || this.minElement.data > degreeArray[i].data) + { + this.minElement = degreeArray[i]; + } + this.treeRoot = degreeArray[i]; + if (this.treeRoot.rightSib != null) + { + this.cmd("Connect", this.treeRoot.internalGraphicID, + this.treeRoot.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", this.treeRoot.rightSib.internalGraphicID, + this.treeRoot.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + } + } + + this.cmd("Delete", degreeGraphic[i]); + this.cmd("Delete", indexID[i]); + + } + if (this.minElement != null) + { + this.cmd("CreateLabel", this.minID,"Min element", this.minElement.x,FibonacciHeap.TMP_PTR_Y); + this.cmd("Connect", this.minID, + this.minElement.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", this.minID, + this.minElement.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 1, // Directed + ""); // Label + } + this.cmd("Delete", tmpPtrID); + +} + +FibonacciHeap.prototype.MoveAllTrees = function(tree, treeList, tree2) +{ + if (tree2 != null && tree2 != undefined) + { + this.moveTree(tree2); + } + if (tree != null) + { + this.moveTree(tree); + } + for (var i = 0; i < treeList.length; i++) + { + if (treeList[i] != null) + { + this.moveTree(treeList[i]); + } + } + this.cmd("Step"); + + +} + + +FibonacciHeap.prototype.SetAllTreePositions = function(tree, treeList, tree2) +{ + var leftSize = FibonacciHeap.STARTING_X; + if (tree2 != null && tree2 != undefined) + { + leftSize = this.setPositions(tree2, leftSize, FibonacciHeap.STARTING_Y); // +FibonacciHeap.NODE_WIDTH; + } + if (tree != null) + { + leftSize = this.setPositions(tree, leftSize, FibonacciHeap.STARTING_Y); // + FibonacciHeap.NODE_WIDTH; + + } + for (var i = 0; i < treeList.length; i++) + { + if (treeList[i] != null) + { + leftSize = this.setPositions(treeList[i], leftSize, FibonacciHeap.STARTING_Y); // + FibonacciHeap.NODE_WIDTH; + } + } +} + +FibonacciHeap.prototype.combineTrees = function(tree1, tree2) +{ + if (tree2.data < tree1.data) + { + var tmp = tree2; + tree2 = tree1; + tree1 = tmp; + } + if (tree1.degree != tree2.degree) + { + return null; + } + tree2.rightSib = tree1.leftChild; + tree2.parent =tree1; + tree1.leftChild = tree2; + tree1.degree++; + + if (tree1.leftChild.rightSib != null) + { + this.cmd("Disconnect", tree1.internalGraphicID, tree1.leftChild.rightSib.internalGraphicID); + this.cmd("Connect", tree1.leftChild.internalGraphicID, + tree1.leftChild.rightSib.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.3, // Curve + 1, // Directed + ""); // Label + this.cmd("Connect", tree1.leftChild.rightSib.internalGraphicID, + tree1.leftChild.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.3, // Curve + 1, // Directed + ""); // Label + } + + this.cmd("Connect", tree1.internalGraphicID, + tree1.leftChild.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.15, // Curve + 1, // Directed + ""); // Label + + this.cmd("Connect", tree1.leftChild.internalGraphicID, + tree1.internalGraphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0.0, // Curve + 1, // Directed + ""); // Label + + this.cmd("SetText", tree1.degreeID, tree1.degree); + this.cmd("Connect", tree1.graphicID, + tree2.graphicID, + FibonacciHeap.FOREGROUND_COLOR, + 0, // Curve + 0, // Directed + ""); // Label + // TODO: Add all the internal links &etc + + return tree1; + +} + +FibonacciHeap.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +FibonacciHeap.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new FibonacciHeap(animManag, canvas.width, canvas.height); +} + + + + +function BinomialNode(val, id, initialX, initialY) +{ + this.data = val; + this.x = initialX; + this.y = initialY; + this.graphicID = id; + this.degree = 0; + this.leftChild = null; + this.rightSib = null; + this.parent = null; + this.internalGraphicID = -1; + this.degreeID = -1; +} + + diff --git a/AlgorithmLibrary/Graph.js b/AlgorithmLibrary/Graph.js index 8e68118..e547e1c 100644 --- a/AlgorithmLibrary/Graph.js +++ b/AlgorithmLibrary/Graph.js @@ -1,719 +1,719 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -// TODO: UNDO (all the way) is BROKEN. Redo reset ... - - -function Graph(am, w, h, dir, dag) -{ - // this shouldn't happen if subclassing is done properly - if (!am) - throw "this shouldn't happen"; - - this.init(am, w, h, dir,dag); -} - -Graph.inheritFrom(Algorithm); - -var LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, false, false, false, false, false, true, false, false, false], - [true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false], - [true, true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false], - [false, false, true, false, false,false, true, false, false, false, true, false, false, false, false, false, false, true], - [true, true, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false], - [false, true, true, false, true, false, true, false, true, true, false, false, false, false, false, false, false, false], - [false, false, true, true, false, true, false, false, false, true, true, false, false, false, false, false, false, false], - [true, false, false, false, true, false, false, false, true, false, false, true, false, false, true, false, false, false], - [false, false, false, false, true, true, false, true, false, true, false, true, true, false, false, false, false, false], - [false, false, false, false, false, true, true, false, true, false, true, false, true, true, false, false, false, false], - [false, false, false, true, false, false, true, false, false, true, false, false, false, true, false, false, false, true], - [false, false, false, false, false, false, false, true, true, false, false, false, true, false, true, true, false, false], - [false, false, false, false, false, false, false, false, true, true, false, true, false, true, false, true, true, false], - [false, false, false, false, false, false, false, false, false, true, true, false, true, false, false, false, true, true], - [false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, true, false, false], - [false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true, true], - [false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true], - [false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, true, true, false]]; - -var LARGE_CURVE = [[0, 0, -0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.25], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [-0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.4, 0, 0]] - - - -var LARGE_X_POS_LOGICAL = [600, 700, 800, 900, - 650, 750, 850, - 600, 700, 800, 900, - 650, 750, 850, - 600, 700, 800, 900]; - - -var LARGE_Y_POS_LOGICAL = [50, 50, 50, 50, - 150, 150, 150, - 250, 250, 250, 250, - 350, 350, 350, - 450, 450, 450, 450]; - - -var SMALL_ALLLOWED = [[false, true, true, true, true, false, false, false], - [true, false, true, true, false, true, true, false], - [true, true, false, false, true, true, true, false], - [true, true, false, false, false, true, false, true], - [true, false, true, false, false, false, true, true], - [false, true, true, true, false, false, true, true], - [false, true, true, false, true, true, false, true], - [false, false, false, true, true, true, true, false]]; - -var SMALL_CURVE = [[0, 0.001, 0, 0.5, -0.5, 0, 0, 0], - [0, 0, 0, 0.001, 0, 0.001, -0.2, 0], - [0, 0.001, 0, 0, 0, 0.2, 0, 0], - [-0.5, 0, 0, 0, 0, 0.001, 0, 0.5], - [0.5, 0, 0, 0, 0, 0, 0, -0.5], - [0, 0, -0.2, 0, 0, 0, 0.001, 0.001], - [0, 0.2, 0, 0, 0, 0, 0, 0], - [0, 0, 0, -0.5, 0.5, 0, 0, 0]] - -var SMALL_X_POS_LOGICAL = [800, 725, 875, 650, 950, 725, 875, 800]; -var SMALL_Y_POS_LOGICAL = [25, 125, 125, 225, 225, 325, 325, 425]; - - -var SMALL_ADJ_MATRIX_X_START = 700; -var SMALL_ADJ_MATRIX_Y_START = 40; -var SMALL_ADJ_MATRIX_WIDTH = 30; -var SMALL_ADJ_MATRIX_HEIGHT = 30; - -var SMALL_ADJ_LIST_X_START = 600; -var SMALL_ADJ_LIST_Y_START = 30; - -var SMALL_ADJ_LIST_ELEM_WIDTH = 50; -var SMALL_ADJ_LIST_ELEM_HEIGHT = 30; - -var SMALL_ADJ_LIST_HEIGHT = 36; -var SMALL_ADJ_LIST_WIDTH = 36; - -var SMALL_ADJ_LIST_SPACING = 10; - - -var LARGE_ADJ_MATRIX_X_START = 575; -var LARGE_ADJ_MATRIX_Y_START = 30; -var LARGE_ADJ_MATRIX_WIDTH = 23; -var LARGE_ADJ_MATRIX_HEIGHT = 23; - -var LARGE_ADJ_LIST_X_START = 600; -var LARGE_ADJ_LIST_Y_START = 30; - -var LARGE_ADJ_LIST_ELEM_WIDTH = 50; -var LARGE_ADJ_LIST_ELEM_HEIGHT = 26; - -var LARGE_ADJ_LIST_HEIGHT = 30; -var LARGE_ADJ_LIST_WIDTH = 30; - -var LARGE_ADJ_LIST_SPACING = 10; - - - -var VERTEX_INDEX_COLOR ="#0000FF"; -var EDGE_COLOR = "#000000"; - -var SMALL_SIZE = 8; -var LARGE_SIZE = 18; - -var HIGHLIGHT_COLOR = "#0000FF"; - - - - - -Graph.prototype.init = function(am, w, h, directed, dag) -{ - directed = (directed == undefined) ? true : directed; - dag = (dag == undefined) ? false : dag; - - Graph.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - - this.currentLayer = 1; - this.isDAG = dag; - this.directed = directed; - this.currentLayer = 1; - this.addControls(); - - this.setup_small(); -} - -Graph.prototype.addControls = function(addDirection) -{ - if (addDirection == undefined) - { - addDirection = true; - } - this.newGraphButton = this.addControlToAlgorithmBar("Button", "New Graph"); - this.newGraphButton.onclick = this.newGraphCallback.bind(this); - - if (addDirection) - { - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Directed Graph", "Undirected Graph"], "GraphType"); - this.directedGraphButton = radioButtonList[0]; - this.directedGraphButton.onclick = this.directedGraphCallback.bind(this, true); - this.undirectedGraphButton = radioButtonList[1]; - this.undirectedGraphButton.onclick = this.directedGraphCallback.bind(this, false); - this.directedGraphButton.checked = this.directed; - this.undirectedGraphButton.checked = !this.directed; - } - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small Graph", "Large Graph"], "GraphSize"); - this.smallGraphButton = radioButtonList[0]; - this.smallGraphButton.onclick = this.smallGraphCallback.bind(this); - this.largeGraphButton = radioButtonList[1]; - this.largeGraphButton.onclick = this.largeGraphCallback.bind(this); - this.smallGraphButton.checked = true; - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", - "Adjacency List Representation", - "Adjacency Matrix Representation" - ], - "GraphRepresentation"); - this.logicalButton = radioButtonList[0]; - this.logicalButton.onclick = this.graphRepChangedCallback.bind(this,1); - this.adjacencyListButton = radioButtonList[1]; - this.adjacencyListButton.onclick = this.graphRepChangedCallback.bind(this,2); - this.adjacencyMatrixButton = radioButtonList[2]; - this.adjacencyMatrixButton.onclick = this.graphRepChangedCallback.bind(this,3); - this.logicalButton.checked = true; - -} - -Graph.prototype.directedGraphCallback = function (newDirected, event) -{ - if (newDirected != this.directed) - { - this.directed =newDirected; - this.animationManager.resetAll(); - this.setup(); - } -} - - - -Graph.prototype.smallGraphCallback = function (event) -{ - if (this.size != SMALL_SIZE) - { - this.animationManager.resetAll(); - this.setup_small(); - } -} - -Graph.prototype.largeGraphCallback = function (event) -{ - if (this.size != LARGE_SIZE) - { - this.animationManager.resetAll(); - this.setup_large(); - } -} - - -Graph.prototype.newGraphCallback = function(event) -{ - this.animationManager.resetAll(); - this.setup(); -} - - - -Graph.prototype.graphRepChangedCallback = function(newLayer, event) -{ - this.animationManager.setAllLayers([0,newLayer]); - this.currentLayer = newLayer; -} - - -Graph.prototype.recolorGraph = function() -{ - for (var i = 0; i < this.size; i++) - { - for (var j = 0; j < this.size; j++) - { - if (this.adj_matrix[i][j] >= 0) - { - this.setEdgeColor(i, j, EDGE_COLOR); - } - } - } -} - -Graph.prototype.highlightEdge = function(i,j, highlightVal) -{ - this.cmd("SetHighlight", this.adj_list_edges[i][j], highlightVal); - this.cmd("SetHighlight", this.adj_matrixID[i][j], highlightVal); - this.cmd("SetEdgeHighlight", this.circleID[i], this.circleID[j], highlightVal); - if (!this.directed) - { - this.cmd("SetEdgeHighlight", this.circleID[j], this.circleID[i], highlightVal); - } -} - -Graph.prototype.setEdgeColor = function(i,j, color) -{ - this.cmd("SetForegroundColor", this.adj_list_edges[i][j], color); - this.cmd("SetTextColor", this.adj_matrixID[i][j], color); - this.cmd("SetEdgeColor", this.circleID[i], this.circleID[j], color); - if (!this.directed) - { - this.cmd("SetEdgeColor", this.circleID[j], this.circleID[i], color); - } -} - - - -Graph.prototype.clearEdges = function() -{ - for (var i = 0; i < this.size; i++) - { - for (var j = 0; j < this.size; j++) - { - if (this.adj_matrix[i][j] >= 0) - { - this.cmd("Disconnect", this.circleID[i], this.circleID[j]); - } - } - } -} - - -Graph.prototype.rebuildEdges = function() -{ - this.clearEdges(); - this.buildEdges(); -} - - - -Graph.prototype.buildEdges = function() -{ - - for (var i = 0; i < this.size; i++) - { - for (var j = 0; j < this.size; j++) - { - if (this.adj_matrix[i][j] >= 0) - { - var edgeLabel; - if (this.showEdgeCosts) - { - edgeLabel = String(this.adj_matrix[i][j]); - } - else - { - edgeLabel = ""; - } - if (this.directed) - { - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.adjustCurveForDirectedEdges(this.curve[i][j], this.adj_matrix[j][i] >= 0), 1, edgeLabel); - } - else if (i < j) - { - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); - } - } - } - } - -} - -Graph.prototype.setup_small = function() -{ - this.allowed = SMALL_ALLLOWED; - this.curve = SMALL_CURVE; - this. x_pos_logical = SMALL_X_POS_LOGICAL; - this. y_pos_logical = SMALL_Y_POS_LOGICAL; - this.adj_matrix_x_start = SMALL_ADJ_MATRIX_X_START; - this.adj_matrix_y_start = SMALL_ADJ_MATRIX_Y_START; - this.adj_matrix_width = SMALL_ADJ_MATRIX_WIDTH; - this.adj_matrix_height = SMALL_ADJ_MATRIX_HEIGHT; - this.adj_list_x_start = SMALL_ADJ_LIST_X_START; - this.adj_list_y_start = SMALL_ADJ_LIST_Y_START; - this.adj_list_elem_width = SMALL_ADJ_LIST_ELEM_WIDTH; - this.adj_list_elem_height = SMALL_ADJ_LIST_ELEM_HEIGHT; - this.adj_list_height = SMALL_ADJ_LIST_HEIGHT; - this.adj_list_width = SMALL_ADJ_LIST_WIDTH; - this.adj_list_spacing = SMALL_ADJ_LIST_SPACING; - this.size = SMALL_SIZE; - this.setup(); -} - -Graph.prototype.setup_large = function() -{ - this.allowed = LARGE_ALLOWED; - this.curve = LARGE_CURVE; - this. x_pos_logical = LARGE_X_POS_LOGICAL; - this. y_pos_logical = LARGE_Y_POS_LOGICAL; - this.adj_matrix_x_start = LARGE_ADJ_MATRIX_X_START; - this.adj_matrix_y_start = LARGE_ADJ_MATRIX_Y_START; - this.adj_matrix_width = LARGE_ADJ_MATRIX_WIDTH; - this.adj_matrix_height = LARGE_ADJ_MATRIX_HEIGHT; - this.adj_list_x_start = LARGE_ADJ_LIST_X_START; - this.adj_list_y_start = LARGE_ADJ_LIST_Y_START; - this.adj_list_elem_width = LARGE_ADJ_LIST_ELEM_WIDTH; - this.adj_list_elem_height = LARGE_ADJ_LIST_ELEM_HEIGHT; - this.adj_list_height = LARGE_ADJ_LIST_HEIGHT; - this.adj_list_width = LARGE_ADJ_LIST_WIDTH; - this.adj_list_spacing = LARGE_ADJ_LIST_SPACING; - this.size = LARGE_SIZE; - this.setup(); -} - -Graph.prototype.adjustCurveForDirectedEdges = function(curve, bidirectional) -{ - if (!bidirectional || Math.abs(curve) > 0.01) - { - return curve; - } - else - { - return 0.1; - } - -} - -Graph.prototype.setup = function() -{ - this.commands = new Array(); - this.circleID = new Array(this.size); - for (var i = 0; i < this.size; i++) - { - this.circleID[i] = this.nextIndex++; - this.cmd("CreateCircle", this.circleID[i], i, this. x_pos_logical[i], this. y_pos_logical[i]); - this.cmd("SetTextColor", this.circleID[i], VERTEX_INDEX_COLOR, 0); - - this.cmd("SetLayer", this.circleID[i], 1); - } - - this.adj_matrix = new Array(this.size); - this.adj_matrixID = new Array(this.size); - for (i = 0; i < this.size; i++) - { - this.adj_matrix[i] = new Array(this.size); - this.adj_matrixID[i] = new Array(this.size); - } - - var edgePercent; - if (this.size == SMALL_SIZE) - { - if (this.directed) - { - edgePercent = 0.4; - } - else - { - edgePercent = 0.5; - } - - } - else - { - if (this.directed) - { - edgePercent = 0.35; - } - else - { - edgePercent = 0.6; - } - - } - - var lowerBound = 0; - - if (this.directed) - { - for (i = 0; i < this.size; i++) - { - for (var j = 0; j < this.size; j++) - { - this.adj_matrixID[i][j] = this.nextIndex++; - if ((this.allowed[i][j]) && Math.random() <= edgePercent && (i < j || Math.abs(this.curve[i][j]) < 0.01 || this.adj_matrixID[j][i] == -1) && (!this.isDAG || (i < j))) - { - if (this.showEdgeCosts) - { - this.adj_matrix[i][j] = Math.floor(Math.random()* 9) + 1; - } - else - { - this.adj_matrix[i][j] = 1; - } - - } - else - { - this.adj_matrix[i][j] = -1; - } - - } - } - this.buildEdges(); - - } - else - { - for (i = 0; i < this.size; i++) - { - for (j = i+1; j < this.size; j++) - { - - this.adj_matrixID[i][j] = this.nextIndex++; - this.adj_matrixID[j][i] = this.nextIndex++; - - if ((this.allowed[i][j]) && Math.random() <= edgePercent) - { - if (this.showEdgeCosts) - { - this.adj_matrix[i][j] = Math.floor(Math.random()* 9) + 1; - } - else - { - this.adj_matrix[i][j] = 1; - } - this.adj_matrix[j][i] = this.adj_matrix[i][j]; - if (this.showEdgeCosts) - { - var edgeLabel = String(this.adj_matrix[i][j]); - } - else - { - edgeLabel = ""; - } - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); - } - else - { - this.adj_matrix[i][j] = -1; - this.adj_matrix[j][i] = -1; - } - - } - } - - this.buildEdges(); - - - for (i=0; i < this.size; i++) - { - this.adj_matrix[i][i] = -1; - } - - } - - - // Craate Adj List - - - this.buildAdjList(); - - - // Create Adj Matrix - - this.buildAdjMatrix(); - - - this.animationManager.setAllLayers([0, this.currentLayer]); - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.clearHistory(); -} - -Graph.prototype.resetAll = function() -{ - -} - - -Graph.prototype.buildAdjMatrix = function() -{ - - this.adj_matrix_index_x = new Array(this.size); - this.adj_matrix_index_y = new Array(this.size); - for (var i = 0; i < this.size; i++) - { - this.adj_matrix_index_x[i] = this.nextIndex++; - this.adj_matrix_index_y[i] = this.nextIndex++; - this.cmd("CreateLabel", this.adj_matrix_index_x[i], i, this.adj_matrix_x_start + i*this.adj_matrix_width, this.adj_matrix_y_start - this.adj_matrix_height); - this.cmd("SetForegroundColor", this.adj_matrix_index_x[i], VERTEX_INDEX_COLOR); - this.cmd("CreateLabel", this.adj_matrix_index_y[i], i, this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + i* this.adj_matrix_height); - this.cmd("SetForegroundColor", this.adj_matrix_index_y[i], VERTEX_INDEX_COLOR); - this.cmd("SetLayer", this.adj_matrix_index_x[i], 3); - this.cmd("SetLayer", this.adj_matrix_index_y[i], 3); - - for (var j = 0; j < this.size; j++) - { - this.adj_matrixID[i][j] = this.nextIndex++; - if (this.adj_matrix[i][j] < 0) - { - var lab = "" - } - else - { - lab = String(this.adj_matrix[i][j]) - } - this.cmd("CreateRectangle", this.adj_matrixID[i][j], lab, this.adj_matrix_width, this.adj_matrix_height, - this.adj_matrix_x_start + j*this.adj_matrix_width,this.adj_matrix_y_start + i * this.adj_matrix_height); - this.cmd("SetLayer", this.adj_matrixID[i][j], 3); - - - } - } -} - - - -Graph.prototype.removeAdjList = function() -{ - for (var i = 0; i < this.size; i++) - { - this.cmd("Delete", this.adj_list_list[i], "RAL1"); - this.cmd("Delete", this.adj_list_index[i], "RAL2"); - for (var j = 0; j < this.size; j++) - { - if (this.adj_matrix[i][j] > 0) - { - this.cmd("Delete", this.adj_list_edges[i][j], "RAL3"); - } - } - } - -} - - -Graph.prototype.buildAdjList = function() -{ - this.adj_list_index = new Array(this.size); - this.adj_list_list = new Array(this.size); - this.adj_list_edges = new Array(this.size); - - for (var i = 0; i < this.size; i++) - { - this.adj_list_index[i] = this.nextIndex++; - this.adj_list_edges[i] = new Array(this.size); - this.adj_list_index[i] = this.nextIndex++; - this.adj_list_list[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.adj_list_list[i], "", this.adj_list_width, this.adj_list_height, this.adj_list_x_start, this.adj_list_y_start + i*this.adj_list_height); - this.cmd("SetLayer", this.adj_list_list[i], 2); - this.cmd("CreateLabel", this.adj_list_index[i], i, this.adj_list_x_start - this.adj_list_width , this.adj_list_y_start + i*this.adj_list_height); - this.cmd("SetForegroundColor", this.adj_list_index[i], VERTEX_INDEX_COLOR); - this.cmd("SetLayer", this.adj_list_index[i], 2); - var lastElem = this.adj_list_list[i]; - var nextXPos = this.adj_list_x_start + this.adj_list_width + this.adj_list_spacing; - var hasEdges = false; - for (var j = 0; j < this.size; j++) - { - if (this.adj_matrix[i][j] > 0) - { - hasEdges = true; - this.adj_list_edges[i][j] = this.nextIndex++; - this.cmd("CreateLinkedList",this.adj_list_edges[i][j], j,this.adj_list_elem_width, this.adj_list_elem_height, - nextXPos, this.adj_list_y_start + i*this.adj_list_height, 0.25, 0, 1, 2); - this.cmd("SetNull", this.adj_list_edges[i][j], 1); - this.cmd("SetText", this.adj_list_edges[i][j], this.adj_matrix[i][j], 1); - this.cmd("SetTextColor", this.adj_list_edges[i][j], VERTEX_INDEX_COLOR, 0); - this.cmd("SetLayer", this.adj_list_edges[i][j], 2); - - nextXPos = nextXPos + this.adj_list_elem_width + this.adj_list_spacing; - this.cmd("Connect", lastElem, this.adj_list_edges[i][j]); - this.cmd("SetNull", lastElem, 0); - lastElem = this.adj_list_edges[i][j]; - } - } - if (!hasEdges) - { - this.cmd("SetNull", this.adj_list_list[i], 1); - } - } -} - - - - -// NEED TO OVERRIDE IN PARENT -Graph.prototype.reset = function() -{ - // Throw an error? -} - - -Graph.prototype.disableUI = function(event) -{ - this.newGraphButton.disabled = true; - if (this.directedGraphButton != null && this.directedGraphButton != undefined) - this.directedGraphButton.disabled = true; - if (this.undirectedGraphButton != null && this.undirectedGraphButton != undefined) - this.undirectedGraphButton.disabled = true; - this.smallGraphButton.disabled = true; - this.largeGraphButton.disabled = true; -} - - - -Graph.prototype.enableUI = function(event) -{ - - this.newGraphButton.disabled = false; - if (this.directedGraphButton != null && this.directedGraphButton != undefined) - this.directedGraphButton.disabled = false; - if (this.undirectedGraphButton != null && this.undirectedGraphButton != undefined) - this.undirectedGraphButton.disabled = false; - this.smallGraphButton.disabled = false; - this.largeGraphButton.disabled = false; -} - - - -/* no init, this is only a base class! */ - var currentAlg; - function init() - { - var animManag = initCanvas(); - currentAlg = new Graph(animManag, canvas.width, canvas.height); -} - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +// TODO: UNDO (all the way) is BROKEN. Redo reset ... + + +function Graph(am, w, h, dir, dag) +{ + // this shouldn't happen if subclassing is done properly + if (!am) + throw "this shouldn't happen"; + + this.init(am, w, h, dir,dag); +} + +Graph.inheritFrom(Algorithm); + +var LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, false, false, false, false, false, true, false, false, false], + [true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false], + [true, true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false], + [false, false, true, false, false,false, true, false, false, false, true, false, false, false, false, false, false, true], + [true, true, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false], + [false, true, true, false, true, false, true, false, true, true, false, false, false, false, false, false, false, false], + [false, false, true, true, false, true, false, false, false, true, true, false, false, false, false, false, false, false], + [true, false, false, false, true, false, false, false, true, false, false, true, false, false, true, false, false, false], + [false, false, false, false, true, true, false, true, false, true, false, true, true, false, false, false, false, false], + [false, false, false, false, false, true, true, false, true, false, true, false, true, true, false, false, false, false], + [false, false, false, true, false, false, true, false, false, true, false, false, false, true, false, false, false, true], + [false, false, false, false, false, false, false, true, true, false, false, false, true, false, true, true, false, false], + [false, false, false, false, false, false, false, false, true, true, false, true, false, true, false, true, true, false], + [false, false, false, false, false, false, false, false, false, true, true, false, true, false, false, false, true, true], + [false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, true, false, false], + [false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true, true], + [false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true], + [false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, true, true, false]]; + +var LARGE_CURVE = [[0, 0, -0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.25], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [-0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.4, 0, 0]] + + + +var LARGE_X_POS_LOGICAL = [600, 700, 800, 900, + 650, 750, 850, + 600, 700, 800, 900, + 650, 750, 850, + 600, 700, 800, 900]; + + +var LARGE_Y_POS_LOGICAL = [50, 50, 50, 50, + 150, 150, 150, + 250, 250, 250, 250, + 350, 350, 350, + 450, 450, 450, 450]; + + +var SMALL_ALLLOWED = [[false, true, true, true, true, false, false, false], + [true, false, true, true, false, true, true, false], + [true, true, false, false, true, true, true, false], + [true, true, false, false, false, true, false, true], + [true, false, true, false, false, false, true, true], + [false, true, true, true, false, false, true, true], + [false, true, true, false, true, true, false, true], + [false, false, false, true, true, true, true, false]]; + +var SMALL_CURVE = [[0, 0.001, 0, 0.5, -0.5, 0, 0, 0], + [0, 0, 0, 0.001, 0, 0.001, -0.2, 0], + [0, 0.001, 0, 0, 0, 0.2, 0, 0], + [-0.5, 0, 0, 0, 0, 0.001, 0, 0.5], + [0.5, 0, 0, 0, 0, 0, 0, -0.5], + [0, 0, -0.2, 0, 0, 0, 0.001, 0.001], + [0, 0.2, 0, 0, 0, 0, 0, 0], + [0, 0, 0, -0.5, 0.5, 0, 0, 0]] + +var SMALL_X_POS_LOGICAL = [800, 725, 875, 650, 950, 725, 875, 800]; +var SMALL_Y_POS_LOGICAL = [25, 125, 125, 225, 225, 325, 325, 425]; + + +var SMALL_ADJ_MATRIX_X_START = 700; +var SMALL_ADJ_MATRIX_Y_START = 40; +var SMALL_ADJ_MATRIX_WIDTH = 30; +var SMALL_ADJ_MATRIX_HEIGHT = 30; + +var SMALL_ADJ_LIST_X_START = 600; +var SMALL_ADJ_LIST_Y_START = 30; + +var SMALL_ADJ_LIST_ELEM_WIDTH = 50; +var SMALL_ADJ_LIST_ELEM_HEIGHT = 30; + +var SMALL_ADJ_LIST_HEIGHT = 36; +var SMALL_ADJ_LIST_WIDTH = 36; + +var SMALL_ADJ_LIST_SPACING = 10; + + +var LARGE_ADJ_MATRIX_X_START = 575; +var LARGE_ADJ_MATRIX_Y_START = 30; +var LARGE_ADJ_MATRIX_WIDTH = 23; +var LARGE_ADJ_MATRIX_HEIGHT = 23; + +var LARGE_ADJ_LIST_X_START = 600; +var LARGE_ADJ_LIST_Y_START = 30; + +var LARGE_ADJ_LIST_ELEM_WIDTH = 50; +var LARGE_ADJ_LIST_ELEM_HEIGHT = 26; + +var LARGE_ADJ_LIST_HEIGHT = 30; +var LARGE_ADJ_LIST_WIDTH = 30; + +var LARGE_ADJ_LIST_SPACING = 10; + + + +var VERTEX_INDEX_COLOR ="#0000FF"; +var EDGE_COLOR = "#000000"; + +var SMALL_SIZE = 8; +var LARGE_SIZE = 18; + +var HIGHLIGHT_COLOR = "#0000FF"; + + + + + +Graph.prototype.init = function(am, w, h, directed, dag) +{ + directed = (directed == undefined) ? true : directed; + dag = (dag == undefined) ? false : dag; + + Graph.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + + this.currentLayer = 1; + this.isDAG = dag; + this.directed = directed; + this.currentLayer = 1; + this.addControls(); + + this.setup_small(); +} + +Graph.prototype.addControls = function(addDirection) +{ + if (addDirection == undefined) + { + addDirection = true; + } + this.newGraphButton = this.addControlToAlgorithmBar("Button", "New Graph"); + this.newGraphButton.onclick = this.newGraphCallback.bind(this); + + if (addDirection) + { + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Directed Graph", "Undirected Graph"], "GraphType"); + this.directedGraphButton = radioButtonList[0]; + this.directedGraphButton.onclick = this.directedGraphCallback.bind(this, true); + this.undirectedGraphButton = radioButtonList[1]; + this.undirectedGraphButton.onclick = this.directedGraphCallback.bind(this, false); + this.directedGraphButton.checked = this.directed; + this.undirectedGraphButton.checked = !this.directed; + } + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small Graph", "Large Graph"], "GraphSize"); + this.smallGraphButton = radioButtonList[0]; + this.smallGraphButton.onclick = this.smallGraphCallback.bind(this); + this.largeGraphButton = radioButtonList[1]; + this.largeGraphButton.onclick = this.largeGraphCallback.bind(this); + this.smallGraphButton.checked = true; + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Logical Representation", + "Adjacency List Representation", + "Adjacency Matrix Representation" + ], + "GraphRepresentation"); + this.logicalButton = radioButtonList[0]; + this.logicalButton.onclick = this.graphRepChangedCallback.bind(this,1); + this.adjacencyListButton = radioButtonList[1]; + this.adjacencyListButton.onclick = this.graphRepChangedCallback.bind(this,2); + this.adjacencyMatrixButton = radioButtonList[2]; + this.adjacencyMatrixButton.onclick = this.graphRepChangedCallback.bind(this,3); + this.logicalButton.checked = true; + +} + +Graph.prototype.directedGraphCallback = function (newDirected, event) +{ + if (newDirected != this.directed) + { + this.directed =newDirected; + this.animationManager.resetAll(); + this.setup(); + } +} + + + +Graph.prototype.smallGraphCallback = function (event) +{ + if (this.size != SMALL_SIZE) + { + this.animationManager.resetAll(); + this.setup_small(); + } +} + +Graph.prototype.largeGraphCallback = function (event) +{ + if (this.size != LARGE_SIZE) + { + this.animationManager.resetAll(); + this.setup_large(); + } +} + + +Graph.prototype.newGraphCallback = function(event) +{ + this.animationManager.resetAll(); + this.setup(); +} + + + +Graph.prototype.graphRepChangedCallback = function(newLayer, event) +{ + this.animationManager.setAllLayers([0,newLayer]); + this.currentLayer = newLayer; +} + + +Graph.prototype.recolorGraph = function() +{ + for (var i = 0; i < this.size; i++) + { + for (var j = 0; j < this.size; j++) + { + if (this.adj_matrix[i][j] >= 0) + { + this.setEdgeColor(i, j, EDGE_COLOR); + } + } + } +} + +Graph.prototype.highlightEdge = function(i,j, highlightVal) +{ + this.cmd("SetHighlight", this.adj_list_edges[i][j], highlightVal); + this.cmd("SetHighlight", this.adj_matrixID[i][j], highlightVal); + this.cmd("SetEdgeHighlight", this.circleID[i], this.circleID[j], highlightVal); + if (!this.directed) + { + this.cmd("SetEdgeHighlight", this.circleID[j], this.circleID[i], highlightVal); + } +} + +Graph.prototype.setEdgeColor = function(i,j, color) +{ + this.cmd("SetForegroundColor", this.adj_list_edges[i][j], color); + this.cmd("SetTextColor", this.adj_matrixID[i][j], color); + this.cmd("SetEdgeColor", this.circleID[i], this.circleID[j], color); + if (!this.directed) + { + this.cmd("SetEdgeColor", this.circleID[j], this.circleID[i], color); + } +} + + + +Graph.prototype.clearEdges = function() +{ + for (var i = 0; i < this.size; i++) + { + for (var j = 0; j < this.size; j++) + { + if (this.adj_matrix[i][j] >= 0) + { + this.cmd("Disconnect", this.circleID[i], this.circleID[j]); + } + } + } +} + + +Graph.prototype.rebuildEdges = function() +{ + this.clearEdges(); + this.buildEdges(); +} + + + +Graph.prototype.buildEdges = function() +{ + + for (var i = 0; i < this.size; i++) + { + for (var j = 0; j < this.size; j++) + { + if (this.adj_matrix[i][j] >= 0) + { + var edgeLabel; + if (this.showEdgeCosts) + { + edgeLabel = String(this.adj_matrix[i][j]); + } + else + { + edgeLabel = ""; + } + if (this.directed) + { + this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.adjustCurveForDirectedEdges(this.curve[i][j], this.adj_matrix[j][i] >= 0), 1, edgeLabel); + } + else if (i < j) + { + this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); + } + } + } + } + +} + +Graph.prototype.setup_small = function() +{ + this.allowed = SMALL_ALLLOWED; + this.curve = SMALL_CURVE; + this. x_pos_logical = SMALL_X_POS_LOGICAL; + this. y_pos_logical = SMALL_Y_POS_LOGICAL; + this.adj_matrix_x_start = SMALL_ADJ_MATRIX_X_START; + this.adj_matrix_y_start = SMALL_ADJ_MATRIX_Y_START; + this.adj_matrix_width = SMALL_ADJ_MATRIX_WIDTH; + this.adj_matrix_height = SMALL_ADJ_MATRIX_HEIGHT; + this.adj_list_x_start = SMALL_ADJ_LIST_X_START; + this.adj_list_y_start = SMALL_ADJ_LIST_Y_START; + this.adj_list_elem_width = SMALL_ADJ_LIST_ELEM_WIDTH; + this.adj_list_elem_height = SMALL_ADJ_LIST_ELEM_HEIGHT; + this.adj_list_height = SMALL_ADJ_LIST_HEIGHT; + this.adj_list_width = SMALL_ADJ_LIST_WIDTH; + this.adj_list_spacing = SMALL_ADJ_LIST_SPACING; + this.size = SMALL_SIZE; + this.setup(); +} + +Graph.prototype.setup_large = function() +{ + this.allowed = LARGE_ALLOWED; + this.curve = LARGE_CURVE; + this. x_pos_logical = LARGE_X_POS_LOGICAL; + this. y_pos_logical = LARGE_Y_POS_LOGICAL; + this.adj_matrix_x_start = LARGE_ADJ_MATRIX_X_START; + this.adj_matrix_y_start = LARGE_ADJ_MATRIX_Y_START; + this.adj_matrix_width = LARGE_ADJ_MATRIX_WIDTH; + this.adj_matrix_height = LARGE_ADJ_MATRIX_HEIGHT; + this.adj_list_x_start = LARGE_ADJ_LIST_X_START; + this.adj_list_y_start = LARGE_ADJ_LIST_Y_START; + this.adj_list_elem_width = LARGE_ADJ_LIST_ELEM_WIDTH; + this.adj_list_elem_height = LARGE_ADJ_LIST_ELEM_HEIGHT; + this.adj_list_height = LARGE_ADJ_LIST_HEIGHT; + this.adj_list_width = LARGE_ADJ_LIST_WIDTH; + this.adj_list_spacing = LARGE_ADJ_LIST_SPACING; + this.size = LARGE_SIZE; + this.setup(); +} + +Graph.prototype.adjustCurveForDirectedEdges = function(curve, bidirectional) +{ + if (!bidirectional || Math.abs(curve) > 0.01) + { + return curve; + } + else + { + return 0.1; + } + +} + +Graph.prototype.setup = function() +{ + this.commands = new Array(); + this.circleID = new Array(this.size); + for (var i = 0; i < this.size; i++) + { + this.circleID[i] = this.nextIndex++; + this.cmd("CreateCircle", this.circleID[i], i, this. x_pos_logical[i], this. y_pos_logical[i]); + this.cmd("SetTextColor", this.circleID[i], VERTEX_INDEX_COLOR, 0); + + this.cmd("SetLayer", this.circleID[i], 1); + } + + this.adj_matrix = new Array(this.size); + this.adj_matrixID = new Array(this.size); + for (i = 0; i < this.size; i++) + { + this.adj_matrix[i] = new Array(this.size); + this.adj_matrixID[i] = new Array(this.size); + } + + var edgePercent; + if (this.size == SMALL_SIZE) + { + if (this.directed) + { + edgePercent = 0.4; + } + else + { + edgePercent = 0.5; + } + + } + else + { + if (this.directed) + { + edgePercent = 0.35; + } + else + { + edgePercent = 0.6; + } + + } + + var lowerBound = 0; + + if (this.directed) + { + for (i = 0; i < this.size; i++) + { + for (var j = 0; j < this.size; j++) + { + this.adj_matrixID[i][j] = this.nextIndex++; + if ((this.allowed[i][j]) && Math.random() <= edgePercent && (i < j || Math.abs(this.curve[i][j]) < 0.01 || this.adj_matrixID[j][i] == -1) && (!this.isDAG || (i < j))) + { + if (this.showEdgeCosts) + { + this.adj_matrix[i][j] = Math.floor(Math.random()* 9) + 1; + } + else + { + this.adj_matrix[i][j] = 1; + } + + } + else + { + this.adj_matrix[i][j] = -1; + } + + } + } + this.buildEdges(); + + } + else + { + for (i = 0; i < this.size; i++) + { + for (j = i+1; j < this.size; j++) + { + + this.adj_matrixID[i][j] = this.nextIndex++; + this.adj_matrixID[j][i] = this.nextIndex++; + + if ((this.allowed[i][j]) && Math.random() <= edgePercent) + { + if (this.showEdgeCosts) + { + this.adj_matrix[i][j] = Math.floor(Math.random()* 9) + 1; + } + else + { + this.adj_matrix[i][j] = 1; + } + this.adj_matrix[j][i] = this.adj_matrix[i][j]; + if (this.showEdgeCosts) + { + var edgeLabel = String(this.adj_matrix[i][j]); + } + else + { + edgeLabel = ""; + } + this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); + } + else + { + this.adj_matrix[i][j] = -1; + this.adj_matrix[j][i] = -1; + } + + } + } + + this.buildEdges(); + + + for (i=0; i < this.size; i++) + { + this.adj_matrix[i][i] = -1; + } + + } + + + // Craate Adj List + + + this.buildAdjList(); + + + // Create Adj Matrix + + this.buildAdjMatrix(); + + + this.animationManager.setAllLayers([0, this.currentLayer]); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.clearHistory(); +} + +Graph.prototype.resetAll = function() +{ + +} + + +Graph.prototype.buildAdjMatrix = function() +{ + + this.adj_matrix_index_x = new Array(this.size); + this.adj_matrix_index_y = new Array(this.size); + for (var i = 0; i < this.size; i++) + { + this.adj_matrix_index_x[i] = this.nextIndex++; + this.adj_matrix_index_y[i] = this.nextIndex++; + this.cmd("CreateLabel", this.adj_matrix_index_x[i], i, this.adj_matrix_x_start + i*this.adj_matrix_width, this.adj_matrix_y_start - this.adj_matrix_height); + this.cmd("SetForegroundColor", this.adj_matrix_index_x[i], VERTEX_INDEX_COLOR); + this.cmd("CreateLabel", this.adj_matrix_index_y[i], i, this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + i* this.adj_matrix_height); + this.cmd("SetForegroundColor", this.adj_matrix_index_y[i], VERTEX_INDEX_COLOR); + this.cmd("SetLayer", this.adj_matrix_index_x[i], 3); + this.cmd("SetLayer", this.adj_matrix_index_y[i], 3); + + for (var j = 0; j < this.size; j++) + { + this.adj_matrixID[i][j] = this.nextIndex++; + if (this.adj_matrix[i][j] < 0) + { + var lab = "" + } + else + { + lab = String(this.adj_matrix[i][j]) + } + this.cmd("CreateRectangle", this.adj_matrixID[i][j], lab, this.adj_matrix_width, this.adj_matrix_height, + this.adj_matrix_x_start + j*this.adj_matrix_width,this.adj_matrix_y_start + i * this.adj_matrix_height); + this.cmd("SetLayer", this.adj_matrixID[i][j], 3); + + + } + } +} + + + +Graph.prototype.removeAdjList = function() +{ + for (var i = 0; i < this.size; i++) + { + this.cmd("Delete", this.adj_list_list[i], "RAL1"); + this.cmd("Delete", this.adj_list_index[i], "RAL2"); + for (var j = 0; j < this.size; j++) + { + if (this.adj_matrix[i][j] > 0) + { + this.cmd("Delete", this.adj_list_edges[i][j], "RAL3"); + } + } + } + +} + + +Graph.prototype.buildAdjList = function() +{ + this.adj_list_index = new Array(this.size); + this.adj_list_list = new Array(this.size); + this.adj_list_edges = new Array(this.size); + + for (var i = 0; i < this.size; i++) + { + this.adj_list_index[i] = this.nextIndex++; + this.adj_list_edges[i] = new Array(this.size); + this.adj_list_index[i] = this.nextIndex++; + this.adj_list_list[i] = this.nextIndex++; + this.cmd("CreateRectangle", this.adj_list_list[i], "", this.adj_list_width, this.adj_list_height, this.adj_list_x_start, this.adj_list_y_start + i*this.adj_list_height); + this.cmd("SetLayer", this.adj_list_list[i], 2); + this.cmd("CreateLabel", this.adj_list_index[i], i, this.adj_list_x_start - this.adj_list_width , this.adj_list_y_start + i*this.adj_list_height); + this.cmd("SetForegroundColor", this.adj_list_index[i], VERTEX_INDEX_COLOR); + this.cmd("SetLayer", this.adj_list_index[i], 2); + var lastElem = this.adj_list_list[i]; + var nextXPos = this.adj_list_x_start + this.adj_list_width + this.adj_list_spacing; + var hasEdges = false; + for (var j = 0; j < this.size; j++) + { + if (this.adj_matrix[i][j] > 0) + { + hasEdges = true; + this.adj_list_edges[i][j] = this.nextIndex++; + this.cmd("CreateLinkedList",this.adj_list_edges[i][j], j,this.adj_list_elem_width, this.adj_list_elem_height, + nextXPos, this.adj_list_y_start + i*this.adj_list_height, 0.25, 0, 1, 2); + this.cmd("SetNull", this.adj_list_edges[i][j], 1); + this.cmd("SetText", this.adj_list_edges[i][j], this.adj_matrix[i][j], 1); + this.cmd("SetTextColor", this.adj_list_edges[i][j], VERTEX_INDEX_COLOR, 0); + this.cmd("SetLayer", this.adj_list_edges[i][j], 2); + + nextXPos = nextXPos + this.adj_list_elem_width + this.adj_list_spacing; + this.cmd("Connect", lastElem, this.adj_list_edges[i][j]); + this.cmd("SetNull", lastElem, 0); + lastElem = this.adj_list_edges[i][j]; + } + } + if (!hasEdges) + { + this.cmd("SetNull", this.adj_list_list[i], 1); + } + } +} + + + + +// NEED TO OVERRIDE IN PARENT +Graph.prototype.reset = function() +{ + // Throw an error? +} + + +Graph.prototype.disableUI = function(event) +{ + this.newGraphButton.disabled = true; + if (this.directedGraphButton != null && this.directedGraphButton != undefined) + this.directedGraphButton.disabled = true; + if (this.undirectedGraphButton != null && this.undirectedGraphButton != undefined) + this.undirectedGraphButton.disabled = true; + this.smallGraphButton.disabled = true; + this.largeGraphButton.disabled = true; +} + + + +Graph.prototype.enableUI = function(event) +{ + + this.newGraphButton.disabled = false; + if (this.directedGraphButton != null && this.directedGraphButton != undefined) + this.directedGraphButton.disabled = false; + if (this.undirectedGraphButton != null && this.undirectedGraphButton != undefined) + this.undirectedGraphButton.disabled = false; + this.smallGraphButton.disabled = false; + this.largeGraphButton.disabled = false; +} + + + +/* no init, this is only a base class! */ + var currentAlg; + function init() + { + var animManag = initCanvas(); + currentAlg = new Graph(animManag, canvas.width, canvas.height); +} + + \ No newline at end of file diff --git a/AlgorithmLibrary/LeftistHeap.js b/AlgorithmLibrary/LeftistHeap.js index 80e1dab..5752a63 100644 --- a/AlgorithmLibrary/LeftistHeap.js +++ b/AlgorithmLibrary/LeftistHeap.js @@ -1,566 +1,566 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function LeftistHeap(am, w, h) -{ - this.init(am, w, h); - -} - -LeftistHeap.inheritFrom(Algorithm); - -LeftistHeap.LINK_COLOR = "#007700"; -LeftistHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; -LeftistHeap.FOREGROUND_COLOR = "#007700"; -LeftistHeap.BACKGROUND_COLOR = "#EEFFEE"; - -LeftistHeap.WIDTH_DELTA = 50; -LeftistHeap.HEIGHT_DELTA = 50; -LeftistHeap.STARTING_Y = 85; - -LeftistHeap.INSERT_X = 50; -LeftistHeap.INSERT_Y = 45; -LeftistHeap.BACKGROUND_ALPHA = 0.5; - -LeftistHeap.MESSAGE_X = 20; -LeftistHeap.MESSAGE_Y = 10; - - -LeftistHeap.NPL_OFFSET_X = 20; -LeftistHeap.NPL_OFFSET_Y = 20; -LeftistHeap.NPL_COLOR = "#0000FF"; - -LeftistHeap.MESSAGE_ID = 0; - -LeftistHeap.prototype.init = function(am, w, h) -{ - LeftistHeap.superclass.init.call(this, am, w, h); - this.addControls(); - this.treeRoot = null; - this.secondaryRoot = null; - this.animationManager.setAllLayers([0, 1]); - this.nextIndex = 1; - this.commands = []; - this.cmd("CreateLabel", 0, "", LeftistHeap.MESSAGE_X, LeftistHeap.MESSAGE_Y, 0); - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.commands = []; -} - - -LeftistHeap.prototype.addControls = function() -{ - this.controls = []; - this.insertField = this.addControlToAlgorithmBar("Text", ""); - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.controls.push(this.insertField); - - this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); - this.insertButton.onclick = this.insertCallback.bind(this); - this.controls.push(this.insertButton); - - this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); - this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); - this.controls.push(this.removeSmallestButton); - - this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); - this.clearHeapButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearHeapButton); - - this.showNPLBox = this.addCheckboxToAlgorithmBar("Show Null Path Lengths"); - this.showNPLBox.checked = true; - - this.showNPLBox.onclick = this.NPLChangedHandler.bind(this); -} - - -LeftistHeap.prototype.NPLChangedHandler = function(logicalRep, event) -{ - if (this.showNPLBox.checked) - { - this.animationManager.setAllLayers([0,1]); - } - else - { - this.animationManager.setAllLayers([0]); - } -} - - - - -LeftistHeap.prototype.insertCallback = function(event) -{ - var insertedValue; - - insertedValue = this.normalizeNumber(this.insertField.value, 4); - if (insertedValue != "") - { - this.insertField.value = ""; - this.implementAction(this.insertElement.bind(this),insertedValue); - } -} - -LeftistHeap.prototype.clearCallback = function(event) -{ - this.implementAction(this.clear.bind(this, "")); -} - -LeftistHeap.prototype.clear = function(ignored) -{ - this.commands = new Array(); - this.clearTree(this.treeRoot); - this.treeRoot = null; - this.nexIndex = 1; - return this.commands; -} - -LeftistHeap.prototype.clearTree = function(tree) -{ - if (tree != null) - { - this.cmd("Delete", tree.graphicID); - this.cmd("Delete", tree.nplID); - this.clearTree(tree.left); - this.clearTree(tree.right); - } - -} - -LeftistHeap.prototype.reset = function() -{ - this.treeRoot = null; - this.secondaryRoot = null; - this.nextIndex = 1; -} - -LeftistHeap.prototype.removeSmallestCallback = function(event) -{ - this.implementAction(this.removeSmallest.bind(this),""); -} - - - -LeftistHeap.prototype.removeSmallest = function(dummy) -{ - - this.commands = new Array(); - - if (this.treeRoot != null) - { - this.highlightLeft = this.nextIndex++; - this.highlightRight = this.nextIndex++; - - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Remove root element, leaving two subtrees"); - if (this.treeRoot.left != null) - { - this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.left.graphicID); - } - if (this.treeRoot.right != null) - { - this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.right.graphicID); - } - var oldElem = this.treeRoot.graphicID; - this.cmd("Delete", this.treeRoot.nplID); - this.cmd("Move", this.treeRoot.graphicID, LeftistHeap.INSERT_X, LeftistHeap.INSERT_Y); - this.cmd("Step"); - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merge the two subtrees"); - - if (this.treeRoot.left == null) - { - this.treeRoot = null; - } - else if (this.treeRoot.right == null) - { - this.treeRoot = this.treeRoot.left; - this.resizeTrees(); - } - else - { - var secondTree = this.treeRoot.right; - this.secondaryRoot = secondTree; - this.treeRoot = this.treeRoot.left; - this.resizeTrees(); - //this.secondaryRoot = null; - this.cmd("CreateHighlightCircle", this.highlightLeft, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); - - this.cmd("CreateHighlightCircle", this.highlightRight, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, secondTree.x, secondTree.y); - this.treeRoot = this.merge(this.treeRoot, secondTree); - this.secondaryRoot = null; - } - this.resizeTrees(); - this.cmd("Delete", oldElem); - this.cmd("SetText", LeftistHeap.MESSAGE_ID, ""); - - - } - // Clear for real - return this.commands; - -} - - - -LeftistHeap.prototype.insertElement = function(insertedValue) -{ - this.commands = new Array(); - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Create a heap with one node, merge with existing heap."); - - this.secondaryRoot = new LeftistHeapNode(insertedValue, this.nextIndex++, this.nextIndex++, LeftistHeap.INSERT_X, LeftistHeap.INSERT_Y); - this.cmd("CreateCircle", this.secondaryRoot.graphicID, insertedValue, this.secondaryRoot.x, this.secondaryRoot.y); - this.cmd("CreateLabel", this.secondaryRoot.nplID, 0, LeftistHeap.INSERT_X -LeftistHeap.NPL_OFFSET_X, LeftistHeap.INSERT_Y - LeftistHeap.NPL_OFFSET_Y); - this.cmd("SetForegroundColor", this.secondaryRoot.nplID, LeftistHeap.NPL_COLOR); - this.cmd("SetLayer", this.secondaryRoot.nplID, 1); - this.cmd("SetForegroundColor", this.secondaryRoot.graphicID, LeftistHeap.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.secondaryRoot.graphicID, LeftistHeap.BACKGROUND_COLOR); - - - if (this.treeRoot != null) - { - this.resizeTrees(); - this.highlightLeft = this.nextIndex++; - this.highlightRight = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.highlightLeft, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); - - this.cmd("CreateHighlightCircle", this.highlightRight, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.secondaryRoot.x, this.secondaryRoot.y); - - - var rightTree = this.secondaryRoot; - this.secondaryRoot = null; - - this.treeRoot = this.merge(this.treeRoot, rightTree); - - this.resizeTrees(); - } - else - { - this.treeRoot = this.secondaryRoot; - this.secondaryRoot = null; - this.resizeTrees(); - } - this.cmd("SetText", LeftistHeap.MESSAGE_ID, ""); - - - return this.commands; -} - - -LeftistHeap.prototype.merge = function(tree1, tree2) -{ - if (tree1 == null) - { - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merging right heap with empty heap, return right heap"); - this.cmd("Step"); - this.cmd("Delete", this.highlightRight); - this.cmd("Delete", this.highlightLeft); - - return tree2; - } - if (tree2 == null) - { - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merging left heap with empty heap, return left heap"); - this.cmd("Step"); - this.cmd("Delete", this.highlightRight); - this.cmd("Delete", this.highlightLeft); - - return tree1; - } - var tmp; - this.cmd("SetHighlight", tree1.graphicID, 1); - this.cmd("SetHighlight", tree2.graphicID, 1); - if (tree2.data < tree1.data) - { - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Min element is in right heap. Recursively merge right subtree of right heap with left heap"); - tmp = tree1; - tree1 = tree2; - tree2 = tmp; - tmp = this.highlightRight; - this.highlightRight = this.highlightLeft; - this.highlightLeft = tmp; - } - else - { - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Min element is in left heap. Recursively merge right subtree of left heap with right heap"); - } - this.cmd("Step"); - this.cmd("SetHighlight", tree1.graphicID, 0); - this.cmd("SetHighlight", tree2.graphicID, 0); - if (tree1.right == null) - { - this.cmd("Move", this.highlightLeft, tree1.x + LeftistHeap.WIDTH_DELTA / 2, tree1.y + LeftistHeap.HEIGHT_DELTA); - } - else - { - this.cmd("Move", this.highlightLeft, tree1.right.x, tree1.right.y); - - } - this.cmd("Step"); - if (tree1.right != null) - { - this.cmd("Disconnect", tree1.graphicID, tree1.right.graphicID, LeftistHeap.LINK_COLOR); - } - var next = tree1.right; - this.cmd("SetAlpha", tree1.graphicID, LeftistHeap.BACKGROUND_ALPHA); - this.cmd("SetAlpha", tree1.nplID, LeftistHeap.BACKGROUND_ALPHA); - if (tree1.left != null) - { - this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, LeftistHeap.BACKGROUND_ALPHA); - this.setTreeAlpha(tree1.left, LeftistHeap.BACKGROUND_ALPHA); - - } - this.cmd("Step"); - tree1.right = this.merge(next, tree2); - if (this.secondaryRoot == tree1.right) - { - this.secondaryRoot = null; - } - if (this.treeRoot == tree1.right) - { - this.treeRoot = null; - } - if (tree1.right.parent != tree1) - { - tree1.right.disconnectFromParent(); - } - tree1.right.parent = tree1; - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Reconnecting tree after merge"); - - this.cmd("Connect", tree1.graphicID, tree1.right.graphicID, LeftistHeap.LINK_COLOR); - this.cmd("SetAlpha", tree1.graphicID, 1); - this.cmd("SetAlpha", tree1.nplID, 1); - - this.resizeTrees(); - if (tree1.left != null) - { - this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, 1); - this.setTreeAlpha(tree1.left, 1); - this.cmd("Step"); - } - - if (tree1.left == null || (tree1.left.npl < tree1.right.npl)) - { - this.cmd("SetHighlight", tree1.graphicID, 1); - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Right subtree has larger Null Path Length than left subtree. Swapping ..."); - this.cmd("Step") - this.cmd("SetHighlight", tree1.graphicID, 0); - var tmp = tree1.left; - tree1.left = tree1.right; - tree1.right = tmp; - this.resizeTrees(); - } - else - { - this.cmd("SetHighlight", tree1.graphicID, 1); - this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Left subtree has Null Path Length at least as large as right subtree. No swap required ..."); - this.cmd("Step") - this.cmd("SetHighlight", tree1.graphicID, 0); - - } - if (tree1.right == null) - { - tree1.npl = 0; - } - else - { - tree1.npl = Math.min(tree1.left.npl, tree1.right.npl) + 1; - } - this.cmd("SetText", tree1.nplID, tree1.npl); - - return tree1; -} - - - -LeftistHeap.prototype.setTreeAlpha = function(tree, newAlpha) -{ - if (tree != null) - { - this.cmd("SetAlpha", tree.graphicID, newAlpha); - this.cmd("SetAlpha", tree.nplID, newAlpha); - if (tree.left != null) - { - this.cmd("SetEdgeAlpha", tree.graphicID, tree.left.graphicID, newAlpha); - this.setTreeAlpha(tree.left, newAlpha); - } - if (tree.right != null) - { - this.cmd("SetEdgeAlpha", tree.graphicID, tree.right.graphicID, newAlpha); - this.setTreeAlpha(tree.right, newAlpha); - } - } -} - -LeftistHeap.prototype.resizeWidths = function(tree) -{ - if (tree == null) - { - return 0; - } - tree.leftWidth = Math.max(this.resizeWidths(tree.left), LeftistHeap.WIDTH_DELTA / 2); - tree.rightWidth = Math.max(this.resizeWidths(tree.right), LeftistHeap.WIDTH_DELTA / 2); - return tree.leftWidth + tree.rightWidth; -} - - - -LeftistHeap.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -LeftistHeap.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -LeftistHeap.prototype.resizeTrees = function() -{ - var firstTreeStart; - var secondTreeStart; - this.resizeWidths(this.treeRoot); - this.resizeWidths(this.secondaryRoot); - - if (this.treeRoot != null) - { - startingPoint = this.treeRoot.leftWidth; - this.setNewPositions(this.treeRoot, startingPoint, LeftistHeap.STARTING_Y, 0); - this.animateNewPositions(this.treeRoot); - if (this.secondaryRoot != null) - { - secondTreeStart = this.treeRoot.leftWidth + this.treeRoot.rightWidth + this.secondaryRoot.leftWidth + 50; - this.setNewPositions(this.secondaryRoot, secondTreeStart, LeftistHeap.STARTING_Y, 0); - this.animateNewPositions(this.secondaryRoot); - } - - this.cmd("Step"); - } - else if (this.secondaryRoot != null) - { - startingPoint = this.secondaryRoot.leftWidth; - this.setNewPositions(this.secondaryRoot, startingPoint, LeftistHeap.STARTING_Y, 0); - this.animateNewPositions(this.secondaryRoot); - } - -} - -LeftistHeap.prototype.setNewPositions = function(tree, xPosition, yPosition, side) -{ - if (tree != null) - { - tree.y = yPosition; - if (side == -1) - { - xPosition = xPosition - tree.rightWidth; - tree.npX = xPosition - LeftistHeap.NPL_OFFSET_X; - } - else if (side == 1) - { - xPosition = xPosition + tree.leftWidth; - tree.npX = xPosition + LeftistHeap.NPL_OFFSET_X; - } - else - { - tree.heightLabelX = xPosition - LeftistHeap.NPL_OFFSET_Y;; - tree.npX = xPosition + LeftistHeap.NPL_OFFSET_X; - } - tree.x = xPosition; - tree.npY = tree.y - LeftistHeap.NPL_OFFSET_Y; - this.setNewPositions(tree.left, xPosition, yPosition + LeftistHeap.HEIGHT_DELTA, -1) - this.setNewPositions(tree.right, xPosition, yPosition + LeftistHeap.HEIGHT_DELTA, 1) - } - -} - - -LeftistHeap.prototype.animateNewPositions = function(tree) -{ - if (tree != null) - { - this.cmd("Move", tree.graphicID, tree.x, tree.y); - this.cmd("Move", tree.nplID, tree.npX, tree.npY); - this.animateNewPositions(tree.left); - this.animateNewPositions(tree.right); - } -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new LeftistHeap(animManag, canvas.width, canvas.height); -} - - - - -function LeftistHeapNode(val, id, nplID, initialX, initialY) -{ - this.data = val; - this.x = (initialX == undefined) ? 0 : initialX; - this.y = (initialY == undefined) ? 0 : initialY; - this.npX = initialX - LeftistHeap.NPL_OFFSET_X; - this.npY = initialY - LeftistHeap.NPL_OFFSET_Y; - - this.graphicID = id; - this.nplID = nplID; - this.npl = 0; - this.left = null; - this.right = null; - this.leftWidth = 0; - this.rightWidth = 0; - this.parent = null; -} - -LeftistHeapNode.prototype.disconnectFromParent = function() -{ - if (this.parent != null) - { - if (this.parent.right == this) - { - this.parent.right = null; - } - else if (this.parent.left === this) - { - this.parent.left == null; - } - } -} - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function LeftistHeap(am, w, h) +{ + this.init(am, w, h); + +} + +LeftistHeap.inheritFrom(Algorithm); + +LeftistHeap.LINK_COLOR = "#007700"; +LeftistHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +LeftistHeap.FOREGROUND_COLOR = "#007700"; +LeftistHeap.BACKGROUND_COLOR = "#EEFFEE"; + +LeftistHeap.WIDTH_DELTA = 50; +LeftistHeap.HEIGHT_DELTA = 50; +LeftistHeap.STARTING_Y = 85; + +LeftistHeap.INSERT_X = 50; +LeftistHeap.INSERT_Y = 45; +LeftistHeap.BACKGROUND_ALPHA = 0.5; + +LeftistHeap.MESSAGE_X = 20; +LeftistHeap.MESSAGE_Y = 10; + + +LeftistHeap.NPL_OFFSET_X = 20; +LeftistHeap.NPL_OFFSET_Y = 20; +LeftistHeap.NPL_COLOR = "#0000FF"; + +LeftistHeap.MESSAGE_ID = 0; + +LeftistHeap.prototype.init = function(am, w, h) +{ + LeftistHeap.superclass.init.call(this, am, w, h); + this.addControls(); + this.treeRoot = null; + this.secondaryRoot = null; + this.animationManager.setAllLayers([0, 1]); + this.nextIndex = 1; + this.commands = []; + this.cmd("CreateLabel", 0, "", LeftistHeap.MESSAGE_X, LeftistHeap.MESSAGE_Y, 0); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.commands = []; +} + + +LeftistHeap.prototype.addControls = function() +{ + this.controls = []; + this.insertField = this.addControlToAlgorithmBar("Text", ""); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); + this.controls.push(this.insertField); + + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); + this.insertButton.onclick = this.insertCallback.bind(this); + this.controls.push(this.insertButton); + + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); + this.controls.push(this.removeSmallestButton); + + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearHeapButton); + + this.showNPLBox = this.addCheckboxToAlgorithmBar("Show Null Path Lengths"); + this.showNPLBox.checked = true; + + this.showNPLBox.onclick = this.NPLChangedHandler.bind(this); +} + + +LeftistHeap.prototype.NPLChangedHandler = function(logicalRep, event) +{ + if (this.showNPLBox.checked) + { + this.animationManager.setAllLayers([0,1]); + } + else + { + this.animationManager.setAllLayers([0]); + } +} + + + + +LeftistHeap.prototype.insertCallback = function(event) +{ + var insertedValue; + + insertedValue = this.normalizeNumber(this.insertField.value, 4); + if (insertedValue != "") + { + this.insertField.value = ""; + this.implementAction(this.insertElement.bind(this),insertedValue); + } +} + +LeftistHeap.prototype.clearCallback = function(event) +{ + this.implementAction(this.clear.bind(this, "")); +} + +LeftistHeap.prototype.clear = function(ignored) +{ + this.commands = new Array(); + this.clearTree(this.treeRoot); + this.treeRoot = null; + this.nexIndex = 1; + return this.commands; +} + +LeftistHeap.prototype.clearTree = function(tree) +{ + if (tree != null) + { + this.cmd("Delete", tree.graphicID); + this.cmd("Delete", tree.nplID); + this.clearTree(tree.left); + this.clearTree(tree.right); + } + +} + +LeftistHeap.prototype.reset = function() +{ + this.treeRoot = null; + this.secondaryRoot = null; + this.nextIndex = 1; +} + +LeftistHeap.prototype.removeSmallestCallback = function(event) +{ + this.implementAction(this.removeSmallest.bind(this),""); +} + + + +LeftistHeap.prototype.removeSmallest = function(dummy) +{ + + this.commands = new Array(); + + if (this.treeRoot != null) + { + this.highlightLeft = this.nextIndex++; + this.highlightRight = this.nextIndex++; + + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Remove root element, leaving two subtrees"); + if (this.treeRoot.left != null) + { + this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.left.graphicID); + } + if (this.treeRoot.right != null) + { + this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.right.graphicID); + } + var oldElem = this.treeRoot.graphicID; + this.cmd("Delete", this.treeRoot.nplID); + this.cmd("Move", this.treeRoot.graphicID, LeftistHeap.INSERT_X, LeftistHeap.INSERT_Y); + this.cmd("Step"); + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merge the two subtrees"); + + if (this.treeRoot.left == null) + { + this.treeRoot = null; + } + else if (this.treeRoot.right == null) + { + this.treeRoot = this.treeRoot.left; + this.resizeTrees(); + } + else + { + var secondTree = this.treeRoot.right; + this.secondaryRoot = secondTree; + this.treeRoot = this.treeRoot.left; + this.resizeTrees(); + //this.secondaryRoot = null; + this.cmd("CreateHighlightCircle", this.highlightLeft, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); + + this.cmd("CreateHighlightCircle", this.highlightRight, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, secondTree.x, secondTree.y); + this.treeRoot = this.merge(this.treeRoot, secondTree); + this.secondaryRoot = null; + } + this.resizeTrees(); + this.cmd("Delete", oldElem); + this.cmd("SetText", LeftistHeap.MESSAGE_ID, ""); + + + } + // Clear for real + return this.commands; + +} + + + +LeftistHeap.prototype.insertElement = function(insertedValue) +{ + this.commands = new Array(); + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Create a heap with one node, merge with existing heap."); + + this.secondaryRoot = new LeftistHeapNode(insertedValue, this.nextIndex++, this.nextIndex++, LeftistHeap.INSERT_X, LeftistHeap.INSERT_Y); + this.cmd("CreateCircle", this.secondaryRoot.graphicID, insertedValue, this.secondaryRoot.x, this.secondaryRoot.y); + this.cmd("CreateLabel", this.secondaryRoot.nplID, 0, LeftistHeap.INSERT_X -LeftistHeap.NPL_OFFSET_X, LeftistHeap.INSERT_Y - LeftistHeap.NPL_OFFSET_Y); + this.cmd("SetForegroundColor", this.secondaryRoot.nplID, LeftistHeap.NPL_COLOR); + this.cmd("SetLayer", this.secondaryRoot.nplID, 1); + this.cmd("SetForegroundColor", this.secondaryRoot.graphicID, LeftistHeap.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.secondaryRoot.graphicID, LeftistHeap.BACKGROUND_COLOR); + + + if (this.treeRoot != null) + { + this.resizeTrees(); + this.highlightLeft = this.nextIndex++; + this.highlightRight = this.nextIndex++; + this.cmd("CreateHighlightCircle", this.highlightLeft, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); + + this.cmd("CreateHighlightCircle", this.highlightRight, LeftistHeap.HIGHLIGHT_CIRCLE_COLOR, this.secondaryRoot.x, this.secondaryRoot.y); + + + var rightTree = this.secondaryRoot; + this.secondaryRoot = null; + + this.treeRoot = this.merge(this.treeRoot, rightTree); + + this.resizeTrees(); + } + else + { + this.treeRoot = this.secondaryRoot; + this.secondaryRoot = null; + this.resizeTrees(); + } + this.cmd("SetText", LeftistHeap.MESSAGE_ID, ""); + + + return this.commands; +} + + +LeftistHeap.prototype.merge = function(tree1, tree2) +{ + if (tree1 == null) + { + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merging right heap with empty heap, return right heap"); + this.cmd("Step"); + this.cmd("Delete", this.highlightRight); + this.cmd("Delete", this.highlightLeft); + + return tree2; + } + if (tree2 == null) + { + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Merging left heap with empty heap, return left heap"); + this.cmd("Step"); + this.cmd("Delete", this.highlightRight); + this.cmd("Delete", this.highlightLeft); + + return tree1; + } + var tmp; + this.cmd("SetHighlight", tree1.graphicID, 1); + this.cmd("SetHighlight", tree2.graphicID, 1); + if (tree2.data < tree1.data) + { + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Min element is in right heap. Recursively merge right subtree of right heap with left heap"); + tmp = tree1; + tree1 = tree2; + tree2 = tmp; + tmp = this.highlightRight; + this.highlightRight = this.highlightLeft; + this.highlightLeft = tmp; + } + else + { + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Min element is in left heap. Recursively merge right subtree of left heap with right heap"); + } + this.cmd("Step"); + this.cmd("SetHighlight", tree1.graphicID, 0); + this.cmd("SetHighlight", tree2.graphicID, 0); + if (tree1.right == null) + { + this.cmd("Move", this.highlightLeft, tree1.x + LeftistHeap.WIDTH_DELTA / 2, tree1.y + LeftistHeap.HEIGHT_DELTA); + } + else + { + this.cmd("Move", this.highlightLeft, tree1.right.x, tree1.right.y); + + } + this.cmd("Step"); + if (tree1.right != null) + { + this.cmd("Disconnect", tree1.graphicID, tree1.right.graphicID, LeftistHeap.LINK_COLOR); + } + var next = tree1.right; + this.cmd("SetAlpha", tree1.graphicID, LeftistHeap.BACKGROUND_ALPHA); + this.cmd("SetAlpha", tree1.nplID, LeftistHeap.BACKGROUND_ALPHA); + if (tree1.left != null) + { + this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, LeftistHeap.BACKGROUND_ALPHA); + this.setTreeAlpha(tree1.left, LeftistHeap.BACKGROUND_ALPHA); + + } + this.cmd("Step"); + tree1.right = this.merge(next, tree2); + if (this.secondaryRoot == tree1.right) + { + this.secondaryRoot = null; + } + if (this.treeRoot == tree1.right) + { + this.treeRoot = null; + } + if (tree1.right.parent != tree1) + { + tree1.right.disconnectFromParent(); + } + tree1.right.parent = tree1; + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Reconnecting tree after merge"); + + this.cmd("Connect", tree1.graphicID, tree1.right.graphicID, LeftistHeap.LINK_COLOR); + this.cmd("SetAlpha", tree1.graphicID, 1); + this.cmd("SetAlpha", tree1.nplID, 1); + + this.resizeTrees(); + if (tree1.left != null) + { + this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, 1); + this.setTreeAlpha(tree1.left, 1); + this.cmd("Step"); + } + + if (tree1.left == null || (tree1.left.npl < tree1.right.npl)) + { + this.cmd("SetHighlight", tree1.graphicID, 1); + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Right subtree has larger Null Path Length than left subtree. Swapping ..."); + this.cmd("Step") + this.cmd("SetHighlight", tree1.graphicID, 0); + var tmp = tree1.left; + tree1.left = tree1.right; + tree1.right = tmp; + this.resizeTrees(); + } + else + { + this.cmd("SetHighlight", tree1.graphicID, 1); + this.cmd("SetText", LeftistHeap.MESSAGE_ID, "Left subtree has Null Path Length at least as large as right subtree. No swap required ..."); + this.cmd("Step") + this.cmd("SetHighlight", tree1.graphicID, 0); + + } + if (tree1.right == null) + { + tree1.npl = 0; + } + else + { + tree1.npl = Math.min(tree1.left.npl, tree1.right.npl) + 1; + } + this.cmd("SetText", tree1.nplID, tree1.npl); + + return tree1; +} + + + +LeftistHeap.prototype.setTreeAlpha = function(tree, newAlpha) +{ + if (tree != null) + { + this.cmd("SetAlpha", tree.graphicID, newAlpha); + this.cmd("SetAlpha", tree.nplID, newAlpha); + if (tree.left != null) + { + this.cmd("SetEdgeAlpha", tree.graphicID, tree.left.graphicID, newAlpha); + this.setTreeAlpha(tree.left, newAlpha); + } + if (tree.right != null) + { + this.cmd("SetEdgeAlpha", tree.graphicID, tree.right.graphicID, newAlpha); + this.setTreeAlpha(tree.right, newAlpha); + } + } +} + +LeftistHeap.prototype.resizeWidths = function(tree) +{ + if (tree == null) + { + return 0; + } + tree.leftWidth = Math.max(this.resizeWidths(tree.left), LeftistHeap.WIDTH_DELTA / 2); + tree.rightWidth = Math.max(this.resizeWidths(tree.right), LeftistHeap.WIDTH_DELTA / 2); + return tree.leftWidth + tree.rightWidth; +} + + + +LeftistHeap.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +LeftistHeap.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +LeftistHeap.prototype.resizeTrees = function() +{ + var firstTreeStart; + var secondTreeStart; + this.resizeWidths(this.treeRoot); + this.resizeWidths(this.secondaryRoot); + + if (this.treeRoot != null) + { + startingPoint = this.treeRoot.leftWidth; + this.setNewPositions(this.treeRoot, startingPoint, LeftistHeap.STARTING_Y, 0); + this.animateNewPositions(this.treeRoot); + if (this.secondaryRoot != null) + { + secondTreeStart = this.treeRoot.leftWidth + this.treeRoot.rightWidth + this.secondaryRoot.leftWidth + 50; + this.setNewPositions(this.secondaryRoot, secondTreeStart, LeftistHeap.STARTING_Y, 0); + this.animateNewPositions(this.secondaryRoot); + } + + this.cmd("Step"); + } + else if (this.secondaryRoot != null) + { + startingPoint = this.secondaryRoot.leftWidth; + this.setNewPositions(this.secondaryRoot, startingPoint, LeftistHeap.STARTING_Y, 0); + this.animateNewPositions(this.secondaryRoot); + } + +} + +LeftistHeap.prototype.setNewPositions = function(tree, xPosition, yPosition, side) +{ + if (tree != null) + { + tree.y = yPosition; + if (side == -1) + { + xPosition = xPosition - tree.rightWidth; + tree.npX = xPosition - LeftistHeap.NPL_OFFSET_X; + } + else if (side == 1) + { + xPosition = xPosition + tree.leftWidth; + tree.npX = xPosition + LeftistHeap.NPL_OFFSET_X; + } + else + { + tree.heightLabelX = xPosition - LeftistHeap.NPL_OFFSET_Y;; + tree.npX = xPosition + LeftistHeap.NPL_OFFSET_X; + } + tree.x = xPosition; + tree.npY = tree.y - LeftistHeap.NPL_OFFSET_Y; + this.setNewPositions(tree.left, xPosition, yPosition + LeftistHeap.HEIGHT_DELTA, -1) + this.setNewPositions(tree.right, xPosition, yPosition + LeftistHeap.HEIGHT_DELTA, 1) + } + +} + + +LeftistHeap.prototype.animateNewPositions = function(tree) +{ + if (tree != null) + { + this.cmd("Move", tree.graphicID, tree.x, tree.y); + this.cmd("Move", tree.nplID, tree.npX, tree.npY); + this.animateNewPositions(tree.left); + this.animateNewPositions(tree.right); + } +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new LeftistHeap(animManag, canvas.width, canvas.height); +} + + + + +function LeftistHeapNode(val, id, nplID, initialX, initialY) +{ + this.data = val; + this.x = (initialX == undefined) ? 0 : initialX; + this.y = (initialY == undefined) ? 0 : initialY; + this.npX = initialX - LeftistHeap.NPL_OFFSET_X; + this.npY = initialY - LeftistHeap.NPL_OFFSET_Y; + + this.graphicID = id; + this.nplID = nplID; + this.npl = 0; + this.left = null; + this.right = null; + this.leftWidth = 0; + this.rightWidth = 0; + this.parent = null; +} + +LeftistHeapNode.prototype.disconnectFromParent = function() +{ + if (this.parent != null) + { + if (this.parent.right == this) + { + this.parent.right = null; + } + else if (this.parent.left === this) + { + this.parent.left == null; + } + } +} + diff --git a/AlgorithmLibrary/QueueArray.js b/AlgorithmLibrary/QueueArray.js index 84ba27b..4fd20b9 100644 --- a/AlgorithmLibrary/QueueArray.js +++ b/AlgorithmLibrary/QueueArray.js @@ -1,322 +1,322 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var ARRAY_START_X = 100; -var ARRAY_START_Y = 200; -var ARRAY_ELEM_WIDTH = 50; -var ARRAY_ELEM_HEIGHT = 50; - -var ARRRAY_ELEMS_PER_LINE = 15; -var ARRAY_LINE_SPACING = 130; - -var HEAD_POS_X = 180; -var HEAD_POS_Y = 100; -var HEAD_LABEL_X = 130; -var HEAD_LABEL_Y = 100; - -var TAIL_POS_X = 280; -var TAIL_POS_Y = 100; -var TAIL_LABEL_X = 230; -var TAIL_LABEL_Y = 100; - -var QUEUE_LABEL_X = 50; -var QUEUE_LABEL_Y = 30; -var QUEUE_ELEMENT_X = 120; -var QUEUE_ELEMENT_Y = 30; - -var INDEX_COLOR = "#0000FF" - -var SIZE = 15; - -function QueueArray(am, w, h) -{ - this.init(am, w, h); - -} - -QueueArray.inheritFrom(Algorithm); - - -QueueArray.prototype.init = function(am, w, h) -{ - QueueArray.superclass.init.call(this, am, w, h); - this.addControls(); - this.nextIndex = 0; - this.commands = []; - //this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; -// this.tail_label_y = this.tail_pos_y; - this.setup(); - this.initialIndex = this.nextIndex; -} - - -QueueArray.prototype.addControls = function() -{ - this.controls = []; - this.enqueueField = this.addControlToAlgorithmBar("Text", ""); - this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); - this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); - this.enqueueButton.onclick = this.enqueueCallback.bind(this); - this.controls.push(this.enqueueField); - this.controls.push(this.enqueueButton); - - this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); - this.dequeueButton.onclick = this.dequeueCallback.bind(this); - this.controls.push(this.dequeueButton); - - this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); - this.clearButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearButton); - -} - -QueueArray.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -QueueArray.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -QueueArray.prototype.setup = function() -{ - - this.nextIndex = 0; - - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - - this.arrayID[i]= this.nextIndex++; - this.arrayLabelID[i]= this.nextIndex++; - } - this.headID = this.nextIndex++; - headLabelID = this.nextIndex++; - this.tailID = this.nextIndex++; - tailLabelID = this.nextIndex++; - - this.arrayData = new Array(SIZE); - this.head = 0; - this.tail = 0; - this.leftoverLabelID = this.nextIndex++; - - - for (var i = 0; i < SIZE; i++) - { - var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); - this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("SetForegroundColor", this.arrayLabelID[i], INDEX_COLOR); - - } - this.cmd("CreateLabel", headLabelID, "Head", HEAD_LABEL_X, HEAD_LABEL_Y); - this.cmd("CreateRectangle", this.headID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, HEAD_POS_X, HEAD_POS_Y); - - this.cmd("CreateLabel", tailLabelID, "Tail", TAIL_LABEL_X, TAIL_LABEL_Y); - this.cmd("CreateRectangle", this.tailID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TAIL_POS_X, TAIL_POS_Y); - - - - this.cmd("CreateLabel", this.leftoverLabelID, "", QUEUE_LABEL_X, QUEUE_LABEL_Y); - - - this.initialIndex = this.nextIndex; - - this.highlight1ID = this.nextIndex++; - this.highlight2ID = this.nextIndex++; - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - - -} - - -QueueArray.prototype.reset = function() -{ - this.top = 0; - this.nextIndex = this.initialIndex; - -} - - -QueueArray.prototype.enqueueCallback = function(event) -{ - if ((this.tail + 1) % SIZE != this.head && this.enqueueField.value != "") - { - var pushVal = this.enqueueField.value; - this.enqueueField.value = "" - this.implementAction(this.enqueue.bind(this), pushVal); - } -} - - -QueueArray.prototype.dequeueCallback = function(event) -{ - if (this.tail != this.head) - { - this.implementAction(this.dequeue.bind(this), ""); - } -} - - -QueueArray.prototype.clearCallback = function(event) -{ - this.implementAction(this.clearAll.bind(this), ""); -} - - - -QueueArray.prototype.enqueue = function(elemToEnqueue) -{ - this.commands = new Array(); - - var labEnqueueID = this.nextIndex++; - var labEnqueueValID = this.nextIndex++; - this.arrayData[this.tail] = elemToEnqueue; - this.cmd("SetText", this.leftoverLabelID, ""); - - this.cmd("CreateLabel", labEnqueueID, "Enqueuing Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); - this.cmd("CreateLabel", labEnqueueValID,elemToEnqueue, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); - - this.cmd("Step"); - this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, TAIL_POS_X, TAIL_POS_Y); - this.cmd("Step"); - - var xpos = (this.tail % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.tail / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("Step"); - - this.cmd("Move", labEnqueueValID, xpos, ypos); - this.cmd("Step"); - - this.cmd("Settext", this.arrayID[this.tail], elemToEnqueue); - this.cmd("Delete", labEnqueueValID); - - this.cmd("Delete", this.highlight1ID); - - this.cmd("SetHighlight", this.tailID, 1); - this.cmd("Step"); - this.tail = (this.tail + 1) % SIZE; - this.cmd("SetText", this.tailID, this.tail) - this.cmd("Step"); - this.cmd("SetHighlight", this.tailID, 0); - this.cmd("Delete", labEnqueueID); - - return this.commands; -} - -QueueArray.prototype.dequeue = function(ignored) -{ - this.commands = new Array(); - - var labDequeueID = this.nextIndex++; - var labDequeueValID = this.nextIndex++; - - this.cmd("SetText", this.leftoverLabelID, ""); - - - this.cmd("CreateLabel", labDequeueID, "Dequeued Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); - - this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, HEAD_POS_X, HEAD_POS_Y); - this.cmd("Step"); - - var xpos = (this.head % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.head / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("Step"); - - this.cmd("Delete", this.highlight1ID); - - - var dequeuedVal = this.arrayData[this.head] - this.cmd("CreateLabel", labDequeueValID,dequeuedVal, xpos, ypos); - this.cmd("Settext", this.arrayID[this.head], ""); - this.cmd("Move", labDequeueValID, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); - this.cmd("Step"); - - this.cmd("SetHighlight", this.headID, 1); - this.cmd("Step"); - this.head = (this.head + 1 ) % SIZE; - this.cmd("SetText", this.headID, this.head) - this.cmd("Step"); - this.cmd("SetHighlight", this.headID, 0); - - this.cmd("SetText", this.leftoverLabelID, "Dequeued Value: " + dequeuedVal); - - - this.cmd("Delete", labDequeueID) - this.cmd("Delete", labDequeueValID); - - - - return this.commands; -} - - - -QueueArray.prototype.clearAll = function() -{ - this.commands = new Array(); - this.cmd("SetText", this.leftoverLabelID, ""); - - for (var i = 0; i < SIZE; i++) - { - this.cmd("SetText", this.arrayID[i], ""); - } - this.head = 0; - this.tail = 0; - this.cmd("SetText", this.headID, "0"); - this.cmd("SetText", this.tailID, "0"); - return this.commands; - -} - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new QueueArray(animManag, canvas.width, canvas.height); -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var ARRAY_START_X = 100; +var ARRAY_START_Y = 200; +var ARRAY_ELEM_WIDTH = 50; +var ARRAY_ELEM_HEIGHT = 50; + +var ARRRAY_ELEMS_PER_LINE = 15; +var ARRAY_LINE_SPACING = 130; + +var HEAD_POS_X = 180; +var HEAD_POS_Y = 100; +var HEAD_LABEL_X = 130; +var HEAD_LABEL_Y = 100; + +var TAIL_POS_X = 280; +var TAIL_POS_Y = 100; +var TAIL_LABEL_X = 230; +var TAIL_LABEL_Y = 100; + +var QUEUE_LABEL_X = 50; +var QUEUE_LABEL_Y = 30; +var QUEUE_ELEMENT_X = 120; +var QUEUE_ELEMENT_Y = 30; + +var INDEX_COLOR = "#0000FF" + +var SIZE = 15; + +function QueueArray(am, w, h) +{ + this.init(am, w, h); + +} + +QueueArray.inheritFrom(Algorithm); + + +QueueArray.prototype.init = function(am, w, h) +{ + QueueArray.superclass.init.call(this, am, w, h); + this.addControls(); + this.nextIndex = 0; + this.commands = []; + //this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; +// this.tail_label_y = this.tail_pos_y; + this.setup(); + this.initialIndex = this.nextIndex; +} + + +QueueArray.prototype.addControls = function() +{ + this.controls = []; + this.enqueueField = this.addControlToAlgorithmBar("Text", ""); + this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); + this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); + this.enqueueButton.onclick = this.enqueueCallback.bind(this); + this.controls.push(this.enqueueField); + this.controls.push(this.enqueueButton); + + this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); + this.dequeueButton.onclick = this.dequeueCallback.bind(this); + this.controls.push(this.dequeueButton); + + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); + this.clearButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearButton); + +} + +QueueArray.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +QueueArray.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +QueueArray.prototype.setup = function() +{ + + this.nextIndex = 0; + + this.arrayID = new Array(SIZE); + this.arrayLabelID = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + + this.arrayID[i]= this.nextIndex++; + this.arrayLabelID[i]= this.nextIndex++; + } + this.headID = this.nextIndex++; + headLabelID = this.nextIndex++; + this.tailID = this.nextIndex++; + tailLabelID = this.nextIndex++; + + this.arrayData = new Array(SIZE); + this.head = 0; + this.tail = 0; + this.leftoverLabelID = this.nextIndex++; + + + for (var i = 0; i < SIZE; i++) + { + var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); + this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("SetForegroundColor", this.arrayLabelID[i], INDEX_COLOR); + + } + this.cmd("CreateLabel", headLabelID, "Head", HEAD_LABEL_X, HEAD_LABEL_Y); + this.cmd("CreateRectangle", this.headID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, HEAD_POS_X, HEAD_POS_Y); + + this.cmd("CreateLabel", tailLabelID, "Tail", TAIL_LABEL_X, TAIL_LABEL_Y); + this.cmd("CreateRectangle", this.tailID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TAIL_POS_X, TAIL_POS_Y); + + + + this.cmd("CreateLabel", this.leftoverLabelID, "", QUEUE_LABEL_X, QUEUE_LABEL_Y); + + + this.initialIndex = this.nextIndex; + + this.highlight1ID = this.nextIndex++; + this.highlight2ID = this.nextIndex++; + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + + +} + + +QueueArray.prototype.reset = function() +{ + this.top = 0; + this.nextIndex = this.initialIndex; + +} + + +QueueArray.prototype.enqueueCallback = function(event) +{ + if ((this.tail + 1) % SIZE != this.head && this.enqueueField.value != "") + { + var pushVal = this.enqueueField.value; + this.enqueueField.value = "" + this.implementAction(this.enqueue.bind(this), pushVal); + } +} + + +QueueArray.prototype.dequeueCallback = function(event) +{ + if (this.tail != this.head) + { + this.implementAction(this.dequeue.bind(this), ""); + } +} + + +QueueArray.prototype.clearCallback = function(event) +{ + this.implementAction(this.clearAll.bind(this), ""); +} + + + +QueueArray.prototype.enqueue = function(elemToEnqueue) +{ + this.commands = new Array(); + + var labEnqueueID = this.nextIndex++; + var labEnqueueValID = this.nextIndex++; + this.arrayData[this.tail] = elemToEnqueue; + this.cmd("SetText", this.leftoverLabelID, ""); + + this.cmd("CreateLabel", labEnqueueID, "Enqueuing Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); + this.cmd("CreateLabel", labEnqueueValID,elemToEnqueue, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); + + this.cmd("Step"); + this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, TAIL_POS_X, TAIL_POS_Y); + this.cmd("Step"); + + var xpos = (this.tail % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(this.tail / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + + this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Step"); + + this.cmd("Move", labEnqueueValID, xpos, ypos); + this.cmd("Step"); + + this.cmd("Settext", this.arrayID[this.tail], elemToEnqueue); + this.cmd("Delete", labEnqueueValID); + + this.cmd("Delete", this.highlight1ID); + + this.cmd("SetHighlight", this.tailID, 1); + this.cmd("Step"); + this.tail = (this.tail + 1) % SIZE; + this.cmd("SetText", this.tailID, this.tail) + this.cmd("Step"); + this.cmd("SetHighlight", this.tailID, 0); + this.cmd("Delete", labEnqueueID); + + return this.commands; +} + +QueueArray.prototype.dequeue = function(ignored) +{ + this.commands = new Array(); + + var labDequeueID = this.nextIndex++; + var labDequeueValID = this.nextIndex++; + + this.cmd("SetText", this.leftoverLabelID, ""); + + + this.cmd("CreateLabel", labDequeueID, "Dequeued Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); + + this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, HEAD_POS_X, HEAD_POS_Y); + this.cmd("Step"); + + var xpos = (this.head % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(this.head / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + + this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Step"); + + this.cmd("Delete", this.highlight1ID); + + + var dequeuedVal = this.arrayData[this.head] + this.cmd("CreateLabel", labDequeueValID,dequeuedVal, xpos, ypos); + this.cmd("Settext", this.arrayID[this.head], ""); + this.cmd("Move", labDequeueValID, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); + this.cmd("Step"); + + this.cmd("SetHighlight", this.headID, 1); + this.cmd("Step"); + this.head = (this.head + 1 ) % SIZE; + this.cmd("SetText", this.headID, this.head) + this.cmd("Step"); + this.cmd("SetHighlight", this.headID, 0); + + this.cmd("SetText", this.leftoverLabelID, "Dequeued Value: " + dequeuedVal); + + + this.cmd("Delete", labDequeueID) + this.cmd("Delete", labDequeueValID); + + + + return this.commands; +} + + + +QueueArray.prototype.clearAll = function() +{ + this.commands = new Array(); + this.cmd("SetText", this.leftoverLabelID, ""); + + for (var i = 0; i < SIZE; i++) + { + this.cmd("SetText", this.arrayID[i], ""); + } + this.head = 0; + this.tail = 0; + this.cmd("SetText", this.headID, "0"); + this.cmd("SetText", this.tailID, "0"); + return this.commands; + +} + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new QueueArray(animManag, canvas.width, canvas.height); +} diff --git a/AlgorithmLibrary/QueueLL.js b/AlgorithmLibrary/QueueLL.js index 0e86b98..b29647d 100644 --- a/AlgorithmLibrary/QueueLL.js +++ b/AlgorithmLibrary/QueueLL.js @@ -1,329 +1,329 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var LINKED_LIST_START_X = 100; -var LINKED_LIST_START_Y = 200; -var LINKED_LIST_ELEM_WIDTH = 70; -var LINKED_LIST_ELEM_HEIGHT = 30; - - -var LINKED_LIST_INSERT_X = 250; -var LINKED_LIST_INSERT_Y = 50; - -var LINKED_LIST_ELEMS_PER_LINE = 8; -var LINKED_LIST_ELEM_SPACING = 100; -var LINKED_LIST_LINE_SPACING = 100; - -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; - -var TOP_ELEM_WIDTH = 30; -var TOP_ELEM_HEIGHT = 30; - -var TAIL_POS_X = 180; -var TAIL_LABEL_X = 130; - -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; - -var SIZE = 32; - -function QueueLL(am, w, h) -{ - this.init(am, w, h); - -} - -QueueLL.inheritFrom(Algorithm); - - -QueueLL.prototype.init = function(am, w, h) -{ - QueueLL.superclass.init.call(this, am, w, h); - this.addControls(); - this.nextIndex = 0; - this.commands = []; - this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; - this.tail_label_y = this.tail_pos_y; - this.setup(); - this.initialIndex = this.nextIndex; -} - - -QueueLL.prototype.addControls = function() -{ - this.controls = []; - this.enqueueField = this.addControlToAlgorithmBar("Text", ""); - this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); - this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); - this.enqueueButton.onclick = this.enqueueCallback.bind(this); - this.controls.push(this.enqueueField); - this.controls.push(this.enqueueButton); - - this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); - this.dequeueButton.onclick = this.dequeueCallback.bind(this); - this.controls.push(this.dequeueButton); - - this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); - this.clearButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearButton); - -} - -QueueLL.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -QueueLL.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -QueueLL.prototype.setup = function() -{ - - this.linkedListElemID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - - this.linkedListElemID[i]= this.nextIndex++; - } - this.headID = this.nextIndex++; - this.headLabelID = this.nextIndex++; - - this.tailID = this.nextIndex++; - this.tailLabelID = this.nextIndex++; - - - this.arrayData = new Array(SIZE); - this.top = 0; - this.leftoverLabelID = this.nextIndex++; - - this.cmd("CreateLabel", this.headLabelID, "Head", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.headID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); - this.cmd("SetNull", this.headID, 1); - - - this.cmd("CreateLabel", this.tailLabelID, "Tail", TAIL_LABEL_X, this.tail_label_y); - this.cmd("CreateRectangle", this.tailID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TAIL_POS_X, this.tail_pos_y); - this.cmd("SetNull", this.tailID, 1); - - this.cmd("CreateLabel", this.leftoverLabelID, "", 5, PUSH_LABEL_Y,0); - - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - -} - -QueueLL.prototype.resetLinkedListPositions = function() -{ - for (var i = this.top - 1; i >= 0; i--) - { - var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; - var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; - this.cmd("Move", this.linkedListElemID[i], nextX, nextY); - } - -} - - - - -QueueLL.prototype.reset = function() -{ - this.top = 0; - this.nextIndex = this.initialIndex; - -} - - -QueueLL.prototype.enqueueCallback = function(event) -{ - if (this.top < SIZE && this.enqueueField.value != "") - { - var pushVal = this.enqueueField.value; - this.enqueueField.value = "" - this.implementAction(this.enqueue.bind(this), pushVal); - } -} - - -QueueLL.prototype.dequeueCallback = function(event) -{ - if (this.top > 0) - { - this.implementAction(this.dequeue.bind(this), ""); - } -} - - -QueueLL.prototype.clearCallback = function(event) -{ - this.implementAction(this.clearData.bind(this), ""); -} - - - -QueueLL.prototype.enqueue = function(elemToPush) -{ - this.commands = new Array(); - - this.arrayData[this.top] = elemToPush; - - this.cmd("SetText", this.leftoverLabelID, ""); - - for (var i = this.top; i > 0; i--) - { - this.arrayData[i] = this.arrayData[i-1]; - this.linkedListElemID[i] =this.linkedListElemID[i-1]; - } - this.arrayData[0] = elemToPush; - this.linkedListElemID[0] = this.nextIndex++; - - var labPushID = this.nextIndex++; - var labPushValID = this.nextIndex++; - this.cmd("CreateLinkedList",this.linkedListElemID[0], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, - LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); - - this.cmd("SetNull", this.linkedListElemID[0], 1); - this.cmd("CreateLabel", labPushID, "Enqueuing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - - this.cmd("Step"); - - - - this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); - - this.cmd("Step"); - this.cmd("SetText", this.linkedListElemID[0], elemToPush); - this.cmd("Delete", labPushValID); - - if (this.top == 0) - { - this.cmd("SetNull", this.headID, 0); - this.cmd("SetNull", this.tailID, 0); - this.cmd("connect", this.headID, this.linkedListElemID[this.top]); - this.cmd("connect", this.tailID, this.linkedListElemID[this.top]); - } - else - { - this.cmd("SetNull", this.linkedListElemID[1], 0); - this.cmd("Connect", this.linkedListElemID[1], this.linkedListElemID[0]); - this.cmd("Step"); - this.cmd("Disconnect", this.tailID, this.linkedListElemID[1]); - } - this.cmd("Connect", this.tailID, this.linkedListElemID[0]); - - this.cmd("Step"); - this.top = this.top + 1; - this.resetLinkedListPositions(); - this.cmd("Delete", labPushID); - this.cmd("Step"); - - return this.commands; -} - -QueueLL.prototype.dequeue = function(ignored) -{ - this.commands = new Array(); - - var labPopID = this.nextIndex++; - var labPopValID = this.nextIndex++; - - this.cmd("SetText", this.leftoverLabelID, ""); - - - this.cmd("CreateLabel", labPopID, "Dequeued Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); - - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - this.cmd("Step"); - this.cmd("Disconnect", this.headID, this.linkedListElemID[this.top - 1]); - - if (this.top == 1) - { - this.cmd("SetNull", this.headID, 1); - this.cmd("SetNull", this.tailID, 1); - this.cmd("Disconnect", this.tailID, this.linkedListElemID[this.top-1]); - } - else - { - this.cmd("Connect", this.headID, this.linkedListElemID[this.top-2]); - } - this.cmd("Step"); - this.cmd("Delete", this.linkedListElemID[this.top - 1]); - this.top = this.top - 1; - this.resetLinkedListPositions(); - - this.cmd("Delete", labPopValID) - this.cmd("Delete", labPopID); - this.cmd("SetText", this.leftoverLabelID, "Dequeued Value: " + this.arrayData[this.top]); - - - - return this.commands; -} - - - -QueueLL.prototype.clearAll = function() -{ - this.commands = new Array(); - for (var i = 0; i < this.top; i++) - { - this.cmd("Delete", this.linkedListElemID[i]); - } - this.top = 0; - this.cmd("SetNull", this.headID, 1); - return this.commands; - -} - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new QueueLL(animManag, canvas.width, canvas.height); -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var LINKED_LIST_START_X = 100; +var LINKED_LIST_START_Y = 200; +var LINKED_LIST_ELEM_WIDTH = 70; +var LINKED_LIST_ELEM_HEIGHT = 30; + + +var LINKED_LIST_INSERT_X = 250; +var LINKED_LIST_INSERT_Y = 50; + +var LINKED_LIST_ELEMS_PER_LINE = 8; +var LINKED_LIST_ELEM_SPACING = 100; +var LINKED_LIST_LINE_SPACING = 100; + +var TOP_POS_X = 180; +var TOP_POS_Y = 100; +var TOP_LABEL_X = 130; +var TOP_LABEL_Y = 100; + +var TOP_ELEM_WIDTH = 30; +var TOP_ELEM_HEIGHT = 30; + +var TAIL_POS_X = 180; +var TAIL_LABEL_X = 130; + +var PUSH_LABEL_X = 50; +var PUSH_LABEL_Y = 30; +var PUSH_ELEMENT_X = 120; +var PUSH_ELEMENT_Y = 30; + +var SIZE = 32; + +function QueueLL(am, w, h) +{ + this.init(am, w, h); + +} + +QueueLL.inheritFrom(Algorithm); + + +QueueLL.prototype.init = function(am, w, h) +{ + QueueLL.superclass.init.call(this, am, w, h); + this.addControls(); + this.nextIndex = 0; + this.commands = []; + this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; + this.tail_label_y = this.tail_pos_y; + this.setup(); + this.initialIndex = this.nextIndex; +} + + +QueueLL.prototype.addControls = function() +{ + this.controls = []; + this.enqueueField = this.addControlToAlgorithmBar("Text", ""); + this.enqueueField.onkeydown = this.returnSubmit(this.enqueueField, this.enqueueCallback.bind(this), 6); + this.enqueueButton = this.addControlToAlgorithmBar("Button", "Enqueue"); + this.enqueueButton.onclick = this.enqueueCallback.bind(this); + this.controls.push(this.enqueueField); + this.controls.push(this.enqueueButton); + + this.dequeueButton = this.addControlToAlgorithmBar("Button", "Dequeue"); + this.dequeueButton.onclick = this.dequeueCallback.bind(this); + this.controls.push(this.dequeueButton); + + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Queue"); + this.clearButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearButton); + +} + +QueueLL.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +QueueLL.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +QueueLL.prototype.setup = function() +{ + + this.linkedListElemID = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + + this.linkedListElemID[i]= this.nextIndex++; + } + this.headID = this.nextIndex++; + this.headLabelID = this.nextIndex++; + + this.tailID = this.nextIndex++; + this.tailLabelID = this.nextIndex++; + + + this.arrayData = new Array(SIZE); + this.top = 0; + this.leftoverLabelID = this.nextIndex++; + + this.cmd("CreateLabel", this.headLabelID, "Head", TOP_LABEL_X, TOP_LABEL_Y); + this.cmd("CreateRectangle", this.headID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + this.cmd("SetNull", this.headID, 1); + + + this.cmd("CreateLabel", this.tailLabelID, "Tail", TAIL_LABEL_X, this.tail_label_y); + this.cmd("CreateRectangle", this.tailID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TAIL_POS_X, this.tail_pos_y); + this.cmd("SetNull", this.tailID, 1); + + this.cmd("CreateLabel", this.leftoverLabelID, "", 5, PUSH_LABEL_Y,0); + + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + +} + +QueueLL.prototype.resetLinkedListPositions = function() +{ + for (var i = this.top - 1; i >= 0; i--) + { + var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; + var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; + this.cmd("Move", this.linkedListElemID[i], nextX, nextY); + } + +} + + + + +QueueLL.prototype.reset = function() +{ + this.top = 0; + this.nextIndex = this.initialIndex; + +} + + +QueueLL.prototype.enqueueCallback = function(event) +{ + if (this.top < SIZE && this.enqueueField.value != "") + { + var pushVal = this.enqueueField.value; + this.enqueueField.value = "" + this.implementAction(this.enqueue.bind(this), pushVal); + } +} + + +QueueLL.prototype.dequeueCallback = function(event) +{ + if (this.top > 0) + { + this.implementAction(this.dequeue.bind(this), ""); + } +} + + +QueueLL.prototype.clearCallback = function(event) +{ + this.implementAction(this.clearData.bind(this), ""); +} + + + +QueueLL.prototype.enqueue = function(elemToPush) +{ + this.commands = new Array(); + + this.arrayData[this.top] = elemToPush; + + this.cmd("SetText", this.leftoverLabelID, ""); + + for (var i = this.top; i > 0; i--) + { + this.arrayData[i] = this.arrayData[i-1]; + this.linkedListElemID[i] =this.linkedListElemID[i-1]; + } + this.arrayData[0] = elemToPush; + this.linkedListElemID[0] = this.nextIndex++; + + var labPushID = this.nextIndex++; + var labPushValID = this.nextIndex++; + this.cmd("CreateLinkedList",this.linkedListElemID[0], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, + LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); + + this.cmd("SetNull", this.linkedListElemID[0], 1); + this.cmd("CreateLabel", labPushID, "Enqueuing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + + this.cmd("Step"); + + + + this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); + + this.cmd("Step"); + this.cmd("SetText", this.linkedListElemID[0], elemToPush); + this.cmd("Delete", labPushValID); + + if (this.top == 0) + { + this.cmd("SetNull", this.headID, 0); + this.cmd("SetNull", this.tailID, 0); + this.cmd("connect", this.headID, this.linkedListElemID[this.top]); + this.cmd("connect", this.tailID, this.linkedListElemID[this.top]); + } + else + { + this.cmd("SetNull", this.linkedListElemID[1], 0); + this.cmd("Connect", this.linkedListElemID[1], this.linkedListElemID[0]); + this.cmd("Step"); + this.cmd("Disconnect", this.tailID, this.linkedListElemID[1]); + } + this.cmd("Connect", this.tailID, this.linkedListElemID[0]); + + this.cmd("Step"); + this.top = this.top + 1; + this.resetLinkedListPositions(); + this.cmd("Delete", labPushID); + this.cmd("Step"); + + return this.commands; +} + +QueueLL.prototype.dequeue = function(ignored) +{ + this.commands = new Array(); + + var labPopID = this.nextIndex++; + var labPopValID = this.nextIndex++; + + this.cmd("SetText", this.leftoverLabelID, ""); + + + this.cmd("CreateLabel", labPopID, "Dequeued Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); + + this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Step"); + this.cmd("Disconnect", this.headID, this.linkedListElemID[this.top - 1]); + + if (this.top == 1) + { + this.cmd("SetNull", this.headID, 1); + this.cmd("SetNull", this.tailID, 1); + this.cmd("Disconnect", this.tailID, this.linkedListElemID[this.top-1]); + } + else + { + this.cmd("Connect", this.headID, this.linkedListElemID[this.top-2]); + } + this.cmd("Step"); + this.cmd("Delete", this.linkedListElemID[this.top - 1]); + this.top = this.top - 1; + this.resetLinkedListPositions(); + + this.cmd("Delete", labPopValID) + this.cmd("Delete", labPopID); + this.cmd("SetText", this.leftoverLabelID, "Dequeued Value: " + this.arrayData[this.top]); + + + + return this.commands; +} + + + +QueueLL.prototype.clearAll = function() +{ + this.commands = new Array(); + for (var i = 0; i < this.top; i++) + { + this.cmd("Delete", this.linkedListElemID[i]); + } + this.top = 0; + this.cmd("SetNull", this.headID, 1); + return this.commands; + +} + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new QueueLL(animManag, canvas.width, canvas.height); +} diff --git a/AlgorithmLibrary/RecFact.js b/AlgorithmLibrary/RecFact.js index fb44732..9b83813 100644 --- a/AlgorithmLibrary/RecFact.js +++ b/AlgorithmLibrary/RecFact.js @@ -1,217 +1,217 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function RecFact(am, w, h) -{ - // call superclass' constructor, which calls init - RecFact.superclass.constructor.call(this, am, w, h); -} -RecFact.inheritFrom(Recursive); - - -RecFact.MAX_VALUE = 20; - -RecFact.ACTIVATION_FIELDS = ["n ", "subValue ", "returnValue "]; -RecFact.CODE = [["def ","factorial(n)",":"], - [" if ","(n <= 1): "], - [" return 1"], - [" else:"], - [" subSolution = ", "factorial(n - 1)"], - [" solution = ", "subSolution * n"], - [" return ", "solution"]]; - - -RecFact.RECURSIVE_DELTA_Y = RecFact.ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; - -RecFact.ACTIVATION_RECORT_START_X = 330; -RecFact.ACTIVATION_RECORT_START_Y = 20; - - - -RecFact.prototype.init = function(am, w, h) -{ - RecFact.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = RecFact.CODE; - - - this.addCodeToCanvas(this.code); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -RecFact.prototype.addControls = function() -{ - this.controls = []; - this.factorialField = this.addControlToAlgorithmBar("Text", ""); - this.factorialField.onkeydown = this.returnSubmit(this.factorialField, this.factorialCallback.bind(this), 2, true); - this.controls.push(this.factorialField); - - this.factorialButton = this.addControlToAlgorithmBar("Button", "Factorial"); - this.factorialButton.onclick = this.factorialCallback.bind(this); - this.controls.push(this.factorialButton); - -} - - - - -RecFact.prototype.factorialCallback = function(event) -{ - var factValue; - - if (this.factorialField.value != "") - { - var factValue = Math.min(parseInt(this.factorialField.value), RecFact.MAX_VALUE); - this.factorialField.value = String(factValue); - this.implementAction(this.doFactorial.bind(this),factValue); - } -} - - - - -RecFact.prototype.doFactorial = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - this.currentY = RecFact.ACTIVATION_RECORT_START_Y; - this.currentX = RecFact.ACTIVATION_RECORT_START_X; - - var final = this.factorial(value); - var resultID = this.nextIndex++; - this.oldIDs.push(resultID); - this.cmd("CreateLabel", resultID, "factorial(" + String(value) + ") = " + String(final), - Recursive.CODE_START_X, Recursive.CODE_START_Y + (this.code.length + 1) * Recursive.CODE_LINE_HEIGHT, 0); - //this.cmd("SetText", functionCallID, "factorial(" + String(value) + ") = " + String(final)); - return this.commands; -} - - -RecFact.prototype.factorial = function(value) -{ - var activationRec = this.createActivation("factorial ", RecFact.ACTIVATION_FIELDS, this.currentX, this.currentY); - this.cmd("SetText", activationRec.fieldIDs[0], value); -// this.cmd("CreateLabel", ID, "", 10, this.currentY, 0); - var oldX = this.currentX; - var oldY = this.currentY; - this.currentY += RecFact.RECURSIVE_DELTA_Y; - if (this.currentY + Recursive.RECURSIVE_DELTA_Y > this.canvasHeight) - { - this.currentY = RecFact.ACTIVATION_RECORT_START_Y; - this.currentX += Recursive.ACTIVATION_RECORD_SPACING; - } - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); - if (value > 1) - { - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); - - var firstValue = this.factorial(value-1); - - this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", activationRec.fieldIDs[1], firstValue); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); - - this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", activationRec.fieldIDs[2], firstValue * value); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); - - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_HIGHLIGHT_COLOR); - - this.cmd("Step"); - this.deleteActivation(activationRec); - this.currentY = oldY; - this.currentX = oldX; - this.cmd("CreateLabel", this.nextIndex, "Return Value = " + String(firstValue * value), oldX, oldY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("Delete",this.nextIndex); - - - -// this.cmd("SetForegroundColor", this.codeID[4][3], Recursive.CODE_HIGHLIGHT_COLOR); -// this.cmd("Step"); - - return firstValue *value; - } - else - { - this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_STANDARD_COLOR); - - - this.currentY = oldY; - this.currentX = oldX; - this.deleteActivation(activationRec); - this.cmd("CreateLabel", this.nextIndex, "Return Value = 1", oldX, oldY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("Delete",this.nextIndex); - - return 1; - } - - - -} -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new RecFact(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY David Galles ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Galles OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function RecFact(am, w, h) +{ + // call superclass' constructor, which calls init + RecFact.superclass.constructor.call(this, am, w, h); +} +RecFact.inheritFrom(Recursive); + + +RecFact.MAX_VALUE = 20; + +RecFact.ACTIVATION_FIELDS = ["n ", "subValue ", "returnValue "]; +RecFact.CODE = [["def ","factorial(n)",":"], + [" if ","(n <= 1): "], + [" return 1"], + [" else:"], + [" subSolution = ", "factorial(n - 1)"], + [" solution = ", "subSolution * n"], + [" return ", "solution"]]; + + +RecFact.RECURSIVE_DELTA_Y = RecFact.ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; + +RecFact.ACTIVATION_RECORT_START_X = 330; +RecFact.ACTIVATION_RECORT_START_Y = 20; + + + +RecFact.prototype.init = function(am, w, h) +{ + RecFact.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = RecFact.CODE; + + + this.addCodeToCanvas(this.code); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +RecFact.prototype.addControls = function() +{ + this.controls = []; + this.factorialField = this.addControlToAlgorithmBar("Text", ""); + this.factorialField.onkeydown = this.returnSubmit(this.factorialField, this.factorialCallback.bind(this), 2, true); + this.controls.push(this.factorialField); + + this.factorialButton = this.addControlToAlgorithmBar("Button", "Factorial"); + this.factorialButton.onclick = this.factorialCallback.bind(this); + this.controls.push(this.factorialButton); + +} + + + + +RecFact.prototype.factorialCallback = function(event) +{ + var factValue; + + if (this.factorialField.value != "") + { + var factValue = Math.min(parseInt(this.factorialField.value), RecFact.MAX_VALUE); + this.factorialField.value = String(factValue); + this.implementAction(this.doFactorial.bind(this),factValue); + } +} + + + + +RecFact.prototype.doFactorial = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + this.currentY = RecFact.ACTIVATION_RECORT_START_Y; + this.currentX = RecFact.ACTIVATION_RECORT_START_X; + + var final = this.factorial(value); + var resultID = this.nextIndex++; + this.oldIDs.push(resultID); + this.cmd("CreateLabel", resultID, "factorial(" + String(value) + ") = " + String(final), + Recursive.CODE_START_X, Recursive.CODE_START_Y + (this.code.length + 1) * Recursive.CODE_LINE_HEIGHT, 0); + //this.cmd("SetText", functionCallID, "factorial(" + String(value) + ") = " + String(final)); + return this.commands; +} + + +RecFact.prototype.factorial = function(value) +{ + var activationRec = this.createActivation("factorial ", RecFact.ACTIVATION_FIELDS, this.currentX, this.currentY); + this.cmd("SetText", activationRec.fieldIDs[0], value); +// this.cmd("CreateLabel", ID, "", 10, this.currentY, 0); + var oldX = this.currentX; + var oldY = this.currentY; + this.currentY += RecFact.RECURSIVE_DELTA_Y; + if (this.currentY + Recursive.RECURSIVE_DELTA_Y > this.canvasHeight) + { + this.currentY = RecFact.ACTIVATION_RECORT_START_Y; + this.currentX += Recursive.ACTIVATION_RECORD_SPACING; + } + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); + if (value > 1) + { + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); + + var firstValue = this.factorial(value-1); + + this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", activationRec.fieldIDs[1], firstValue); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); + + this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", activationRec.fieldIDs[2], firstValue * value); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); + + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_HIGHLIGHT_COLOR); + + this.cmd("Step"); + this.deleteActivation(activationRec); + this.currentY = oldY; + this.currentX = oldX; + this.cmd("CreateLabel", this.nextIndex, "Return Value = " + String(firstValue * value), oldX, oldY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("Delete",this.nextIndex); + + + +// this.cmd("SetForegroundColor", this.codeID[4][3], Recursive.CODE_HIGHLIGHT_COLOR); +// this.cmd("Step"); + + return firstValue *value; + } + else + { + this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_STANDARD_COLOR); + + + this.currentY = oldY; + this.currentX = oldX; + this.deleteActivation(activationRec); + this.cmd("CreateLabel", this.nextIndex, "Return Value = 1", oldX, oldY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("Delete",this.nextIndex); + + return 1; + } + + + +} +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new RecFact(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/RecQueens.js b/AlgorithmLibrary/RecQueens.js index 5733f59..c1115af 100644 --- a/AlgorithmLibrary/RecQueens.js +++ b/AlgorithmLibrary/RecQueens.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/RecReverse.js b/AlgorithmLibrary/RecReverse.js index 098452f..aa1c2f1 100644 --- a/AlgorithmLibrary/RecReverse.js +++ b/AlgorithmLibrary/RecReverse.js @@ -1,226 +1,226 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function Reverse(am, w, h) -{ - // call superclass' constructor, which calls init - Reverse.superclass.constructor.call(this, am, w, h); -} -Reverse.inheritFrom(Recursive); - -Reverse.ACTIVATION_FIELDS = ["word ", "subProblem ", "subSolution ", "solution "]; - -Reverse.CODE = [["def ","reverse(word)",":"], - [" if ","(word == \"\"): "], - [" return word"], - [" else:"], - [" subProblem = ", "word[1:]"], - [" subSolution = ", "reverse(subProblem)"], - [" solution = ", "subSolution + word[0]"], - [" return = ", "solution"]]; - - -Reverse.RECURSIVE_DELTA_Y = Reverse.ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; - - -Reverse.ACTIVATION_RECORT_START_X = 375; -Reverse.ACTIVATION_RECORT_START_Y = 20; - - - -Reverse.prototype.init = function(am, w, h) -{ - Reverse.superclass.init.call(this, am, w, h); - this.nextIndex = 0; - this.addControls(); - this.code = Reverse.CODE; - - - this.addCodeToCanvas(this.code); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.initialIndex = this.nextIndex; - this.oldIDs = []; - this.commands = []; -} - - -Reverse.prototype.addControls = function() -{ - this.controls = []; - this.reverseField = this.addControlToAlgorithmBar("Text", ""); - this.reverseField.onkeydown = this.returnSubmit(this.reverseField, this.reverseCallback.bind(this), 10, false); - this.controls.push(this.reverseField); - - this.reverseButton = this.addControlToAlgorithmBar("Button", "Reverse"); - this.reverseButton.onclick = this.reverseCallback.bind(this); - this.controls.push(this.reverseButton); - -} - - - - -Reverse.prototype.reverseCallback = function(event) -{ - var factValue; - - if (this.reverseField.value != "") - { - var revValue =this.reverseField.value; - this.implementAction(this.doReverse.bind(this),revValue); - } -} - - - - -Reverse.prototype.doReverse = function(value) -{ - this.commands = []; - - this.clearOldIDs(); - - this.currentY = Reverse.ACTIVATION_RECORT_START_Y; - this.currentX = Reverse.ACTIVATION_RECORT_START_X; - - var final = this.reverse(value); - var resultID = this.nextIndex++; - this.oldIDs.push(resultID); - this.cmd("CreateLabel", resultID, "reverse(" + String(value) + ") = " + String(final), - Recursive.CODE_START_X, Recursive.CODE_START_Y + (this.code.length + 1) * Recursive.CODE_LINE_HEIGHT, 0); - return this.commands; -} - - -Reverse.prototype.reverse = function(value) -{ - - var activationRec = this.createActivation("reverse ", Reverse.ACTIVATION_FIELDS, this.currentX, this.currentY); - this.cmd("SetText", activationRec.fieldIDs[0], value); -// this.cmd("CreateLabel", ID, "", 10, this.currentY, 0); - var oldX = this.currentX; - var oldY = this.currentY; - this.currentY += Reverse.RECURSIVE_DELTA_Y; - if (this.currentY + Recursive.RECURSIVE_DELTA_Y > this.canvasHeight) - { - this.currentY = Reverse.ACTIVATION_RECORT_START_Y; - this.currentX += Recursive.ACTIVATION_RECORD_SPACING; - } - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); - if (value != "") - { - this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); - var subProblem = value.substr(1); - this.cmd("SetText", activationRec.fieldIDs[1], subProblem); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); - - - - var subSolution = this.reverse(subProblem); - - this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", activationRec.fieldIDs[2], subSolution); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); - - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_HIGHLIGHT_COLOR); - var solution = subSolution + value[0]; - this.cmd("SetText", activationRec.fieldIDs[3], solution); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_STANDARD_COLOR); - - this.cmd("SetForegroundColor", this.codeID[7][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.codeID[7][1], Recursive.CODE_HIGHLIGHT_COLOR); - - this.cmd("Step"); - this.deleteActivation(activationRec); - this.currentY = oldY; - this.currentX = oldX; - this.cmd("CreateLabel", this.nextIndex, "Return Value = \"" + solution + "\"", oldX, oldY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[7][0], Recursive.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.codeID[7][1], Recursive.CODE_STANDARD_COLOR); - this.cmd("Delete",this.nextIndex); - - - -// this.cmd("SetForegroundColor", this.codeID[4][3], Recursive.CODE_HIGHLIGHT_COLOR); -// this.cmd("Step"); - - return solution; - } - else - { - this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_STANDARD_COLOR); - - - this.currentY = oldY; - this.currentX = oldX; - this.deleteActivation(activationRec); - this.cmd("CreateLabel", this.nextIndex, "Return Value = \"\"", oldX, oldY); - this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("Delete",this.nextIndex); - - return ""; - } - - - -} -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new Reverse(animManag, canvas.width, canvas.height); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function Reverse(am, w, h) +{ + // call superclass' constructor, which calls init + Reverse.superclass.constructor.call(this, am, w, h); +} +Reverse.inheritFrom(Recursive); + +Reverse.ACTIVATION_FIELDS = ["word ", "subProblem ", "subSolution ", "solution "]; + +Reverse.CODE = [["def ","reverse(word)",":"], + [" if ","(word == \"\"): "], + [" return word"], + [" else:"], + [" subProblem = ", "word[1:]"], + [" subSolution = ", "reverse(subProblem)"], + [" solution = ", "subSolution + word[0]"], + [" return = ", "solution"]]; + + +Reverse.RECURSIVE_DELTA_Y = Reverse.ACTIVATION_FIELDS.length * Recursive.ACTIVATION_RECORD_HEIGHT; + + +Reverse.ACTIVATION_RECORT_START_X = 375; +Reverse.ACTIVATION_RECORT_START_Y = 20; + + + +Reverse.prototype.init = function(am, w, h) +{ + Reverse.superclass.init.call(this, am, w, h); + this.nextIndex = 0; + this.addControls(); + this.code = Reverse.CODE; + + + this.addCodeToCanvas(this.code); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.initialIndex = this.nextIndex; + this.oldIDs = []; + this.commands = []; +} + + +Reverse.prototype.addControls = function() +{ + this.controls = []; + this.reverseField = this.addControlToAlgorithmBar("Text", ""); + this.reverseField.onkeydown = this.returnSubmit(this.reverseField, this.reverseCallback.bind(this), 10, false); + this.controls.push(this.reverseField); + + this.reverseButton = this.addControlToAlgorithmBar("Button", "Reverse"); + this.reverseButton.onclick = this.reverseCallback.bind(this); + this.controls.push(this.reverseButton); + +} + + + + +Reverse.prototype.reverseCallback = function(event) +{ + var factValue; + + if (this.reverseField.value != "") + { + var revValue =this.reverseField.value; + this.implementAction(this.doReverse.bind(this),revValue); + } +} + + + + +Reverse.prototype.doReverse = function(value) +{ + this.commands = []; + + this.clearOldIDs(); + + this.currentY = Reverse.ACTIVATION_RECORT_START_Y; + this.currentX = Reverse.ACTIVATION_RECORT_START_X; + + var final = this.reverse(value); + var resultID = this.nextIndex++; + this.oldIDs.push(resultID); + this.cmd("CreateLabel", resultID, "reverse(" + String(value) + ") = " + String(final), + Recursive.CODE_START_X, Recursive.CODE_START_Y + (this.code.length + 1) * Recursive.CODE_LINE_HEIGHT, 0); + return this.commands; +} + + +Reverse.prototype.reverse = function(value) +{ + + var activationRec = this.createActivation("reverse ", Reverse.ACTIVATION_FIELDS, this.currentX, this.currentY); + this.cmd("SetText", activationRec.fieldIDs[0], value); +// this.cmd("CreateLabel", ID, "", 10, this.currentY, 0); + var oldX = this.currentX; + var oldY = this.currentY; + this.currentY += Reverse.RECURSIVE_DELTA_Y; + if (this.currentY + Recursive.RECURSIVE_DELTA_Y > this.canvasHeight) + { + this.currentY = Reverse.ACTIVATION_RECORT_START_Y; + this.currentX += Recursive.ACTIVATION_RECORD_SPACING; + } + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[0][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[1][1], Recursive.CODE_STANDARD_COLOR); + if (value != "") + { + this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_HIGHLIGHT_COLOR); + var subProblem = value.substr(1); + this.cmd("SetText", activationRec.fieldIDs[1], subProblem); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[4][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[4][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); + + + + var subSolution = this.reverse(subProblem); + + this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", activationRec.fieldIDs[2], subSolution); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[5][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[5][1], Recursive.CODE_STANDARD_COLOR); + + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_HIGHLIGHT_COLOR); + var solution = subSolution + value[0]; + this.cmd("SetText", activationRec.fieldIDs[3], solution); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[6][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[6][1], Recursive.CODE_STANDARD_COLOR); + + this.cmd("SetForegroundColor", this.codeID[7][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.codeID[7][1], Recursive.CODE_HIGHLIGHT_COLOR); + + this.cmd("Step"); + this.deleteActivation(activationRec); + this.currentY = oldY; + this.currentX = oldX; + this.cmd("CreateLabel", this.nextIndex, "Return Value = \"" + solution + "\"", oldX, oldY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[7][0], Recursive.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.codeID[7][1], Recursive.CODE_STANDARD_COLOR); + this.cmd("Delete",this.nextIndex); + + + +// this.cmd("SetForegroundColor", this.codeID[4][3], Recursive.CODE_HIGHLIGHT_COLOR); +// this.cmd("Step"); + + return solution; + } + else + { + this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.codeID[2][0], Recursive.CODE_STANDARD_COLOR); + + + this.currentY = oldY; + this.currentX = oldX; + this.deleteActivation(activationRec); + this.cmd("CreateLabel", this.nextIndex, "Return Value = \"\"", oldX, oldY); + this.cmd("SetForegroundColor", this.nextIndex, Recursive.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("Delete",this.nextIndex); + + return ""; + } + + + +} +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new Reverse(animManag, canvas.width, canvas.height); +} + + + diff --git a/AlgorithmLibrary/Recursive.js b/AlgorithmLibrary/Recursive.js index f6d8627..e42dc05 100644 --- a/AlgorithmLibrary/Recursive.js +++ b/AlgorithmLibrary/Recursive.js @@ -1,221 +1,221 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function Recursive(am, w, h) -{ - // this shouldn't happen if subclassing is done properly - if (!am) - throw "this shouldn't happen"; - - this.init(am, w, h); -} -Recursive.inheritFrom(Algorithm); - - -Recursive.CODE_START_X = 10; -Recursive.CODE_START_Y = 10; -Recursive.CODE_LINE_HEIGHT = 14; - -Recursive.RECURSIVE_START_X = 20; -Recursive.RECURSIVE_START_Y = 120; -Recursive.RECURSIVE_DELTA_Y = 14; -Recursive.RECURSIVE_DELTA_X = 15; -Recursive.CODE_HIGHLIGHT_COLOR = "#FF0000"; -Recursive.CODE_STANDARD_COLOR = "#000000"; - -Recursive.TABLE_INDEX_COLOR = "#0000FF" -Recursive.CODE_RECURSIVE_1_COLOR = "#339933"; -Recursive.CODE_RECURSIVE_2_COLOR = "#0099FF"; - -Recursive.ACTIVATION_RECORD_WIDTH = 100; -Recursive.ACTIVATION_RECORD_HEIGHT = 20; - -Recursive.ACTIVATION_RECORD_SPACING = 2 * Recursive.ACTIVATION_RECORD_WIDTH + 10; - - - - -Recursive.SEPARATING_LINE_COLOR = "#0000FF" - -Recursive.prototype.addCodeToCanvas = function(code) -{ - this.codeID = this.addCodeToCanvasBase(code, Recursive.CODE_START_X, Recursive.CODE_START_Y, Recursive.CODE_LINE_HEIGHT, Recursive.CODE_STANDARD_COLOR); -/* this.codeID = Array(this.code.length); - var i, j; - for (i = 0; i < code.length; i++) - { - this.codeID[i] = new Array(code[i].length); - for (j = 0; j < code[i].length; j++) - { - this.codeID[i][j] = this.nextIndex++; - this.cmd("CreateLabel", this.codeID[i][j], code[i][j], Recursive.CODE_START_X, Recursive.CODE_START_Y + i * Recursive.CODE_LINE_HEIGHT, 0); - this.cmd("SetForegroundColor", this.codeID[i][j], Recursive.CODE_STANDARD_COLOR); - if (j > 0) - { - this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); - } - } - - - } */ - -} - - -Recursive.prototype.init = function(am, w, h) -{ - Recursive.superclass.init.call(this, am, w, h); -} - - -Recursive.prototype.clearOldIDs = function() -{ - for (var i = 0; i < this.oldIDs.length; i++) - { - this.cmd("Delete", this.oldIDs[i]); - } - this.oldIDs =[]; - this.nextIndex = this.initialIndex; - -} - - -Recursive.prototype.reset = function() -{ - this.oldIDs =[]; - this.nextIndex = this.initialIndex; -} - - - - -Recursive.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -Recursive.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -Recursive.prototype.deleteActivation = function(activationRec) -{ - var i; - for (i = 0; i < activationRec.labelIDs.length; i++) - { - this.cmd("Delete", activationRec.labelIDs[i]); - this.cmd("Delete", activationRec.fieldIDs[i]); - } - this.cmd("Delete", activationRec.separatingLineID); - this.cmd("Delete", activationRec.nameID); -} - - -Recursive.prototype.createActivation = function(functionName, argList, x, y, labelsOnLeft) -{ - var activationRec = new ActivationRecord(argList); - var i; - activationRec.nameID = this.nextIndex++; - labelsOnLeft = (labelsOnLeft == undefined) ? true : labelsOnLeft; - for (i = 0; i < argList.length; i++) - { - var valueID = this.nextIndex++; - activationRec.fieldIDs[i] = valueID; - - this.cmd("CreateRectangle", valueID, - "", - Recursive.ACTIVATION_RECORD_WIDTH, - Recursive.ACTIVATION_RECORD_HEIGHT, - x, - y + i * Recursive.ACTIVATION_RECORD_HEIGHT); - - var labelID = this.nextIndex++; - activationRec.labelIDs[i] = labelID; - this.cmd("CreateLabel", labelID, argList[i]); - if (labelsOnLeft) - this.cmd("AlignLeft", labelID, valueID); - else - this.cmd("AlignRight", labelID, valueID); - } - activationRec.separatingLineID = this.nextIndex++; - this.cmd("CreateLabel", activationRec.nameID, " " + functionName + " "); - this.cmd("SetForegroundColor", activationRec.nameID, Recursive.SEPARATING_LINE_COLOR); - - if (labelsOnLeft) - { - this.cmd("CreateRectangle", activationRec.separatingLineID, - "", - Recursive.ACTIVATION_RECORD_WIDTH * 2, - 1, - x - Recursive.ACTIVATION_RECORD_WIDTH / 2, - y - Recursive.ACTIVATION_RECORD_HEIGHT / 2); - this.cmd("AlignLeft", activationRec.nameID, activationRec.labelIDs[0]); - } - else - { - this.cmd("CreateRectangle", activationRec.separatingLineID, - "", - Recursive.ACTIVATION_RECORD_WIDTH * 2, - 1, - x + Recursive.ACTIVATION_RECORD_WIDTH / 2, - y - Recursive.ACTIVATION_RECORD_HEIGHT / 2); - this.cmd("AlignRight", activationRec.nameID, activationRec.labelIDs[0]); - - } - this.cmd("SetForegroundColor", activationRec.separatingLineID, Recursive.SEPARATING_LINE_COLOR); - return activationRec; - -} - - - -function ActivationRecord(fields) -{ - this.fields = fields; - this.values = new Array(this.fields.length); - var i; - for (i = 0; i < this.fields.length; i++) - { - this.values[i] = ""; - } - this.fieldIDs = new Array(this.fields.length); - this.labelIDs = new Array(this.fields.length); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function Recursive(am, w, h) +{ + // this shouldn't happen if subclassing is done properly + if (!am) + throw "this shouldn't happen"; + + this.init(am, w, h); +} +Recursive.inheritFrom(Algorithm); + + +Recursive.CODE_START_X = 10; +Recursive.CODE_START_Y = 10; +Recursive.CODE_LINE_HEIGHT = 14; + +Recursive.RECURSIVE_START_X = 20; +Recursive.RECURSIVE_START_Y = 120; +Recursive.RECURSIVE_DELTA_Y = 14; +Recursive.RECURSIVE_DELTA_X = 15; +Recursive.CODE_HIGHLIGHT_COLOR = "#FF0000"; +Recursive.CODE_STANDARD_COLOR = "#000000"; + +Recursive.TABLE_INDEX_COLOR = "#0000FF" +Recursive.CODE_RECURSIVE_1_COLOR = "#339933"; +Recursive.CODE_RECURSIVE_2_COLOR = "#0099FF"; + +Recursive.ACTIVATION_RECORD_WIDTH = 100; +Recursive.ACTIVATION_RECORD_HEIGHT = 20; + +Recursive.ACTIVATION_RECORD_SPACING = 2 * Recursive.ACTIVATION_RECORD_WIDTH + 10; + + + + +Recursive.SEPARATING_LINE_COLOR = "#0000FF" + +Recursive.prototype.addCodeToCanvas = function(code) +{ + this.codeID = this.addCodeToCanvasBase(code, Recursive.CODE_START_X, Recursive.CODE_START_Y, Recursive.CODE_LINE_HEIGHT, Recursive.CODE_STANDARD_COLOR); +/* this.codeID = Array(this.code.length); + var i, j; + for (i = 0; i < code.length; i++) + { + this.codeID[i] = new Array(code[i].length); + for (j = 0; j < code[i].length; j++) + { + this.codeID[i][j] = this.nextIndex++; + this.cmd("CreateLabel", this.codeID[i][j], code[i][j], Recursive.CODE_START_X, Recursive.CODE_START_Y + i * Recursive.CODE_LINE_HEIGHT, 0); + this.cmd("SetForegroundColor", this.codeID[i][j], Recursive.CODE_STANDARD_COLOR); + if (j > 0) + { + this.cmd("AlignRight", this.codeID[i][j], this.codeID[i][j-1]); + } + } + + + } */ + +} + + +Recursive.prototype.init = function(am, w, h) +{ + Recursive.superclass.init.call(this, am, w, h); +} + + +Recursive.prototype.clearOldIDs = function() +{ + for (var i = 0; i < this.oldIDs.length; i++) + { + this.cmd("Delete", this.oldIDs[i]); + } + this.oldIDs =[]; + this.nextIndex = this.initialIndex; + +} + + +Recursive.prototype.reset = function() +{ + this.oldIDs =[]; + this.nextIndex = this.initialIndex; +} + + + + +Recursive.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +Recursive.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +Recursive.prototype.deleteActivation = function(activationRec) +{ + var i; + for (i = 0; i < activationRec.labelIDs.length; i++) + { + this.cmd("Delete", activationRec.labelIDs[i]); + this.cmd("Delete", activationRec.fieldIDs[i]); + } + this.cmd("Delete", activationRec.separatingLineID); + this.cmd("Delete", activationRec.nameID); +} + + +Recursive.prototype.createActivation = function(functionName, argList, x, y, labelsOnLeft) +{ + var activationRec = new ActivationRecord(argList); + var i; + activationRec.nameID = this.nextIndex++; + labelsOnLeft = (labelsOnLeft == undefined) ? true : labelsOnLeft; + for (i = 0; i < argList.length; i++) + { + var valueID = this.nextIndex++; + activationRec.fieldIDs[i] = valueID; + + this.cmd("CreateRectangle", valueID, + "", + Recursive.ACTIVATION_RECORD_WIDTH, + Recursive.ACTIVATION_RECORD_HEIGHT, + x, + y + i * Recursive.ACTIVATION_RECORD_HEIGHT); + + var labelID = this.nextIndex++; + activationRec.labelIDs[i] = labelID; + this.cmd("CreateLabel", labelID, argList[i]); + if (labelsOnLeft) + this.cmd("AlignLeft", labelID, valueID); + else + this.cmd("AlignRight", labelID, valueID); + } + activationRec.separatingLineID = this.nextIndex++; + this.cmd("CreateLabel", activationRec.nameID, " " + functionName + " "); + this.cmd("SetForegroundColor", activationRec.nameID, Recursive.SEPARATING_LINE_COLOR); + + if (labelsOnLeft) + { + this.cmd("CreateRectangle", activationRec.separatingLineID, + "", + Recursive.ACTIVATION_RECORD_WIDTH * 2, + 1, + x - Recursive.ACTIVATION_RECORD_WIDTH / 2, + y - Recursive.ACTIVATION_RECORD_HEIGHT / 2); + this.cmd("AlignLeft", activationRec.nameID, activationRec.labelIDs[0]); + } + else + { + this.cmd("CreateRectangle", activationRec.separatingLineID, + "", + Recursive.ACTIVATION_RECORD_WIDTH * 2, + 1, + x + Recursive.ACTIVATION_RECORD_WIDTH / 2, + y - Recursive.ACTIVATION_RECORD_HEIGHT / 2); + this.cmd("AlignRight", activationRec.nameID, activationRec.labelIDs[0]); + + } + this.cmd("SetForegroundColor", activationRec.separatingLineID, Recursive.SEPARATING_LINE_COLOR); + return activationRec; + +} + + + +function ActivationRecord(fields) +{ + this.fields = fields; + this.values = new Array(this.fields.length); + var i; + for (i = 0; i < this.fields.length; i++) + { + this.values[i] = ""; + } + this.fieldIDs = new Array(this.fields.length); + this.labelIDs = new Array(this.fields.length); +} + + + diff --git a/AlgorithmLibrary/RotateScale2D.js b/AlgorithmLibrary/RotateScale2D.js index 0ed54b0..651466c 100644 --- a/AlgorithmLibrary/RotateScale2D.js +++ b/AlgorithmLibrary/RotateScale2D.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/RotateScale3D.js b/AlgorithmLibrary/RotateScale3D.js index 60ee1fe..d76c3aa 100644 --- a/AlgorithmLibrary/RotateScale3D.js +++ b/AlgorithmLibrary/RotateScale3D.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, areobjectVertexLocalPosition // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/RotateTranslate2D.js b/AlgorithmLibrary/RotateTranslate2D.js index c35773f..0a35a9c 100644 --- a/AlgorithmLibrary/RotateTranslate2D.js +++ b/AlgorithmLibrary/RotateTranslate2D.js @@ -1,4 +1,4 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: diff --git a/AlgorithmLibrary/Search.js b/AlgorithmLibrary/Search.js index 2925e0d..9097df0 100644 --- a/AlgorithmLibrary/Search.js +++ b/AlgorithmLibrary/Search.js @@ -1,732 +1,732 @@ -// Copyright 2015 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -Search.CODE_START_X = 10; -Search.CODE_START_Y = 10; -Search.CODE_LINE_HEIGHT = 14; - - -Search.CODE_HIGHLIGHT_COLOR = "#FF0000"; -Search.CODE_STANDARD_COLOR = "#000000"; - -var SMALL_SIZE = 0; -var LARGE_SIZE = 1; - -var EXTRA_FIELD_WIDTH = 50; -var EXTRA_FIELD_HEIGHT = 50; - -var SEARCH_FOR_X = 450; -var SEARCH_FOR_Y = 30; - - -var RESULT_X = 550; -var RESULT_Y = 30; - - -var INDEX_X = 450; -var INDEX_Y = 130; - - -var HIGHLIGHT_CIRCLE_SIZE_SMALL = 20; -var HIGHLIGHT_CIRCLE_SIZE_LARGE = 10; -var HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; - - -var LOW_CIRCLE_COLOR = "#1010FF"; -var LOW_BACKGROUND_COLOR = "#F0F0FF"; -var MID_CIRCLE_COLOR = "#118C4E"; -var MID_BACKGROUND_COLOR = "#F0FFF0"; -var HIGH_CIRCLE_COLOR = "#FF9009"; -var HIGH_BACKGROUND_COLOR = "#FFFFF0"; - -var LOW_POS_X = 350; -var LOW_POS_Y = 130; - - -var MID_POS_X = 450; -var MID_POS_Y = 130; - -var HIGH_POS_X = 550; -var HIGH_POS_Y = 130; - - - -var ARRAY_START_X_SMALL = 100; -var ARRAY_START_X_LARGE = 100; -var ARRAY_START_X = ARRAY_START_X_SMALL; -var ARRAY_START_Y_SMALL = 240; -var ARRAY_START_Y_LARGE = 200; -var ARRAY_START_Y = ARRAY_START_Y_SMALL; -var ARRAY_ELEM_WIDTH_SMALL = 50; -var ARRAY_ELEM_WIDTH_LARGE = 25; -var ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; - -var ARRAY_ELEM_HEIGHT_SMALL = 50; -var ARRAY_ELEM_HEIGHT_LARGE = 20; -var ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; - -var ARRAY_ELEMS_PER_LINE_SMALL = 16; -var ARRAY_ELEMS_PER_LINE_LARGE = 30; -var ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; - - -var ARRAY_LINE_SPACING_LARGE = 40; -var ARRAY_LINE_SPACING_SMALL = 130; -var ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; - -var SIZE_SMALL = 32; -var SIZE_LARGE = 180; -var SIZE = SIZE_SMALL; - -function Search(am, w, h) -{ - this.init(am, w, h); - -} - -Search.inheritFrom(Algorithm); - - -Search.LINEAR_CODE = [ ["def ", "linearSearch(listData, value)"], - [" index = 0"], - [" while (","index < len(listData)", " and ", "listData[index] < value","):"], - [" index++;"], - [" if (", "index >= len(listData", " or ", "listData[index] != value", "):"], - [" return -1"], - [" return index"]]; -Search.BINARY_CODE = [ ["def ", "binarySearch(listData, value)"], - [" low = 0"], - [" high = len(listData) - 1"], - [" while (","low <= high",")"], - [" mid = (low + high) / 2"] , - [" if (","listData[mid] == value","):"], - [" return mid"], - [" elif (","listData[mid] < value",")"], - [" low = mid + 1"], - [" else:"], - [" high = mid - 1"], - [" return -1"]] - - - -Search.prototype.init = function(am, w, h) -{ - Search.superclass.init.call(this, am, w, h); - this.addControls(); - this.nextIndex = 0; - this.commands = []; - this.setup(); - this.initialIndex = this.nextIndex; -} - - -Search.prototype.addControls = function() -{ - this.controls = []; - this.searchField = this.addControlToAlgorithmBar("Text", ""); - this.searchField.onkeydown = this.returnSubmit(this.searchField, null, 6, true); - this.linearSearchButton = this.addControlToAlgorithmBar("Button", "Linear Search"); - this.linearSearchButton.onclick = this.linearSearchCallback.bind(this); - this.controls.push(this.searchField); - this.controls.push(this.linearSearchButton); - - - this.binarySearchButton = this.addControlToAlgorithmBar("Button", "Binary Search"); - this.binarySearchButton.onclick = this.binarySearchCallback.bind(this); - this.controls.push(this.binarySearchButton); - - - var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small", "Large"], "List Size"); - this.smallListButton = radioButtonList[0]; - this.smallListButton.onclick = this.smallListCallback.bind(this); - this.largeListButton = radioButtonList[1]; - this.largeListButton.onclick = this.largeListCallback.bind(this); - this.smallListButton.checked = true; - -} - - - -Search.prototype.smallListCallback = function (event) -{ - if (this.size != SMALL_SIZE) - { - this.animationManager.resetAll(); - this.setup_small(); - } -} - - -Search.prototype.largeListCallback = function (event) -{ - if (this.size != LARGE_SIZE) - { - this.animationManager.resetAll(); - this.setup_large(); - } -} - - - -Search.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -Search.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -Search.prototype.getIndexX = function(index) { - var xpos = (index % ARRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - return xpos; -} - - -Search.prototype.getIndexY = function(index) { - if (index == -1) { - index = 0; - } - var ypos = Math.floor(index / ARRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y + ARRAY_ELEM_HEIGHT; - return ypos; -} - -Search.prototype.setup = function() -{ - this.nextIndex = 0; - - this.values = new Array(SIZE); - this.arrayData = new Array(SIZE); - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - this.arrayData[i] = Math.floor(1+Math.random()*999); - this.arrayID[i]= this.nextIndex++; - this.arrayLabelID[i]= this.nextIndex++; - } - - for (var i = 1; i < SIZE; i++) { - var nxt = this.arrayData[i]; - var j = i - while (j > 0 && this.arrayData[j-1] > nxt) { - this.arrayData[j] = this.arrayData[j-1]; - j = j - 1; - } - this.arrayData[j] = nxt; - } - - this.leftoverLabelID = this.nextIndex++; - this.commands = new Array(); - - - for (var i = 0; i < SIZE; i++) - { - var xLabelpos = this.getIndexX(i); - var yLabelpos = this.getIndexY(i); - this.cmd("CreateRectangle", this.arrayID[i],this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xLabelpos, yLabelpos - ARRAY_ELEM_HEIGHT); - this.cmd("CreateLabel",this.arrayLabelID[i], i, xLabelpos, yLabelpos); - this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); - - } - - this.movingLabelID = this.nextIndex++; - this.cmd("CreateLabel",this.movingLabelID, "", 0, 0); - - // this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); - - - this.searchForBoxID = this.nextIndex++; - this.searchForBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.searchForBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,SEARCH_FOR_X, SEARCH_FOR_Y); - this.cmd("CreateLabel", this.searchForBoxLabel, "Seaching For ", SEARCH_FOR_X, SEARCH_FOR_Y); - this.cmd("AlignLeft", this.searchForBoxLabel, this.searchForBoxID); - - this.resultBoxID = this.nextIndex++; - this.resultBoxLabel = this.nextIndex++; - this.resultString = this.nextIndex++; - this.cmd("CreateRectangle", this.resultBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,RESULT_X, RESULT_Y); - this.cmd("CreateLabel", this.resultBoxLabel, "Result ", RESULT_X, RESULT_Y); - this.cmd("CreateLabel", this.resultString, "", RESULT_X, RESULT_Y); - this.cmd("AlignLeft", this.resultBoxLabel, this.resultBoxID); - this.cmd("AlignRight", this.resultString, this.resultBoxID); - this.cmd("SetTextColor", this.resultString, "#FF0000"); - - - - this.indexBoxID = this.nextIndex++; - this.indexBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.indexBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,INDEX_X, INDEX_Y); - this.cmd("CreateLabel", this.indexBoxLabel, "index ", INDEX_X, INDEX_Y); - this.cmd("AlignLeft", this.indexBoxLabel, this.indexBoxID); - - - - this.midBoxID = this.nextIndex++; - this.midBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.midBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,MID_POS_X, MID_POS_Y); - this.cmd("CreateLabel", this.midBoxLabel, "mid ", MID_POS_X, MID_POS_Y); - this.cmd("AlignLeft", this.midBoxLabel, this.midBoxID); - this.cmd("SetForegroundColor", this.midBoxID, MID_CIRCLE_COLOR); - this.cmd("SetTextColor", this.midBoxID, MID_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.midBoxID, MID_BACKGROUND_COLOR); - - this.midCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.midCircleID, MID_CIRCLE_COLOR, 0, 0, HIGHLIGHT_CIRCLE_SIZE); - - - this.lowBoxID = this.nextIndex++; - this.lowBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.lowBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,LOW_POS_X, LOW_POS_Y); - this.cmd("CreateLabel", this.lowBoxLabel, "low ", LOW_POS_X, LOW_POS_Y); - this.cmd("AlignLeft", this.lowBoxLabel, this.lowBoxID); - this.cmd("SetForegroundColor", this.lowBoxID, LOW_CIRCLE_COLOR); - this.cmd("SetTextColor", this.lowBoxID, LOW_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.lowBoxID, LOW_BACKGROUND_COLOR); - - this.lowCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.lowCircleID, LOW_CIRCLE_COLOR, 0,0,HIGHLIGHT_CIRCLE_SIZE); - - - - this.highBoxID = this.nextIndex++; - this.highBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.highBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,HIGH_POS_X, HIGH_POS_Y); - this.cmd("CreateLabel", this.highBoxLabel, "high ", HIGH_POS_X, HIGH_POS_Y); - this.cmd("AlignLeft", this.highBoxLabel, this.highBoxID); - this.cmd("SetForegroundColor", this.highBoxID, HIGH_CIRCLE_COLOR); - this.cmd("SetTextColor", this.highBoxID, HIGH_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.highBoxID, HIGH_BACKGROUND_COLOR); - - - this.highCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.highCircleID, HIGH_CIRCLE_COLOR, 0 , 0, HIGHLIGHT_CIRCLE_SIZE); - - - this.cmd("SetALpha", this.lowBoxID, 0); - this.cmd("SetALpha", this.lowBoxLabel, 0); - this.cmd("SetALpha", this.midBoxID, 0); - this.cmd("SetALpha", this.midBoxLabel, 0); - this.cmd("SetALpha", this.highBoxID, 0); - this.cmd("SetALpha", this.highBoxLabel, 0); - - this.cmd("SetALpha", this.midCircleID, 0); - this.cmd("SetALpha", this.lowCircleID, 0); - this.cmd("SetALpha", this.highCircleID, 0); - - this.cmd("SetALpha", this.indexBoxID, 0); - this.cmd("SetALpha", this.indexBoxLabel, 0); - - this.highlight1ID = this.nextIndex++; - this.highlight2ID = this.nextIndex++; - - this.binaryCodeID = this.addCodeToCanvasBase(Search.BINARY_CODE, Search.CODE_START_X, Search.CODE_START_Y, Search.CODE_LINE_HEIGHT, Search.CODE_STANDARD_COLOR); - - this.linearCodeID = this.addCodeToCanvasBase(Search.LINEAR_CODE, Search.CODE_START_X, Search.CODE_START_Y, Search.CODE_LINE_HEIGHT, Search.CODE_STANDARD_COLOR); - - this.setCodeAlpha(this.binaryCodeID, 0); - this.setCodeAlpha(this.linearCodeID, 0); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); -} - -Search.prototype.setup_small = function() { - - HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; - ARRAY_START_X = ARRAY_START_X_SMALL; - ARRAY_START_Y = ARRAY_START_Y_SMALL; - ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; - ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; - ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; - ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; - SIZE = SIZE_SMALL; - this.size = SMALL_SIZE; - this.setup(); - -} - - -Search.prototype.setup_large = function() { - - HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_LARGE; - ARRAY_START_X = ARRAY_START_X_LARGE; - ARRAY_START_Y = ARRAY_START_Y_LARGE; - ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_LARGE; - ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_LARGE; - ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_LARGE; - ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_LARGE; - SIZE = SIZE_LARGE; - this.size = LARGE_SIZE; - this.setup() - -} - - - - -Search.prototype.linearSearchCallback = function(event) -{ - var searchVal = this.searchField.value; - this.implementAction(this.linearSearch.bind(this), searchVal); -} - - -Search.prototype.binarySearchCallback = function(event) -{ - - var searchVal = this.searchField.value; - this.implementAction(this.binarySearch.bind(this), searchVal); - -} - - - -Search.prototype.binarySearch = function(searchVal) -{ - this.commands = new Array(); - this.setCodeAlpha(this.binaryCodeID, 1); - this.setCodeAlpha(this.linearCodeID, 0); - - this.cmd("SetALpha", this.lowBoxID, 1); - this.cmd("SetALpha", this.lowBoxLabel, 1); - this.cmd("SetALpha", this.midBoxID, 1); - this.cmd("SetALpha", this.midBoxLabel, 1); - this.cmd("SetALpha", this.highBoxID, 1); - this.cmd("SetALpha", this.highBoxLabel, 1); - - this.cmd("SetAlpha", this.lowCircleID, 1); - this.cmd("SetAlpha", this.midCircleID, 1); - this.cmd("SetAlpha", this.highCircleID, 1); - this.cmd("SetPosition", this.lowCircleID, LOW_POS_X, LOW_POS_Y); - this.cmd("SetPosition", this.midCircleID, MID_POS_X, MID_POS_Y); - this.cmd("SetPosition", this.highCircleID, HIGH_POS_X, HIGH_POS_Y); - this.cmd("SetAlpha", this.indexBoxID, 0); - this.cmd("SetAlpha", this.indexBoxLabel, 0); - - this.cmd("SetText", this.resultString, ""); - this.cmd("SetText", this.resultBoxID, ""); - this.cmd("SetText", this.movingLabelID, ""); - - - var low = 0; - var high = SIZE- 1; - this.cmd("Move", this.lowCircleID, this.getIndexX(0), this.getIndexY(0)); - this.cmd("SetText", this.searchForBoxID, searchVal); - this.cmd("SetForegroundColor", this.binaryCodeID[1][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.lowBoxID, 1) - this.cmd("SetText", this.lowBoxID, 0) - this.cmd("step"); - this.cmd("SetForegroundColor", this.binaryCodeID[1][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.lowBoxID, 0) - this.cmd("SetForegroundColor", this.binaryCodeID[2][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.highBoxID, 1) - this.cmd("SetText", this.highBoxID, SIZE-1) - this.cmd("Move", this.highCircleID, this.getIndexX(SIZE-1), this.getIndexY(SIZE-1)); - this.cmd("step"); - this.cmd("SetForegroundColor", this.binaryCodeID[2][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.highBoxID, 0) - var keepGoing = true; - - while (keepGoing) { - this.cmd("SetHighlight", this.highBoxID, 1) - this.cmd("SetHighlight", this.lowBoxID, 1) - this.cmd("SetForegroundColor", this.binaryCodeID[3][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("step"); - this.cmd("SetHighlight", this.highBoxID, 0) - this.cmd("SetHighlight", this.lowBoxID, 0) - this.cmd("SetForegroundColor", this.binaryCodeID[3][1], Search.CODE_STANDARD_COLOR); - if (low > high) - { - keepGoing = false; - } else { - var mid = Math.floor((high + low) / 2); - this.cmd("SetForegroundColor", this.binaryCodeID[4][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.highBoxID, 1) - this.cmd("SetHighlight", this.lowBoxID, 1) - this.cmd("SetHighlight", this.midBoxID, 1) - this.cmd("SetText", this.midBoxID, mid) - this.cmd("Move", this.midCircleID, this.getIndexX(mid), this.getIndexY(mid)); - - this.cmd("step"); - this.cmd("SetForegroundColor", this.binaryCodeID[4][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.midBoxID, 0) - this.cmd("SetHighlight", this.highBoxID, 0) - this.cmd("SetHighlight", this.lowBoxID, 0) - this.cmd("SetHighlight", this.searchForBoxID, 1) - this.cmd("SetHighlight", this.arrayID[mid],1); - this.cmd("SetForegroundColor", this.binaryCodeID[5][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("step"); - this.cmd("SetHighlight", this.searchForBoxID, 0) - this.cmd("SetHighlight", this.arrayID[mid],0); - this.cmd("SetForegroundColor", this.binaryCodeID[5][1], Search.CODE_STANDARD_COLOR); - if (this.arrayData[mid] == searchVal) { -// HIGHLIGHT CODE! - keepGoing = false; - - } - else { - - this.cmd("SetForegroundColor", this.binaryCodeID[7][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.searchForBoxID, 1) - this.cmd("SetHighlight", this.arrayID[mid],1); - this.cmd("step") - this.cmd("SetForegroundColor", this.binaryCodeID[7][1], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.searchForBoxID, 0) - this.cmd("SetHighlight", this.arrayID[mid],0); - if (this.arrayData[mid] < searchVal) { - this.cmd("SetForegroundColor", this.binaryCodeID[8][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.lowID,1); - this.cmd("SetText", this.lowBoxID,mid+1); - this.cmd("Move", this.lowCircleID, this.getIndexX(mid+1), this.getIndexY(mid+1)); - - low = mid + 1; - for (var i = 0; i < low; i++) { - this.cmd("SetAlpha", this.arrayID[i],0.2); - } - this.cmd("Step"); - this.cmd("SetForegroundColor", this.binaryCodeID[8][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.lowBoxID,0); - } else { - this.cmd("SetForegroundColor", this.binaryCodeID[10][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.highBoxID,1); - high = mid - 1; - this.cmd("SetText", this.highBoxID,high); - this.cmd("Move", this.highCircleID, this.getIndexX(high), this.getIndexY(high)); - - for (var i = high + 1; i < SIZE; i++) { - this.cmd("SetAlpha", this.arrayID[i],0.2); - } - this.cmd("Step"); - - this.cmd("SetForegroundColor", this.binaryCodeID[10][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.midBoxID,0); - - - } - } - - } - - } - if (high < low) { - this.cmd("SetText", this.resultString, " Element Not found"); - this.cmd("SetText", this.resultBoxID, -1); - this.cmd("AlignRight", this.resultString, this.resultBoxID); - this.cmd("SetForegroundColor", this.binaryCodeID[11][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetForegroundColor", this.binaryCodeID[11][0], Search.CODE_STANDARD_COLOR); - - } else { - this.cmd("SetText", this.resultString, " Element found"); - this.cmd("SetText", this.movingLabelID, mid); - this.cmd("SetPosition", this.movingLabelID, this.getIndexX(mid), this.getIndexY(mid)); - - this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); - - this.cmd("AlignRight", this.resultString, this.resultBoxID); - this.cmd("SetForegroundColor", this.binaryCodeID[6][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetForegroundColor", this.binaryCodeID[6][0], Search.CODE_STANDARD_COLOR); - - } - - for (var i = 0; i < SIZE; i++) { - this.cmd("SetAlpha", this.arrayID[i],1); - } - return this.commands; - - - - -} - - -Search.prototype.linearSearch = function(searchVal) -{ - this.commands = new Array(); - this.setCodeAlpha(this.binaryCodeID, 0); - this.setCodeAlpha(this.linearCodeID, 1); - - this.cmd("SetALpha", this.lowBoxID, 0); - this.cmd("SetALpha", this.lowBoxLabel, 0); - this.cmd("SetALpha", this.midBoxID, 0); - this.cmd("SetALpha", this.midBoxLabel, 0); - this.cmd("SetALpha", this.highBoxID, 0); - this.cmd("SetALpha", this.highBoxLabel, 0); - - - this.cmd("SetAlpha", this.lowCircleID, 1); - this.cmd("SetAlpha", this.midCircleID, 0); - this.cmd("SetAlpha", this.highCircleID, 0); - - this.cmd("SetPosition", this.lowCircleID, INDEX_X, INDEX_Y); - - this.cmd("SetALpha", this.indexBoxID, 1); - this.cmd("SetALpha", this.indexBoxLabel, 1); - - this.cmd("SetText", this.resultString, ""); - this.cmd("SetText", this.resultBoxID, ""); - this.cmd("SetText", this.movingLabelID, ""); - - - - var goOn = true; - var nextSearch = 0; - this.cmd("SetText", this.searchForBoxID, searchVal); - this.cmd("SetForegroundColor", this.linearCodeID[1][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.indexBoxID,1); - this.cmd("SetText", this.indexBoxID, "0"); - this.cmd("Move", this.lowCircleID, this.getIndexX(0), this.getIndexY(0)); - - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[1][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.indexBoxID,0); - - - var foundIndex = 0 - while (goOn) { - if (foundIndex == SIZE) { - this.cmd("SetForegroundColor", this.linearCodeID[2][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[2][1], Search.CODE_STANDARD_COLOR); - goOn = false; - - } else { - this.cmd("SetHighlight", this.arrayID[foundIndex],1); - this.cmd("SetHighlight", this.searchForBoxID,1); - this.cmd("SetForegroundColor", this.linearCodeID[2][3], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step") - this.cmd("SetForegroundColor", this.linearCodeID[2][3], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.arrayID[foundIndex],0); - this.cmd("SetHighlight", this.searchForBoxID,0); - goOn = this.arrayData[foundIndex] < searchVal - if (goOn) - { - foundIndex++; - - this.cmd("SetForegroundColor", this.linearCodeID[3][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.indexBoxID,1); - this.cmd("SetText", this.indexBoxID, foundIndex); - this.cmd("Move", this.lowCircleID, this.getIndexX(foundIndex), this.getIndexY(foundIndex)); - - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[3][0], Search.CODE_STANDARD_COLOR); - this.cmd("SetHighlight", this.indexBoxID,0); - } - } - } - if (foundIndex ==SIZE) - { - this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_STANDARD_COLOR); - - - } - - else if (this.arrayData[foundIndex] == searchVal) - { - this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[4][2], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetHighlight", this.arrayID[foundIndex],1); - this.cmd("SetHighlight", this.searchForBoxID,1); - this.cmd("Step"); - - this.cmd("SetHighlight", this.arrayID[foundIndex],0); - this.cmd("SetHighlight", this.searchForBoxID,0); - - - - this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[4][2], Search.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[6][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", this.resultString, " Element found"); - this.cmd("SetText", this.movingLabelID, foundIndex); - this.cmd("SetPosition", this.movingLabelID, this.getIndexX(foundIndex), this.getIndexY(foundIndex)); - - this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); - - this.cmd("AlignRight", this.resultString, this.resultBoxID); - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[6][0], Search.CODE_STANDARD_COLOR); - - - - } - else - { - this.cmd("SetHighlight", this.arrayID[foundIndex],1); - this.cmd("SetHighlight", this.searchForBoxID,1); - this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("Step"); - this.cmd("SetHighlight", this.arrayID[foundIndex],0); - this.cmd("SetHighlight", this.searchForBoxID,0); - this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_STANDARD_COLOR); - this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_HIGHLIGHT_COLOR); - this.cmd("SetText", this.resultString, " Element Not found"); - this.cmd("SetText", this.resultBoxID, -1); - this.cmd("AlignRight", this.resultString, this.resultBoxID); - - this.cmd("Step"); - this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_STANDARD_COLOR); - - - - } - return this.commands; - - -} - - - - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new Search(animManag, canvas.width, canvas.height); -} +// Copyright 2015 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +Search.CODE_START_X = 10; +Search.CODE_START_Y = 10; +Search.CODE_LINE_HEIGHT = 14; + + +Search.CODE_HIGHLIGHT_COLOR = "#FF0000"; +Search.CODE_STANDARD_COLOR = "#000000"; + +var SMALL_SIZE = 0; +var LARGE_SIZE = 1; + +var EXTRA_FIELD_WIDTH = 50; +var EXTRA_FIELD_HEIGHT = 50; + +var SEARCH_FOR_X = 450; +var SEARCH_FOR_Y = 30; + + +var RESULT_X = 550; +var RESULT_Y = 30; + + +var INDEX_X = 450; +var INDEX_Y = 130; + + +var HIGHLIGHT_CIRCLE_SIZE_SMALL = 20; +var HIGHLIGHT_CIRCLE_SIZE_LARGE = 10; +var HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; + + +var LOW_CIRCLE_COLOR = "#1010FF"; +var LOW_BACKGROUND_COLOR = "#F0F0FF"; +var MID_CIRCLE_COLOR = "#118C4E"; +var MID_BACKGROUND_COLOR = "#F0FFF0"; +var HIGH_CIRCLE_COLOR = "#FF9009"; +var HIGH_BACKGROUND_COLOR = "#FFFFF0"; + +var LOW_POS_X = 350; +var LOW_POS_Y = 130; + + +var MID_POS_X = 450; +var MID_POS_Y = 130; + +var HIGH_POS_X = 550; +var HIGH_POS_Y = 130; + + + +var ARRAY_START_X_SMALL = 100; +var ARRAY_START_X_LARGE = 100; +var ARRAY_START_X = ARRAY_START_X_SMALL; +var ARRAY_START_Y_SMALL = 240; +var ARRAY_START_Y_LARGE = 200; +var ARRAY_START_Y = ARRAY_START_Y_SMALL; +var ARRAY_ELEM_WIDTH_SMALL = 50; +var ARRAY_ELEM_WIDTH_LARGE = 25; +var ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; + +var ARRAY_ELEM_HEIGHT_SMALL = 50; +var ARRAY_ELEM_HEIGHT_LARGE = 20; +var ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; + +var ARRAY_ELEMS_PER_LINE_SMALL = 16; +var ARRAY_ELEMS_PER_LINE_LARGE = 30; +var ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; + + +var ARRAY_LINE_SPACING_LARGE = 40; +var ARRAY_LINE_SPACING_SMALL = 130; +var ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; + +var SIZE_SMALL = 32; +var SIZE_LARGE = 180; +var SIZE = SIZE_SMALL; + +function Search(am, w, h) +{ + this.init(am, w, h); + +} + +Search.inheritFrom(Algorithm); + + +Search.LINEAR_CODE = [ ["def ", "linearSearch(listData, value)"], + [" index = 0"], + [" while (","index < len(listData)", " and ", "listData[index] < value","):"], + [" index++;"], + [" if (", "index >= len(listData", " or ", "listData[index] != value", "):"], + [" return -1"], + [" return index"]]; +Search.BINARY_CODE = [ ["def ", "binarySearch(listData, value)"], + [" low = 0"], + [" high = len(listData) - 1"], + [" while (","low <= high",")"], + [" mid = (low + high) / 2"] , + [" if (","listData[mid] == value","):"], + [" return mid"], + [" elif (","listData[mid] < value",")"], + [" low = mid + 1"], + [" else:"], + [" high = mid - 1"], + [" return -1"]] + + + +Search.prototype.init = function(am, w, h) +{ + Search.superclass.init.call(this, am, w, h); + this.addControls(); + this.nextIndex = 0; + this.commands = []; + this.setup(); + this.initialIndex = this.nextIndex; +} + + +Search.prototype.addControls = function() +{ + this.controls = []; + this.searchField = this.addControlToAlgorithmBar("Text", ""); + this.searchField.onkeydown = this.returnSubmit(this.searchField, null, 6, true); + this.linearSearchButton = this.addControlToAlgorithmBar("Button", "Linear Search"); + this.linearSearchButton.onclick = this.linearSearchCallback.bind(this); + this.controls.push(this.searchField); + this.controls.push(this.linearSearchButton); + + + this.binarySearchButton = this.addControlToAlgorithmBar("Button", "Binary Search"); + this.binarySearchButton.onclick = this.binarySearchCallback.bind(this); + this.controls.push(this.binarySearchButton); + + + var radioButtonList = this.addRadioButtonGroupToAlgorithmBar(["Small", "Large"], "List Size"); + this.smallListButton = radioButtonList[0]; + this.smallListButton.onclick = this.smallListCallback.bind(this); + this.largeListButton = radioButtonList[1]; + this.largeListButton.onclick = this.largeListCallback.bind(this); + this.smallListButton.checked = true; + +} + + + +Search.prototype.smallListCallback = function (event) +{ + if (this.size != SMALL_SIZE) + { + this.animationManager.resetAll(); + this.setup_small(); + } +} + + +Search.prototype.largeListCallback = function (event) +{ + if (this.size != LARGE_SIZE) + { + this.animationManager.resetAll(); + this.setup_large(); + } +} + + + +Search.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +Search.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +Search.prototype.getIndexX = function(index) { + var xpos = (index % ARRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + return xpos; +} + + +Search.prototype.getIndexY = function(index) { + if (index == -1) { + index = 0; + } + var ypos = Math.floor(index / ARRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y + ARRAY_ELEM_HEIGHT; + return ypos; +} + +Search.prototype.setup = function() +{ + this.nextIndex = 0; + + this.values = new Array(SIZE); + this.arrayData = new Array(SIZE); + this.arrayID = new Array(SIZE); + this.arrayLabelID = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + this.arrayData[i] = Math.floor(1+Math.random()*999); + this.arrayID[i]= this.nextIndex++; + this.arrayLabelID[i]= this.nextIndex++; + } + + for (var i = 1; i < SIZE; i++) { + var nxt = this.arrayData[i]; + var j = i + while (j > 0 && this.arrayData[j-1] > nxt) { + this.arrayData[j] = this.arrayData[j-1]; + j = j - 1; + } + this.arrayData[j] = nxt; + } + + this.leftoverLabelID = this.nextIndex++; + this.commands = new Array(); + + + for (var i = 0; i < SIZE; i++) + { + var xLabelpos = this.getIndexX(i); + var yLabelpos = this.getIndexY(i); + this.cmd("CreateRectangle", this.arrayID[i],this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xLabelpos, yLabelpos - ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",this.arrayLabelID[i], i, xLabelpos, yLabelpos); + this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); + + } + + this.movingLabelID = this.nextIndex++; + this.cmd("CreateLabel",this.movingLabelID, "", 0, 0); + + // this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + + + this.searchForBoxID = this.nextIndex++; + this.searchForBoxLabel = this.nextIndex++; + this.cmd("CreateRectangle", this.searchForBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,SEARCH_FOR_X, SEARCH_FOR_Y); + this.cmd("CreateLabel", this.searchForBoxLabel, "Seaching For ", SEARCH_FOR_X, SEARCH_FOR_Y); + this.cmd("AlignLeft", this.searchForBoxLabel, this.searchForBoxID); + + this.resultBoxID = this.nextIndex++; + this.resultBoxLabel = this.nextIndex++; + this.resultString = this.nextIndex++; + this.cmd("CreateRectangle", this.resultBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,RESULT_X, RESULT_Y); + this.cmd("CreateLabel", this.resultBoxLabel, "Result ", RESULT_X, RESULT_Y); + this.cmd("CreateLabel", this.resultString, "", RESULT_X, RESULT_Y); + this.cmd("AlignLeft", this.resultBoxLabel, this.resultBoxID); + this.cmd("AlignRight", this.resultString, this.resultBoxID); + this.cmd("SetTextColor", this.resultString, "#FF0000"); + + + + this.indexBoxID = this.nextIndex++; + this.indexBoxLabel = this.nextIndex++; + this.cmd("CreateRectangle", this.indexBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,INDEX_X, INDEX_Y); + this.cmd("CreateLabel", this.indexBoxLabel, "index ", INDEX_X, INDEX_Y); + this.cmd("AlignLeft", this.indexBoxLabel, this.indexBoxID); + + + + this.midBoxID = this.nextIndex++; + this.midBoxLabel = this.nextIndex++; + this.cmd("CreateRectangle", this.midBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,MID_POS_X, MID_POS_Y); + this.cmd("CreateLabel", this.midBoxLabel, "mid ", MID_POS_X, MID_POS_Y); + this.cmd("AlignLeft", this.midBoxLabel, this.midBoxID); + this.cmd("SetForegroundColor", this.midBoxID, MID_CIRCLE_COLOR); + this.cmd("SetTextColor", this.midBoxID, MID_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.midBoxID, MID_BACKGROUND_COLOR); + + this.midCircleID = this.nextIndex++; + this.cmd("CreateHighlightCircle", this.midCircleID, MID_CIRCLE_COLOR, 0, 0, HIGHLIGHT_CIRCLE_SIZE); + + + this.lowBoxID = this.nextIndex++; + this.lowBoxLabel = this.nextIndex++; + this.cmd("CreateRectangle", this.lowBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,LOW_POS_X, LOW_POS_Y); + this.cmd("CreateLabel", this.lowBoxLabel, "low ", LOW_POS_X, LOW_POS_Y); + this.cmd("AlignLeft", this.lowBoxLabel, this.lowBoxID); + this.cmd("SetForegroundColor", this.lowBoxID, LOW_CIRCLE_COLOR); + this.cmd("SetTextColor", this.lowBoxID, LOW_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.lowBoxID, LOW_BACKGROUND_COLOR); + + this.lowCircleID = this.nextIndex++; + this.cmd("CreateHighlightCircle", this.lowCircleID, LOW_CIRCLE_COLOR, 0,0,HIGHLIGHT_CIRCLE_SIZE); + + + + this.highBoxID = this.nextIndex++; + this.highBoxLabel = this.nextIndex++; + this.cmd("CreateRectangle", this.highBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,HIGH_POS_X, HIGH_POS_Y); + this.cmd("CreateLabel", this.highBoxLabel, "high ", HIGH_POS_X, HIGH_POS_Y); + this.cmd("AlignLeft", this.highBoxLabel, this.highBoxID); + this.cmd("SetForegroundColor", this.highBoxID, HIGH_CIRCLE_COLOR); + this.cmd("SetTextColor", this.highBoxID, HIGH_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.highBoxID, HIGH_BACKGROUND_COLOR); + + + this.highCircleID = this.nextIndex++; + this.cmd("CreateHighlightCircle", this.highCircleID, HIGH_CIRCLE_COLOR, 0 , 0, HIGHLIGHT_CIRCLE_SIZE); + + + this.cmd("SetALpha", this.lowBoxID, 0); + this.cmd("SetALpha", this.lowBoxLabel, 0); + this.cmd("SetALpha", this.midBoxID, 0); + this.cmd("SetALpha", this.midBoxLabel, 0); + this.cmd("SetALpha", this.highBoxID, 0); + this.cmd("SetALpha", this.highBoxLabel, 0); + + this.cmd("SetALpha", this.midCircleID, 0); + this.cmd("SetALpha", this.lowCircleID, 0); + this.cmd("SetALpha", this.highCircleID, 0); + + this.cmd("SetALpha", this.indexBoxID, 0); + this.cmd("SetALpha", this.indexBoxLabel, 0); + + this.highlight1ID = this.nextIndex++; + this.highlight2ID = this.nextIndex++; + + this.binaryCodeID = this.addCodeToCanvasBase(Search.BINARY_CODE, Search.CODE_START_X, Search.CODE_START_Y, Search.CODE_LINE_HEIGHT, Search.CODE_STANDARD_COLOR); + + this.linearCodeID = this.addCodeToCanvasBase(Search.LINEAR_CODE, Search.CODE_START_X, Search.CODE_START_Y, Search.CODE_LINE_HEIGHT, Search.CODE_STANDARD_COLOR); + + this.setCodeAlpha(this.binaryCodeID, 0); + this.setCodeAlpha(this.linearCodeID, 0); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); +} + +Search.prototype.setup_small = function() { + + HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; + ARRAY_START_X = ARRAY_START_X_SMALL; + ARRAY_START_Y = ARRAY_START_Y_SMALL; + ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; + ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; + ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; + ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; + SIZE = SIZE_SMALL; + this.size = SMALL_SIZE; + this.setup(); + +} + + +Search.prototype.setup_large = function() { + + HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_LARGE; + ARRAY_START_X = ARRAY_START_X_LARGE; + ARRAY_START_Y = ARRAY_START_Y_LARGE; + ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_LARGE; + ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_LARGE; + ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_LARGE; + ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_LARGE; + SIZE = SIZE_LARGE; + this.size = LARGE_SIZE; + this.setup() + +} + + + + +Search.prototype.linearSearchCallback = function(event) +{ + var searchVal = this.searchField.value; + this.implementAction(this.linearSearch.bind(this), searchVal); +} + + +Search.prototype.binarySearchCallback = function(event) +{ + + var searchVal = this.searchField.value; + this.implementAction(this.binarySearch.bind(this), searchVal); + +} + + + +Search.prototype.binarySearch = function(searchVal) +{ + this.commands = new Array(); + this.setCodeAlpha(this.binaryCodeID, 1); + this.setCodeAlpha(this.linearCodeID, 0); + + this.cmd("SetALpha", this.lowBoxID, 1); + this.cmd("SetALpha", this.lowBoxLabel, 1); + this.cmd("SetALpha", this.midBoxID, 1); + this.cmd("SetALpha", this.midBoxLabel, 1); + this.cmd("SetALpha", this.highBoxID, 1); + this.cmd("SetALpha", this.highBoxLabel, 1); + + this.cmd("SetAlpha", this.lowCircleID, 1); + this.cmd("SetAlpha", this.midCircleID, 1); + this.cmd("SetAlpha", this.highCircleID, 1); + this.cmd("SetPosition", this.lowCircleID, LOW_POS_X, LOW_POS_Y); + this.cmd("SetPosition", this.midCircleID, MID_POS_X, MID_POS_Y); + this.cmd("SetPosition", this.highCircleID, HIGH_POS_X, HIGH_POS_Y); + this.cmd("SetAlpha", this.indexBoxID, 0); + this.cmd("SetAlpha", this.indexBoxLabel, 0); + + this.cmd("SetText", this.resultString, ""); + this.cmd("SetText", this.resultBoxID, ""); + this.cmd("SetText", this.movingLabelID, ""); + + + var low = 0; + var high = SIZE- 1; + this.cmd("Move", this.lowCircleID, this.getIndexX(0), this.getIndexY(0)); + this.cmd("SetText", this.searchForBoxID, searchVal); + this.cmd("SetForegroundColor", this.binaryCodeID[1][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.lowBoxID, 1) + this.cmd("SetText", this.lowBoxID, 0) + this.cmd("step"); + this.cmd("SetForegroundColor", this.binaryCodeID[1][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.lowBoxID, 0) + this.cmd("SetForegroundColor", this.binaryCodeID[2][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.highBoxID, 1) + this.cmd("SetText", this.highBoxID, SIZE-1) + this.cmd("Move", this.highCircleID, this.getIndexX(SIZE-1), this.getIndexY(SIZE-1)); + this.cmd("step"); + this.cmd("SetForegroundColor", this.binaryCodeID[2][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.highBoxID, 0) + var keepGoing = true; + + while (keepGoing) { + this.cmd("SetHighlight", this.highBoxID, 1) + this.cmd("SetHighlight", this.lowBoxID, 1) + this.cmd("SetForegroundColor", this.binaryCodeID[3][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("step"); + this.cmd("SetHighlight", this.highBoxID, 0) + this.cmd("SetHighlight", this.lowBoxID, 0) + this.cmd("SetForegroundColor", this.binaryCodeID[3][1], Search.CODE_STANDARD_COLOR); + if (low > high) + { + keepGoing = false; + } else { + var mid = Math.floor((high + low) / 2); + this.cmd("SetForegroundColor", this.binaryCodeID[4][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.highBoxID, 1) + this.cmd("SetHighlight", this.lowBoxID, 1) + this.cmd("SetHighlight", this.midBoxID, 1) + this.cmd("SetText", this.midBoxID, mid) + this.cmd("Move", this.midCircleID, this.getIndexX(mid), this.getIndexY(mid)); + + this.cmd("step"); + this.cmd("SetForegroundColor", this.binaryCodeID[4][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.midBoxID, 0) + this.cmd("SetHighlight", this.highBoxID, 0) + this.cmd("SetHighlight", this.lowBoxID, 0) + this.cmd("SetHighlight", this.searchForBoxID, 1) + this.cmd("SetHighlight", this.arrayID[mid],1); + this.cmd("SetForegroundColor", this.binaryCodeID[5][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("step"); + this.cmd("SetHighlight", this.searchForBoxID, 0) + this.cmd("SetHighlight", this.arrayID[mid],0); + this.cmd("SetForegroundColor", this.binaryCodeID[5][1], Search.CODE_STANDARD_COLOR); + if (this.arrayData[mid] == searchVal) { +// HIGHLIGHT CODE! + keepGoing = false; + + } + else { + + this.cmd("SetForegroundColor", this.binaryCodeID[7][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.searchForBoxID, 1) + this.cmd("SetHighlight", this.arrayID[mid],1); + this.cmd("step") + this.cmd("SetForegroundColor", this.binaryCodeID[7][1], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.searchForBoxID, 0) + this.cmd("SetHighlight", this.arrayID[mid],0); + if (this.arrayData[mid] < searchVal) { + this.cmd("SetForegroundColor", this.binaryCodeID[8][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.lowID,1); + this.cmd("SetText", this.lowBoxID,mid+1); + this.cmd("Move", this.lowCircleID, this.getIndexX(mid+1), this.getIndexY(mid+1)); + + low = mid + 1; + for (var i = 0; i < low; i++) { + this.cmd("SetAlpha", this.arrayID[i],0.2); + } + this.cmd("Step"); + this.cmd("SetForegroundColor", this.binaryCodeID[8][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.lowBoxID,0); + } else { + this.cmd("SetForegroundColor", this.binaryCodeID[10][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.highBoxID,1); + high = mid - 1; + this.cmd("SetText", this.highBoxID,high); + this.cmd("Move", this.highCircleID, this.getIndexX(high), this.getIndexY(high)); + + for (var i = high + 1; i < SIZE; i++) { + this.cmd("SetAlpha", this.arrayID[i],0.2); + } + this.cmd("Step"); + + this.cmd("SetForegroundColor", this.binaryCodeID[10][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.midBoxID,0); + + + } + } + + } + + } + if (high < low) { + this.cmd("SetText", this.resultString, " Element Not found"); + this.cmd("SetText", this.resultBoxID, -1); + this.cmd("AlignRight", this.resultString, this.resultBoxID); + this.cmd("SetForegroundColor", this.binaryCodeID[11][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetForegroundColor", this.binaryCodeID[11][0], Search.CODE_STANDARD_COLOR); + + } else { + this.cmd("SetText", this.resultString, " Element found"); + this.cmd("SetText", this.movingLabelID, mid); + this.cmd("SetPosition", this.movingLabelID, this.getIndexX(mid), this.getIndexY(mid)); + + this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); + + this.cmd("AlignRight", this.resultString, this.resultBoxID); + this.cmd("SetForegroundColor", this.binaryCodeID[6][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetForegroundColor", this.binaryCodeID[6][0], Search.CODE_STANDARD_COLOR); + + } + + for (var i = 0; i < SIZE; i++) { + this.cmd("SetAlpha", this.arrayID[i],1); + } + return this.commands; + + + + +} + + +Search.prototype.linearSearch = function(searchVal) +{ + this.commands = new Array(); + this.setCodeAlpha(this.binaryCodeID, 0); + this.setCodeAlpha(this.linearCodeID, 1); + + this.cmd("SetALpha", this.lowBoxID, 0); + this.cmd("SetALpha", this.lowBoxLabel, 0); + this.cmd("SetALpha", this.midBoxID, 0); + this.cmd("SetALpha", this.midBoxLabel, 0); + this.cmd("SetALpha", this.highBoxID, 0); + this.cmd("SetALpha", this.highBoxLabel, 0); + + + this.cmd("SetAlpha", this.lowCircleID, 1); + this.cmd("SetAlpha", this.midCircleID, 0); + this.cmd("SetAlpha", this.highCircleID, 0); + + this.cmd("SetPosition", this.lowCircleID, INDEX_X, INDEX_Y); + + this.cmd("SetALpha", this.indexBoxID, 1); + this.cmd("SetALpha", this.indexBoxLabel, 1); + + this.cmd("SetText", this.resultString, ""); + this.cmd("SetText", this.resultBoxID, ""); + this.cmd("SetText", this.movingLabelID, ""); + + + + var goOn = true; + var nextSearch = 0; + this.cmd("SetText", this.searchForBoxID, searchVal); + this.cmd("SetForegroundColor", this.linearCodeID[1][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.indexBoxID,1); + this.cmd("SetText", this.indexBoxID, "0"); + this.cmd("Move", this.lowCircleID, this.getIndexX(0), this.getIndexY(0)); + + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[1][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.indexBoxID,0); + + + var foundIndex = 0 + while (goOn) { + if (foundIndex == SIZE) { + this.cmd("SetForegroundColor", this.linearCodeID[2][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[2][1], Search.CODE_STANDARD_COLOR); + goOn = false; + + } else { + this.cmd("SetHighlight", this.arrayID[foundIndex],1); + this.cmd("SetHighlight", this.searchForBoxID,1); + this.cmd("SetForegroundColor", this.linearCodeID[2][3], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step") + this.cmd("SetForegroundColor", this.linearCodeID[2][3], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.arrayID[foundIndex],0); + this.cmd("SetHighlight", this.searchForBoxID,0); + goOn = this.arrayData[foundIndex] < searchVal + if (goOn) + { + foundIndex++; + + this.cmd("SetForegroundColor", this.linearCodeID[3][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.indexBoxID,1); + this.cmd("SetText", this.indexBoxID, foundIndex); + this.cmd("Move", this.lowCircleID, this.getIndexX(foundIndex), this.getIndexY(foundIndex)); + + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[3][0], Search.CODE_STANDARD_COLOR); + this.cmd("SetHighlight", this.indexBoxID,0); + } + } + } + if (foundIndex ==SIZE) + { + this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_STANDARD_COLOR); + + + } + + else if (this.arrayData[foundIndex] == searchVal) + { + this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[4][2], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetHighlight", this.arrayID[foundIndex],1); + this.cmd("SetHighlight", this.searchForBoxID,1); + this.cmd("Step"); + + this.cmd("SetHighlight", this.arrayID[foundIndex],0); + this.cmd("SetHighlight", this.searchForBoxID,0); + + + + this.cmd("SetForegroundColor", this.linearCodeID[4][1], Search.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[4][2], Search.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[6][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", this.resultString, " Element found"); + this.cmd("SetText", this.movingLabelID, foundIndex); + this.cmd("SetPosition", this.movingLabelID, this.getIndexX(foundIndex), this.getIndexY(foundIndex)); + + this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); + + this.cmd("AlignRight", this.resultString, this.resultBoxID); + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[6][0], Search.CODE_STANDARD_COLOR); + + + + } + else + { + this.cmd("SetHighlight", this.arrayID[foundIndex],1); + this.cmd("SetHighlight", this.searchForBoxID,1); + this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("Step"); + this.cmd("SetHighlight", this.arrayID[foundIndex],0); + this.cmd("SetHighlight", this.searchForBoxID,0); + this.cmd("SetForegroundColor", this.linearCodeID[4][3], Search.CODE_STANDARD_COLOR); + this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_HIGHLIGHT_COLOR); + this.cmd("SetText", this.resultString, " Element Not found"); + this.cmd("SetText", this.resultBoxID, -1); + this.cmd("AlignRight", this.resultString, this.resultBoxID); + + this.cmd("Step"); + this.cmd("SetForegroundColor", this.linearCodeID[5][0], Search.CODE_STANDARD_COLOR); + + + + } + return this.commands; + + +} + + + + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new Search(animManag, canvas.width, canvas.height); +} diff --git a/AlgorithmLibrary/SkewHeap.js b/AlgorithmLibrary/SkewHeap.js index 2dc4bbb..bbfa869 100644 --- a/AlgorithmLibrary/SkewHeap.js +++ b/AlgorithmLibrary/SkewHeap.js @@ -1,510 +1,510 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - - -function SkewHeap(am, w, h) -{ - this.init(am, w, h); - -} - -SkewHeap.inheritFrom(Algorithm); - -SkewHeap.LINK_COLOR = "#007700"; -SkewHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; -SkewHeap.FOREGROUND_COLOR = "#007700"; -SkewHeap.BACKGROUND_COLOR = "#EEFFEE"; - -SkewHeap.WIDTH_DELTA = 50; -SkewHeap.HEIGHT_DELTA = 50; -SkewHeap.STARTING_Y = 90; - -SkewHeap.INSERT_X = 50; -SkewHeap.INSERT_Y = 45; -SkewHeap.BACKGROUND_ALPHA = 0.5; - -SkewHeap.MESSAGE_X = 20; -SkewHeap.MESSAGE_Y = 10; - - - -SkewHeap.MESSAGE_ID = 0; - -SkewHeap.prototype.init = function(am, w, h) -{ - SkewHeap.superclass.init.call(this, am, w, h); - this.addControls(); - this.treeRoot = null; - this.secondaryRoot = null; - this.animationManager.setAllLayers([0, 1]); - this.nextIndex = 1; - this.commands = []; - this.cmd("CreateLabel", 0, "", SkewHeap.MESSAGE_X, SkewHeap.MESSAGE_Y, 0); - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - this.commands = []; -} - - -SkewHeap.prototype.addControls = function() -{ - this.controls = []; - this.insertField = this.addControlToAlgorithmBar("Text", ""); - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); - this.controls.push(this.insertField); - - this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); - this.insertButton.onclick = this.insertCallback.bind(this); - this.controls.push(this.insertButton); - - this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); - this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); - this.controls.push(this.removeSmallestButton); - - this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); - this.clearHeapButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearHeapButton); - -} - - - - - -SkewHeap.prototype.insertCallback = function(event) -{ - var insertedValue; - - insertedValue = this.normalizeNumber(this.insertField.value, 4); - if (insertedValue != "") - { - this.insertField.value = ""; - this.implementAction(this.insertElement.bind(this),insertedValue); - } -} - -SkewHeap.prototype.clearCallback = function(event) -{ - this.implementAction(this.clear.bind(this, "")); -} - -SkewHeap.prototype.clear = function(ignored) -{ - this.commands = new Array(); - this.clearTree(this.treeRoot); - this.treeRoot = null; - this.nexIndex = 1; - return this.commands; -} - -SkewHeap.prototype.clearTree = function(tree) -{ - if (tree != null) - { - this.cmd("Delete", tree.graphicID); - this.clearTree(tree.left); - this.clearTree(tree.right); - } - -} - -SkewHeap.prototype.reset = function() -{ - this.treeRoot = null; - this.secondaryRoot = null; - this.nextIndex = 1; -} - -SkewHeap.prototype.removeSmallestCallback = function(event) -{ - this.implementAction(this.removeSmallest.bind(this),""); -} - - - -SkewHeap.prototype.removeSmallest = function(dummy) -{ - - this.commands = new Array(); - - if (this.treeRoot != null) - { - this.highlightLeft = this.nextIndex++; - this.highlightRight = this.nextIndex++; - - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Remove root element, leaving two subtrees"); - if (this.treeRoot.left != null) - { - this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.left.graphicID); - } - if (this.treeRoot.right != null) - { - this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.right.graphicID); - } - var oldElem = this.treeRoot.graphicID; - this.cmd("Move", this.treeRoot.graphicID, SkewHeap.INSERT_X, SkewHeap.INSERT_Y); - this.cmd("Step"); - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merge the two subtrees"); - - if (this.treeRoot.left == null) - { - this.treeRoot = null; - } - else if (this.treeRoot.right == null) - { - this.treeRoot = this.treeRoot.left; - this.resizeTrees(); - } - else - { - var secondTree = this.treeRoot.right; - this.secondaryRoot = secondTree; - this.treeRoot = this.treeRoot.left; - this.resizeTrees(); - //this.secondaryRoot = null; - this.cmd("CreateHighlightCircle", this.highlightLeft, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); - - this.cmd("CreateHighlightCircle", this.highlightRight, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, secondTree.x, secondTree.y); - this.treeRoot = this.merge(this.treeRoot, secondTree); - this.secondaryRoot = null; - } - this.resizeTrees(); - this.cmd("Delete", oldElem); - this.cmd("SetText", SkewHeap.MESSAGE_ID, ""); - - - } - // Clear for real - return this.commands; - -} - - - -SkewHeap.prototype.insertElement = function(insertedValue) -{ - this.commands = new Array(); - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Create a heap with one node, merge with existing heap."); - - this.secondaryRoot = new SkewHeapNode(insertedValue, this.nextIndex++, SkewHeap.INSERT_X, SkewHeap.INSERT_Y); - this.cmd("CreateCircle", this.secondaryRoot.graphicID, insertedValue, this.secondaryRoot.x, this.secondaryRoot.y); - this.cmd("SetForegroundColor", this.secondaryRoot.graphicID, SkewHeap.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.secondaryRoot.graphicID, SkewHeap.BACKGROUND_COLOR); - - - if (this.treeRoot != null) - { - this.resizeTrees(); - this.highlightLeft = this.nextIndex++; - this.highlightRight = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.highlightLeft, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); - - this.cmd("CreateHighlightCircle", this.highlightRight, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.secondaryRoot.x, this.secondaryRoot.y); - - - var rightTree = this.secondaryRoot; - this.secondaryRoot = null; - - this.treeRoot = this.merge(this.treeRoot, rightTree); - - this.resizeTrees(); - } - else - { - this.treeRoot = this.secondaryRoot; - this.secondaryRoot = null; - this.resizeTrees(); - } - this.cmd("SetText", SkewHeap.MESSAGE_ID, ""); - - - return this.commands; -} - - -SkewHeap.prototype.merge = function(tree1, tree2) -{ - if (tree1 == null) - { - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merging right heap with empty heap, return right heap"); - this.cmd("Step"); - this.cmd("Delete", this.highlightRight); - this.cmd("Delete", this.highlightLeft); - - return tree2; - } - if (tree2 == null) - { - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merging left heap with empty heap, return left heap"); - this.cmd("Step"); - this.cmd("Delete", this.highlightRight); - this.cmd("Delete", this.highlightLeft); - - return tree1; - } - var tmp; - this.cmd("SetHighlight", tree1.graphicID, 1); - this.cmd("SetHighlight", tree2.graphicID, 1); - if (tree2.data < tree1.data) - { - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Min element is in right heap. Recursively merge right subtree of right heap with left heap"); - tmp = tree1; - tree1 = tree2; - tree2 = tmp; - tmp = this.highlightRight; - this.highlightRight = this.highlightLeft; - this.highlightLeft = tmp; - } - else - { - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Min element is in left heap. Recursively merge right subtree of left heap with right heap"); - } - this.cmd("Step"); - this.cmd("SetHighlight", tree1.graphicID, 0); - this.cmd("SetHighlight", tree2.graphicID, 0); - if (tree1.right == null) - { - this.cmd("Move", this.highlightLeft, tree1.x + SkewHeap.WIDTH_DELTA / 2, tree1.y + SkewHeap.HEIGHT_DELTA); - } - else - { - this.cmd("Move", this.highlightLeft, tree1.right.x, tree1.right.y); - - } - this.cmd("Step"); - if (tree1.right != null) - { - this.cmd("Disconnect", tree1.graphicID, tree1.right.graphicID, SkewHeap.LINK_COLOR); - } - var next = tree1.right; - this.cmd("SetAlpha", tree1.graphicID, SkewHeap.BACKGROUND_ALPHA); - if (tree1.left != null) - { - this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, SkewHeap.BACKGROUND_ALPHA); - this.setTreeAlpha(tree1.left, SkewHeap.BACKGROUND_ALPHA); - - } - this.cmd("Step"); - tree1.right = this.merge(next, tree2); - if (this.secondaryRoot == tree1.right) - { - this.secondaryRoot = null; - } - if (this.treeRoot == tree1.right) - { - this.treeRoot = null; - } - if (tree1.right.parent != tree1) - { - tree1.right.disconnectFromParent(); - } - tree1.right.parent = tree1; - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Reconnecting tree after merge"); - - this.cmd("Connect", tree1.graphicID, tree1.right.graphicID, SkewHeap.LINK_COLOR); - this.cmd("SetAlpha", tree1.graphicID, 1); - - this.resizeTrees(); - if (tree1.left != null) - { - this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, 1); - this.setTreeAlpha(tree1.left, 1); - this.cmd("Step"); - } - - this.cmd("SetHighlight", tree1.graphicID, 1); - this.cmd("SetText", SkewHeap.MESSAGE_ID, "Swapping subtrees after merge ..."); - this.cmd("Step") - this.cmd("SetHighlight", tree1.graphicID, 0); - var tmp = tree1.left; - tree1.left = tree1.right; - tree1.right = tmp; - this.resizeTrees(); - - return tree1; -} - - - -SkewHeap.prototype.setTreeAlpha = function(tree, newAlpha) -{ - if (tree != null) - { - this.cmd("SetAlpha", tree.graphicID, newAlpha); - if (tree.left != null) - { - this.cmd("SetEdgeAlpha", tree.graphicID, tree.left.graphicID, newAlpha); - this.setTreeAlpha(tree.left, newAlpha); - } - if (tree.right != null) - { - this.cmd("SetEdgeAlpha", tree.graphicID, tree.right.graphicID, newAlpha); - this.setTreeAlpha(tree.right, newAlpha); - } - } -} - -SkewHeap.prototype.resizeWidths = function(tree) -{ - if (tree == null) - { - return 0; - } - tree.leftWidth = Math.max(this.resizeWidths(tree.left), SkewHeap.WIDTH_DELTA / 2); - tree.rightWidth = Math.max(this.resizeWidths(tree.right), SkewHeap.WIDTH_DELTA / 2); - return tree.leftWidth + tree.rightWidth; -} - - - -SkewHeap.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -SkewHeap.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - - -SkewHeap.prototype.resizeTrees = function() -{ - var firstTreeStart; - var secondTreeStart; - this.resizeWidths(this.treeRoot); - this.resizeWidths(this.secondaryRoot); - - if (this.treeRoot != null) - { - startingPoint = this.treeRoot.leftWidth; - this.setNewPositions(this.treeRoot, startingPoint, SkewHeap.STARTING_Y, 0); - this.animateNewPositions(this.treeRoot); - if (this.secondaryRoot != null) - { - secondTreeStart = this.treeRoot.leftWidth + this.treeRoot.rightWidth + this.secondaryRoot.leftWidth + 50; - this.setNewPositions(this.secondaryRoot, secondTreeStart, SkewHeap.STARTING_Y, 0); - this.animateNewPositions(this.secondaryRoot); - } - - this.cmd("Step"); - } - else if (this.secondaryRoot != null) - { - startingPoint = this.secondaryRoot.leftWidth; - this.setNewPositions(this.secondaryRoot, startingPoint, SkewHeap.STARTING_Y, 0); - this.animateNewPositions(this.secondaryRoot); - } - -} - -SkewHeap.prototype.setNewPositions = function(tree, xPosition, yPosition, side) -{ - if (tree != null) - { - tree.y = yPosition; - if (side == -1) - { - xPosition = xPosition - tree.rightWidth; - } - else if (side == 1) - { - xPosition = xPosition + tree.leftWidth; - } - else - { -// ??? tree.heightLabelX = xPosition - SkewHeap.NPL_OFFSET_Y; - } - tree.x = xPosition; - this.setNewPositions(tree.left, xPosition, yPosition + SkewHeap.HEIGHT_DELTA, -1) - this.setNewPositions(tree.right, xPosition, yPosition + SkewHeap.HEIGHT_DELTA, 1) - } - -} - - -SkewHeap.prototype.animateNewPositions = function(tree) -{ - if (tree != null) - { - this.cmd("Move", tree.graphicID, tree.x, tree.y); - this.animateNewPositions(tree.left); - this.animateNewPositions(tree.right); - } -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new SkewHeap(animManag, canvas.width, canvas.height); -} - - - - -function SkewHeapNode(val, id, initialX, initialY) -{ - this.data = val; - this.x = (initialX == undefined) ? 0 : initialX; - this.y = (initialY == undefined) ? 0 : initialY; - - this.graphicID = id; - this.left = null; - this.right = null; - this.leftWidth = 0; - this.rightWidth = 0; - this.parent = null; -} - -SkewHeapNode.prototype.disconnectFromParent = function() -{ - if (this.parent != null) - { - if (this.parent.right == this) - { - this.parent.right = null; - } - else if (this.parent.left === this) - { - this.parent.left == null; - } - } -} - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + + +function SkewHeap(am, w, h) +{ + this.init(am, w, h); + +} + +SkewHeap.inheritFrom(Algorithm); + +SkewHeap.LINK_COLOR = "#007700"; +SkewHeap.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +SkewHeap.FOREGROUND_COLOR = "#007700"; +SkewHeap.BACKGROUND_COLOR = "#EEFFEE"; + +SkewHeap.WIDTH_DELTA = 50; +SkewHeap.HEIGHT_DELTA = 50; +SkewHeap.STARTING_Y = 90; + +SkewHeap.INSERT_X = 50; +SkewHeap.INSERT_Y = 45; +SkewHeap.BACKGROUND_ALPHA = 0.5; + +SkewHeap.MESSAGE_X = 20; +SkewHeap.MESSAGE_Y = 10; + + + +SkewHeap.MESSAGE_ID = 0; + +SkewHeap.prototype.init = function(am, w, h) +{ + SkewHeap.superclass.init.call(this, am, w, h); + this.addControls(); + this.treeRoot = null; + this.secondaryRoot = null; + this.animationManager.setAllLayers([0, 1]); + this.nextIndex = 1; + this.commands = []; + this.cmd("CreateLabel", 0, "", SkewHeap.MESSAGE_X, SkewHeap.MESSAGE_Y, 0); + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + this.commands = []; +} + + +SkewHeap.prototype.addControls = function() +{ + this.controls = []; + this.insertField = this.addControlToAlgorithmBar("Text", ""); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); + this.controls.push(this.insertField); + + this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); + this.insertButton.onclick = this.insertCallback.bind(this); + this.controls.push(this.insertButton); + + this.removeSmallestButton = this.addControlToAlgorithmBar("Button", "Remove Smallest"); + this.removeSmallestButton.onclick = this.removeSmallestCallback.bind(this); + this.controls.push(this.removeSmallestButton); + + this.clearHeapButton = this.addControlToAlgorithmBar("Button", "Clear Heap"); + this.clearHeapButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearHeapButton); + +} + + + + + +SkewHeap.prototype.insertCallback = function(event) +{ + var insertedValue; + + insertedValue = this.normalizeNumber(this.insertField.value, 4); + if (insertedValue != "") + { + this.insertField.value = ""; + this.implementAction(this.insertElement.bind(this),insertedValue); + } +} + +SkewHeap.prototype.clearCallback = function(event) +{ + this.implementAction(this.clear.bind(this, "")); +} + +SkewHeap.prototype.clear = function(ignored) +{ + this.commands = new Array(); + this.clearTree(this.treeRoot); + this.treeRoot = null; + this.nexIndex = 1; + return this.commands; +} + +SkewHeap.prototype.clearTree = function(tree) +{ + if (tree != null) + { + this.cmd("Delete", tree.graphicID); + this.clearTree(tree.left); + this.clearTree(tree.right); + } + +} + +SkewHeap.prototype.reset = function() +{ + this.treeRoot = null; + this.secondaryRoot = null; + this.nextIndex = 1; +} + +SkewHeap.prototype.removeSmallestCallback = function(event) +{ + this.implementAction(this.removeSmallest.bind(this),""); +} + + + +SkewHeap.prototype.removeSmallest = function(dummy) +{ + + this.commands = new Array(); + + if (this.treeRoot != null) + { + this.highlightLeft = this.nextIndex++; + this.highlightRight = this.nextIndex++; + + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Remove root element, leaving two subtrees"); + if (this.treeRoot.left != null) + { + this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.left.graphicID); + } + if (this.treeRoot.right != null) + { + this.cmd("Disconnect", this.treeRoot.graphicID, this.treeRoot.right.graphicID); + } + var oldElem = this.treeRoot.graphicID; + this.cmd("Move", this.treeRoot.graphicID, SkewHeap.INSERT_X, SkewHeap.INSERT_Y); + this.cmd("Step"); + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merge the two subtrees"); + + if (this.treeRoot.left == null) + { + this.treeRoot = null; + } + else if (this.treeRoot.right == null) + { + this.treeRoot = this.treeRoot.left; + this.resizeTrees(); + } + else + { + var secondTree = this.treeRoot.right; + this.secondaryRoot = secondTree; + this.treeRoot = this.treeRoot.left; + this.resizeTrees(); + //this.secondaryRoot = null; + this.cmd("CreateHighlightCircle", this.highlightLeft, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); + + this.cmd("CreateHighlightCircle", this.highlightRight, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, secondTree.x, secondTree.y); + this.treeRoot = this.merge(this.treeRoot, secondTree); + this.secondaryRoot = null; + } + this.resizeTrees(); + this.cmd("Delete", oldElem); + this.cmd("SetText", SkewHeap.MESSAGE_ID, ""); + + + } + // Clear for real + return this.commands; + +} + + + +SkewHeap.prototype.insertElement = function(insertedValue) +{ + this.commands = new Array(); + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Create a heap with one node, merge with existing heap."); + + this.secondaryRoot = new SkewHeapNode(insertedValue, this.nextIndex++, SkewHeap.INSERT_X, SkewHeap.INSERT_Y); + this.cmd("CreateCircle", this.secondaryRoot.graphicID, insertedValue, this.secondaryRoot.x, this.secondaryRoot.y); + this.cmd("SetForegroundColor", this.secondaryRoot.graphicID, SkewHeap.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.secondaryRoot.graphicID, SkewHeap.BACKGROUND_COLOR); + + + if (this.treeRoot != null) + { + this.resizeTrees(); + this.highlightLeft = this.nextIndex++; + this.highlightRight = this.nextIndex++; + this.cmd("CreateHighlightCircle", this.highlightLeft, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); + + this.cmd("CreateHighlightCircle", this.highlightRight, SkewHeap.HIGHLIGHT_CIRCLE_COLOR, this.secondaryRoot.x, this.secondaryRoot.y); + + + var rightTree = this.secondaryRoot; + this.secondaryRoot = null; + + this.treeRoot = this.merge(this.treeRoot, rightTree); + + this.resizeTrees(); + } + else + { + this.treeRoot = this.secondaryRoot; + this.secondaryRoot = null; + this.resizeTrees(); + } + this.cmd("SetText", SkewHeap.MESSAGE_ID, ""); + + + return this.commands; +} + + +SkewHeap.prototype.merge = function(tree1, tree2) +{ + if (tree1 == null) + { + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merging right heap with empty heap, return right heap"); + this.cmd("Step"); + this.cmd("Delete", this.highlightRight); + this.cmd("Delete", this.highlightLeft); + + return tree2; + } + if (tree2 == null) + { + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Merging left heap with empty heap, return left heap"); + this.cmd("Step"); + this.cmd("Delete", this.highlightRight); + this.cmd("Delete", this.highlightLeft); + + return tree1; + } + var tmp; + this.cmd("SetHighlight", tree1.graphicID, 1); + this.cmd("SetHighlight", tree2.graphicID, 1); + if (tree2.data < tree1.data) + { + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Min element is in right heap. Recursively merge right subtree of right heap with left heap"); + tmp = tree1; + tree1 = tree2; + tree2 = tmp; + tmp = this.highlightRight; + this.highlightRight = this.highlightLeft; + this.highlightLeft = tmp; + } + else + { + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Min element is in left heap. Recursively merge right subtree of left heap with right heap"); + } + this.cmd("Step"); + this.cmd("SetHighlight", tree1.graphicID, 0); + this.cmd("SetHighlight", tree2.graphicID, 0); + if (tree1.right == null) + { + this.cmd("Move", this.highlightLeft, tree1.x + SkewHeap.WIDTH_DELTA / 2, tree1.y + SkewHeap.HEIGHT_DELTA); + } + else + { + this.cmd("Move", this.highlightLeft, tree1.right.x, tree1.right.y); + + } + this.cmd("Step"); + if (tree1.right != null) + { + this.cmd("Disconnect", tree1.graphicID, tree1.right.graphicID, SkewHeap.LINK_COLOR); + } + var next = tree1.right; + this.cmd("SetAlpha", tree1.graphicID, SkewHeap.BACKGROUND_ALPHA); + if (tree1.left != null) + { + this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, SkewHeap.BACKGROUND_ALPHA); + this.setTreeAlpha(tree1.left, SkewHeap.BACKGROUND_ALPHA); + + } + this.cmd("Step"); + tree1.right = this.merge(next, tree2); + if (this.secondaryRoot == tree1.right) + { + this.secondaryRoot = null; + } + if (this.treeRoot == tree1.right) + { + this.treeRoot = null; + } + if (tree1.right.parent != tree1) + { + tree1.right.disconnectFromParent(); + } + tree1.right.parent = tree1; + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Reconnecting tree after merge"); + + this.cmd("Connect", tree1.graphicID, tree1.right.graphicID, SkewHeap.LINK_COLOR); + this.cmd("SetAlpha", tree1.graphicID, 1); + + this.resizeTrees(); + if (tree1.left != null) + { + this.cmd("SetEdgeAlpha", tree1.graphicID, tree1.left.graphicID, 1); + this.setTreeAlpha(tree1.left, 1); + this.cmd("Step"); + } + + this.cmd("SetHighlight", tree1.graphicID, 1); + this.cmd("SetText", SkewHeap.MESSAGE_ID, "Swapping subtrees after merge ..."); + this.cmd("Step") + this.cmd("SetHighlight", tree1.graphicID, 0); + var tmp = tree1.left; + tree1.left = tree1.right; + tree1.right = tmp; + this.resizeTrees(); + + return tree1; +} + + + +SkewHeap.prototype.setTreeAlpha = function(tree, newAlpha) +{ + if (tree != null) + { + this.cmd("SetAlpha", tree.graphicID, newAlpha); + if (tree.left != null) + { + this.cmd("SetEdgeAlpha", tree.graphicID, tree.left.graphicID, newAlpha); + this.setTreeAlpha(tree.left, newAlpha); + } + if (tree.right != null) + { + this.cmd("SetEdgeAlpha", tree.graphicID, tree.right.graphicID, newAlpha); + this.setTreeAlpha(tree.right, newAlpha); + } + } +} + +SkewHeap.prototype.resizeWidths = function(tree) +{ + if (tree == null) + { + return 0; + } + tree.leftWidth = Math.max(this.resizeWidths(tree.left), SkewHeap.WIDTH_DELTA / 2); + tree.rightWidth = Math.max(this.resizeWidths(tree.right), SkewHeap.WIDTH_DELTA / 2); + return tree.leftWidth + tree.rightWidth; +} + + + +SkewHeap.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +SkewHeap.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + + +SkewHeap.prototype.resizeTrees = function() +{ + var firstTreeStart; + var secondTreeStart; + this.resizeWidths(this.treeRoot); + this.resizeWidths(this.secondaryRoot); + + if (this.treeRoot != null) + { + startingPoint = this.treeRoot.leftWidth; + this.setNewPositions(this.treeRoot, startingPoint, SkewHeap.STARTING_Y, 0); + this.animateNewPositions(this.treeRoot); + if (this.secondaryRoot != null) + { + secondTreeStart = this.treeRoot.leftWidth + this.treeRoot.rightWidth + this.secondaryRoot.leftWidth + 50; + this.setNewPositions(this.secondaryRoot, secondTreeStart, SkewHeap.STARTING_Y, 0); + this.animateNewPositions(this.secondaryRoot); + } + + this.cmd("Step"); + } + else if (this.secondaryRoot != null) + { + startingPoint = this.secondaryRoot.leftWidth; + this.setNewPositions(this.secondaryRoot, startingPoint, SkewHeap.STARTING_Y, 0); + this.animateNewPositions(this.secondaryRoot); + } + +} + +SkewHeap.prototype.setNewPositions = function(tree, xPosition, yPosition, side) +{ + if (tree != null) + { + tree.y = yPosition; + if (side == -1) + { + xPosition = xPosition - tree.rightWidth; + } + else if (side == 1) + { + xPosition = xPosition + tree.leftWidth; + } + else + { +// ??? tree.heightLabelX = xPosition - SkewHeap.NPL_OFFSET_Y; + } + tree.x = xPosition; + this.setNewPositions(tree.left, xPosition, yPosition + SkewHeap.HEIGHT_DELTA, -1) + this.setNewPositions(tree.right, xPosition, yPosition + SkewHeap.HEIGHT_DELTA, 1) + } + +} + + +SkewHeap.prototype.animateNewPositions = function(tree) +{ + if (tree != null) + { + this.cmd("Move", tree.graphicID, tree.x, tree.y); + this.animateNewPositions(tree.left); + this.animateNewPositions(tree.right); + } +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new SkewHeap(animManag, canvas.width, canvas.height); +} + + + + +function SkewHeapNode(val, id, initialX, initialY) +{ + this.data = val; + this.x = (initialX == undefined) ? 0 : initialX; + this.y = (initialY == undefined) ? 0 : initialY; + + this.graphicID = id; + this.left = null; + this.right = null; + this.leftWidth = 0; + this.rightWidth = 0; + this.parent = null; +} + +SkewHeapNode.prototype.disconnectFromParent = function() +{ + if (this.parent != null) + { + if (this.parent.right == this) + { + this.parent.right = null; + } + else if (this.parent.left === this) + { + this.parent.left == null; + } + } +} + diff --git a/AlgorithmLibrary/StackArray.js b/AlgorithmLibrary/StackArray.js index 50a20bd..e19518e 100644 --- a/AlgorithmLibrary/StackArray.js +++ b/AlgorithmLibrary/StackArray.js @@ -1,300 +1,300 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var ARRAY_START_X = 100; -var ARRAY_START_Y = 200; -var ARRAY_ELEM_WIDTH = 50; -var ARRAY_ELEM_HEIGHT = 50; - -var ARRRAY_ELEMS_PER_LINE = 15; -var ARRAY_LINE_SPACING = 130; - -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; - -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; - -var SIZE = 30; - -function StackArray(am, w, h) -{ - this.init(am, w, h); - -} - -StackArray.inheritFrom(Algorithm); - - -StackArray.prototype.init = function(am, w, h) -{ - StackArray.superclass.init.call(this, am, w, h); - this.addControls(); - this.nextIndex = 0; - this.commands = []; - this.setup(); - this.initialIndex = this.nextIndex; -} - - -StackArray.prototype.addControls = function() -{ - this.controls = []; - this.pushField = this.addControlToAlgorithmBar("Text", ""); - this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); - this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); - this.pushButton.onclick = this.pushCallback.bind(this); - this.controls.push(this.pushField); - this.controls.push(this.pushButton); - - this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); - this.popButton.onclick = this.popCallback.bind(this); - this.controls.push(this.popButton); - - this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); - this.clearButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearButton); - -} - -StackArray.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -StackArray.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -StackArray.prototype.setup = function() -{ - this.nextIndex = 0; - - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - - this.arrayID[i]= this.nextIndex++; - this.arrayLabelID[i]= this.nextIndex++; - } - this.topID = this.nextIndex++; - this.topLabelID = this.nextIndex++; - - this.arrayData = new Array(SIZE); - this.top = 0; - this.leftoverLabelID = this.nextIndex++; - this.commands = new Array(); - - for (var i = 0; i < SIZE; i++) - { - var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); - this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); - - } - this.cmd("CreateLabel", this.topLabelID, "top", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.topID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); - - this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); - - this.highlight1ID = this.nextIndex++; - this.highlight2ID = this.nextIndex++; - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - -} - - - -StackArray.prototype.reset = function() -{ - this.top = 0; - this.nextIndex = this.initialIndex; - -} - - -StackArray.prototype.pushCallback = function(event) -{ - if (this.top < SIZE && this.pushField.value != "") - { - var pushVal = this.pushField.value; - this.pushField.value = "" - this.implementAction(this.push.bind(this), pushVal); - } -} - - -StackArray.prototype.popCallback = function(event) -{ - if (this.top > 0) - { - this.implementAction(this.pop.bind(this), ""); - } -} - - -StackArray.prototype.clearCallback = function(event) -{ - this.implementAction(this.clearData.bind(this), ""); -} - -StackArray.prototype.clearData = function(ignored) -{ - this.commands = new Array(); - this.clearAll(); - return this.commands; -} - - -StackArray.prototype.push = function(elemToPush) -{ - this.commands = new Array(); - - var labPushID = this.nextIndex++; - var labPushValID = this.nextIndex++; - this.arrayData[this.top] = elemToPush; - - this.cmd("SetText", this.leftoverLabelID, ""); - - this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - - this.cmd("Step"); - this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); - this.cmd("Step"); - - var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("Step"); - - this.cmd("Move", labPushValID, xpos, ypos); - this.cmd("Step"); - - this.cmd("Settext", this.arrayID[this.top], elemToPush); - this.cmd("Delete", labPushValID); - - this.cmd("Delete", this.highlight1ID); - - this.cmd("SetHighlight", this.topID, 1); - this.cmd("Step"); - this.top = this.top + 1; - this.cmd("SetText", this.topID, this.top) - this.cmd("Delete", labPushID); - this.cmd("Step"); - this.cmd("SetHighlight", this.topID, 0); - - return this.commands; -} - -StackArray.prototype.pop = function(ignored) -{ - this.commands = new Array(); - - var labPopID = this.nextIndex++; - var labPopValID = this.nextIndex++; - - this.cmd("SetText", this.leftoverLabelID, ""); - - - this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - - - this.cmd("SetHighlight", this.topID, 1); - this.cmd("Step"); - this.top = this.top - 1; - this.cmd("SetText", this.topID, this.top) - this.cmd("Step"); - this.cmd("SetHighlight", this.topID, 0); - - this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); - this.cmd("Step"); - - var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("Step"); - - this.cmd("CreateLabel", labPopValID,this.arrayData[this.top], xpos, ypos); - this.cmd("Settext", this.arrayID[this.top], ""); - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - this.cmd("Step"); - this.cmd("Delete", labPopValID) - this.cmd("Delete", labPopID); - this.cmd("Delete", this.highlight1ID); - this.cmd("SetText", this.leftoverLabelID, "Popped Value: " + this.arrayData[this.top]); - - - - return this.commands; -} - - - -StackArray.prototype.clearAll = function() -{ - this.commands = new Array(); - for (var i = 0; i < this.top; i++) - { - this.cmd("SetText", this.arrayID[i], ""); - } - this.top = 0; - this.cmd("SetText", this.topID, "0"); - return this.commands; - -} - - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new StackArray(animManag, canvas.width, canvas.height); -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var ARRAY_START_X = 100; +var ARRAY_START_Y = 200; +var ARRAY_ELEM_WIDTH = 50; +var ARRAY_ELEM_HEIGHT = 50; + +var ARRRAY_ELEMS_PER_LINE = 15; +var ARRAY_LINE_SPACING = 130; + +var TOP_POS_X = 180; +var TOP_POS_Y = 100; +var TOP_LABEL_X = 130; +var TOP_LABEL_Y = 100; + +var PUSH_LABEL_X = 50; +var PUSH_LABEL_Y = 30; +var PUSH_ELEMENT_X = 120; +var PUSH_ELEMENT_Y = 30; + +var SIZE = 30; + +function StackArray(am, w, h) +{ + this.init(am, w, h); + +} + +StackArray.inheritFrom(Algorithm); + + +StackArray.prototype.init = function(am, w, h) +{ + StackArray.superclass.init.call(this, am, w, h); + this.addControls(); + this.nextIndex = 0; + this.commands = []; + this.setup(); + this.initialIndex = this.nextIndex; +} + + +StackArray.prototype.addControls = function() +{ + this.controls = []; + this.pushField = this.addControlToAlgorithmBar("Text", ""); + this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); + this.pushButton.onclick = this.pushCallback.bind(this); + this.controls.push(this.pushField); + this.controls.push(this.pushButton); + + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); + this.popButton.onclick = this.popCallback.bind(this); + this.controls.push(this.popButton); + + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); + this.clearButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearButton); + +} + +StackArray.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +StackArray.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +StackArray.prototype.setup = function() +{ + this.nextIndex = 0; + + this.arrayID = new Array(SIZE); + this.arrayLabelID = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + + this.arrayID[i]= this.nextIndex++; + this.arrayLabelID[i]= this.nextIndex++; + } + this.topID = this.nextIndex++; + this.topLabelID = this.nextIndex++; + + this.arrayData = new Array(SIZE); + this.top = 0; + this.leftoverLabelID = this.nextIndex++; + this.commands = new Array(); + + for (var i = 0; i < SIZE; i++) + { + var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); + this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); + + } + this.cmd("CreateLabel", this.topLabelID, "top", TOP_LABEL_X, TOP_LABEL_Y); + this.cmd("CreateRectangle", this.topID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + + this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + + this.highlight1ID = this.nextIndex++; + this.highlight2ID = this.nextIndex++; + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + +} + + + +StackArray.prototype.reset = function() +{ + this.top = 0; + this.nextIndex = this.initialIndex; + +} + + +StackArray.prototype.pushCallback = function(event) +{ + if (this.top < SIZE && this.pushField.value != "") + { + var pushVal = this.pushField.value; + this.pushField.value = "" + this.implementAction(this.push.bind(this), pushVal); + } +} + + +StackArray.prototype.popCallback = function(event) +{ + if (this.top > 0) + { + this.implementAction(this.pop.bind(this), ""); + } +} + + +StackArray.prototype.clearCallback = function(event) +{ + this.implementAction(this.clearData.bind(this), ""); +} + +StackArray.prototype.clearData = function(ignored) +{ + this.commands = new Array(); + this.clearAll(); + return this.commands; +} + + +StackArray.prototype.push = function(elemToPush) +{ + this.commands = new Array(); + + var labPushID = this.nextIndex++; + var labPushValID = this.nextIndex++; + this.arrayData[this.top] = elemToPush; + + this.cmd("SetText", this.leftoverLabelID, ""); + + this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + + this.cmd("Step"); + this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); + this.cmd("Step"); + + var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + + this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Step"); + + this.cmd("Move", labPushValID, xpos, ypos); + this.cmd("Step"); + + this.cmd("Settext", this.arrayID[this.top], elemToPush); + this.cmd("Delete", labPushValID); + + this.cmd("Delete", this.highlight1ID); + + this.cmd("SetHighlight", this.topID, 1); + this.cmd("Step"); + this.top = this.top + 1; + this.cmd("SetText", this.topID, this.top) + this.cmd("Delete", labPushID); + this.cmd("Step"); + this.cmd("SetHighlight", this.topID, 0); + + return this.commands; +} + +StackArray.prototype.pop = function(ignored) +{ + this.commands = new Array(); + + var labPopID = this.nextIndex++; + var labPopValID = this.nextIndex++; + + this.cmd("SetText", this.leftoverLabelID, ""); + + + this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + + + this.cmd("SetHighlight", this.topID, 1); + this.cmd("Step"); + this.top = this.top - 1; + this.cmd("SetText", this.topID, this.top) + this.cmd("Step"); + this.cmd("SetHighlight", this.topID, 0); + + this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); + this.cmd("Step"); + + var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + + this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Step"); + + this.cmd("CreateLabel", labPopValID,this.arrayData[this.top], xpos, ypos); + this.cmd("Settext", this.arrayID[this.top], ""); + this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Step"); + this.cmd("Delete", labPopValID) + this.cmd("Delete", labPopID); + this.cmd("Delete", this.highlight1ID); + this.cmd("SetText", this.leftoverLabelID, "Popped Value: " + this.arrayData[this.top]); + + + + return this.commands; +} + + + +StackArray.prototype.clearAll = function() +{ + this.commands = new Array(); + for (var i = 0; i < this.top; i++) + { + this.cmd("SetText", this.arrayID[i], ""); + } + this.top = 0; + this.cmd("SetText", this.topID, "0"); + return this.commands; + +} + + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new StackArray(animManag, canvas.width, canvas.height); +} diff --git a/AlgorithmLibrary/StackLL.js b/AlgorithmLibrary/StackLL.js index 263de92..f633afd 100644 --- a/AlgorithmLibrary/StackLL.js +++ b/AlgorithmLibrary/StackLL.js @@ -1,299 +1,299 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -var LINKED_LIST_START_X = 100; -var LINKED_LIST_START_Y = 200; -var LINKED_LIST_ELEM_WIDTH = 70; -var LINKED_LIST_ELEM_HEIGHT = 30; - - -var LINKED_LIST_INSERT_X = 250; -var LINKED_LIST_INSERT_Y = 50; - -var LINKED_LIST_ELEMS_PER_LINE = 8; -var LINKED_LIST_ELEM_SPACING = 100; -var LINKED_LIST_LINE_SPACING = 100; - -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; - -var TOP_ELEM_WIDTH = 30; -var TOP_ELEM_HEIGHT = 30; - -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; - -var SIZE = 32; - -function StackLL(am, w, h) -{ - this.init(am, w, h); - -} - -StackLL.inheritFrom(Algorithm); - - -StackLL.prototype.init = function(am, w, h) -{ - StackLL.superclass.init.call(this, am, w, h); - this.addControls(); - this.nextIndex = 0; - this.commands = []; - this.setup(); - this.initialIndex = this.nextIndex; -} - - -StackLL.prototype.addControls = function() -{ - this.controls = []; - this.pushField = this.addControlToAlgorithmBar("Text", ""); - this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); - this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); - this.pushButton.onclick = this.pushCallback.bind(this); - this.controls.push(this.pushField); - this.controls.push(this.pushButton); - - this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); - this.popButton.onclick = this.popCallback.bind(this); - this.controls.push(this.popButton); - - this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); - this.clearButton.onclick = this.clearCallback.bind(this); - this.controls.push(this.clearButton); - -} - -StackLL.prototype.enableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = false; - } - - -} -StackLL.prototype.disableUI = function(event) -{ - for (var i = 0; i < this.controls.length; i++) - { - this.controls[i].disabled = true; - } -} - - -StackLL.prototype.setup = function() -{ - - this.linkedListElemID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) - { - - this.linkedListElemID[i]= this.nextIndex++; - } - this.topID = this.nextIndex++; - this.topLabelID = this.nextIndex++; - - this.arrayData = new Array(SIZE); - this.top = 0; - this.leftoverLabelID = this.nextIndex++; - - this.cmd("CreateLabel", this.topLabelID, "Top", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.topID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); - this.cmd("SetNull", this.topID, 1); - - this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); - - this.animationManager.StartNewAnimation(this.commands); - this.animationManager.skipForward(); - this.animationManager.clearHistory(); - -} - -StackLL.prototype.resetLinkedListPositions = function() -{ - for (var i = this.top - 1; i >= 0; i--) - { - var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; - var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; - this.cmd("Move", this.linkedListElemID[i], nextX, nextY); - } - -} - - - - -StackLL.prototype.reset = function() -{ - this.top = 0; - this.nextIndex = this.initialIndex; - -} - - -StackLL.prototype.pushCallback = function(event) -{ - if (this.top < SIZE && this.pushField.value != "") - { - var pushVal = this.pushField.value; - this.pushField.value = "" - this.implementAction(this.push.bind(this), pushVal); - } -} - - -StackLL.prototype.popCallback = function(event) -{ - if (this.top > 0) - { - this.implementAction(this.pop.bind(this), ""); - } -} - - -StackLL.prototype.clearCallback = function(event) -{ - this.implementAction(this.clearAll.bind(this), ""); -} - - - -StackLL.prototype.push = function(elemToPush) -{ - this.commands = new Array(); - - var labPushID = this.nextIndex++; - var labPushValID = this.nextIndex++; - this.arrayData[this.top] = elemToPush; - - this.cmd("SetText", this.leftoverLabelID, ""); - - this.cmd("CreateLinkedList",this.linkedListElemID[this.top], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, - LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); - - this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - - this.cmd("Step"); - - - - this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); - - this.cmd("Step"); - this.cmd("SetText", this.linkedListElemID[this.top], elemToPush); - this.cmd("Delete", labPushValID); - - if (this.top == 0) - { - this.cmd("SetNull", this.topID, 0); - this.cmd("SetNull", this.linkedListElemID[this.top], 1); - } - else - { - this.cmd("Connect", this.linkedListElemID[this.top], this.linkedListElemID[this.top - 1]); - this.cmd("Step"); - this.cmd("Disconnect", this.topID, this.linkedListElemID[this.top-1]); - } - this.cmd("Connect", this.topID, this.linkedListElemID[this.top]); - - this.cmd("Step"); - this.top = this.top + 1; - this.resetLinkedListPositions(); - this.cmd("Delete", labPushID); - this.cmd("Step"); - - return this.commands; -} - -StackLL.prototype.pop = function(ignored) -{ - this.commands = new Array(); - - var labPopID = this.nextIndex++; - var labPopValID = this.nextIndex++; - - this.cmd("SetText", this.leftoverLabelID, ""); - - - this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); - - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); - this.cmd("Step"); - this.cmd("Disconnect", this.topID, this.linkedListElemID[this.top - 1]); - - if (this.top == 1) - { - this.cmd("SetNull", this.topID, 1); - } - else - { - this.cmd("Connect", this.topID, this.linkedListElemID[this.top-2]); - - } - this.cmd("Step"); - this.cmd("Delete", this.linkedListElemID[this.top - 1]); - this.top = this.top - 1; - this.resetLinkedListPositions(); - - this.cmd("Delete", labPopValID) - this.cmd("Delete", labPopID); - this.cmd("SetText", this.leftoverLabelID, "Popped Value: " + this.arrayData[this.top]); - - - - return this.commands; -} - - - -StackLL.prototype.clearAll = function() -{ - this.commands = new Array(); - for (var i = 0; i < this.top; i++) - { - this.cmd("Delete", this.linkedListElemID[i]); - } - this.top = 0; - this.cmd("SetNull", this.topID, 1); - return this.commands; -} - - -var currentAlg; - -function init() -{ - var animManag = initCanvas(); - currentAlg = new StackLL(animManag, canvas.width, canvas.height); -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +var LINKED_LIST_START_X = 100; +var LINKED_LIST_START_Y = 200; +var LINKED_LIST_ELEM_WIDTH = 70; +var LINKED_LIST_ELEM_HEIGHT = 30; + + +var LINKED_LIST_INSERT_X = 250; +var LINKED_LIST_INSERT_Y = 50; + +var LINKED_LIST_ELEMS_PER_LINE = 8; +var LINKED_LIST_ELEM_SPACING = 100; +var LINKED_LIST_LINE_SPACING = 100; + +var TOP_POS_X = 180; +var TOP_POS_Y = 100; +var TOP_LABEL_X = 130; +var TOP_LABEL_Y = 100; + +var TOP_ELEM_WIDTH = 30; +var TOP_ELEM_HEIGHT = 30; + +var PUSH_LABEL_X = 50; +var PUSH_LABEL_Y = 30; +var PUSH_ELEMENT_X = 120; +var PUSH_ELEMENT_Y = 30; + +var SIZE = 32; + +function StackLL(am, w, h) +{ + this.init(am, w, h); + +} + +StackLL.inheritFrom(Algorithm); + + +StackLL.prototype.init = function(am, w, h) +{ + StackLL.superclass.init.call(this, am, w, h); + this.addControls(); + this.nextIndex = 0; + this.commands = []; + this.setup(); + this.initialIndex = this.nextIndex; +} + + +StackLL.prototype.addControls = function() +{ + this.controls = []; + this.pushField = this.addControlToAlgorithmBar("Text", ""); + this.pushField.onkeydown = this.returnSubmit(this.pushField, this.pushCallback.bind(this), 6); + this.pushButton = this.addControlToAlgorithmBar("Button", "Push"); + this.pushButton.onclick = this.pushCallback.bind(this); + this.controls.push(this.pushField); + this.controls.push(this.pushButton); + + this.popButton = this.addControlToAlgorithmBar("Button", "Pop"); + this.popButton.onclick = this.popCallback.bind(this); + this.controls.push(this.popButton); + + this.clearButton = this.addControlToAlgorithmBar("Button", "Clear Stack"); + this.clearButton.onclick = this.clearCallback.bind(this); + this.controls.push(this.clearButton); + +} + +StackLL.prototype.enableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = false; + } + + +} +StackLL.prototype.disableUI = function(event) +{ + for (var i = 0; i < this.controls.length; i++) + { + this.controls[i].disabled = true; + } +} + + +StackLL.prototype.setup = function() +{ + + this.linkedListElemID = new Array(SIZE); + for (var i = 0; i < SIZE; i++) + { + + this.linkedListElemID[i]= this.nextIndex++; + } + this.topID = this.nextIndex++; + this.topLabelID = this.nextIndex++; + + this.arrayData = new Array(SIZE); + this.top = 0; + this.leftoverLabelID = this.nextIndex++; + + this.cmd("CreateLabel", this.topLabelID, "Top", TOP_LABEL_X, TOP_LABEL_Y); + this.cmd("CreateRectangle", this.topID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + this.cmd("SetNull", this.topID, 1); + + this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + + this.animationManager.StartNewAnimation(this.commands); + this.animationManager.skipForward(); + this.animationManager.clearHistory(); + +} + +StackLL.prototype.resetLinkedListPositions = function() +{ + for (var i = this.top - 1; i >= 0; i--) + { + var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; + var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; + this.cmd("Move", this.linkedListElemID[i], nextX, nextY); + } + +} + + + + +StackLL.prototype.reset = function() +{ + this.top = 0; + this.nextIndex = this.initialIndex; + +} + + +StackLL.prototype.pushCallback = function(event) +{ + if (this.top < SIZE && this.pushField.value != "") + { + var pushVal = this.pushField.value; + this.pushField.value = "" + this.implementAction(this.push.bind(this), pushVal); + } +} + + +StackLL.prototype.popCallback = function(event) +{ + if (this.top > 0) + { + this.implementAction(this.pop.bind(this), ""); + } +} + + +StackLL.prototype.clearCallback = function(event) +{ + this.implementAction(this.clearAll.bind(this), ""); +} + + + +StackLL.prototype.push = function(elemToPush) +{ + this.commands = new Array(); + + var labPushID = this.nextIndex++; + var labPushValID = this.nextIndex++; + this.arrayData[this.top] = elemToPush; + + this.cmd("SetText", this.leftoverLabelID, ""); + + this.cmd("CreateLinkedList",this.linkedListElemID[this.top], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, + LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); + + this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + + this.cmd("Step"); + + + + this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); + + this.cmd("Step"); + this.cmd("SetText", this.linkedListElemID[this.top], elemToPush); + this.cmd("Delete", labPushValID); + + if (this.top == 0) + { + this.cmd("SetNull", this.topID, 0); + this.cmd("SetNull", this.linkedListElemID[this.top], 1); + } + else + { + this.cmd("Connect", this.linkedListElemID[this.top], this.linkedListElemID[this.top - 1]); + this.cmd("Step"); + this.cmd("Disconnect", this.topID, this.linkedListElemID[this.top-1]); + } + this.cmd("Connect", this.topID, this.linkedListElemID[this.top]); + + this.cmd("Step"); + this.top = this.top + 1; + this.resetLinkedListPositions(); + this.cmd("Delete", labPushID); + this.cmd("Step"); + + return this.commands; +} + +StackLL.prototype.pop = function(ignored) +{ + this.commands = new Array(); + + var labPopID = this.nextIndex++; + var labPopValID = this.nextIndex++; + + this.cmd("SetText", this.leftoverLabelID, ""); + + + this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); + + this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Step"); + this.cmd("Disconnect", this.topID, this.linkedListElemID[this.top - 1]); + + if (this.top == 1) + { + this.cmd("SetNull", this.topID, 1); + } + else + { + this.cmd("Connect", this.topID, this.linkedListElemID[this.top-2]); + + } + this.cmd("Step"); + this.cmd("Delete", this.linkedListElemID[this.top - 1]); + this.top = this.top - 1; + this.resetLinkedListPositions(); + + this.cmd("Delete", labPopValID) + this.cmd("Delete", labPopID); + this.cmd("SetText", this.leftoverLabelID, "Popped Value: " + this.arrayData[this.top]); + + + + return this.commands; +} + + + +StackLL.prototype.clearAll = function() +{ + this.commands = new Array(); + for (var i = 0; i < this.top; i++) + { + this.cmd("Delete", this.linkedListElemID[i]); + } + this.top = 0; + this.cmd("SetNull", this.topID, 1); + return this.commands; +} + + +var currentAlg; + +function init() +{ + var animManag = initCanvas(); + currentAlg = new StackLL(animManag, canvas.width, canvas.height); +} diff --git a/AnimationLibrary/AnimatedBTreeNode.js b/AnimationLibrary/AnimatedBTreeNode.js index b3c1d79..3bfdb1d 100644 --- a/AnimationLibrary/AnimatedBTreeNode.js +++ b/AnimationLibrary/AnimatedBTreeNode.js @@ -1,301 +1,301 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor) -{ - this.objectID = id; - this.widthPerElement = widthPerElem; - this.nodeHeight = h; - this.numLabels = numElems; - this.backgroundColor = (fillColor == undefined)? "#FFFFFF" : fillColor; - this.foregroundColor = (edgeColor == undefined)? "#000000" : edgeColor; - - // call superclass' constructor, which calls init - AnimatedBTreeNode.superclass.constructor.call(this); -} -AnimatedBTreeNode.inheritFrom(AnimatedObject); - -AnimatedBTreeNode.MIN_WIDTH = 10; -AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; - - -AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fillColor, edgeColor) -{ - AnimatedBTreeNode.superclass.init.call(this); - - this.labels = new Array(this.numLabels); - this.labelColors = new Array(this.numLabels); - for (var i = 0; i < this.numLabels; i++) - { - this.labelColors[i] = this.foregroundColor; - } -} - -AnimatedBTreeNode.prototype.getNumElements = function() -{ - return this.numLabels; -} - -AnimatedBTreeNode.prototype.getWidth = function() -{ - if (this.numLabels > 0) - { - return (this.widthPerElement * this.numLabels); - } - else - { - return AnimatedBTreeNode.MIN_WIDTH; - } -} - - -AnimatedBTreeNode.prototype.setNumElements = function(newNumElements) -{ - var i; - if (this.numLabels < newNumElements) - { - for (i = this.numLabels; i < newNumElements; i++) - { - this.labels[i] = ""; - this.labelColors[i] = this.foregroundColor; - } - this.numLabels = newNumElements; - } - else if (this.numLabels > newNumElements) - { - for (i = newNumElements; i < this.numLabels; i++) - { - this.labels[i] = null; - } - this.numLabels = newNumElements; - } -} - - -AnimatedBTreeNode.prototype.left = function() -{ - return this.x - this.getWidth() / 2.0; -} - -AnimatedBTreeNode.prototype.right = function() -{ - return this.x + this.getWidth() / 2.0; -} - -AnimatedBTreeNode.prototype.top = function() -{ - return this.y - this.nodeHeight / 2.0; -} - -AnimatedBTreeNode.prototype.bottom = function() -{ - return this.y + this.nodeHeight / 2.0; -} - - -AnimatedBTreeNode.prototype.draw = function(context) -{ - var startX; - var startY; - - startX = this.left(); - if (startX == NaN) - { - startX = 0; - } - startY = this.top(); - - if (this.highlighted) - { - context.strokeStyle = "#ff0000"; - context.fillStyle = "#ff0000"; - - context.beginPath(); - context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.getWidth() + this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.getWidth() + this.highlightDiff,startY+this.nodeHeight + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY+this.nodeHeight + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); - context.closePath(); - context.stroke(); - context.fill(); - } - - context.strokeStyle = this.foregroundColor; - context.fillStyle = this.backgroundColor; - - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX + this.getWidth(), startY); - context.lineTo(startX + this.getWidth(), startY + this.nodeHeight); - context.lineTo(startX, startY + this.nodeHeight); - context.lineTo(startX, startY); - context.closePath(); - context.stroke(); - context.fill(); - - context.textAlign = 'center'; - context.textBaseline = 'middle'; - - - for (var i = 0; i < this.numLabels; i++) - { - var labelx = this.x - this.widthPerElement * this.numLabels / 2 + this.widthPerElement / 2 + i * this.widthPerElement; - var labely = this.y - - context.fillStyle = this.labelColors[i]; - context.fillText(this.labels[i], labelx, labely); - } -} - - - -AnimatedBTreeNode.prototype.getHeight = function() -{ - return this.nodeHeight; -} - - - -AnimatedBTreeNode.prototype.setForegroundColor = function(newColor) -{ - this.foregroundColor = newColor; - for (var i = 0; i < numLabels; i++) - { - labelColor[i] = newColor; - } -} - - -// TODO: Kill the magic numbers here -AnimatedBTreeNode.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor) -{ - if (anchor == 0) - { - return [this.left() + AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y]; - } - else if (anchor == this.numLabels) - { - return [this.right() - AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y]; - } - else - { - return [this.left() + anchor * this.widthPerElement, this.y] - } -} - - -AnimatedBTreeNode.prototype.getHeadPointerAttachPos = function(fromX, fromY) -{ - if (fromY < this.y - this.nodeHeight / 2) - { - return [this.x, this.y - this.nodeHeight / 2]; - } - else if (this.fromY > this.y + this.nodeHeight / 2) - { - return [this.x, this.y + this.nodeHeight / 2]; - } - else if (fromX < this.x - this.getWidth() / 2) - { - return [this.x - this.getWidth() / 2, this.y]; - } - else - { - return [this.x + this.getWidth() / 2, this.y]; - } -} - - - -AnimatedBTreeNode.prototype.createUndoDelete = function() -{ - return new UndoDeleteBTreeNode(this.objectID, this.numLabels, this.labels, this.x, this.y, this.widthPerElement, this.nodeHeight, this.labelColors, this.backgroundColor, this.foregroundColor, this.layer, this.highlighted); -} - - -AnimatedBTreeNode.prototype.getTextColor = function(textIndex) -{ - textIndex = (textIndex == undefined) ? 0 : textIndex; - return this.labelColors[textIndex]; -} - -AnimatedBTreeNode.prototype.getText = function(index) -{ - index = (index == undefined) ? 0 : index; - return this.labels[index]; -} - -AnimatedBTreeNode.prototype.setTextColor = function(color, textIndex) -{ - textIndex = (textIndex == undefined) ? 0 : textIndex; - this.labelColors[textIndex] = color; -} - - -AnimatedBTreeNode.prototype.setText = function(newText, textIndex) -{ - textIndex = (textIndex == undefined) ? 0 : textIndex; - this.labels[textIndex] = newText; -} - - - -function UndoDeleteBTreeNode(id, numLab, labelText, x, y, wPerElement, nHeight, lColors, bgColor, fgColor, l, highlighted) -{ - this.objectID = id; - this.posX = x; - this.posY = y; - this.widthPerElem = wPerElement; - this.nodeHeight = nHeight; - this.backgroundColor= bgColor; - this.foregroundColor = fgColor; - this.numElems = numLab; - this.labels = labelText; - - this.labelColors = lColors; - this.layer = l; - this.highlighted = highlighted; -} - -UndoDeleteBTreeNode.inheritFrom(UndoBlock); - -UndoDeleteBTreeNode.prototype.undoInitialStep = function(world) -{ - - world.addBTreeNode(this.objectID, this.widthPerElem, this.nodeHeight, this.numElems, this.backgroundColor, this.foregroundColor); - world.setNodePosition(this.objectID, this.posX, this.posY); - for (var i = 0; i < this.numElems; i++) - { - world.setText(this.objectID, this.labels[i], i); - world.setTextColor(this.objectID, this.labelColors[i],i); - } - world.setHighlight(this.objectID, this.highlighted); - world.setLayer(this.objectID, this.layer); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor) +{ + this.objectID = id; + this.widthPerElement = widthPerElem; + this.nodeHeight = h; + this.numLabels = numElems; + this.backgroundColor = (fillColor == undefined)? "#FFFFFF" : fillColor; + this.foregroundColor = (edgeColor == undefined)? "#000000" : edgeColor; + + // call superclass' constructor, which calls init + AnimatedBTreeNode.superclass.constructor.call(this); +} +AnimatedBTreeNode.inheritFrom(AnimatedObject); + +AnimatedBTreeNode.MIN_WIDTH = 10; +AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; + + +AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fillColor, edgeColor) +{ + AnimatedBTreeNode.superclass.init.call(this); + + this.labels = new Array(this.numLabels); + this.labelColors = new Array(this.numLabels); + for (var i = 0; i < this.numLabels; i++) + { + this.labelColors[i] = this.foregroundColor; + } +} + +AnimatedBTreeNode.prototype.getNumElements = function() +{ + return this.numLabels; +} + +AnimatedBTreeNode.prototype.getWidth = function() +{ + if (this.numLabels > 0) + { + return (this.widthPerElement * this.numLabels); + } + else + { + return AnimatedBTreeNode.MIN_WIDTH; + } +} + + +AnimatedBTreeNode.prototype.setNumElements = function(newNumElements) +{ + var i; + if (this.numLabels < newNumElements) + { + for (i = this.numLabels; i < newNumElements; i++) + { + this.labels[i] = ""; + this.labelColors[i] = this.foregroundColor; + } + this.numLabels = newNumElements; + } + else if (this.numLabels > newNumElements) + { + for (i = newNumElements; i < this.numLabels; i++) + { + this.labels[i] = null; + } + this.numLabels = newNumElements; + } +} + + +AnimatedBTreeNode.prototype.left = function() +{ + return this.x - this.getWidth() / 2.0; +} + +AnimatedBTreeNode.prototype.right = function() +{ + return this.x + this.getWidth() / 2.0; +} + +AnimatedBTreeNode.prototype.top = function() +{ + return this.y - this.nodeHeight / 2.0; +} + +AnimatedBTreeNode.prototype.bottom = function() +{ + return this.y + this.nodeHeight / 2.0; +} + + +AnimatedBTreeNode.prototype.draw = function(context) +{ + var startX; + var startY; + + startX = this.left(); + if (startX == NaN) + { + startX = 0; + } + startY = this.top(); + + if (this.highlighted) + { + context.strokeStyle = "#ff0000"; + context.fillStyle = "#ff0000"; + + context.beginPath(); + context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.getWidth() + this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.getWidth() + this.highlightDiff,startY+this.nodeHeight + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY+this.nodeHeight + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); + context.closePath(); + context.stroke(); + context.fill(); + } + + context.strokeStyle = this.foregroundColor; + context.fillStyle = this.backgroundColor; + + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX + this.getWidth(), startY); + context.lineTo(startX + this.getWidth(), startY + this.nodeHeight); + context.lineTo(startX, startY + this.nodeHeight); + context.lineTo(startX, startY); + context.closePath(); + context.stroke(); + context.fill(); + + context.textAlign = 'center'; + context.textBaseline = 'middle'; + + + for (var i = 0; i < this.numLabels; i++) + { + var labelx = this.x - this.widthPerElement * this.numLabels / 2 + this.widthPerElement / 2 + i * this.widthPerElement; + var labely = this.y + + context.fillStyle = this.labelColors[i]; + context.fillText(this.labels[i], labelx, labely); + } +} + + + +AnimatedBTreeNode.prototype.getHeight = function() +{ + return this.nodeHeight; +} + + + +AnimatedBTreeNode.prototype.setForegroundColor = function(newColor) +{ + this.foregroundColor = newColor; + for (var i = 0; i < numLabels; i++) + { + labelColor[i] = newColor; + } +} + + +// TODO: Kill the magic numbers here +AnimatedBTreeNode.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor) +{ + if (anchor == 0) + { + return [this.left() + AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y]; + } + else if (anchor == this.numLabels) + { + return [this.right() - AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y]; + } + else + { + return [this.left() + anchor * this.widthPerElement, this.y] + } +} + + +AnimatedBTreeNode.prototype.getHeadPointerAttachPos = function(fromX, fromY) +{ + if (fromY < this.y - this.nodeHeight / 2) + { + return [this.x, this.y - this.nodeHeight / 2]; + } + else if (this.fromY > this.y + this.nodeHeight / 2) + { + return [this.x, this.y + this.nodeHeight / 2]; + } + else if (fromX < this.x - this.getWidth() / 2) + { + return [this.x - this.getWidth() / 2, this.y]; + } + else + { + return [this.x + this.getWidth() / 2, this.y]; + } +} + + + +AnimatedBTreeNode.prototype.createUndoDelete = function() +{ + return new UndoDeleteBTreeNode(this.objectID, this.numLabels, this.labels, this.x, this.y, this.widthPerElement, this.nodeHeight, this.labelColors, this.backgroundColor, this.foregroundColor, this.layer, this.highlighted); +} + + +AnimatedBTreeNode.prototype.getTextColor = function(textIndex) +{ + textIndex = (textIndex == undefined) ? 0 : textIndex; + return this.labelColors[textIndex]; +} + +AnimatedBTreeNode.prototype.getText = function(index) +{ + index = (index == undefined) ? 0 : index; + return this.labels[index]; +} + +AnimatedBTreeNode.prototype.setTextColor = function(color, textIndex) +{ + textIndex = (textIndex == undefined) ? 0 : textIndex; + this.labelColors[textIndex] = color; +} + + +AnimatedBTreeNode.prototype.setText = function(newText, textIndex) +{ + textIndex = (textIndex == undefined) ? 0 : textIndex; + this.labels[textIndex] = newText; +} + + + +function UndoDeleteBTreeNode(id, numLab, labelText, x, y, wPerElement, nHeight, lColors, bgColor, fgColor, l, highlighted) +{ + this.objectID = id; + this.posX = x; + this.posY = y; + this.widthPerElem = wPerElement; + this.nodeHeight = nHeight; + this.backgroundColor= bgColor; + this.foregroundColor = fgColor; + this.numElems = numLab; + this.labels = labelText; + + this.labelColors = lColors; + this.layer = l; + this.highlighted = highlighted; +} + +UndoDeleteBTreeNode.inheritFrom(UndoBlock); + +UndoDeleteBTreeNode.prototype.undoInitialStep = function(world) +{ + + world.addBTreeNode(this.objectID, this.widthPerElem, this.nodeHeight, this.numElems, this.backgroundColor, this.foregroundColor); + world.setNodePosition(this.objectID, this.posX, this.posY); + for (var i = 0; i < this.numElems; i++) + { + world.setText(this.objectID, this.labels[i], i); + world.setTextColor(this.objectID, this.labelColors[i],i); + } + world.setHighlight(this.objectID, this.highlighted); + world.setLayer(this.objectID, this.layer); +} + + + diff --git a/AnimationLibrary/AnimatedCircle.js b/AnimationLibrary/AnimatedCircle.js index 36e1c25..ccf533b 100644 --- a/AnimationLibrary/AnimatedCircle.js +++ b/AnimationLibrary/AnimatedCircle.js @@ -1,211 +1,211 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -var AnimatedCircle = function(objectID, objectLabel) -{ - // call superclass' constructor - AnimatedCircle.superclass.constructor.call(this); - - this.objectID = objectID; - this.label = objectLabel; - this.radius = 20; - this.thickness = 3; - this.x = 0; - this.y = 0; - this.alpha = 1.0; - this.addedToScene = true; - this.highlightIndex = -1; - this.textHeight = 10; -/* this.foregroundColor = '#007700'; - this.backgroundColor = '#EEFFEE'; - */ -} -AnimatedCircle.inheritFrom(AnimatedObject); - -AnimatedCircle.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint) -{ - return this.getHeadPointerAttachPos(fromX, fromY); -} - - -AnimatedCircle.prototype.getWidth = function() -{ - return this.radius * 2; -} - -AnimatedObject.prototype.setWidth = function(newWidth) -{ - this.radius = newWidth / 2; -} - - - - - -AnimatedCircle.prototype.getHeadPointerAttachPos = function(fromX, fromY) -{ - var xVec = fromX - this.x; - var yVec = fromY - this.y; - var len = Math.sqrt(xVec * xVec + yVec*yVec); - if (len == 0) - { - return [this.x, this.y]; - } - return [this.x+(xVec/len)*(this.radius), this.y +(yVec/len)*(this.radius)]; -} - - -AnimatedCircle.prototype.setHighlightIndex = function(hlIndex) -{ - this.highlightIndex = hlIndex; - this.highlightIndexDirty = true; - -} - -AnimatedCircle.prototype.draw = function(ctx) -{ - ctx.globalAlpha = this.alpha; - - if (this.highlighted) - { - ctx.fillStyle = "#ff0000"; - ctx.beginPath(); - ctx.arc(this.x,this.y,this.radius + this.highlightDiff,0,Math.PI*2, true); - ctx.closePath(); - ctx.fill(); - } - - - ctx.fillStyle = this.backgroundColor; - ctx.strokeStyle = this.foregroundColor; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - ctx.textAlign = 'center'; - ctx.font = this.textHeight.toString() + 'px sans-serif'; - ctx.textBaseline = 'middle'; - ctx.lineWidth = 1; - ctx.fillStyle = this.foregroundColor; - - var strList = this.label.split("\n"); - if (strList.length == 1) - { - if (this.highlightIndexDirty && this.highlightIndex != -1) - { - this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width; - this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width; - this.textWidth = ctx.measureText(this.label).width; - this.highlightIndexDirty = false; - } - if (this.highlightIndex != -1 && this.highlightIndex < this.label.length) //this.highlghtIndex < this.label.length) - { - var startingXForHighlight = this.x - this.textWidth / 2; - ctx.textAlign = 'left'; - var leftStr = this.label.substring(0, this.highlightIndex); - var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1) - var rightStr = this.label.substring(this.highlightIndex + 1) - ctx.fillText(leftStr, startingXForHighlight, this.y) - ctx.strokeStyle = "#FF0000"; - ctx.fillStyle = "#FF0000"; - ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y) - - - ctx.strokeStyle = this.labelColor; - ctx.fillStyle = this.labelColor; - ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y) - - - - } - else - { - ctx.fillText(this.label, this.x, this.y); - } - } - else if (strList.length % 2 == 0) - { - var i; - var mid = strList.length / 2; - for (i = 0; i < strList.length / 2; i++) - { - ctx.fillText(strList[mid - i - 1], this.x, this.y - (i + 0.5) * 12); - ctx.fillText(strList[mid + i], this.x, this.y + (i + 0.5) * 12); - - } - } - else - { - var mid = (strList.length - 1) / 2; - var i; - ctx.fillText(strList[mid], this.x, this.y); - for (i = 0; i < mid; i++) - { - ctx.fillText(strList[mid - (i + 1)], this.x, this.y - (i + 1) * 12); - ctx.fillText(strList[mid + (i + 1)], this.x, this.y + (i + 1) * 12); - } - - } - -} - - -AnimatedCircle.prototype.createUndoDelete = function() -{ - return new UndoDeleteCircle(this.objectID, this.label, this.x, this.y, this.foregroundColor, this.backgroundColor, this.layer, this.radius); -} - - -function UndoDeleteCircle(id, lab, x, y, foregroundColor, backgroundColor, l, radius) -{ - this.objectID = id; - this.posX = x; - this.posY = y; - this.nodeLabel = lab; - this.fgColor = foregroundColor; - this.bgColor = backgroundColor; - this.layer = l; - this.radius = radius; -} - -UndoDeleteCircle.inheritFrom(UndoBlock); - -UndoDeleteCircle.prototype.undoInitialStep = function(world) -{ - world.addCircleObject(this.objectID, this.nodeLabel); - world.setWidth(this.objectID, this.radius * 2); - world.setNodePosition(this.objectID, this.posX, this.posY); - world.setForegroundColor(this.objectID, this.fgColor); - world.setBackgroundColor(this.objectID, this.bgColor); - world.setLayer(this.objectID, this.layer); -} - - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +var AnimatedCircle = function(objectID, objectLabel) +{ + // call superclass' constructor + AnimatedCircle.superclass.constructor.call(this); + + this.objectID = objectID; + this.label = objectLabel; + this.radius = 20; + this.thickness = 3; + this.x = 0; + this.y = 0; + this.alpha = 1.0; + this.addedToScene = true; + this.highlightIndex = -1; + this.textHeight = 10; +/* this.foregroundColor = '#007700'; + this.backgroundColor = '#EEFFEE'; + */ +} +AnimatedCircle.inheritFrom(AnimatedObject); + +AnimatedCircle.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint) +{ + return this.getHeadPointerAttachPos(fromX, fromY); +} + + +AnimatedCircle.prototype.getWidth = function() +{ + return this.radius * 2; +} + +AnimatedObject.prototype.setWidth = function(newWidth) +{ + this.radius = newWidth / 2; +} + + + + + +AnimatedCircle.prototype.getHeadPointerAttachPos = function(fromX, fromY) +{ + var xVec = fromX - this.x; + var yVec = fromY - this.y; + var len = Math.sqrt(xVec * xVec + yVec*yVec); + if (len == 0) + { + return [this.x, this.y]; + } + return [this.x+(xVec/len)*(this.radius), this.y +(yVec/len)*(this.radius)]; +} + + +AnimatedCircle.prototype.setHighlightIndex = function(hlIndex) +{ + this.highlightIndex = hlIndex; + this.highlightIndexDirty = true; + +} + +AnimatedCircle.prototype.draw = function(ctx) +{ + ctx.globalAlpha = this.alpha; + + if (this.highlighted) + { + ctx.fillStyle = "#ff0000"; + ctx.beginPath(); + ctx.arc(this.x,this.y,this.radius + this.highlightDiff,0,Math.PI*2, true); + ctx.closePath(); + ctx.fill(); + } + + + ctx.fillStyle = this.backgroundColor; + ctx.strokeStyle = this.foregroundColor; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + ctx.textAlign = 'center'; + ctx.font = this.textHeight.toString() + 'px sans-serif'; + ctx.textBaseline = 'middle'; + ctx.lineWidth = 1; + ctx.fillStyle = this.foregroundColor; + + var strList = this.label.split("\n"); + if (strList.length == 1) + { + if (this.highlightIndexDirty && this.highlightIndex != -1) + { + this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width; + this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width; + this.textWidth = ctx.measureText(this.label).width; + this.highlightIndexDirty = false; + } + if (this.highlightIndex != -1 && this.highlightIndex < this.label.length) //this.highlghtIndex < this.label.length) + { + var startingXForHighlight = this.x - this.textWidth / 2; + ctx.textAlign = 'left'; + var leftStr = this.label.substring(0, this.highlightIndex); + var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1) + var rightStr = this.label.substring(this.highlightIndex + 1) + ctx.fillText(leftStr, startingXForHighlight, this.y) + ctx.strokeStyle = "#FF0000"; + ctx.fillStyle = "#FF0000"; + ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y) + + + ctx.strokeStyle = this.labelColor; + ctx.fillStyle = this.labelColor; + ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y) + + + + } + else + { + ctx.fillText(this.label, this.x, this.y); + } + } + else if (strList.length % 2 == 0) + { + var i; + var mid = strList.length / 2; + for (i = 0; i < strList.length / 2; i++) + { + ctx.fillText(strList[mid - i - 1], this.x, this.y - (i + 0.5) * 12); + ctx.fillText(strList[mid + i], this.x, this.y + (i + 0.5) * 12); + + } + } + else + { + var mid = (strList.length - 1) / 2; + var i; + ctx.fillText(strList[mid], this.x, this.y); + for (i = 0; i < mid; i++) + { + ctx.fillText(strList[mid - (i + 1)], this.x, this.y - (i + 1) * 12); + ctx.fillText(strList[mid + (i + 1)], this.x, this.y + (i + 1) * 12); + } + + } + +} + + +AnimatedCircle.prototype.createUndoDelete = function() +{ + return new UndoDeleteCircle(this.objectID, this.label, this.x, this.y, this.foregroundColor, this.backgroundColor, this.layer, this.radius); +} + + +function UndoDeleteCircle(id, lab, x, y, foregroundColor, backgroundColor, l, radius) +{ + this.objectID = id; + this.posX = x; + this.posY = y; + this.nodeLabel = lab; + this.fgColor = foregroundColor; + this.bgColor = backgroundColor; + this.layer = l; + this.radius = radius; +} + +UndoDeleteCircle.inheritFrom(UndoBlock); + +UndoDeleteCircle.prototype.undoInitialStep = function(world) +{ + world.addCircleObject(this.objectID, this.nodeLabel); + world.setWidth(this.objectID, this.radius * 2); + world.setNodePosition(this.objectID, this.posX, this.posY); + world.setForegroundColor(this.objectID, this.fgColor); + world.setBackgroundColor(this.objectID, this.bgColor); + world.setLayer(this.objectID, this.layer); +} + + + + diff --git a/AnimationLibrary/AnimatedLabel.js b/AnimationLibrary/AnimatedLabel.js index 2198387..9509f85 100644 --- a/AnimationLibrary/AnimatedLabel.js +++ b/AnimationLibrary/AnimatedLabel.js @@ -1,454 +1,454 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -function AnimatedLabel(id, val, center, initialWidth, ctx) -{ - // call superclass' constructor - AnimatedLabel.superclass.constructor.call(this); - - this.centering = center; - this.label = val; - this.highlighted = false; - this.objectID = id; - this.alpha = 1.0; - this.addedToScene = true; - this.labelColor = "#000000"; - this.textWidth = 0; - this.ctx = ctx; - this.height = 10; - - if (initialWidth != undefined || false) - { - this.textWidth = initialWidth; - } - else - { - this.width = getTextWidth(); - } - - this.leftWidth = -1; - this.centerWidth = -1; - this.highlightIndex = -1; -} -AnimatedLabel.inheritFrom(AnimatedObject); - -AnimatedLabel.prototype.alwaysOnTop = true; - - -AnimatedLabel.prototype.centered = function() -{ - return this.centering; -} - - -AnimatedLabel.prototype.draw = function(ctx) -{ - if (!this.addedToScene) - { - return; - } - - ctx.globalAlpha = this.alpha; - ctx.font = this.height.toString() + 'px sans-serif'; -// ctx.font = 'px sans-serif'; - - var startingXForHighlight = this.x; - - if (this.highlightIndex >= this.label.length) - { - this.highlightIndex = -1; - } - if (this.highlightIndexDirty && this.highlightIndex != -1) - { - this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width; - this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width; - this.highlightIndexDirty = false; - } - - if (this.centering) - { - if (this.highlightIndex != -1) - { - startingXForHighlight = this.x - this.width / 2; - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - } - else - { - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - } - } - else - { - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - } - if (this.highlighted) - { - ctx.strokeStyle = "#ffaaaa"; - ctx.fillStyle = "#ff0000"; - ctx.lineWidth = this.highlightDiff; - ctx.strokeText(this.label, this.x, this.y); - //ctx.fillText(this.label, this.x, this.y); - } - ctx.strokeStyle = this.labelColor; - ctx.fillStyle = this.labelColor; - ctx.lineWidth = 1; - strList = this.label.split("\n"); - if (strList.length == 1) - { - if (this.highlightIndex == -1) - { - ctx.fillText(this.label, this.x, this.y); - } - else - { - var leftStr = this.label.substring(0, this.highlightIndex); - var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1) - var rightStr = this.label.substring(this.highlightIndex + 1) - ctx.fillText(leftStr, startingXForHighlight, this.y) - ctx.strokeStyle = "#FF0000"; - ctx.fillStyle = "#FF0000"; - ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y) - - - ctx.strokeStyle = this.labelColor; - ctx.fillStyle = this.labelColor; - ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y) - - - } - //this.textWidth = ctx.measureText(this.label).width; - } - else - { - var offset = (this.centering)? (1.0 - strList.length) / 2.0 : 0; - for (var i = 0; i < strList.length; i++) - { - ctx.fillText(strList[i], this.x, this.y + offset + i * 12); - //this.textWidth = Math.max(this.textWidth, ctx.measureText(strList[i]).width); - } - } - ctx.closePath(); -} - - - -AnimatedLabel.prototype.getTextWidth = function() -{ - this.ctx.font = this.height.toString() + 'px sans-serif'; - var strList = this.label.split("\n"); - var width = 0; - if (strList.length == 1) - { - width = this.ctx.measureText(this.label).width; - } - else - { - for (var i = 0; i < strList.length; i++) - { - width = Math.max(width, this.ctx.measureText(strList[i]).width); - } - } - return width; -} - -AnimatedLabel.prototype.getAlignLeftPos = function(otherObject) -{ - if (this.centering) - { - return [otherObject.left() - this.textWidth / 2, this.y = otherObject.centerY()]; - } - else - { - return [otherObject.left() - this.textWidth, otherObject.centerY() - this.height / 2]; - } -} - -AnimatedLabel.prototype.alignLeft = function(otherObject) -{ - if (this.centering) - { - this.y = otherObject.centerY(); - this.x = otherObject.left() - this.textWidth / 2; - } - else - { - this.y = otherObject.centerY() - this.height / 2; - this.x = otherObject.left() - this.textWidth; - } -} - -AnimatedLabel.prototype.alignRight = function(otherObject) -{ - if (this.centering) - { - this.y = otherObject.centerY(); - this.x = otherObject.right() + this.textWidth / 2; - } - else - { - this.y = otherObject.centerY() - this.height / 2; - this.x = otherObject.right(); - } -} -AnimatedLabel.prototype.getAlignRightPos = function(otherObject) -{ - if (this.centering) - { - return [otherObject.right() + this.textWidth / 2, otherObject.centerY()]; - } - else - { - return [otherObject.right(), otherObject.centerY() - this.height / 2]; - } -} - - -AnimatedLabel.prototype.alignTop = function(otherObject) -{ - if (this.centering) - { - this.y = otherObject.top() - this.height / 2; - this.x = otherObject.centerX(); - } - else - { - this.y = otherObject.top() - 10; - this.x = otherObject.centerX() -this.textWidth / 2; - } -} - - -AnimatedLabel.prototype.getAlignTopPos = function(otherObject) -{ - if (this.centering) - { - return [otherObject.centerX(), otherObject.top() - this.height/ 2]; - } - else - { - return [otherObject.centerX() -this.textWidth / 2, otherObject.top() - 10]; - } -} - - -AnimatedLabel.prototype.alignBottom = function(otherObject) -{ - if (this.centering) - { - this.y = otherObject.bottom() + this.height / 2; - this.x = otherObject.centerX(); - } - else - { - this.y = otherObject.bottom(); - this.x = otherObject.centerX() - this.textWidth / 2; - } -} - - -AnimatedLabel.prototype.getAlignBottomPos = function(otherObject) -{ - if (this.centering) - { - return [otherObject.centerX(), otherObject.bottom() + this.height / 2]; - } - else - { - return [otherObject.centerX() - this.textWidth / 2, otherObject.bottom()]; - } -} - - - -AnimatedLabel.prototype.getWidth = function() -{ - return this.textWidth; -} - -AnimatedLabel.prototype.getHeight = function() -{ - return this.height; -} - -AnimatedLabel.prototype.setHeight = function(newHeight) -{ - this.height = newHeight; - this.textWidth =this.getTextWidth(); -} - -AnimatedLabel.prototype.setHighlight = function(value) -{ - this.highlighted = value; -} - -AnimatedLabel.prototype.createUndoDelete = function() -{ - return new UndoDeleteLabel(this.objectID, this.label, this.x, this.y, this.centering, this.labelColor, this.layer, this.highlightIndex); -} - - -AnimatedLabel.prototype.centerX = function() -{ - if (this.centering) - { - return this.x; - } - else - { - return this.x + this.textWidth; - } - -} - -AnimatedLabel.prototype.centerY = function() -{ - if (this.centering) - { - return this.y; - } - else - { - return this.y + this.height / 2; // - } - -} - -AnimatedLabel.prototype.top = function() -{ - if (this.centering) - { - return this.y - this.height/2; //TODO: Un-Hardwire - } - else - { - return this.y; - } -} - - -AnimatedLabel.prototype.bottom = function() -{ - if (this.centering) - { - return this.y + this.height/2; // TODO: + height / 2; - } - else - { - return this.y + this.height; // TODO: + hieght; - } -} - - -AnimatedLabel.prototype.right = function() -{ - if (this.centering) - { - return this.x + this.textWidth / 2; // TODO: + width / 2; - } - else - { - return this.x + this.textWidth; // TODO: + width; - } -} - - -AnimatedLabel.prototype.left = function() -{ - if (this.centering) - { - return this. x - this.textWidth / 2; - } - else - { - return this.x; // TODO: - a little? - } -} - - -AnimatedLabel.prototype.setHighlightIndex = function(hlIndex) -{ - // Only allow highlight index for labels that don't have End-Of-Line - if (this.label.indexOf("\n") == -1 && this.label.length > hlIndex) - { - this.highlightIndex = hlIndex; - this.highlightIndexDirty = true; - } - else - { - this.highlightIndex = -1; - - } -} - - - AnimatedLabel.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint) - { - return this.getClosestCardinalPoint(fromX, fromY); - } - -AnimatedLabel.prototype.getHeadPointerAttachPos = function (fromX, fromY) -{ - return this.getClosestCardinalPoint(fromX, fromY); -} - -AnimatedLabel.prototype.setText = function(newText, textIndex, initialWidth) -{ - this.label = newText; - if (initialWidth != undefined) - { - this.textWidth = initialWidth; - } - this.textWidth = this.getTextWidth(); -} - - - -function UndoDeleteLabel(id, lab, x, y, centered, color, l, hli) -{ - this.objectID = id; - this.posX = x; - this.posY = y; - this.nodeLabel = lab; - this.labCentered = centered; - this.labelColor = color; - this.layer = l; - this.highlightIndex = hli; - this.dirty = true; -} - -UndoDeleteLabel.inheritFrom(UndoBlock); - -UndoDeleteLabel.prototype.undoInitialStep = function(world) -{ - world.addLabelObject(this.objectID, this.nodeLabel, this.labCentered); - world.setNodePosition(this.objectID, this.posX, this.posY); - world.setForegroundColor(this.objectID, this.labelColor); - world.setLayer(this.objectID, this.layer); -} - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +function AnimatedLabel(id, val, center, initialWidth, ctx) +{ + // call superclass' constructor + AnimatedLabel.superclass.constructor.call(this); + + this.centering = center; + this.label = val; + this.highlighted = false; + this.objectID = id; + this.alpha = 1.0; + this.addedToScene = true; + this.labelColor = "#000000"; + this.textWidth = 0; + this.ctx = ctx; + this.height = 10; + + if (initialWidth != undefined || false) + { + this.textWidth = initialWidth; + } + else + { + this.width = getTextWidth(); + } + + this.leftWidth = -1; + this.centerWidth = -1; + this.highlightIndex = -1; +} +AnimatedLabel.inheritFrom(AnimatedObject); + +AnimatedLabel.prototype.alwaysOnTop = true; + + +AnimatedLabel.prototype.centered = function() +{ + return this.centering; +} + + +AnimatedLabel.prototype.draw = function(ctx) +{ + if (!this.addedToScene) + { + return; + } + + ctx.globalAlpha = this.alpha; + ctx.font = this.height.toString() + 'px sans-serif'; +// ctx.font = 'px sans-serif'; + + var startingXForHighlight = this.x; + + if (this.highlightIndex >= this.label.length) + { + this.highlightIndex = -1; + } + if (this.highlightIndexDirty && this.highlightIndex != -1) + { + this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width; + this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width; + this.highlightIndexDirty = false; + } + + if (this.centering) + { + if (this.highlightIndex != -1) + { + startingXForHighlight = this.x - this.width / 2; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + } + else + { + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + } + } + else + { + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + } + if (this.highlighted) + { + ctx.strokeStyle = "#ffaaaa"; + ctx.fillStyle = "#ff0000"; + ctx.lineWidth = this.highlightDiff; + ctx.strokeText(this.label, this.x, this.y); + //ctx.fillText(this.label, this.x, this.y); + } + ctx.strokeStyle = this.labelColor; + ctx.fillStyle = this.labelColor; + ctx.lineWidth = 1; + strList = this.label.split("\n"); + if (strList.length == 1) + { + if (this.highlightIndex == -1) + { + ctx.fillText(this.label, this.x, this.y); + } + else + { + var leftStr = this.label.substring(0, this.highlightIndex); + var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1) + var rightStr = this.label.substring(this.highlightIndex + 1) + ctx.fillText(leftStr, startingXForHighlight, this.y) + ctx.strokeStyle = "#FF0000"; + ctx.fillStyle = "#FF0000"; + ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y) + + + ctx.strokeStyle = this.labelColor; + ctx.fillStyle = this.labelColor; + ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y) + + + } + //this.textWidth = ctx.measureText(this.label).width; + } + else + { + var offset = (this.centering)? (1.0 - strList.length) / 2.0 : 0; + for (var i = 0; i < strList.length; i++) + { + ctx.fillText(strList[i], this.x, this.y + offset + i * 12); + //this.textWidth = Math.max(this.textWidth, ctx.measureText(strList[i]).width); + } + } + ctx.closePath(); +} + + + +AnimatedLabel.prototype.getTextWidth = function() +{ + this.ctx.font = this.height.toString() + 'px sans-serif'; + var strList = this.label.split("\n"); + var width = 0; + if (strList.length == 1) + { + width = this.ctx.measureText(this.label).width; + } + else + { + for (var i = 0; i < strList.length; i++) + { + width = Math.max(width, this.ctx.measureText(strList[i]).width); + } + } + return width; +} + +AnimatedLabel.prototype.getAlignLeftPos = function(otherObject) +{ + if (this.centering) + { + return [otherObject.left() - this.textWidth / 2, this.y = otherObject.centerY()]; + } + else + { + return [otherObject.left() - this.textWidth, otherObject.centerY() - this.height / 2]; + } +} + +AnimatedLabel.prototype.alignLeft = function(otherObject) +{ + if (this.centering) + { + this.y = otherObject.centerY(); + this.x = otherObject.left() - this.textWidth / 2; + } + else + { + this.y = otherObject.centerY() - this.height / 2; + this.x = otherObject.left() - this.textWidth; + } +} + +AnimatedLabel.prototype.alignRight = function(otherObject) +{ + if (this.centering) + { + this.y = otherObject.centerY(); + this.x = otherObject.right() + this.textWidth / 2; + } + else + { + this.y = otherObject.centerY() - this.height / 2; + this.x = otherObject.right(); + } +} +AnimatedLabel.prototype.getAlignRightPos = function(otherObject) +{ + if (this.centering) + { + return [otherObject.right() + this.textWidth / 2, otherObject.centerY()]; + } + else + { + return [otherObject.right(), otherObject.centerY() - this.height / 2]; + } +} + + +AnimatedLabel.prototype.alignTop = function(otherObject) +{ + if (this.centering) + { + this.y = otherObject.top() - this.height / 2; + this.x = otherObject.centerX(); + } + else + { + this.y = otherObject.top() - 10; + this.x = otherObject.centerX() -this.textWidth / 2; + } +} + + +AnimatedLabel.prototype.getAlignTopPos = function(otherObject) +{ + if (this.centering) + { + return [otherObject.centerX(), otherObject.top() - this.height/ 2]; + } + else + { + return [otherObject.centerX() -this.textWidth / 2, otherObject.top() - 10]; + } +} + + +AnimatedLabel.prototype.alignBottom = function(otherObject) +{ + if (this.centering) + { + this.y = otherObject.bottom() + this.height / 2; + this.x = otherObject.centerX(); + } + else + { + this.y = otherObject.bottom(); + this.x = otherObject.centerX() - this.textWidth / 2; + } +} + + +AnimatedLabel.prototype.getAlignBottomPos = function(otherObject) +{ + if (this.centering) + { + return [otherObject.centerX(), otherObject.bottom() + this.height / 2]; + } + else + { + return [otherObject.centerX() - this.textWidth / 2, otherObject.bottom()]; + } +} + + + +AnimatedLabel.prototype.getWidth = function() +{ + return this.textWidth; +} + +AnimatedLabel.prototype.getHeight = function() +{ + return this.height; +} + +AnimatedLabel.prototype.setHeight = function(newHeight) +{ + this.height = newHeight; + this.textWidth =this.getTextWidth(); +} + +AnimatedLabel.prototype.setHighlight = function(value) +{ + this.highlighted = value; +} + +AnimatedLabel.prototype.createUndoDelete = function() +{ + return new UndoDeleteLabel(this.objectID, this.label, this.x, this.y, this.centering, this.labelColor, this.layer, this.highlightIndex); +} + + +AnimatedLabel.prototype.centerX = function() +{ + if (this.centering) + { + return this.x; + } + else + { + return this.x + this.textWidth; + } + +} + +AnimatedLabel.prototype.centerY = function() +{ + if (this.centering) + { + return this.y; + } + else + { + return this.y + this.height / 2; // + } + +} + +AnimatedLabel.prototype.top = function() +{ + if (this.centering) + { + return this.y - this.height/2; //TODO: Un-Hardwire + } + else + { + return this.y; + } +} + + +AnimatedLabel.prototype.bottom = function() +{ + if (this.centering) + { + return this.y + this.height/2; // TODO: + height / 2; + } + else + { + return this.y + this.height; // TODO: + hieght; + } +} + + +AnimatedLabel.prototype.right = function() +{ + if (this.centering) + { + return this.x + this.textWidth / 2; // TODO: + width / 2; + } + else + { + return this.x + this.textWidth; // TODO: + width; + } +} + + +AnimatedLabel.prototype.left = function() +{ + if (this.centering) + { + return this. x - this.textWidth / 2; + } + else + { + return this.x; // TODO: - a little? + } +} + + +AnimatedLabel.prototype.setHighlightIndex = function(hlIndex) +{ + // Only allow highlight index for labels that don't have End-Of-Line + if (this.label.indexOf("\n") == -1 && this.label.length > hlIndex) + { + this.highlightIndex = hlIndex; + this.highlightIndexDirty = true; + } + else + { + this.highlightIndex = -1; + + } +} + + + AnimatedLabel.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint) + { + return this.getClosestCardinalPoint(fromX, fromY); + } + +AnimatedLabel.prototype.getHeadPointerAttachPos = function (fromX, fromY) +{ + return this.getClosestCardinalPoint(fromX, fromY); +} + +AnimatedLabel.prototype.setText = function(newText, textIndex, initialWidth) +{ + this.label = newText; + if (initialWidth != undefined) + { + this.textWidth = initialWidth; + } + this.textWidth = this.getTextWidth(); +} + + + +function UndoDeleteLabel(id, lab, x, y, centered, color, l, hli) +{ + this.objectID = id; + this.posX = x; + this.posY = y; + this.nodeLabel = lab; + this.labCentered = centered; + this.labelColor = color; + this.layer = l; + this.highlightIndex = hli; + this.dirty = true; +} + +UndoDeleteLabel.inheritFrom(UndoBlock); + +UndoDeleteLabel.prototype.undoInitialStep = function(world) +{ + world.addLabelObject(this.objectID, this.nodeLabel, this.labCentered); + world.setNodePosition(this.objectID, this.posX, this.posY); + world.setForegroundColor(this.objectID, this.labelColor); + world.setLayer(this.objectID, this.layer); +} + diff --git a/AnimationLibrary/AnimatedLinkedList.js b/AnimationLibrary/AnimatedLinkedList.js index 14d4df7..1ad192f 100644 --- a/AnimationLibrary/AnimatedLinkedList.js +++ b/AnimationLibrary/AnimatedLinkedList.js @@ -1,469 +1,469 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor) -{ - this.w = wth; - this.h = hgt; - this.backgroundColor = fillColor; - this.foregroundColor = edgeColor; - this.val = val; - - this.vertical = verticalOrientation; - this.linkPositionEnd = linkPosEnd; - this.linkPercent = linkPer; - - this.numLabels = numLab; - this.objectID = id; - - // call superclass' constructor, which calls init - AnimatedLinkedList.superclass.constructor.call(this); -} - -AnimatedLinkedList.inheritFrom(AnimatedObject); - - -AnimatedLinkedList.prototype.init = function() -{ - AnimatedLinkedList.superclass.init.call(this); - - this.labels = []; - this.labelPosX = []; - this.labelPosY = []; - this.labelColors = []; - this.nullPointer = false; - - this.currentHeightDif = 6; - this.maxHeightDiff = 5; - this.minHeightDiff = 3; - - for (var i = 0; i < this.numLabels; i++) - { - this.labels[i] = ""; - this.labelPosX[i] = 0; - this.labelPosY[i] = 0; - this.labelColors[i] = this.foregroundColor; - } - - this.labels[0] = this.val; - this.highlighted = false; -} - - - -AnimatedLinkedList.prototype.left = function() -{ - if (this.vertical) - { - return this.x - this.w / 2.0; - } - else if (this.linkPositionEnd) - { - return this.x - ((this.w * (1 - this.linkPercent)) / 2); - } - else - { - return this.x - (this.w * (this.linkPercent + 1)) / 2; - } -} - - -AnimatedLinkedList.prototype.setNull = function(np) -{ - if (this.nullPointer != np) - { - this.nullPointer = np; - } - -} - -AnimatedLinkedList.prototype.getNull = function() -{ - return this.nullPointer; -} - -AnimatedLinkedList.prototype.right = function() -{ - if (this.vertical) - { - return this.x + this.w / 2.0; - } - else if (this.linkPositionEnd) - { - return this.x + ((this.w * (this.linkPercent + 1)) / 2); - } - else - { - return this.x + (this.w * (1 - this.linkPercent)) / 2; - } -} - -AnimatedLinkedList.prototype.top = function() -{ - if (!this.vertical) - { - return this.y - this.h / 2.0; - } - else if (this.linkPositionEnd) - { - return this.y - (this.h * (1 -this.linkPercent)) / 2; - } - else - { - return this.y - (this.h * (1 + this.linkPercent)) / 2; - } -} - -AnimatedLinkedList.prototype.bottom = function() -{ - if (!this.vertical) - { - return this.y + this.h / 2.0; - } - else if (this.linkPositionEnd) - { - return this.y + (this.h * (1 +this.linkPercent)) / 2; - } - else - { - return this.y + (this.h * (1 - this.linkPercent)) / 2; - } -} - - -// TODO: Should we move this to the draw function, and save the -// space of the arrays? Bit of a leftover from the Flash code, -// which did drawing differently -AnimatedLinkedList.prototype.resetTextPosition = function() -{ - if (this.vertical) - { - this.labelPosX[0] = this.x; - - this.labelPosY[0] = this.y + this.h * (1-this.linkPercent)/2 *(1/this.numLabels - 1); - // labelPosY[0] = -height * (1-linkPercent) / 2 + height*(1-linkPercent)/2*numLabels; - for (var i = 1; i < this.numLabels; i++) - { - this.labelPosY[i] = this.labelPosY[i-1] + this.h*(1-this.linkPercent)/this.numLabels; - this.labelPosX[i] = this.x; - } - } - else - { - this.labelPosY[0] = this.y; - this.labelPosX[0] = this.x + this.w * (1-this.linkPercent)/2*(1/this.numLabels - 1); - for (var i = 1; i < this.numLabels; i++) - { - this.labelPosY[i] = this.y; - this.labelPosX[i] = this.labelPosX[i-1] + this.w*(1-this.linkPercent)/this.numLabels; - } - } - -} - - -AnimatedLinkedList.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor) -{ - if (this.vertical && this.linkPositionEnd) - { - return [this.x, this.y + this.h / 2.0]; - } - else if (this.vertical && !this.linkPositionEnd) - { - return [this.x, this.y - this.h / 2.0]; - } - else if (!this.vertical && this.linkPositionEnd) - { - return [this.x + this.w / 2.0, this.y]; - } - else // (!this.vertical && !this.linkPositionEnd) - { - return [this.x - this.w / 2.0, this.y]; - } -} - - -AnimatedLinkedList.prototype.getHeadPointerAttachPos = function(fromX, fromY) -{ - return this.getClosestCardinalPoint(fromX, fromY); -} - - -AnimatedLinkedList.prototype.setWidth = function(wdth) -{ - this.w = wdth; - this.resetTextPosition(); -} - - -AnimatedLinkedList.prototype.setHeight = function(hght) -{ - this.h = hght; - this.resetTextPosition(); -} - -AnimatedLinkedList.prototype.getWidth = function() -{ - return this.w; -} - -AnimatedLinkedList.prototype.getHeight = function() -{ - return this.h; -} - -AnimatedLinkedList.prototype.draw = function(context) -{ - var startX; - var startY; - - startX = this.left(); - startY = this.top(); - - if (this.highlighted) - { - context.strokeStyle = "#ff0000"; - context.fillStyle = "#ff0000"; - - context.beginPath(); - context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); - context.closePath(); - context.stroke(); - context.fill(); - } - context.strokeStyle = this.foregroundColor; - context.fillStyle = this.backgroundColor; - - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX + this.w, startY); - context.lineTo(startX + this.w, startY + this.h); - context.lineTo(startX, startY + this.h); - context.lineTo(startX, startY); - context.closePath(); - context.stroke(); - context.fill(); - - var i; - if (this.vertical) - { - startX = this.left(); - for (i= 1; i < this.numLabels; i++) - { - //TODO: this doesn't look right ... - startY = this.y + this.h*(1-this.linkPercent)*(i / this.numLabels - 1/2); - - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX + this.w, startY); - context.closePath(); - context.stroke(); - } - } - else - { - startY = this.top(); - for (i = 1; i < this.numLabels; i++) - { - startX = this.x + this.w*(1-this.linkPercent)*(i / this.numLabels - 1/2); - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX, startY + this.h); - context.closePath(); - context.stroke(); - } - } - - if (this.vertical && this.linkPositionEnd) - { - startX = this.left(); - startY = this.bottom() - this.h * this.linkPercent; - - - context.beginPath(); - context.moveTo(startX + this.w ,startY); - context.lineTo(startX, startY); - if (this.nullPointer) - { - context.lineTo(this.startX + this.w, this.bottom()); - } - context.closePath(); - context.stroke(); - } - else if (this.vertical && !this.linkPositionEnd) - { - startX = this.left(); - startY = this.top() + this.h * this.linkPercent; - - context.beginPath(); - context.moveTo(startX + this.w ,startY); - context.lineTo(startX, startY); - if (this.nullPointer) - { - context.lineTo(startX + this.w, this.top()); - } - context.closePath(); - context.stroke(); - - } - else if (!this.vertical && this.linkPositionEnd) - { - startX = this.right() - this.w * this.linkPercent; - startY = this.top(); - - context.beginPath(); - context.moveTo(startX, startY + this.h); - context.lineTo(startX, startY); - if (this.nullPointer) - { - context.lineTo(this.right(), startY + this.h); - } - context.closePath(); - context.stroke(); - - } - else // (!vertical && !linkPositionEnd) - { - startX = this.left() + this.w * this.linkPercent; - startY = this.top() ; - - context.beginPath(); - context.moveTo(startX, startY + this.h); - context.lineTo(startX, startY); - if (this.nullPointer) - { - context.lineTo(this.left(), startY); - } - context.closePath(); - context.stroke(); - } - - - context.textAlign = 'center'; - context.font = '10px sans-serif'; - context.textBaseline = 'middle'; - context.lineWidth = 1; - - - this.resetTextPosition(); - for (i = 0; i < this.numLabels; i++) - { - context.fillStyle = this.labelColors[i]; - context.fillText(this.labels[i], this.labelPosX[i], this.labelPosY[i]); - } -} - - - -AnimatedLinkedList.prototype.setTextColor = function(color, textIndex) -{ - - this.labelColors[textIndex] = color; -} - - - -AnimatedLinkedList.prototype.getTextColor = function(textIndex) -{ - return this.labelColors[textIndex]; -} - - - -AnimatedLinkedList.prototype.getText = function(index) -{ - return this.labels[index]; -} - -AnimatedLinkedList.prototype.setText = function(newText, textIndex) -{ - this.labels[textIndex] = newText; - this.resetTextPosition(); -} - - - - - - - -AnimatedLinkedList.prototype.createUndoDelete = function() -{ - return new UndoDeleteLinkedList(this.objectID, this.numLabels, this.labels, this.x, this.y, this.w, this.h, this.linkPercent, - this.linkPositionEnd, this.vertical, this.labelColors, this.backgroundColor, this.foregroundColor, - this.layer, this.nullPointer); -} - -AnimatedLinkedList.prototype.setHighlight = function(value) -{ - if (value != this.highlighted) - { - this.highlighted = value; - } -} - - - - -function UndoDeleteLinkedList(id, numlab, lab, x, y, w, h, linkper, posEnd, vert, labColors, bgColor, fgColor, l, np) -{ - this.objectID = id; - this.posX = x; - this.posY = y; - this.width = w; - this.height = h; - this.backgroundColor= bgColor; - this.foregroundColor = fgColor; - this.labels = lab; - this.linkPercent = linkper; - this.verticalOrentation = vert; - this.linkAtEnd = posEnd; - this.labelColors = labColors - this.layer = l; - this.numLabels = numlab; - this.nullPointer = np; -} - -UndoDeleteLinkedList.inheritFrom(UndoBlock); - - - -UndoDeleteLinkedList.prototype.undoInitialStep =function(world) -{ - world.addLinkedListObject(this.objectID,this.labels[0], this.width, this.height, this.linkPercent, this.verticalOrentation, this.linkAtEnd, this.numLabels, this.backgroundColor, this.foregroundColor); - world.setNodePosition(this.objectID, this.posX, this.posY); - world.setLayer(this.objectID, this.layer); - world.setNull(this.objectID, this.nullPointer); - for (var i = 0; i < this.numLabels; i++) - { - world.setText(this.objectID, this.labels[i], i); - world.setTextColor(this.objectID, this.labelColors[i], i); - } -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor) +{ + this.w = wth; + this.h = hgt; + this.backgroundColor = fillColor; + this.foregroundColor = edgeColor; + this.val = val; + + this.vertical = verticalOrientation; + this.linkPositionEnd = linkPosEnd; + this.linkPercent = linkPer; + + this.numLabels = numLab; + this.objectID = id; + + // call superclass' constructor, which calls init + AnimatedLinkedList.superclass.constructor.call(this); +} + +AnimatedLinkedList.inheritFrom(AnimatedObject); + + +AnimatedLinkedList.prototype.init = function() +{ + AnimatedLinkedList.superclass.init.call(this); + + this.labels = []; + this.labelPosX = []; + this.labelPosY = []; + this.labelColors = []; + this.nullPointer = false; + + this.currentHeightDif = 6; + this.maxHeightDiff = 5; + this.minHeightDiff = 3; + + for (var i = 0; i < this.numLabels; i++) + { + this.labels[i] = ""; + this.labelPosX[i] = 0; + this.labelPosY[i] = 0; + this.labelColors[i] = this.foregroundColor; + } + + this.labels[0] = this.val; + this.highlighted = false; +} + + + +AnimatedLinkedList.prototype.left = function() +{ + if (this.vertical) + { + return this.x - this.w / 2.0; + } + else if (this.linkPositionEnd) + { + return this.x - ((this.w * (1 - this.linkPercent)) / 2); + } + else + { + return this.x - (this.w * (this.linkPercent + 1)) / 2; + } +} + + +AnimatedLinkedList.prototype.setNull = function(np) +{ + if (this.nullPointer != np) + { + this.nullPointer = np; + } + +} + +AnimatedLinkedList.prototype.getNull = function() +{ + return this.nullPointer; +} + +AnimatedLinkedList.prototype.right = function() +{ + if (this.vertical) + { + return this.x + this.w / 2.0; + } + else if (this.linkPositionEnd) + { + return this.x + ((this.w * (this.linkPercent + 1)) / 2); + } + else + { + return this.x + (this.w * (1 - this.linkPercent)) / 2; + } +} + +AnimatedLinkedList.prototype.top = function() +{ + if (!this.vertical) + { + return this.y - this.h / 2.0; + } + else if (this.linkPositionEnd) + { + return this.y - (this.h * (1 -this.linkPercent)) / 2; + } + else + { + return this.y - (this.h * (1 + this.linkPercent)) / 2; + } +} + +AnimatedLinkedList.prototype.bottom = function() +{ + if (!this.vertical) + { + return this.y + this.h / 2.0; + } + else if (this.linkPositionEnd) + { + return this.y + (this.h * (1 +this.linkPercent)) / 2; + } + else + { + return this.y + (this.h * (1 - this.linkPercent)) / 2; + } +} + + +// TODO: Should we move this to the draw function, and save the +// space of the arrays? Bit of a leftover from the Flash code, +// which did drawing differently +AnimatedLinkedList.prototype.resetTextPosition = function() +{ + if (this.vertical) + { + this.labelPosX[0] = this.x; + + this.labelPosY[0] = this.y + this.h * (1-this.linkPercent)/2 *(1/this.numLabels - 1); + // labelPosY[0] = -height * (1-linkPercent) / 2 + height*(1-linkPercent)/2*numLabels; + for (var i = 1; i < this.numLabels; i++) + { + this.labelPosY[i] = this.labelPosY[i-1] + this.h*(1-this.linkPercent)/this.numLabels; + this.labelPosX[i] = this.x; + } + } + else + { + this.labelPosY[0] = this.y; + this.labelPosX[0] = this.x + this.w * (1-this.linkPercent)/2*(1/this.numLabels - 1); + for (var i = 1; i < this.numLabels; i++) + { + this.labelPosY[i] = this.y; + this.labelPosX[i] = this.labelPosX[i-1] + this.w*(1-this.linkPercent)/this.numLabels; + } + } + +} + + +AnimatedLinkedList.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor) +{ + if (this.vertical && this.linkPositionEnd) + { + return [this.x, this.y + this.h / 2.0]; + } + else if (this.vertical && !this.linkPositionEnd) + { + return [this.x, this.y - this.h / 2.0]; + } + else if (!this.vertical && this.linkPositionEnd) + { + return [this.x + this.w / 2.0, this.y]; + } + else // (!this.vertical && !this.linkPositionEnd) + { + return [this.x - this.w / 2.0, this.y]; + } +} + + +AnimatedLinkedList.prototype.getHeadPointerAttachPos = function(fromX, fromY) +{ + return this.getClosestCardinalPoint(fromX, fromY); +} + + +AnimatedLinkedList.prototype.setWidth = function(wdth) +{ + this.w = wdth; + this.resetTextPosition(); +} + + +AnimatedLinkedList.prototype.setHeight = function(hght) +{ + this.h = hght; + this.resetTextPosition(); +} + +AnimatedLinkedList.prototype.getWidth = function() +{ + return this.w; +} + +AnimatedLinkedList.prototype.getHeight = function() +{ + return this.h; +} + +AnimatedLinkedList.prototype.draw = function(context) +{ + var startX; + var startY; + + startX = this.left(); + startY = this.top(); + + if (this.highlighted) + { + context.strokeStyle = "#ff0000"; + context.fillStyle = "#ff0000"; + + context.beginPath(); + context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); + context.closePath(); + context.stroke(); + context.fill(); + } + context.strokeStyle = this.foregroundColor; + context.fillStyle = this.backgroundColor; + + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX + this.w, startY); + context.lineTo(startX + this.w, startY + this.h); + context.lineTo(startX, startY + this.h); + context.lineTo(startX, startY); + context.closePath(); + context.stroke(); + context.fill(); + + var i; + if (this.vertical) + { + startX = this.left(); + for (i= 1; i < this.numLabels; i++) + { + //TODO: this doesn't look right ... + startY = this.y + this.h*(1-this.linkPercent)*(i / this.numLabels - 1/2); + + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX + this.w, startY); + context.closePath(); + context.stroke(); + } + } + else + { + startY = this.top(); + for (i = 1; i < this.numLabels; i++) + { + startX = this.x + this.w*(1-this.linkPercent)*(i / this.numLabels - 1/2); + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX, startY + this.h); + context.closePath(); + context.stroke(); + } + } + + if (this.vertical && this.linkPositionEnd) + { + startX = this.left(); + startY = this.bottom() - this.h * this.linkPercent; + + + context.beginPath(); + context.moveTo(startX + this.w ,startY); + context.lineTo(startX, startY); + if (this.nullPointer) + { + context.lineTo(this.startX + this.w, this.bottom()); + } + context.closePath(); + context.stroke(); + } + else if (this.vertical && !this.linkPositionEnd) + { + startX = this.left(); + startY = this.top() + this.h * this.linkPercent; + + context.beginPath(); + context.moveTo(startX + this.w ,startY); + context.lineTo(startX, startY); + if (this.nullPointer) + { + context.lineTo(startX + this.w, this.top()); + } + context.closePath(); + context.stroke(); + + } + else if (!this.vertical && this.linkPositionEnd) + { + startX = this.right() - this.w * this.linkPercent; + startY = this.top(); + + context.beginPath(); + context.moveTo(startX, startY + this.h); + context.lineTo(startX, startY); + if (this.nullPointer) + { + context.lineTo(this.right(), startY + this.h); + } + context.closePath(); + context.stroke(); + + } + else // (!vertical && !linkPositionEnd) + { + startX = this.left() + this.w * this.linkPercent; + startY = this.top() ; + + context.beginPath(); + context.moveTo(startX, startY + this.h); + context.lineTo(startX, startY); + if (this.nullPointer) + { + context.lineTo(this.left(), startY); + } + context.closePath(); + context.stroke(); + } + + + context.textAlign = 'center'; + context.font = '10px sans-serif'; + context.textBaseline = 'middle'; + context.lineWidth = 1; + + + this.resetTextPosition(); + for (i = 0; i < this.numLabels; i++) + { + context.fillStyle = this.labelColors[i]; + context.fillText(this.labels[i], this.labelPosX[i], this.labelPosY[i]); + } +} + + + +AnimatedLinkedList.prototype.setTextColor = function(color, textIndex) +{ + + this.labelColors[textIndex] = color; +} + + + +AnimatedLinkedList.prototype.getTextColor = function(textIndex) +{ + return this.labelColors[textIndex]; +} + + + +AnimatedLinkedList.prototype.getText = function(index) +{ + return this.labels[index]; +} + +AnimatedLinkedList.prototype.setText = function(newText, textIndex) +{ + this.labels[textIndex] = newText; + this.resetTextPosition(); +} + + + + + + + +AnimatedLinkedList.prototype.createUndoDelete = function() +{ + return new UndoDeleteLinkedList(this.objectID, this.numLabels, this.labels, this.x, this.y, this.w, this.h, this.linkPercent, + this.linkPositionEnd, this.vertical, this.labelColors, this.backgroundColor, this.foregroundColor, + this.layer, this.nullPointer); +} + +AnimatedLinkedList.prototype.setHighlight = function(value) +{ + if (value != this.highlighted) + { + this.highlighted = value; + } +} + + + + +function UndoDeleteLinkedList(id, numlab, lab, x, y, w, h, linkper, posEnd, vert, labColors, bgColor, fgColor, l, np) +{ + this.objectID = id; + this.posX = x; + this.posY = y; + this.width = w; + this.height = h; + this.backgroundColor= bgColor; + this.foregroundColor = fgColor; + this.labels = lab; + this.linkPercent = linkper; + this.verticalOrentation = vert; + this.linkAtEnd = posEnd; + this.labelColors = labColors + this.layer = l; + this.numLabels = numlab; + this.nullPointer = np; +} + +UndoDeleteLinkedList.inheritFrom(UndoBlock); + + + +UndoDeleteLinkedList.prototype.undoInitialStep =function(world) +{ + world.addLinkedListObject(this.objectID,this.labels[0], this.width, this.height, this.linkPercent, this.verticalOrentation, this.linkAtEnd, this.numLabels, this.backgroundColor, this.foregroundColor); + world.setNodePosition(this.objectID, this.posX, this.posY); + world.setLayer(this.objectID, this.layer); + world.setNull(this.objectID, this.nullPointer); + for (var i = 0; i < this.numLabels; i++) + { + world.setText(this.objectID, this.labels[i], i); + world.setTextColor(this.objectID, this.labelColors[i], i); + } +} diff --git a/AnimationLibrary/AnimatedRectangle.js b/AnimationLibrary/AnimatedRectangle.js index a3c9a84..7816d06 100644 --- a/AnimationLibrary/AnimatedRectangle.js +++ b/AnimationLibrary/AnimatedRectangle.js @@ -1,341 +1,341 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -// Values for xJust / yJust: "center", "left", "right", "top", "bottom" - -AnimatedRectangle = function(id, val, wth, hgt, xJust, yJust, fillColor, edgeColor) -{ - // call superclass' constructor - AnimatedRectangle.superclass.constructor.call(this); - - this.w = wth; - this.h = hgt; - this.xJustify = xJust; - this.yJustify = yJust; - this.label = val; - this.labelColor = edgeColor - - this.backgroundColor = fillColor; - this.foregroundColor = edgeColor; - this.labelColor = this.foregroundColor; - this.highlighted = false; - this.objectID = id; - this.nullPointer = false; - this.alpha = 1.0; - this.addedToScene = true; - -} - -AnimatedRectangle.inheritFrom(AnimatedObject); - -AnimatedRectangle.prototype.setNull = function(np) -{ - this.nullPointer = np; -} - -AnimatedRectangle.prototype.getNull = function() -{ - return this.nullPointer; -} - - -AnimatedRectangle.prototype.left = function() -{ - if (this.xJustify == "left") - { - return this.x; - } - else if (this.xJustify == "center") - { - return this.x - this.w / 2.0; - } - else // (this.xJustify == "right") - { - return this.x - this.w; - } - -} - -AnimatedRectangle.prototype.centerX = function() -{ - if (this.xJustify == "center") - { - return this.x; - } - else if (this.xJustify == "left") - { - return this.x + this.w / 2.0; - } - else // (this.xJustify == "right") - { - return this.x - this.w / 2.0; - } -} - -AnimatedRectangle.prototype.centerY = function() -{ - if (this.yJustify == "center") - { - return this.y; - } - else if (this.yJustify == "top") - { - return this.y + this.h / 2.0; - } - else // (this.xJustify == "bottom") - { - return this.y - this.w / 2.0; - } - -} - -AnimatedRectangle.prototype.top = function() -{ - if (this.yJustify == "top") - { - return this.y; - } - else if (this.yJustify == "center") - { - return this.y - this.h / 2.0; - } - else //(this.xJustify == "bottom") - { - return this.y - this.h; - } -} - -AnimatedRectangle.prototype.bottom = function() -{ - if (this.yJustify == "top") - { - return this.y + this.h; - } - else if (this.yJustify == "center") - { - return this.y + this.h / 2.0; - } - else //(this.xJustify == "bottom") - { - return this.y; - } -} - - -AnimatedRectangle.prototype.right = function() -{ - if (this.xJustify == "left") - { - return this.x + this.w; - } - else if (this.xJustify == "center") - { - return this.x + this.w / 2.0; - } - else // (this.xJustify == "right") - { - return this.x; - } -} - - -AnimatedRectangle.prototype.getHeadPointerAttachPos = function(fromX, fromY) -{ - return this.getClosestCardinalPoint(fromX, fromY); -} - - -AnimatedRectangle.prototype.setWidth = function(wdth) -{ - this.w = wdth; -} - - -AnimatedRectangle.prototype.setHeight = function(hght) -{ - this.h = hght; -} - -AnimatedRectangle.prototype.getWidth = function() -{ - return this.w; -} - -AnimatedRectangle.prototype.getHeight = function() -{ - return this.h; -} - - -// TODO: Fix me! -AnimatedRectangle.prototype.draw = function(context) -{ - if (!this.addedToScene) - { - return; - } - - var startX; - var startY; - var labelPosX; - var labelPosY; - - context.globalAlpha = this.alpha; - - if (this.xJustify == "left") - { - startX = this.x; - labelPosX = this.x + this.w / 2.0; - } - else if (this.xJustify == "center") - { - startX = this.x-this.w / 2.0; - labelPosX = this.x; - - } - else if (this.xJustify == "right") - { - startX = this.x-this.w; - labelPosX = this.x - this.w / 2.0 - } - if (this.yJustify == "top") - { - startY = this.y; - labelPosY = this.y + this.h / 2.0; - } - else if (this.yJustify == "center") - { - startY = this.y - this.h / 2.0; - labelPosY = this.y; - - } - else if (this.yJustify == "bottom") - { - startY = this.y - this.h; - labelPosY = this.y - this.h / 2.0; - } - - context.lineWidth = 1; - - if (this.highlighted) - { - context.strokeStyle = "#ff0000"; - context.fillStyle = "#ff0000"; - - context.beginPath(); - context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff); - context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff); - context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); - context.closePath(); - context.stroke(); - context.fill(); - - } - context.strokeStyle = this.foregroundColor; - context.fillStyle = this.backgroundColor; - - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX + this.w, startY); - context.lineTo(startX + this.w, startY + this.h); - context.lineTo(startX, startY + this.h); - context.lineTo(startX, startY); - context.closePath(); - context.stroke(); - context.fill(); - - if (this.nullPointer) - { - context.beginPath(); - context.moveTo(startX ,startY); - context.lineTo(startX + this.w, startY + this.h); - context.closePath(); - context.stroke(); - } - - context.fillStyle = this.labelColor; - - context.textAlign = 'center'; - context.font = '10px sans-serif'; - context.textBaseline = 'middle'; - context.lineWidth = 1; - context.fillText(this.label, this.x, this.y); - - - -} - -AnimatedRectangle.prototype.setText = function(newText, textIndex) -{ - this.label = newText; - // TODO: setting text position? -} - - -AnimatedRectangle.prototype.createUndoDelete = function() -{ - // TODO: Add color? - return new UndoDeleteRectangle(this.objectID, this.label, this.x, this.y, this.w, this.h, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor, this.highlighted, this.layer); -} - -AnimatedRectangle.prototype.setHighlight = function(value) -{ - this.highlighted = value; -} - - - -function UndoDeleteRectangle(id, lab, x, y, w, h, xJust, yJust, bgColor, fgColor, highlight, lay) -{ - this.objectID = id; - this.posX = x; - this.posY = y; - this.width = w; - this.height = h; - this.xJustify = xJust; - this.yJustify = yJust; - this.backgroundColor= bgColor; - this.foregroundColor = fgColor; - this.nodeLabel = lab; - this.layer = lay; - this.highlighted = highlight; -} - -UndoDeleteRectangle.inheritFrom(UndoBlock); - - -UndoDeleteRectangle.prototype.undoInitialStep = function(world) -{ - world.addRectangleObject(this.objectID, this.nodeLabel, this.width, this.height, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor); - world.setNodePosition(this.objectID, this.posX, this.posY); - world.setLayer(this.objectID, this.layer); - world.setHighlight(this.objectID, this.highlighted); -} - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +// Values for xJust / yJust: "center", "left", "right", "top", "bottom" + +AnimatedRectangle = function(id, val, wth, hgt, xJust, yJust, fillColor, edgeColor) +{ + // call superclass' constructor + AnimatedRectangle.superclass.constructor.call(this); + + this.w = wth; + this.h = hgt; + this.xJustify = xJust; + this.yJustify = yJust; + this.label = val; + this.labelColor = edgeColor + + this.backgroundColor = fillColor; + this.foregroundColor = edgeColor; + this.labelColor = this.foregroundColor; + this.highlighted = false; + this.objectID = id; + this.nullPointer = false; + this.alpha = 1.0; + this.addedToScene = true; + +} + +AnimatedRectangle.inheritFrom(AnimatedObject); + +AnimatedRectangle.prototype.setNull = function(np) +{ + this.nullPointer = np; +} + +AnimatedRectangle.prototype.getNull = function() +{ + return this.nullPointer; +} + + +AnimatedRectangle.prototype.left = function() +{ + if (this.xJustify == "left") + { + return this.x; + } + else if (this.xJustify == "center") + { + return this.x - this.w / 2.0; + } + else // (this.xJustify == "right") + { + return this.x - this.w; + } + +} + +AnimatedRectangle.prototype.centerX = function() +{ + if (this.xJustify == "center") + { + return this.x; + } + else if (this.xJustify == "left") + { + return this.x + this.w / 2.0; + } + else // (this.xJustify == "right") + { + return this.x - this.w / 2.0; + } +} + +AnimatedRectangle.prototype.centerY = function() +{ + if (this.yJustify == "center") + { + return this.y; + } + else if (this.yJustify == "top") + { + return this.y + this.h / 2.0; + } + else // (this.xJustify == "bottom") + { + return this.y - this.w / 2.0; + } + +} + +AnimatedRectangle.prototype.top = function() +{ + if (this.yJustify == "top") + { + return this.y; + } + else if (this.yJustify == "center") + { + return this.y - this.h / 2.0; + } + else //(this.xJustify == "bottom") + { + return this.y - this.h; + } +} + +AnimatedRectangle.prototype.bottom = function() +{ + if (this.yJustify == "top") + { + return this.y + this.h; + } + else if (this.yJustify == "center") + { + return this.y + this.h / 2.0; + } + else //(this.xJustify == "bottom") + { + return this.y; + } +} + + +AnimatedRectangle.prototype.right = function() +{ + if (this.xJustify == "left") + { + return this.x + this.w; + } + else if (this.xJustify == "center") + { + return this.x + this.w / 2.0; + } + else // (this.xJustify == "right") + { + return this.x; + } +} + + +AnimatedRectangle.prototype.getHeadPointerAttachPos = function(fromX, fromY) +{ + return this.getClosestCardinalPoint(fromX, fromY); +} + + +AnimatedRectangle.prototype.setWidth = function(wdth) +{ + this.w = wdth; +} + + +AnimatedRectangle.prototype.setHeight = function(hght) +{ + this.h = hght; +} + +AnimatedRectangle.prototype.getWidth = function() +{ + return this.w; +} + +AnimatedRectangle.prototype.getHeight = function() +{ + return this.h; +} + + +// TODO: Fix me! +AnimatedRectangle.prototype.draw = function(context) +{ + if (!this.addedToScene) + { + return; + } + + var startX; + var startY; + var labelPosX; + var labelPosY; + + context.globalAlpha = this.alpha; + + if (this.xJustify == "left") + { + startX = this.x; + labelPosX = this.x + this.w / 2.0; + } + else if (this.xJustify == "center") + { + startX = this.x-this.w / 2.0; + labelPosX = this.x; + + } + else if (this.xJustify == "right") + { + startX = this.x-this.w; + labelPosX = this.x - this.w / 2.0 + } + if (this.yJustify == "top") + { + startY = this.y; + labelPosY = this.y + this.h / 2.0; + } + else if (this.yJustify == "center") + { + startY = this.y - this.h / 2.0; + labelPosY = this.y; + + } + else if (this.yJustify == "bottom") + { + startY = this.y - this.h; + labelPosY = this.y - this.h / 2.0; + } + + context.lineWidth = 1; + + if (this.highlighted) + { + context.strokeStyle = "#ff0000"; + context.fillStyle = "#ff0000"; + + context.beginPath(); + context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff); + context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff); + context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff); + context.closePath(); + context.stroke(); + context.fill(); + + } + context.strokeStyle = this.foregroundColor; + context.fillStyle = this.backgroundColor; + + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX + this.w, startY); + context.lineTo(startX + this.w, startY + this.h); + context.lineTo(startX, startY + this.h); + context.lineTo(startX, startY); + context.closePath(); + context.stroke(); + context.fill(); + + if (this.nullPointer) + { + context.beginPath(); + context.moveTo(startX ,startY); + context.lineTo(startX + this.w, startY + this.h); + context.closePath(); + context.stroke(); + } + + context.fillStyle = this.labelColor; + + context.textAlign = 'center'; + context.font = '10px sans-serif'; + context.textBaseline = 'middle'; + context.lineWidth = 1; + context.fillText(this.label, this.x, this.y); + + + +} + +AnimatedRectangle.prototype.setText = function(newText, textIndex) +{ + this.label = newText; + // TODO: setting text position? +} + + +AnimatedRectangle.prototype.createUndoDelete = function() +{ + // TODO: Add color? + return new UndoDeleteRectangle(this.objectID, this.label, this.x, this.y, this.w, this.h, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor, this.highlighted, this.layer); +} + +AnimatedRectangle.prototype.setHighlight = function(value) +{ + this.highlighted = value; +} + + + +function UndoDeleteRectangle(id, lab, x, y, w, h, xJust, yJust, bgColor, fgColor, highlight, lay) +{ + this.objectID = id; + this.posX = x; + this.posY = y; + this.width = w; + this.height = h; + this.xJustify = xJust; + this.yJustify = yJust; + this.backgroundColor= bgColor; + this.foregroundColor = fgColor; + this.nodeLabel = lab; + this.layer = lay; + this.highlighted = highlight; +} + +UndoDeleteRectangle.inheritFrom(UndoBlock); + + +UndoDeleteRectangle.prototype.undoInitialStep = function(world) +{ + world.addRectangleObject(this.objectID, this.nodeLabel, this.width, this.height, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor); + world.setNodePosition(this.objectID, this.posX, this.posY); + world.setLayer(this.objectID, this.layer); + world.setHighlight(this.objectID, this.highlighted); +} + + + diff --git a/AnimationLibrary/AnimationMain.js b/AnimationLibrary/AnimationMain.js index be86e2f..e27390e 100644 --- a/AnimationLibrary/AnimationMain.js +++ b/AnimationLibrary/AnimationMain.js @@ -1,1338 +1,1338 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -// Global timer used for doing animation callbacks. -// TODO: Make this an instance variable of Animation Manager. -// var timer; -// var swapped = false; - - -function reorderSibling(node1, node2) -{ - node1.parentNode.replaceChild(node1, node2); - node1.parentNode.insertBefore(node2, node1); -} - - -function swapControlDiv() -{ - this.swapped = !this.swapped; - if (this.swapped) { - reorderSibling(this.canvas, this.generalControlBar.parentNode); - setCookie("VisualizationControlSwapped", "true", 30); - - } else { - reorderSibling(this.generalControlBar.parentNode, this.canvas); - setCookie("VisualizationControlSwapped", "false", 30); - - } -} - - -// Utility funciton to read a cookie -function getCookie(cookieName) -{ - var i, x, y; - var cookies=document.cookie.split(";"); - for (i=0; i < cookies.length; i++) - { - x=cookies[i].substr(0,cookies[i].indexOf("=")); - y=cookies[i].substr(cookies[i].indexOf("=")+1); - x=x.replace(/^\s+|\s+$/g,""); - if (x==cookieName) - { - return unescape(y); - } - } -} - -// Utility funciton to write a cookie -function setCookie(cookieName,value,expireDays) -{ - var exdate=new Date(); - exdate.setDate(exdate.getDate() + expireDays); - var cookieValue=escape(value) + ((expireDays==null) ? "" : "; expires="+exdate.toUTCString()); - document.cookie=cookieName + "=" + value; -} - - -var ANIMATION_SPEED_DEFAULT = 75; - - -// TODO: Move these out of global space into animation manager? -// var objectManager; -// var animationManager; -// var canvas; - -// var paused = false; -// var playPauseBackButton; -// var skipBackButton; -// var stepBackButton; -// var stepForwardButton; -// var skipForwardButton; - -// var widthEntry; -// var heightEntry; -// var sizeButton; - - - -function returnSubmit(field, funct, maxsize, intOnly) -{ - - if (maxsize != undefined) - { - field.size = maxsize; - } - return function(event) - { - var keyASCII = 0; - if(window.event) // IE - { - keyASCII = event.keyCode - } - else if (event.which) // Netscape/Firefox/Opera - { - keyASCII = event.which - } - - if (keyASCII == 13) - { - funct(); - return false; - } - else if (keyASCII == 59 || keyASCII == 45 || keyASCII == 46 || keyASCII == 190 || keyASCII == 173) - { - return false; - } - else if (maxsize != undefined && field.value.length >= maxsize || - intOnly && (keyASCII < 48 || keyASCII > 57)) - - { - if (!controlKey(keyASCII)) - return false; - } - return true; - - } - -} - - -function animWaiting() -{ - this.stepForwardButton.disabled = false; - if (this.skipBackButton.disabled == false) - { - this.stepBackButton.disabled = false; - } - this.objectManager.statusReport.setText("Animation Paused"); - this.objectManager.statusReport.setForegroundColor("#FF0000"); -} - -function animStarted() -{ - this.skipForwardButton.disabled = false; - this.skipBackButton.disabled = false; - this.stepForwardButton.disabled = true; - this.stepBackButton.disabled = true; - this.objectManager.statusReport.setText("Animation Running"); - this.objectManager.statusReport.setForegroundColor("#009900"); -} - -function animEnded() -{ - this.skipForwardButton.disabled = true; - this.stepForwardButton.disabled = true; - if (this.skipBackButton.disabled == false && this.paused) - { - this.stepBackButton.disabled = false; - } - // this.objectManager.statusReport.setText("Animation Completed"); - this.objectManager.statusReport.setText(""); - this.objectManager.statusReport.setForegroundColor("#000000"); -} - - - -function anumUndoUnavailable() -{ - this.skipBackButton.disabled = true; - this.stepBackButton.disabled = true; -} - - -function timeout() -{ - // We need to set the timeout *first*, otherwise if we - // try to clear it later, we get behavior we don't want ... - this.timer = setTimeout(timeout.bind(this), 30); - this.update(); - this.objectManager.draw(); - -} - - -function doPlayPause() -{ - this.paused = !this.paused; - if (this.paused) - { - this.playPauseBackButton.setAttribute("value", "play"); - if (this.skipBackButton.disabled == false) - { - this.stepBackButton.disabled = false; - } - - } - else - { - this.playPauseBackButton.setAttribute("value", "pause"); - } - this.SetPaused(this.paused); -} - - -// Creates and returs an AnimationManager -function initCanvas(canvas, generalControlBar, algorithmControlBar) -{ - // UI nodes should be given, otherwise use defaults. - // This is the only place where getElementById is used - if(!canvas) canvas = document.getElementById("canvas"); - if(!generalControlBar) generalControlBar = document.getElementById('GeneralAnimationControls'); - if(!algorithmControlBar) algorithmControlBar = document.getElementById("AlgorithmSpecificControls"); - - var objectManager = new ObjectManager(canvas); - var animationManager = new AnimationManager(objectManager); - animationManager.canvas = canvas; - animationManager.generalControlBar = generalControlBar; - animationManager.algorithmControlBar = algorithmControlBar; - - animationManager.skipBackButton = animationManager.addControlToAnimationBar("Button", "Skip Back"); - animationManager.skipBackButton.onclick = animationManager.skipBack.bind(animationManager); - animationManager.stepBackButton = animationManager.addControlToAnimationBar("Button", "Step Back"); - animationManager.stepBackButton.onclick = animationManager.stepBack.bind(animationManager); - animationManager.playPauseBackButton = animationManager.addControlToAnimationBar("Button", "Pause"); - animationManager.playPauseBackButton.onclick = doPlayPause.bind(animationManager); - animationManager.stepForwardButton = animationManager.addControlToAnimationBar("Button", "Step Forward"); - animationManager.stepForwardButton.onclick = animationManager.step.bind(animationManager) ; - animationManager.skipForwardButton = animationManager.addControlToAnimationBar("Button", "Skip Forward"); - animationManager.skipForwardButton.onclick = animationManager.skipForward.bind(animationManager); - - - var element = document.createElement("div"); - element.setAttribute("display", "inline-block"); - element.setAttribute("float", "left"); - - - var tableEntry = document.createElement("td"); - - - - - - var newTable = document.createElement("table"); - - var midLevel = document.createElement("tr"); - var bottomLevel = document.createElement("td"); - midLevel.appendChild(bottomLevel); - bottomLevel.appendChild(element); - newTable.appendChild(midLevel); - - - - midLevel = document.createElement("tr"); - bottomLevel = document.createElement("td"); - bottomLevel.align = "center"; - var txtNode = document.createTextNode("Animation Speed"); - midLevel.appendChild(bottomLevel); - bottomLevel.appendChild(txtNode); - newTable.appendChild(midLevel); - - - - tableEntry.appendChild(newTable); - - - - //Append the element in page (in span). - if(generalControlBar) - generalControlBar.appendChild(tableEntry); - - //tableEntry.appendChild(element); - - var speed = getCookie("VisualizationSpeed"); - if (speed == null || speed == "") - { - speed = ANIMATION_SPEED_DEFAULT; - } - else - { - speed = parseInt(speed); - } - - if(generalControlBar) { - $(element).slider({ - animate: true, - value: speed, - change: function(e, ui) - { - setCookie("VisualizationSpeed", String(ui.value), 30); - }, - slide : function(e, ui){ - animationManager.SetSpeed(ui.value); - } - - }); - } - - animationManager.SetSpeed(speed); - - element.setAttribute("style", "width:200px"); - - - - var width=getCookie("VisualizationWidth"); - if (width == null || width == "") - { - width = canvas.width; - } - else - { - width = parseInt(width); - } - var height=getCookie("VisualizationHeight"); - if (height == null || height == "") - { - height = canvas.height; - } - else - { - height = parseInt(height); - } - - var swappedControls=getCookie("VisualizationControlSwapped"); - this.swapped = swappedControls == "true" - if (this.swapped) - { - reorderSibling(this.canvas, this.generalControlBar.parentNode); - } - - canvas.width = width; - canvas.height = height; - - - - tableEntry = document.createElement("td"); - txtNode = document.createTextNode(" w:"); - tableEntry.appendChild(txtNode); - if(generalControlBar) - generalControlBar.appendChild(tableEntry); - - - animationManager.widthEntry = animationManager.addControlToAnimationBar("Text", canvas.width); - animationManager.widthEntry.size = 4; - animationManager.widthEntry.onkeydown = this.returnSubmit(animationManager.widthEntry, animationManager.changeSize.bind(animationManager), 4, true); - - - tableEntry = document.createElement("td"); - txtNode = document.createTextNode(" h:"); - tableEntry.appendChild(txtNode); - if(generalControlBar) - generalControlBar.appendChild(tableEntry); - - animationManager.heightEntry = animationManager.addControlToAnimationBar("Text", canvas.height); - animationManager.heightEntry.onkeydown = this.returnSubmit(animationManager.heightEntry, animationManager.changeSize.bind(animationManager), 4, true); - -// heightEntry.size = 4; - animationManager.sizeButton = animationManager.addControlToAnimationBar("Button", "Change Canvas Size"); - - animationManager.sizeButton.onclick = animationManager.changeSize.bind(animationManager) ; - - - animationManager.swapButton = animationManager.addControlToAnimationBar("Button", "Move Controls"); - animationManager.swapButton.onclick = swapControlDiv.bind(animationManager); - - - animationManager.addListener("AnimationStarted", animationManager, animStarted); - animationManager.addListener("AnimationEnded", animationManager, animEnded); - animationManager.addListener("AnimationWaiting", animationManager, animWaiting); - animationManager.addListener("AnimationUndoUnavailable", animationManager, anumUndoUnavailable); - objectManager.width = canvas.width; - objectManager.height = canvas.height; - return animationManager; -} - - - -function AnimationManager(objectManager) -{ - AnimationManager.superclass.constructor.call(this); - - // Holder for all animated objects. - // All animation is done by manipulating objects in\ - // this container - this.animatedObjects = objectManager; - // TODO: change this to animatedObjects later - this.objectManager = objectManager; - - // Control variables for stopping / starting animation - // TODO: not sure what's the difference between paused and animationPaused - this.paused = false; - - this.animationPaused = false; - this.awaitingStep = false; - this.currentlyAnimating = false; - - // Array holding the code for the animation. This is - // an array of strings, each of which is an animation command - // currentAnimation is an index into this array - this.AnimationSteps = []; - this.currentAnimation = 0; - - this.previousAnimationSteps = []; - - // Control variables for where we are in the current animation block. - // currFrame holds the frame number of the current animation block, - // while animationBlockLength holds the length of the current animation - // block (in frame numbers). - this.currFrame = 0; - this.animationBlockLength = 0; - - // The animation block that is currently running. Array of singleAnimations - this.currentBlock = null; - - ///////////////////////////////////// - // Variables for handling undo. - //////////////////////////////////// - // A stack of UndoBlock objects (subclassed, UndoBlock is an abstract base class) - // each of which can undo a single animation element - this.undoStack = []; - this.doingUndo = false; - - // A stack containing the beginning of each animation block, as an index - // into the AnimationSteps array - this.undoAnimationStepIndices = []; - this.undoAnimationStepIndicesStack = []; - - this.animationBlockLength = 10; - - this.lerp = function(from, to, percent) - { - return (to - from) * percent + from; - } - - // Pause / unpause animation - this.SetPaused = function(pausedValue) - { - this.animationPaused = pausedValue; - if (!this.animationPaused) - { - this.step(); - } - } - - // Set the speed of the animation, from 0 (slow) to 100 (fast) - this.SetSpeed = function(newSpeed) - { - this.animationBlockLength = Math.floor((100-newSpeed) / 2); - } - - - this.parseBool = function(str) - { - var uppercase = str.toUpperCase(); - var returnVal = !(uppercase == "False" || uppercase == "f" || uppercase == " 0" || uppercase == "0" || uppercase == ""); - return returnVal; - - } - - this.parseColor = function(clr) - { - if (clr.charAt(0) == "#") - { - return clr; - } - else if (clr.substring(0,2) == "0x") - { - return "#" + clr.substring(2); - } - } - - - this.changeSize = function() - { - - var width = parseInt(this.widthEntry.value); - var height = parseInt(this.heightEntry.value); - - if (width > 100) - { - this.canvas.width = width; - this.animatedObjects.width = width; - setCookie("VisualizationWidth", String(width), 30); - - } - if (height > 100) - { - this.canvas.height = height; - this.animatedObjects.height = height; - setCookie("VisualizationHeight", String(height), 30); - } - width.value = this.canvas.width; - this.heightEntry.value = this.canvas.height; - - this.animatedObjects.draw(); - this.fireEvent("CanvasSizeChanged",{width:this.canvas.width, height:this.canvas.height}); - } - - this.startNextBlock = function() - { - this.awaitingStep = false; - this.currentBlock = []; - var undoBlock = [] - if (this.currentAnimation == this.AnimationSteps.length ) - { - this.currentlyAnimating = false; - this.awaitingStep = false; - this.fireEvent("AnimationEnded","NoData"); - clearTimeout(this.timer); - this.animatedObjects.update(); - this.animatedObjects.draw(); - - return; - } - this.undoAnimationStepIndices.push(this.currentAnimation); - - var foundBreak= false; - var anyAnimations= false; - - while (this.currentAnimation < this.AnimationSteps.length && !foundBreak) - { - var nextCommand = this.AnimationSteps[this.currentAnimation].split("<;>"); - if (nextCommand[0].toUpperCase() == "CREATECIRCLE") - { - this.animatedObjects.addCircleObject(parseInt(nextCommand[1]), nextCommand[2]); - if (nextCommand.length > 4) - { - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[3]), parseInt(nextCommand[4])); - } - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - - } - else if (nextCommand[0].toUpperCase() == "CONNECT") - { - - if (nextCommand.length > 7) - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - this.parseColor(nextCommand[3]), - parseFloat(nextCommand[4]), - this.parseBool(nextCommand[5]), - nextCommand[6], - parseInt(nextCommand[7])); - } - else if (nextCommand.length > 6) - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - this.parseColor(nextCommand[3]), - parseFloat(nextCommand[4]), - this.parseBool(nextCommand[5]), - nextCommand[6], - 0); - } - else if (nextCommand.length > 5) - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - this.parseColor(nextCommand[3]), - parseFloat(nextCommand[4]), - this.parseBool(nextCommand[5]), - "", - 0); - } - else if (nextCommand.length > 4) - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - this.parseColor(nextCommand[3]), - parseFloat(nextCommand[4]), - true, - "", - 0); - } - else if (nextCommand.length > 3) - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - this.parseColor(nextCommand[3]), - 0.0, - true, - "", - 0); - } - else - { - this.animatedObjects.connectEdge(parseInt(nextCommand[1]), - parseInt(nextCommand[2]), - "#000000", - 0.0, - true, - "", - 0); - - } - undoBlock.push(new UndoConnect(parseInt(nextCommand[1]), parseInt (nextCommand[2]), false)); - } - else if (nextCommand[0].toUpperCase() == "CREATERECTANGLE") - { - if (nextCommand.length == 9) - { - this.animatedObjects.addRectangleObject(parseInt(nextCommand[1]), // ID - nextCommand[2], // Label - parseInt(nextCommand[3]), // w - parseInt(nextCommand[4]), // h - nextCommand[7], // xJustify - nextCommand[8],// yJustify - "#ffffff", // background color - "#000000"); // foreground color - } - else - { - this.animatedObjects.addRectangleObject(parseInt(nextCommand[1]), // ID - nextCommand[2], // Label - parseInt(nextCommand[3]), // w - parseInt(nextCommand[4]), // h - "center", // xJustify - "center",// yJustify - "#ffffff", // background color - "#000000"); // foreground color - - } - if (nextCommand.length > 6) - { - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); - } - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - } - - else if (nextCommand[0].toUpperCase() == "MOVE") - { - var objectID = parseInt(nextCommand[1]); - var nextAnim = new SingleAnimation(objectID, - this.animatedObjects.getNodeX(objectID), - this.animatedObjects.getNodeY(objectID), - parseInt(nextCommand[2]), - parseInt(nextCommand[3])); - this.currentBlock.push(nextAnim); - - undoBlock.push(new UndoMove(nextAnim.objectID, nextAnim.toX, nextAnim.toY, nextAnim.fromX, nextAnim.fromY)); - - anyAnimations = true; - } - - else if (nextCommand[0].toUpperCase() == "MOVETOALIGNRIGHT") - { - var id = parseInt(nextCommand[1]); - var otherId = parseInt(nextCommand[2]); - var newXY = this.animatedObjects.getAlignRightPos(id, otherId); - - - var nextAnim = new SingleAnimation(id, - this.animatedObjects.getNodeX(id), - this.animatedObjects.getNodeY(id), - newXY[0], - newXY[1]); - this.currentBlock.push(nextAnim); - undoBlock.push(new UndoMove(nextAnim.objectID, nextAnim.toX, nextAnim.toY, nextAnim.fromX, nextAnim.fromY)); - anyAnimations = true; - } - - else if (nextCommand[0].toUpperCase() == "STEP") - { - foundBreak = true; - } - else if (nextCommand[0].toUpperCase() == "SETFOREGROUNDCOLOR") - { - var id = parseInt(nextCommand[1]); - var oldColor = this.animatedObjects.foregroundColor(id); - this.animatedObjects.setForegroundColor(id, this.parseColor(nextCommand[2])); - undoBlock.push(new UndoSetForegroundColor(id, oldColor)); - } - else if (nextCommand[0].toUpperCase() == "SETBACKGROUNDCOLOR") - { - id = parseInt(nextCommand[1]); - oldColor = this.animatedObjects.backgroundColor(id); - this.animatedObjects.setBackgroundColor(id, this.parseColor(nextCommand[2])); - undoBlock.push(new UndoSetBackgroundColor(id, oldColor)); - } - else if (nextCommand[0].toUpperCase() == "SETHIGHLIGHT") - { - var newHighlight = this.parseBool(nextCommand[2]); - this.animatedObjects.setHighlight( parseInt(nextCommand[1]), newHighlight); - undoBlock.push(new UndoHighlight( parseInt(nextCommand[1]), !newHighlight)); - } - else if (nextCommand[0].toUpperCase() == "DISCONNECT") - { - var undoConnect = this.animatedObjects.disconnect(parseInt(nextCommand[1]), parseInt(nextCommand[2])); - if (undoConnect != null) - { - undoBlock.push(undoConnect); - } - } - else if (nextCommand[0].toUpperCase() == "SETALPHA") - { - var oldAlpha = this.animatedObjects.getAlpha(parseInt(nextCommand[1])); - this.animatedObjects.setAlpha(parseInt(nextCommand[1]), parseFloat(nextCommand[2])); - undoBlock.push(new UndoSetAlpha(parseInt(nextCommand[1]), oldAlpha)); - } - else if (nextCommand[0].toUpperCase() == "SETTEXT") - { - if (nextCommand.length > 3) - { - var oldText = this.animatedObjects.getText(parseInt(nextCommand[1]), parseInt(nextCommand[3])); - this.animatedObjects.setText(parseInt(nextCommand[1]), nextCommand[2], parseInt(nextCommand[3])); - if (oldText != undefined) - { - undoBlock.push(new UndoSetText(parseInt(nextCommand[1]), oldText, parseInt(nextCommand[3]) )); - } - } - else - { - oldText = this.animatedObjects.getText(parseInt(nextCommand[1]), 0); - this.animatedObjects.setText(parseInt(nextCommand[1]), nextCommand[2], 0); - if (oldText != undefined) - { - undoBlock.push(new UndoSetText(parseInt(nextCommand[1]), oldText, 0)); - } - } - } - else if (nextCommand[0].toUpperCase() == "DELETE") - { - var objectID = parseInt(nextCommand[1]); - - var i; - var removedEdges = this.animatedObjects.deleteIncident(objectID); - if (removedEdges.length > 0) - { - undoBlock = undoBlock.concat(removedEdges); - } - var obj = this.animatedObjects.getObject(objectID); - if (obj != null) - { - undoBlock.push(obj.createUndoDelete()); - this.animatedObjects.removeObject(objectID); - } - } - else if (nextCommand[0].toUpperCase() == "CREATEHIGHLIGHTCIRCLE") - { - if (nextCommand.length > 5) - { - this.animatedObjects.addHighlightCircleObject(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), parseFloat(nextCommand[5])); - } - else - { - this.animatedObjects.addHighlightCircleObject(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), 20); - } - if (nextCommand.length > 4) - { - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[3]), parseInt(nextCommand[4])); - } - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - - - } - else if (nextCommand[0].toUpperCase() == "CREATELABEL") - { - if (nextCommand.length == 6) - { - this.animatedObjects.addLabelObject(parseInt(nextCommand[1]), nextCommand[2], this.parseBool(nextCommand[5])); - } - else - { - this.animatedObjects.addLabelObject(parseInt(nextCommand[1]), nextCommand[2], true); - } - if (nextCommand.length >= 5) - { - - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseFloat(nextCommand[3]), parseFloat(nextCommand[4])); - } - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - } - else if (nextCommand[0].toUpperCase() == "SETEDGECOLOR") - { - var from = parseInt(nextCommand[1]); - var to = parseInt(nextCommand[2]); - var newColor = this.parseColor(nextCommand[3]); - var oldColor = this.animatedObjects.setEdgeColor(from, to, newColor); - undoBlock.push(new UndoSetEdgeColor(from, to, oldColor)); - } - else if (nextCommand[0].toUpperCase() == "SETEDGEALPHA") - { - var from = parseInt(nextCommand[1]); - var to = parseInt(nextCommand[2]); - var newAlpha = parseFloat(nextCommand[3]); - var oldAplpha = this.animatedObjects.setEdgeAlpha(from, to, newAlpha); - undoBlock.push(new UndoSetEdgeAlpha(from, to, oldAplpha)); - } - - - else if (nextCommand[0].toUpperCase() == "SETEDGEHIGHLIGHT") - { - var newHighlight = this.parseBool(nextCommand[3]); - var from = parseInt(nextCommand[1]); - var to = parseInt(nextCommand[2]); - var oldHighlight = this.animatedObjects.setEdgeHighlight(from, to, newHighlight); - undoBlock.push(new UndoHighlightEdge(from, to, oldHighlight)); - } - else if (nextCommand[0].toUpperCase() == "SETHEIGHT") - { - id = parseInt(nextCommand[1]); - var oldHeight = this.animatedObjects.getHeight(id); - this.animatedObjects.setHeight(id, parseInt(nextCommand[2])); - undoBlock.push(new UndoSetHeight(id, oldHeight)); - } - else if (nextCommand[0].toUpperCase() == "SETLAYER") - { - this.animatedObjects.setLayer(parseInt(nextCommand[1]), parseInt(nextCommand[2])); - //TODO: Add undo information here - } - - - else if (nextCommand[0].toUpperCase() == "CREATELINKEDLIST") - { - if (nextCommand.length == 11) - { - this.animatedObjects.addLinkedListObject(parseInt(nextCommand[1]), nextCommand[2], - parseInt(nextCommand[3]), parseInt(nextCommand[4]), parseFloat(nextCommand[7]), - this.parseBool(nextCommand[8]), this.parseBool(nextCommand[9]),parseInt(nextCommand[10]), "#FFFFFF", "#000000"); - } - else - { - this.animatedObjects.addLinkedListObject(parseInt(nextCommand[1]), nextCommand[2], parseInt(nextCommand[3]), parseInt(nextCommand[4]), 0.25, true, false, 1, "#FFFFFF", "#000000"); - } - if (nextCommand.length > 6) - { - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - } - - } - else if (nextCommand[0].toUpperCase() == "SETNULL") - { - var oldNull = this.animatedObjects.getNull(parseInt(nextCommand[1])); - this.animatedObjects.setNull(parseInt(nextCommand[1]), this.parseBool(nextCommand[2])); - undoBlock.push(new UndoSetNull(parseInt(nextCommand[1]), oldNull)); - } - else if (nextCommand[0].toUpperCase() == "SETTEXTCOLOR") - { - if (nextCommand.length > 3) - { - oldColor = this.animatedObjects.getTextColor(parseInt(nextCommand[1]), parseInt(nextCommand[3])); - this.animatedObjects.setTextColor(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), parseInt(nextCommand[3])); - undoBlock.push(new UndoSetTextColor(parseInt(nextCommand[1]), oldColor, parseInt(nextCommand[3]) )); - } - else - { - oldColor = this.animatedObjects.getTextColor(parseInt(nextCommand[1]), 0); - this.animatedObjects.setTextColor(parseInt(nextCommand[1]),this.parseColor(nextCommand[2]), 0); - undoBlock.push(new UndoSetTextColor(parseInt(nextCommand[1]), oldColor, 0)); - } - } - - - else if (nextCommand[0].toUpperCase() == "CREATEBTREENODE") - { - - this.animatedObjects.addBTreeNode(parseInt(nextCommand[1]), parseFloat(nextCommand[2]), parseFloat(nextCommand[3]), - parseInt(nextCommand[4]),this.parseColor(nextCommand[7]), this.parseColor(nextCommand[8])); - this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); - undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); - } - - else if (nextCommand[0].toUpperCase() == "SETWIDTH") - { - var id = parseInt(nextCommand[1]); - this.animatedObjects.setWidth(id, parseInt(nextCommand[2])); - var oldWidth = this.animatedObjects.getWidth(id); - undoBlock.push(new UndoSetWidth(id, oldWidth)); - } - else if (nextCommand[0].toUpperCase() == "SETNUMELEMENTS") - { - var oldElem = this.animatedObjects.getObject(parseInt(nextCommand[1])); - undoBlock.push(new UndoSetNumElements(oldElem, parseInt(nextCommand[2]))); - this.animatedObjects.setNumElements(parseInt(nextCommand[1]), parseInt(nextCommand[2])); - } - else if (nextCommand[0].toUpperCase() == "SETPOSITION") - { - var id = parseInt(nextCommand[1]) - var oldX = this.animatedObjects.getNodeX(id); - var oldY = this.animatedObjects.getNodeY(id); - undoBlock.push(new UndoSetPosition(id, oldX, oldY)); - this.animatedObjects.setNodePosition(id, parseInt(nextCommand[2]), parseInt(nextCommand[3])); - } - else if (nextCommand[0].toUpperCase() == "ALIGNRIGHT") - { - var id = parseInt(nextCommand[1]) - var oldX = this.animatedObjects.getNodeX(id); - var oldY = this.animatedObjects.getNodeY(id); - undoBlock.push(new UndoSetPosition(id, oldX. oldY)); - this.animatedObjects.alignRight(id, parseInt(nextCommand[2])); - } - else if (nextCommand[0].toUpperCase() == "ALIGNLEFT") - { - var id = parseInt(nextCommand[1]) - var oldX = this.animatedObjects.getNodeX(id); - var oldY = this.animatedObjects.getNodeY(id); - undoBlock.push(new UndoSetPosition(id, oldX. oldY)); - this.animatedObjects.alignLeft(id, parseInt(nextCommand[2])); - } - else if (nextCommand[0].toUpperCase() == "ALIGNTOP") - { - var id = parseInt(nextCommand[1]) - var oldX = this.animatedObjects.getNodeX(id); - var oldY = this.animatedObjects.getNodeY(id); - undoBlock.push(new UndoSetPosition(id, oldX. oldY)); - this.animatedObjects.alignTop(id, parseInt(nextCommand[2])); - } - else if (nextCommand[0].toUpperCase() == "ALIGNBOTTOM") - { - var id = parseInt(nextCommand[1]) - var oldX = this.animatedObjects.getNodeX(id); - var oldY = this.animatedObjects.getNodeY(id); - undoBlock.push(new UndoSetPosition(id, oldX. oldY)); - this.animatedObjects.alignBottom(id, parseInt(nextCommand[2])); - } - - - - - - else if (nextCommand[0].toUpperCase() == "SETHIGHLIGHTINDEX") - { - var id = parseInt(nextCommand[1]); - var index = parseInt(nextCommand[2]); - var oldIndex = this.animatedObjects.getHighlightIndex(id) - undoBlock.push(new UndoSetHighlightIndex(id, oldIndex)); - this.animatedObjects.setHighlightIndex(id,index); - } - else - { - // throw "Unknown command: " + nextCommand[0]; - } - - this.currentAnimation = this.currentAnimation+1; - } - this.currFrame = 0; - - // Hack: If there are not any animations, and we are currently paused, - // then set the current frame to the end of the anumation, so that we will - // advance immediagely upon the next step button. If we are not paused, then - // animate as normal. - - if (!anyAnimations && this.animationPaused || (!anyAnimations && this.currentAnimation == this.AnimationSteps.length) ) - { - this.currFrame = this.animationBlockLength; - } - - this.undoStack.push(undoBlock); - } - - // Start a new animation. The input parameter commands is an array of strings, - // which represents the animation to start - this.StartNewAnimation = function(commands) - { - clearTimeout(this.timer); - if (this.AnimationSteps != null) - { - this.previousAnimationSteps.push(this.AnimationSteps); - this.undoAnimationStepIndicesStack.push(this.undoAnimationStepIndices); - } - if (commands == undefined || commands.length == 0) - { - this.AnimationSteps = ["Step"]; - } - else - { - this.AnimationSteps = commands; - } - this.undoAnimationStepIndices = new Array(); - this.currentAnimation = 0; - this.startNextBlock(); - this.currentlyAnimating = true; - this.fireEvent("AnimationStarted","NoData"); - this.timer = setTimeout(timeout.bind(this), 30); - - } - - - // Step backwards one step. A no-op if the animation is not currently paused - this.stepBack = function() - { - if (this.awaitingStep && this.undoStack != null && this.undoStack.length != 0) - { - // TODO: Get events working correctly! - this.fireEvent("AnimationStarted","NoData"); - clearTimeout(this.timer); - - this.awaitingStep = false; - this.undoLastBlock(); - // Re-kick thie timer. The timer may or may not be running at this point, - // so to be safe we'll kill it and start it again. - clearTimeout(this.timer); - this.timer = setTimeout(timeout.bind(this), 30); - - - } - else if (!this.currentlyAnimating && this.animationPaused && this.undoAnimationStepIndices != null) - { - this.fireEvent("AnimationStarted","NoData"); - this.currentlyAnimating = true; - this.undoLastBlock(); - // Re-kick thie timer. The timer may or may not be running at this point, - // so to be safe we'll kill it and start it again. - clearTimeout(this.timer); - this.timer = setTimeout(timeout.bind(this), 30); - - } - - } - // Step forwards one step. A no-op if the animation is not currently paused - this.step = function() - { - if (this.awaitingStep) - { - this.startNextBlock(); - this.fireEvent("AnimationStarted","NoData"); - this.currentlyAnimating = true; - // Re-kick thie timer. The timer should be going now, but we've had some difficulty with - // it timing itself out, so we'll be safe and kick it now. - clearTimeout(this.timer); - this.timer = setTimeout(timeout.bind(this), 30); - } - } - - - /// WARNING: Could be dangerous to call while an animation is running ... - this.clearHistory = function() - { - this.undoStack = []; - this.undoAnimationStepIndices = null; - this.previousAnimationSteps = []; - this.undoAnimationStepIndicesStack = []; - this.AnimationSteps = null; - this.fireEvent("AnimationUndoUnavailable","NoData"); - clearTimeout(this.timer); - this.animatedObjects.update(); - this.animatedObjects.draw(); - - } - - this.skipBack = function() - { - var keepUndoing = this.undoAnimationStepIndices != null && this. undoAnimationStepIndices.length != 0; - if (keepUndoing) - { - var i; - for (i = 0; this.currentBlock != null && i < this.currentBlock.length; i++) - { - var objectID = this.currentBlock[i].objectID; - this.animatedObjects.setNodePosition(objectID, - this.currentBlock[i].toX, - this.currentBlock[i].toY); - } - if (this.doingUndo) - { - this.finishUndoBlock(this.undoStack.pop()) - } - while (keepUndoing) - { - this.undoLastBlock(); - for (i = 0; i < this.currentBlock.length; i++) - { - objectID = this.currentBlock[i].objectID; - this.animatedObjects.setNodePosition(objectID, - this.currentBlock[i].toX, - this.currentBlock[i].toY); - } - keepUndoing = this.finishUndoBlock(this.undoStack.pop()); - - } - clearTimeout(this.timer); - this.animatedObjects.update(); - this.animatedObjects.draw(); - if (this.undoStack == null || this.undoStack.length == 0) - { - this.fireEvent("AnimationUndoUnavailable","NoData"); - } - - } - } - - this.resetAll = function() - { - this.clearHistory(); - this.animatedObjects.clearAllObjects(); - this.animatedObjects.draw(); - clearTimeout(this.timer); - } - - this.skipForward = function() - { - if (this.currentlyAnimating) - { - this.animatedObjects.runFast = true; - while (this.AnimationSteps != null && this.currentAnimation < this.AnimationSteps.length) - { - var i; - for (i = 0; this.currentBlock != null && i < this.currentBlock.length; i++) - { - var objectID = this.currentBlock[i].objectID; - this.animatedObjects.setNodePosition(objectID, - this.currentBlock[i].toX, - this.currentBlock[i].toY); - } - if (this.doingUndo) - { - this.finishUndoBlock(this.undoStack.pop()) - } - this.startNextBlock(); - for (i= 0; i < this.currentBlock.length; i++) - { - var objectID = this.currentBlock[i].objectID; - this.animatedObjects.setNodePosition(objectID, - this.currentBlock[i].toX, - this.currentBlock[i].toY); - } - - } - this.animatedObjects.update(); - this.currentlyAnimating = false; - this.awaitingStep = false; - this.doingUndo = false; - - this.animatedObjects.runFast = false; - this.fireEvent("AnimationEnded","NoData"); - clearTimeout(this.timer); - this.animatedObjects.update(); - this.animatedObjects.draw(); - } - } - - - this.finishUndoBlock = function(undoBlock) - { - for (var i = undoBlock.length - 1; i >= 0; i--) - { - undoBlock[i].undoInitialStep(this.animatedObjects); - - } - this.doingUndo = false; - - // If we are at the final end of the animation ... - if (this.undoAnimationStepIndices.length == 0) - { - this.awaitingStep = false; - this.currentlyAnimating = false; - this.undoAnimationStepIndices = this.undoAnimationStepIndicesStack.pop(); - this.AnimationSteps = this.previousAnimationSteps.pop(); - this.fireEvent("AnimationEnded","NoData"); - this.fireEvent("AnimationUndo","NoData"); - this.currentBlock = []; - if (this.undoStack == null || this.undoStack.length == 0) - { - this.currentlyAnimating = false; - this.awaitingStep = false; - this.fireEvent("AnimationUndoUnavailable","NoData"); - } - - clearTimeout(this.timer); - this.animatedObjects.update(); - this.animatedObjects.draw(); - - - return false; - } - return true; - } - - - this.undoLastBlock = function() - { - - if (this.undoAnimationStepIndices.length == 0) - { - - // Nothing on the undo stack. Return - return; - - } - if (this.undoAnimationStepIndices.length > 0) - { - this.doingUndo = true; - var anyAnimations = false; - this.currentAnimation = this.undoAnimationStepIndices.pop(); - this.currentBlock = []; - var undo = this.undoStack[this.undoStack.length - 1]; - var i; - for (i = undo.length - 1; i >= 0; i--) - { - var animateNext = undo[i].addUndoAnimation(this.currentBlock); - anyAnimations = anyAnimations || animateNext; - - } - this.currFrame = 0; - - // Hack: If there are not any animations, and we are currently paused, - // then set the current frame to the end of the animation, so that we will - // advance immediagely upon the next step button. If we are not paused, then - // animate as normal. - if (!anyAnimations && this.animationPaused ) - { - this.currFrame = this.animationBlockLength; - } - this.currentlyAnimating = true; - } - - } - this.setLayer = function(shown, layers) - { - this.animatedObjects.setLayer(shown, layers) - // Drop in an extra draw call here, just in case we are not - // in the middle of an update loop when this changes - this.animatedObjects.draw(); - } - - - this.setAllLayers = function(layers) - { - this.animatedObjects.setAllLayers(layers); - // Drop in an extra draw call here, just in case we are not - // in the middle of an update loop when this changes - this.animatedObjects.draw(); - } - - - this.update = function() - { - - if (this.currentlyAnimating) - { - this.currFrame = this.currFrame + 1; - var i; - for (i = 0; i < this.currentBlock.length; i++) - { - if (this.currFrame == this.animationBlockLength || (this.currFrame == 1 && this.animationBlockLength == 0)) - { - this.animatedObjects.setNodePosition(this.currentBlock[i].objectID, - this.currentBlock[i].toX, - this.currentBlock[i].toY); - } - else if (this.currFrame < this.animationBlockLength) - { - var objectID = this.currentBlock[i].objectID; - var percent = 1 / (this.animationBlockLength - this.currFrame); - var oldX = this.animatedObjects.getNodeX(objectID); - var oldY = this.animatedObjects.getNodeY(objectID); - var targetX = this.currentBlock[i].toX; - var targety = this.currentBlock[i].toY; - var newX = this.lerp(this.animatedObjects.getNodeX(objectID), this.currentBlock[i].toX, percent); - var newY = this.lerp(this.animatedObjects.getNodeY(objectID), this.currentBlock[i].toY, percent); - this.animatedObjects.setNodePosition(objectID, newX, newY); - } - } - if (this.currFrame >= this.animationBlockLength) - { - if (this.doingUndo) - { - if (this.finishUndoBlock(this.undoStack.pop())) - { - this.awaitingStep = true; - this.fireEvent("AnimationWaiting","NoData"); - } - - } - else - { - if (this.animationPaused && (this.currentAnimation < this.AnimationSteps.length)) - { - this.awaitingStep = true; - this.fireEvent("AnimationWaiting","NoData"); - this.currentBlock = []; - } - else - { - this.startNextBlock(); - } - } - } - this.animatedObjects.update(); - - } - - - } - -} - -AnimationManager.inheritFrom(EventListener); - -AnimationManager.prototype.addControlToAnimationBar = function(type,name,containerType) -{ - // return a dummy object if we're not using a control bar - if(!this.generalControlBar) - return {}; - if (containerType == undefined) - { - containerType = "input"; - } - var element = document.createElement(containerType); - - element.setAttribute("type", type); - element.setAttribute("value", name); - - - var tableEntry = document.createElement("td"); - - tableEntry.appendChild(element); - - - //Append the element in page (in span). - this.generalControlBar.appendChild(tableEntry); - return element; - -} - -function SingleAnimation(id, fromX, fromY, toX, toY) -{ - this.objectID = id; - this.fromX = fromX; - this.fromY = fromY; - this.toX = toX; - this.toY = toY; -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +// Global timer used for doing animation callbacks. +// TODO: Make this an instance variable of Animation Manager. +// var timer; +// var swapped = false; + + +function reorderSibling(node1, node2) +{ + node1.parentNode.replaceChild(node1, node2); + node1.parentNode.insertBefore(node2, node1); +} + + +function swapControlDiv() +{ + this.swapped = !this.swapped; + if (this.swapped) { + reorderSibling(this.canvas, this.generalControlBar.parentNode); + setCookie("VisualizationControlSwapped", "true", 30); + + } else { + reorderSibling(this.generalControlBar.parentNode, this.canvas); + setCookie("VisualizationControlSwapped", "false", 30); + + } +} + + +// Utility funciton to read a cookie +function getCookie(cookieName) +{ + var i, x, y; + var cookies=document.cookie.split(";"); + for (i=0; i < cookies.length; i++) + { + x=cookies[i].substr(0,cookies[i].indexOf("=")); + y=cookies[i].substr(cookies[i].indexOf("=")+1); + x=x.replace(/^\s+|\s+$/g,""); + if (x==cookieName) + { + return unescape(y); + } + } +} + +// Utility funciton to write a cookie +function setCookie(cookieName,value,expireDays) +{ + var exdate=new Date(); + exdate.setDate(exdate.getDate() + expireDays); + var cookieValue=escape(value) + ((expireDays==null) ? "" : "; expires="+exdate.toUTCString()); + document.cookie=cookieName + "=" + value; +} + + +var ANIMATION_SPEED_DEFAULT = 75; + + +// TODO: Move these out of global space into animation manager? +// var objectManager; +// var animationManager; +// var canvas; + +// var paused = false; +// var playPauseBackButton; +// var skipBackButton; +// var stepBackButton; +// var stepForwardButton; +// var skipForwardButton; + +// var widthEntry; +// var heightEntry; +// var sizeButton; + + + +function returnSubmit(field, funct, maxsize, intOnly) +{ + + if (maxsize != undefined) + { + field.size = maxsize; + } + return function(event) + { + var keyASCII = 0; + if(window.event) // IE + { + keyASCII = event.keyCode + } + else if (event.which) // Netscape/Firefox/Opera + { + keyASCII = event.which + } + + if (keyASCII == 13) + { + funct(); + return false; + } + else if (keyASCII == 59 || keyASCII == 45 || keyASCII == 46 || keyASCII == 190 || keyASCII == 173) + { + return false; + } + else if (maxsize != undefined && field.value.length >= maxsize || + intOnly && (keyASCII < 48 || keyASCII > 57)) + + { + if (!controlKey(keyASCII)) + return false; + } + return true; + + } + +} + + +function animWaiting() +{ + this.stepForwardButton.disabled = false; + if (this.skipBackButton.disabled == false) + { + this.stepBackButton.disabled = false; + } + this.objectManager.statusReport.setText("Animation Paused"); + this.objectManager.statusReport.setForegroundColor("#FF0000"); +} + +function animStarted() +{ + this.skipForwardButton.disabled = false; + this.skipBackButton.disabled = false; + this.stepForwardButton.disabled = true; + this.stepBackButton.disabled = true; + this.objectManager.statusReport.setText("Animation Running"); + this.objectManager.statusReport.setForegroundColor("#009900"); +} + +function animEnded() +{ + this.skipForwardButton.disabled = true; + this.stepForwardButton.disabled = true; + if (this.skipBackButton.disabled == false && this.paused) + { + this.stepBackButton.disabled = false; + } + // this.objectManager.statusReport.setText("Animation Completed"); + this.objectManager.statusReport.setText(""); + this.objectManager.statusReport.setForegroundColor("#000000"); +} + + + +function anumUndoUnavailable() +{ + this.skipBackButton.disabled = true; + this.stepBackButton.disabled = true; +} + + +function timeout() +{ + // We need to set the timeout *first*, otherwise if we + // try to clear it later, we get behavior we don't want ... + this.timer = setTimeout(timeout.bind(this), 30); + this.update(); + this.objectManager.draw(); + +} + + +function doPlayPause() +{ + this.paused = !this.paused; + if (this.paused) + { + this.playPauseBackButton.setAttribute("value", "play"); + if (this.skipBackButton.disabled == false) + { + this.stepBackButton.disabled = false; + } + + } + else + { + this.playPauseBackButton.setAttribute("value", "pause"); + } + this.SetPaused(this.paused); +} + + +// Creates and returs an AnimationManager +function initCanvas(canvas, generalControlBar, algorithmControlBar) +{ + // UI nodes should be given, otherwise use defaults. + // This is the only place where getElementById is used + if(!canvas) canvas = document.getElementById("canvas"); + if(!generalControlBar) generalControlBar = document.getElementById('GeneralAnimationControls'); + if(!algorithmControlBar) algorithmControlBar = document.getElementById("AlgorithmSpecificControls"); + + var objectManager = new ObjectManager(canvas); + var animationManager = new AnimationManager(objectManager); + animationManager.canvas = canvas; + animationManager.generalControlBar = generalControlBar; + animationManager.algorithmControlBar = algorithmControlBar; + + animationManager.skipBackButton = animationManager.addControlToAnimationBar("Button", "Skip Back"); + animationManager.skipBackButton.onclick = animationManager.skipBack.bind(animationManager); + animationManager.stepBackButton = animationManager.addControlToAnimationBar("Button", "Step Back"); + animationManager.stepBackButton.onclick = animationManager.stepBack.bind(animationManager); + animationManager.playPauseBackButton = animationManager.addControlToAnimationBar("Button", "Pause"); + animationManager.playPauseBackButton.onclick = doPlayPause.bind(animationManager); + animationManager.stepForwardButton = animationManager.addControlToAnimationBar("Button", "Step Forward"); + animationManager.stepForwardButton.onclick = animationManager.step.bind(animationManager) ; + animationManager.skipForwardButton = animationManager.addControlToAnimationBar("Button", "Skip Forward"); + animationManager.skipForwardButton.onclick = animationManager.skipForward.bind(animationManager); + + + var element = document.createElement("div"); + element.setAttribute("display", "inline-block"); + element.setAttribute("float", "left"); + + + var tableEntry = document.createElement("td"); + + + + + + var newTable = document.createElement("table"); + + var midLevel = document.createElement("tr"); + var bottomLevel = document.createElement("td"); + midLevel.appendChild(bottomLevel); + bottomLevel.appendChild(element); + newTable.appendChild(midLevel); + + + + midLevel = document.createElement("tr"); + bottomLevel = document.createElement("td"); + bottomLevel.align = "center"; + var txtNode = document.createTextNode("Animation Speed"); + midLevel.appendChild(bottomLevel); + bottomLevel.appendChild(txtNode); + newTable.appendChild(midLevel); + + + + tableEntry.appendChild(newTable); + + + + //Append the element in page (in span). + if(generalControlBar) + generalControlBar.appendChild(tableEntry); + + //tableEntry.appendChild(element); + + var speed = getCookie("VisualizationSpeed"); + if (speed == null || speed == "") + { + speed = ANIMATION_SPEED_DEFAULT; + } + else + { + speed = parseInt(speed); + } + + if(generalControlBar) { + $(element).slider({ + animate: true, + value: speed, + change: function(e, ui) + { + setCookie("VisualizationSpeed", String(ui.value), 30); + }, + slide : function(e, ui){ + animationManager.SetSpeed(ui.value); + } + + }); + } + + animationManager.SetSpeed(speed); + + element.setAttribute("style", "width:200px"); + + + + var width=getCookie("VisualizationWidth"); + if (width == null || width == "") + { + width = canvas.width; + } + else + { + width = parseInt(width); + } + var height=getCookie("VisualizationHeight"); + if (height == null || height == "") + { + height = canvas.height; + } + else + { + height = parseInt(height); + } + + var swappedControls=getCookie("VisualizationControlSwapped"); + this.swapped = swappedControls == "true" + if (this.swapped) + { + reorderSibling(this.canvas, this.generalControlBar.parentNode); + } + + canvas.width = width; + canvas.height = height; + + + + tableEntry = document.createElement("td"); + txtNode = document.createTextNode(" w:"); + tableEntry.appendChild(txtNode); + if(generalControlBar) + generalControlBar.appendChild(tableEntry); + + + animationManager.widthEntry = animationManager.addControlToAnimationBar("Text", canvas.width); + animationManager.widthEntry.size = 4; + animationManager.widthEntry.onkeydown = this.returnSubmit(animationManager.widthEntry, animationManager.changeSize.bind(animationManager), 4, true); + + + tableEntry = document.createElement("td"); + txtNode = document.createTextNode(" h:"); + tableEntry.appendChild(txtNode); + if(generalControlBar) + generalControlBar.appendChild(tableEntry); + + animationManager.heightEntry = animationManager.addControlToAnimationBar("Text", canvas.height); + animationManager.heightEntry.onkeydown = this.returnSubmit(animationManager.heightEntry, animationManager.changeSize.bind(animationManager), 4, true); + +// heightEntry.size = 4; + animationManager.sizeButton = animationManager.addControlToAnimationBar("Button", "Change Canvas Size"); + + animationManager.sizeButton.onclick = animationManager.changeSize.bind(animationManager) ; + + + animationManager.swapButton = animationManager.addControlToAnimationBar("Button", "Move Controls"); + animationManager.swapButton.onclick = swapControlDiv.bind(animationManager); + + + animationManager.addListener("AnimationStarted", animationManager, animStarted); + animationManager.addListener("AnimationEnded", animationManager, animEnded); + animationManager.addListener("AnimationWaiting", animationManager, animWaiting); + animationManager.addListener("AnimationUndoUnavailable", animationManager, anumUndoUnavailable); + objectManager.width = canvas.width; + objectManager.height = canvas.height; + return animationManager; +} + + + +function AnimationManager(objectManager) +{ + AnimationManager.superclass.constructor.call(this); + + // Holder for all animated objects. + // All animation is done by manipulating objects in\ + // this container + this.animatedObjects = objectManager; + // TODO: change this to animatedObjects later + this.objectManager = objectManager; + + // Control variables for stopping / starting animation + // TODO: not sure what's the difference between paused and animationPaused + this.paused = false; + + this.animationPaused = false; + this.awaitingStep = false; + this.currentlyAnimating = false; + + // Array holding the code for the animation. This is + // an array of strings, each of which is an animation command + // currentAnimation is an index into this array + this.AnimationSteps = []; + this.currentAnimation = 0; + + this.previousAnimationSteps = []; + + // Control variables for where we are in the current animation block. + // currFrame holds the frame number of the current animation block, + // while animationBlockLength holds the length of the current animation + // block (in frame numbers). + this.currFrame = 0; + this.animationBlockLength = 0; + + // The animation block that is currently running. Array of singleAnimations + this.currentBlock = null; + + ///////////////////////////////////// + // Variables for handling undo. + //////////////////////////////////// + // A stack of UndoBlock objects (subclassed, UndoBlock is an abstract base class) + // each of which can undo a single animation element + this.undoStack = []; + this.doingUndo = false; + + // A stack containing the beginning of each animation block, as an index + // into the AnimationSteps array + this.undoAnimationStepIndices = []; + this.undoAnimationStepIndicesStack = []; + + this.animationBlockLength = 10; + + this.lerp = function(from, to, percent) + { + return (to - from) * percent + from; + } + + // Pause / unpause animation + this.SetPaused = function(pausedValue) + { + this.animationPaused = pausedValue; + if (!this.animationPaused) + { + this.step(); + } + } + + // Set the speed of the animation, from 0 (slow) to 100 (fast) + this.SetSpeed = function(newSpeed) + { + this.animationBlockLength = Math.floor((100-newSpeed) / 2); + } + + + this.parseBool = function(str) + { + var uppercase = str.toUpperCase(); + var returnVal = !(uppercase == "False" || uppercase == "f" || uppercase == " 0" || uppercase == "0" || uppercase == ""); + return returnVal; + + } + + this.parseColor = function(clr) + { + if (clr.charAt(0) == "#") + { + return clr; + } + else if (clr.substring(0,2) == "0x") + { + return "#" + clr.substring(2); + } + } + + + this.changeSize = function() + { + + var width = parseInt(this.widthEntry.value); + var height = parseInt(this.heightEntry.value); + + if (width > 100) + { + this.canvas.width = width; + this.animatedObjects.width = width; + setCookie("VisualizationWidth", String(width), 30); + + } + if (height > 100) + { + this.canvas.height = height; + this.animatedObjects.height = height; + setCookie("VisualizationHeight", String(height), 30); + } + width.value = this.canvas.width; + this.heightEntry.value = this.canvas.height; + + this.animatedObjects.draw(); + this.fireEvent("CanvasSizeChanged",{width:this.canvas.width, height:this.canvas.height}); + } + + this.startNextBlock = function() + { + this.awaitingStep = false; + this.currentBlock = []; + var undoBlock = [] + if (this.currentAnimation == this.AnimationSteps.length ) + { + this.currentlyAnimating = false; + this.awaitingStep = false; + this.fireEvent("AnimationEnded","NoData"); + clearTimeout(this.timer); + this.animatedObjects.update(); + this.animatedObjects.draw(); + + return; + } + this.undoAnimationStepIndices.push(this.currentAnimation); + + var foundBreak= false; + var anyAnimations= false; + + while (this.currentAnimation < this.AnimationSteps.length && !foundBreak) + { + var nextCommand = this.AnimationSteps[this.currentAnimation].split("<;>"); + if (nextCommand[0].toUpperCase() == "CREATECIRCLE") + { + this.animatedObjects.addCircleObject(parseInt(nextCommand[1]), nextCommand[2]); + if (nextCommand.length > 4) + { + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[3]), parseInt(nextCommand[4])); + } + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + + } + else if (nextCommand[0].toUpperCase() == "CONNECT") + { + + if (nextCommand.length > 7) + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + this.parseColor(nextCommand[3]), + parseFloat(nextCommand[4]), + this.parseBool(nextCommand[5]), + nextCommand[6], + parseInt(nextCommand[7])); + } + else if (nextCommand.length > 6) + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + this.parseColor(nextCommand[3]), + parseFloat(nextCommand[4]), + this.parseBool(nextCommand[5]), + nextCommand[6], + 0); + } + else if (nextCommand.length > 5) + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + this.parseColor(nextCommand[3]), + parseFloat(nextCommand[4]), + this.parseBool(nextCommand[5]), + "", + 0); + } + else if (nextCommand.length > 4) + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + this.parseColor(nextCommand[3]), + parseFloat(nextCommand[4]), + true, + "", + 0); + } + else if (nextCommand.length > 3) + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + this.parseColor(nextCommand[3]), + 0.0, + true, + "", + 0); + } + else + { + this.animatedObjects.connectEdge(parseInt(nextCommand[1]), + parseInt(nextCommand[2]), + "#000000", + 0.0, + true, + "", + 0); + + } + undoBlock.push(new UndoConnect(parseInt(nextCommand[1]), parseInt (nextCommand[2]), false)); + } + else if (nextCommand[0].toUpperCase() == "CREATERECTANGLE") + { + if (nextCommand.length == 9) + { + this.animatedObjects.addRectangleObject(parseInt(nextCommand[1]), // ID + nextCommand[2], // Label + parseInt(nextCommand[3]), // w + parseInt(nextCommand[4]), // h + nextCommand[7], // xJustify + nextCommand[8],// yJustify + "#ffffff", // background color + "#000000"); // foreground color + } + else + { + this.animatedObjects.addRectangleObject(parseInt(nextCommand[1]), // ID + nextCommand[2], // Label + parseInt(nextCommand[3]), // w + parseInt(nextCommand[4]), // h + "center", // xJustify + "center",// yJustify + "#ffffff", // background color + "#000000"); // foreground color + + } + if (nextCommand.length > 6) + { + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); + } + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + } + + else if (nextCommand[0].toUpperCase() == "MOVE") + { + var objectID = parseInt(nextCommand[1]); + var nextAnim = new SingleAnimation(objectID, + this.animatedObjects.getNodeX(objectID), + this.animatedObjects.getNodeY(objectID), + parseInt(nextCommand[2]), + parseInt(nextCommand[3])); + this.currentBlock.push(nextAnim); + + undoBlock.push(new UndoMove(nextAnim.objectID, nextAnim.toX, nextAnim.toY, nextAnim.fromX, nextAnim.fromY)); + + anyAnimations = true; + } + + else if (nextCommand[0].toUpperCase() == "MOVETOALIGNRIGHT") + { + var id = parseInt(nextCommand[1]); + var otherId = parseInt(nextCommand[2]); + var newXY = this.animatedObjects.getAlignRightPos(id, otherId); + + + var nextAnim = new SingleAnimation(id, + this.animatedObjects.getNodeX(id), + this.animatedObjects.getNodeY(id), + newXY[0], + newXY[1]); + this.currentBlock.push(nextAnim); + undoBlock.push(new UndoMove(nextAnim.objectID, nextAnim.toX, nextAnim.toY, nextAnim.fromX, nextAnim.fromY)); + anyAnimations = true; + } + + else if (nextCommand[0].toUpperCase() == "STEP") + { + foundBreak = true; + } + else if (nextCommand[0].toUpperCase() == "SETFOREGROUNDCOLOR") + { + var id = parseInt(nextCommand[1]); + var oldColor = this.animatedObjects.foregroundColor(id); + this.animatedObjects.setForegroundColor(id, this.parseColor(nextCommand[2])); + undoBlock.push(new UndoSetForegroundColor(id, oldColor)); + } + else if (nextCommand[0].toUpperCase() == "SETBACKGROUNDCOLOR") + { + id = parseInt(nextCommand[1]); + oldColor = this.animatedObjects.backgroundColor(id); + this.animatedObjects.setBackgroundColor(id, this.parseColor(nextCommand[2])); + undoBlock.push(new UndoSetBackgroundColor(id, oldColor)); + } + else if (nextCommand[0].toUpperCase() == "SETHIGHLIGHT") + { + var newHighlight = this.parseBool(nextCommand[2]); + this.animatedObjects.setHighlight( parseInt(nextCommand[1]), newHighlight); + undoBlock.push(new UndoHighlight( parseInt(nextCommand[1]), !newHighlight)); + } + else if (nextCommand[0].toUpperCase() == "DISCONNECT") + { + var undoConnect = this.animatedObjects.disconnect(parseInt(nextCommand[1]), parseInt(nextCommand[2])); + if (undoConnect != null) + { + undoBlock.push(undoConnect); + } + } + else if (nextCommand[0].toUpperCase() == "SETALPHA") + { + var oldAlpha = this.animatedObjects.getAlpha(parseInt(nextCommand[1])); + this.animatedObjects.setAlpha(parseInt(nextCommand[1]), parseFloat(nextCommand[2])); + undoBlock.push(new UndoSetAlpha(parseInt(nextCommand[1]), oldAlpha)); + } + else if (nextCommand[0].toUpperCase() == "SETTEXT") + { + if (nextCommand.length > 3) + { + var oldText = this.animatedObjects.getText(parseInt(nextCommand[1]), parseInt(nextCommand[3])); + this.animatedObjects.setText(parseInt(nextCommand[1]), nextCommand[2], parseInt(nextCommand[3])); + if (oldText != undefined) + { + undoBlock.push(new UndoSetText(parseInt(nextCommand[1]), oldText, parseInt(nextCommand[3]) )); + } + } + else + { + oldText = this.animatedObjects.getText(parseInt(nextCommand[1]), 0); + this.animatedObjects.setText(parseInt(nextCommand[1]), nextCommand[2], 0); + if (oldText != undefined) + { + undoBlock.push(new UndoSetText(parseInt(nextCommand[1]), oldText, 0)); + } + } + } + else if (nextCommand[0].toUpperCase() == "DELETE") + { + var objectID = parseInt(nextCommand[1]); + + var i; + var removedEdges = this.animatedObjects.deleteIncident(objectID); + if (removedEdges.length > 0) + { + undoBlock = undoBlock.concat(removedEdges); + } + var obj = this.animatedObjects.getObject(objectID); + if (obj != null) + { + undoBlock.push(obj.createUndoDelete()); + this.animatedObjects.removeObject(objectID); + } + } + else if (nextCommand[0].toUpperCase() == "CREATEHIGHLIGHTCIRCLE") + { + if (nextCommand.length > 5) + { + this.animatedObjects.addHighlightCircleObject(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), parseFloat(nextCommand[5])); + } + else + { + this.animatedObjects.addHighlightCircleObject(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), 20); + } + if (nextCommand.length > 4) + { + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[3]), parseInt(nextCommand[4])); + } + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + + + } + else if (nextCommand[0].toUpperCase() == "CREATELABEL") + { + if (nextCommand.length == 6) + { + this.animatedObjects.addLabelObject(parseInt(nextCommand[1]), nextCommand[2], this.parseBool(nextCommand[5])); + } + else + { + this.animatedObjects.addLabelObject(parseInt(nextCommand[1]), nextCommand[2], true); + } + if (nextCommand.length >= 5) + { + + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseFloat(nextCommand[3]), parseFloat(nextCommand[4])); + } + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + } + else if (nextCommand[0].toUpperCase() == "SETEDGECOLOR") + { + var from = parseInt(nextCommand[1]); + var to = parseInt(nextCommand[2]); + var newColor = this.parseColor(nextCommand[3]); + var oldColor = this.animatedObjects.setEdgeColor(from, to, newColor); + undoBlock.push(new UndoSetEdgeColor(from, to, oldColor)); + } + else if (nextCommand[0].toUpperCase() == "SETEDGEALPHA") + { + var from = parseInt(nextCommand[1]); + var to = parseInt(nextCommand[2]); + var newAlpha = parseFloat(nextCommand[3]); + var oldAplpha = this.animatedObjects.setEdgeAlpha(from, to, newAlpha); + undoBlock.push(new UndoSetEdgeAlpha(from, to, oldAplpha)); + } + + + else if (nextCommand[0].toUpperCase() == "SETEDGEHIGHLIGHT") + { + var newHighlight = this.parseBool(nextCommand[3]); + var from = parseInt(nextCommand[1]); + var to = parseInt(nextCommand[2]); + var oldHighlight = this.animatedObjects.setEdgeHighlight(from, to, newHighlight); + undoBlock.push(new UndoHighlightEdge(from, to, oldHighlight)); + } + else if (nextCommand[0].toUpperCase() == "SETHEIGHT") + { + id = parseInt(nextCommand[1]); + var oldHeight = this.animatedObjects.getHeight(id); + this.animatedObjects.setHeight(id, parseInt(nextCommand[2])); + undoBlock.push(new UndoSetHeight(id, oldHeight)); + } + else if (nextCommand[0].toUpperCase() == "SETLAYER") + { + this.animatedObjects.setLayer(parseInt(nextCommand[1]), parseInt(nextCommand[2])); + //TODO: Add undo information here + } + + + else if (nextCommand[0].toUpperCase() == "CREATELINKEDLIST") + { + if (nextCommand.length == 11) + { + this.animatedObjects.addLinkedListObject(parseInt(nextCommand[1]), nextCommand[2], + parseInt(nextCommand[3]), parseInt(nextCommand[4]), parseFloat(nextCommand[7]), + this.parseBool(nextCommand[8]), this.parseBool(nextCommand[9]),parseInt(nextCommand[10]), "#FFFFFF", "#000000"); + } + else + { + this.animatedObjects.addLinkedListObject(parseInt(nextCommand[1]), nextCommand[2], parseInt(nextCommand[3]), parseInt(nextCommand[4]), 0.25, true, false, 1, "#FFFFFF", "#000000"); + } + if (nextCommand.length > 6) + { + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + } + + } + else if (nextCommand[0].toUpperCase() == "SETNULL") + { + var oldNull = this.animatedObjects.getNull(parseInt(nextCommand[1])); + this.animatedObjects.setNull(parseInt(nextCommand[1]), this.parseBool(nextCommand[2])); + undoBlock.push(new UndoSetNull(parseInt(nextCommand[1]), oldNull)); + } + else if (nextCommand[0].toUpperCase() == "SETTEXTCOLOR") + { + if (nextCommand.length > 3) + { + oldColor = this.animatedObjects.getTextColor(parseInt(nextCommand[1]), parseInt(nextCommand[3])); + this.animatedObjects.setTextColor(parseInt(nextCommand[1]), this.parseColor(nextCommand[2]), parseInt(nextCommand[3])); + undoBlock.push(new UndoSetTextColor(parseInt(nextCommand[1]), oldColor, parseInt(nextCommand[3]) )); + } + else + { + oldColor = this.animatedObjects.getTextColor(parseInt(nextCommand[1]), 0); + this.animatedObjects.setTextColor(parseInt(nextCommand[1]),this.parseColor(nextCommand[2]), 0); + undoBlock.push(new UndoSetTextColor(parseInt(nextCommand[1]), oldColor, 0)); + } + } + + + else if (nextCommand[0].toUpperCase() == "CREATEBTREENODE") + { + + this.animatedObjects.addBTreeNode(parseInt(nextCommand[1]), parseFloat(nextCommand[2]), parseFloat(nextCommand[3]), + parseInt(nextCommand[4]),this.parseColor(nextCommand[7]), this.parseColor(nextCommand[8])); + this.animatedObjects.setNodePosition(parseInt(nextCommand[1]), parseInt(nextCommand[5]), parseInt(nextCommand[6])); + undoBlock.push(new UndoCreate(parseInt(nextCommand[1]))); + } + + else if (nextCommand[0].toUpperCase() == "SETWIDTH") + { + var id = parseInt(nextCommand[1]); + this.animatedObjects.setWidth(id, parseInt(nextCommand[2])); + var oldWidth = this.animatedObjects.getWidth(id); + undoBlock.push(new UndoSetWidth(id, oldWidth)); + } + else if (nextCommand[0].toUpperCase() == "SETNUMELEMENTS") + { + var oldElem = this.animatedObjects.getObject(parseInt(nextCommand[1])); + undoBlock.push(new UndoSetNumElements(oldElem, parseInt(nextCommand[2]))); + this.animatedObjects.setNumElements(parseInt(nextCommand[1]), parseInt(nextCommand[2])); + } + else if (nextCommand[0].toUpperCase() == "SETPOSITION") + { + var id = parseInt(nextCommand[1]) + var oldX = this.animatedObjects.getNodeX(id); + var oldY = this.animatedObjects.getNodeY(id); + undoBlock.push(new UndoSetPosition(id, oldX, oldY)); + this.animatedObjects.setNodePosition(id, parseInt(nextCommand[2]), parseInt(nextCommand[3])); + } + else if (nextCommand[0].toUpperCase() == "ALIGNRIGHT") + { + var id = parseInt(nextCommand[1]) + var oldX = this.animatedObjects.getNodeX(id); + var oldY = this.animatedObjects.getNodeY(id); + undoBlock.push(new UndoSetPosition(id, oldX. oldY)); + this.animatedObjects.alignRight(id, parseInt(nextCommand[2])); + } + else if (nextCommand[0].toUpperCase() == "ALIGNLEFT") + { + var id = parseInt(nextCommand[1]) + var oldX = this.animatedObjects.getNodeX(id); + var oldY = this.animatedObjects.getNodeY(id); + undoBlock.push(new UndoSetPosition(id, oldX. oldY)); + this.animatedObjects.alignLeft(id, parseInt(nextCommand[2])); + } + else if (nextCommand[0].toUpperCase() == "ALIGNTOP") + { + var id = parseInt(nextCommand[1]) + var oldX = this.animatedObjects.getNodeX(id); + var oldY = this.animatedObjects.getNodeY(id); + undoBlock.push(new UndoSetPosition(id, oldX. oldY)); + this.animatedObjects.alignTop(id, parseInt(nextCommand[2])); + } + else if (nextCommand[0].toUpperCase() == "ALIGNBOTTOM") + { + var id = parseInt(nextCommand[1]) + var oldX = this.animatedObjects.getNodeX(id); + var oldY = this.animatedObjects.getNodeY(id); + undoBlock.push(new UndoSetPosition(id, oldX. oldY)); + this.animatedObjects.alignBottom(id, parseInt(nextCommand[2])); + } + + + + + + else if (nextCommand[0].toUpperCase() == "SETHIGHLIGHTINDEX") + { + var id = parseInt(nextCommand[1]); + var index = parseInt(nextCommand[2]); + var oldIndex = this.animatedObjects.getHighlightIndex(id) + undoBlock.push(new UndoSetHighlightIndex(id, oldIndex)); + this.animatedObjects.setHighlightIndex(id,index); + } + else + { + // throw "Unknown command: " + nextCommand[0]; + } + + this.currentAnimation = this.currentAnimation+1; + } + this.currFrame = 0; + + // Hack: If there are not any animations, and we are currently paused, + // then set the current frame to the end of the anumation, so that we will + // advance immediagely upon the next step button. If we are not paused, then + // animate as normal. + + if (!anyAnimations && this.animationPaused || (!anyAnimations && this.currentAnimation == this.AnimationSteps.length) ) + { + this.currFrame = this.animationBlockLength; + } + + this.undoStack.push(undoBlock); + } + + // Start a new animation. The input parameter commands is an array of strings, + // which represents the animation to start + this.StartNewAnimation = function(commands) + { + clearTimeout(this.timer); + if (this.AnimationSteps != null) + { + this.previousAnimationSteps.push(this.AnimationSteps); + this.undoAnimationStepIndicesStack.push(this.undoAnimationStepIndices); + } + if (commands == undefined || commands.length == 0) + { + this.AnimationSteps = ["Step"]; + } + else + { + this.AnimationSteps = commands; + } + this.undoAnimationStepIndices = new Array(); + this.currentAnimation = 0; + this.startNextBlock(); + this.currentlyAnimating = true; + this.fireEvent("AnimationStarted","NoData"); + this.timer = setTimeout(timeout.bind(this), 30); + + } + + + // Step backwards one step. A no-op if the animation is not currently paused + this.stepBack = function() + { + if (this.awaitingStep && this.undoStack != null && this.undoStack.length != 0) + { + // TODO: Get events working correctly! + this.fireEvent("AnimationStarted","NoData"); + clearTimeout(this.timer); + + this.awaitingStep = false; + this.undoLastBlock(); + // Re-kick thie timer. The timer may or may not be running at this point, + // so to be safe we'll kill it and start it again. + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); + + + } + else if (!this.currentlyAnimating && this.animationPaused && this.undoAnimationStepIndices != null) + { + this.fireEvent("AnimationStarted","NoData"); + this.currentlyAnimating = true; + this.undoLastBlock(); + // Re-kick thie timer. The timer may or may not be running at this point, + // so to be safe we'll kill it and start it again. + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); + + } + + } + // Step forwards one step. A no-op if the animation is not currently paused + this.step = function() + { + if (this.awaitingStep) + { + this.startNextBlock(); + this.fireEvent("AnimationStarted","NoData"); + this.currentlyAnimating = true; + // Re-kick thie timer. The timer should be going now, but we've had some difficulty with + // it timing itself out, so we'll be safe and kick it now. + clearTimeout(this.timer); + this.timer = setTimeout(timeout.bind(this), 30); + } + } + + + /// WARNING: Could be dangerous to call while an animation is running ... + this.clearHistory = function() + { + this.undoStack = []; + this.undoAnimationStepIndices = null; + this.previousAnimationSteps = []; + this.undoAnimationStepIndicesStack = []; + this.AnimationSteps = null; + this.fireEvent("AnimationUndoUnavailable","NoData"); + clearTimeout(this.timer); + this.animatedObjects.update(); + this.animatedObjects.draw(); + + } + + this.skipBack = function() + { + var keepUndoing = this.undoAnimationStepIndices != null && this. undoAnimationStepIndices.length != 0; + if (keepUndoing) + { + var i; + for (i = 0; this.currentBlock != null && i < this.currentBlock.length; i++) + { + var objectID = this.currentBlock[i].objectID; + this.animatedObjects.setNodePosition(objectID, + this.currentBlock[i].toX, + this.currentBlock[i].toY); + } + if (this.doingUndo) + { + this.finishUndoBlock(this.undoStack.pop()) + } + while (keepUndoing) + { + this.undoLastBlock(); + for (i = 0; i < this.currentBlock.length; i++) + { + objectID = this.currentBlock[i].objectID; + this.animatedObjects.setNodePosition(objectID, + this.currentBlock[i].toX, + this.currentBlock[i].toY); + } + keepUndoing = this.finishUndoBlock(this.undoStack.pop()); + + } + clearTimeout(this.timer); + this.animatedObjects.update(); + this.animatedObjects.draw(); + if (this.undoStack == null || this.undoStack.length == 0) + { + this.fireEvent("AnimationUndoUnavailable","NoData"); + } + + } + } + + this.resetAll = function() + { + this.clearHistory(); + this.animatedObjects.clearAllObjects(); + this.animatedObjects.draw(); + clearTimeout(this.timer); + } + + this.skipForward = function() + { + if (this.currentlyAnimating) + { + this.animatedObjects.runFast = true; + while (this.AnimationSteps != null && this.currentAnimation < this.AnimationSteps.length) + { + var i; + for (i = 0; this.currentBlock != null && i < this.currentBlock.length; i++) + { + var objectID = this.currentBlock[i].objectID; + this.animatedObjects.setNodePosition(objectID, + this.currentBlock[i].toX, + this.currentBlock[i].toY); + } + if (this.doingUndo) + { + this.finishUndoBlock(this.undoStack.pop()) + } + this.startNextBlock(); + for (i= 0; i < this.currentBlock.length; i++) + { + var objectID = this.currentBlock[i].objectID; + this.animatedObjects.setNodePosition(objectID, + this.currentBlock[i].toX, + this.currentBlock[i].toY); + } + + } + this.animatedObjects.update(); + this.currentlyAnimating = false; + this.awaitingStep = false; + this.doingUndo = false; + + this.animatedObjects.runFast = false; + this.fireEvent("AnimationEnded","NoData"); + clearTimeout(this.timer); + this.animatedObjects.update(); + this.animatedObjects.draw(); + } + } + + + this.finishUndoBlock = function(undoBlock) + { + for (var i = undoBlock.length - 1; i >= 0; i--) + { + undoBlock[i].undoInitialStep(this.animatedObjects); + + } + this.doingUndo = false; + + // If we are at the final end of the animation ... + if (this.undoAnimationStepIndices.length == 0) + { + this.awaitingStep = false; + this.currentlyAnimating = false; + this.undoAnimationStepIndices = this.undoAnimationStepIndicesStack.pop(); + this.AnimationSteps = this.previousAnimationSteps.pop(); + this.fireEvent("AnimationEnded","NoData"); + this.fireEvent("AnimationUndo","NoData"); + this.currentBlock = []; + if (this.undoStack == null || this.undoStack.length == 0) + { + this.currentlyAnimating = false; + this.awaitingStep = false; + this.fireEvent("AnimationUndoUnavailable","NoData"); + } + + clearTimeout(this.timer); + this.animatedObjects.update(); + this.animatedObjects.draw(); + + + return false; + } + return true; + } + + + this.undoLastBlock = function() + { + + if (this.undoAnimationStepIndices.length == 0) + { + + // Nothing on the undo stack. Return + return; + + } + if (this.undoAnimationStepIndices.length > 0) + { + this.doingUndo = true; + var anyAnimations = false; + this.currentAnimation = this.undoAnimationStepIndices.pop(); + this.currentBlock = []; + var undo = this.undoStack[this.undoStack.length - 1]; + var i; + for (i = undo.length - 1; i >= 0; i--) + { + var animateNext = undo[i].addUndoAnimation(this.currentBlock); + anyAnimations = anyAnimations || animateNext; + + } + this.currFrame = 0; + + // Hack: If there are not any animations, and we are currently paused, + // then set the current frame to the end of the animation, so that we will + // advance immediagely upon the next step button. If we are not paused, then + // animate as normal. + if (!anyAnimations && this.animationPaused ) + { + this.currFrame = this.animationBlockLength; + } + this.currentlyAnimating = true; + } + + } + this.setLayer = function(shown, layers) + { + this.animatedObjects.setLayer(shown, layers) + // Drop in an extra draw call here, just in case we are not + // in the middle of an update loop when this changes + this.animatedObjects.draw(); + } + + + this.setAllLayers = function(layers) + { + this.animatedObjects.setAllLayers(layers); + // Drop in an extra draw call here, just in case we are not + // in the middle of an update loop when this changes + this.animatedObjects.draw(); + } + + + this.update = function() + { + + if (this.currentlyAnimating) + { + this.currFrame = this.currFrame + 1; + var i; + for (i = 0; i < this.currentBlock.length; i++) + { + if (this.currFrame == this.animationBlockLength || (this.currFrame == 1 && this.animationBlockLength == 0)) + { + this.animatedObjects.setNodePosition(this.currentBlock[i].objectID, + this.currentBlock[i].toX, + this.currentBlock[i].toY); + } + else if (this.currFrame < this.animationBlockLength) + { + var objectID = this.currentBlock[i].objectID; + var percent = 1 / (this.animationBlockLength - this.currFrame); + var oldX = this.animatedObjects.getNodeX(objectID); + var oldY = this.animatedObjects.getNodeY(objectID); + var targetX = this.currentBlock[i].toX; + var targety = this.currentBlock[i].toY; + var newX = this.lerp(this.animatedObjects.getNodeX(objectID), this.currentBlock[i].toX, percent); + var newY = this.lerp(this.animatedObjects.getNodeY(objectID), this.currentBlock[i].toY, percent); + this.animatedObjects.setNodePosition(objectID, newX, newY); + } + } + if (this.currFrame >= this.animationBlockLength) + { + if (this.doingUndo) + { + if (this.finishUndoBlock(this.undoStack.pop())) + { + this.awaitingStep = true; + this.fireEvent("AnimationWaiting","NoData"); + } + + } + else + { + if (this.animationPaused && (this.currentAnimation < this.AnimationSteps.length)) + { + this.awaitingStep = true; + this.fireEvent("AnimationWaiting","NoData"); + this.currentBlock = []; + } + else + { + this.startNextBlock(); + } + } + } + this.animatedObjects.update(); + + } + + + } + +} + +AnimationManager.inheritFrom(EventListener); + +AnimationManager.prototype.addControlToAnimationBar = function(type,name,containerType) +{ + // return a dummy object if we're not using a control bar + if(!this.generalControlBar) + return {}; + if (containerType == undefined) + { + containerType = "input"; + } + var element = document.createElement(containerType); + + element.setAttribute("type", type); + element.setAttribute("value", name); + + + var tableEntry = document.createElement("td"); + + tableEntry.appendChild(element); + + + //Append the element in page (in span). + this.generalControlBar.appendChild(tableEntry); + return element; + +} + +function SingleAnimation(id, fromX, fromY, toX, toY) +{ + this.objectID = id; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; +} diff --git a/AnimationLibrary/HighlightCircle.js b/AnimationLibrary/HighlightCircle.js index 4e0569e..53f32e1 100644 --- a/AnimationLibrary/HighlightCircle.js +++ b/AnimationLibrary/HighlightCircle.js @@ -1,87 +1,87 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - -// "Class" animatedCircle - - -var HighlightCircle = function(objectID, color, radius) -{ - this.objectID = objectID; - this.radius = radius; - this.thickness = 4; - this.foregroundColor = color; - this.x = 0; - this.y = 0; - this.alpha = 1; - - // call superclass' constructor - HighlightCircle.superclass.constructor.call(this); -} -HighlightCircle.inheritFrom(AnimatedObject); - - -HighlightCircle.prototype.draw = function(ctx) -{ - ctx.globalAlpha = this.alpha; - ctx.strokeStyle = this.foregroundColor; - ctx.lineWidth = this.thickness; - ctx.beginPath(); - ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true); - ctx.closePath(); - ctx.stroke(); -} - - -HighlightCircle.prototype.createUndoDelete = function() -{ - return new UndoDeleteHighlightCircle(this.objectID, this.x, this.y, this.foregroundColor, this.radius, this.layer, this.alpha); -} - - -function UndoDeleteHighlightCircle(objectID, x, y, circleColor, r, layer, alpha) -{ - this.objectID = objectID; - this.x = x; - this.y = y; - this.color = circleColor; - this.r = r; - this.layer = layer; - this.alpha = alpha -} - -UndoDeleteHighlightCircle.inheritFrom(UndoBlock); - -UndoDeleteHighlightCircle.prototype.undoInitialStep = function(world) -{ - world.addHighlightCircleObject(this.objectID, this.color, this.r); - world.setLayer(this.objectID, this.layer) - world.setNodePosition(this.objectID, this.x, this.y); - world.setAlpha(this.objectID, this.alpha) -} - - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + +// "Class" animatedCircle + + +var HighlightCircle = function(objectID, color, radius) +{ + this.objectID = objectID; + this.radius = radius; + this.thickness = 4; + this.foregroundColor = color; + this.x = 0; + this.y = 0; + this.alpha = 1; + + // call superclass' constructor + HighlightCircle.superclass.constructor.call(this); +} +HighlightCircle.inheritFrom(AnimatedObject); + + +HighlightCircle.prototype.draw = function(ctx) +{ + ctx.globalAlpha = this.alpha; + ctx.strokeStyle = this.foregroundColor; + ctx.lineWidth = this.thickness; + ctx.beginPath(); + ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true); + ctx.closePath(); + ctx.stroke(); +} + + +HighlightCircle.prototype.createUndoDelete = function() +{ + return new UndoDeleteHighlightCircle(this.objectID, this.x, this.y, this.foregroundColor, this.radius, this.layer, this.alpha); +} + + +function UndoDeleteHighlightCircle(objectID, x, y, circleColor, r, layer, alpha) +{ + this.objectID = objectID; + this.x = x; + this.y = y; + this.color = circleColor; + this.r = r; + this.layer = layer; + this.alpha = alpha +} + +UndoDeleteHighlightCircle.inheritFrom(UndoBlock); + +UndoDeleteHighlightCircle.prototype.undoInitialStep = function(world) +{ + world.addHighlightCircleObject(this.objectID, this.color, this.r); + world.setLayer(this.objectID, this.layer) + world.setNodePosition(this.objectID, this.x, this.y); + world.setAlpha(this.objectID, this.alpha) +} + + + + diff --git a/AnimationLibrary/Line.js b/AnimationLibrary/Line.js index da0621e..d9138de 100644 --- a/AnimationLibrary/Line.js +++ b/AnimationLibrary/Line.js @@ -1,229 +1,229 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -// This class is somewhat poorly named -- it handles links between vertices in graphs, -// pointers in linked lists, and so on. - - -var LINE_maxHeightDiff = 5; -var LINE_minHeightDiff = 3; -var LINE_range= LINE_maxHeightDiff - LINE_minHeightDiff + 1; -var LINE_highlightDiff = 3; - - -function Line(n1, n2, color, cv, d, weight, anchorIndex) -{ - this.arrowHeight = 8; - this. arrowWidth = 4; - - this.Node1 = n1; - this.Node2 = n2; - this.Dirty = false; - this.directed = d; - this.edgeColor = color; - this.edgeLabel = weight; - this.highlighted = false; - this.addedToScene = true; - this.anchorPoint = anchorIndex; - this.highlightDiff = 0; - this.curve = cv; - - this.alpha = 1.0; - this.color = function color() - { - return this.edgeColor; - } - - this.setColor = function(newColor) - { - this.edgeColor = newColor; - Dirty = true; - } - - this.setHighlight = function(highlightVal) - { - this.highlighted = highlightVal; - } - - this.pulseHighlight = function(frameNum) - { - if (this.highlighted) - { - var frameMod = frameNum / 14.0; - var delta = Math.abs((frameMod) % (2 * LINE_range - 2) - LINE_range + 1) - this.highlightDiff = delta + LINE_minHeightDiff; - Dirty = true; - } - } - - - this.hasNode = function(n) - { - return ((this.Node1 == n) || (this.Node2 == n)); - } - - - this.createUndoDisconnect = function() - { - return new UndoConnect(this.Node1.objectID, this.Node2.objectID, true, this.edgeColor, this.directed, this.curve, this.edgeLabel, this.anchorPoint); - } - - - this.sign = function(n) - { - if (n > 0) - { - return 1; - } - else - { - return -1; - } - } - - - this.drawArrow = function(pensize, color, context) - { - context.strokeStyle = color; - context.fillStyle = color; - context.lineWidth = pensize; - var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint); - var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y); - - var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint); - var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y); - - var deltaX = toPos[0] - fromPos[0]; - var deltaY = toPos[1] - fromPos[1]; - var midX = (deltaX) / 2.0 + fromPos[0]; - var midY = (deltaY) / 2.0 + fromPos[1]; - var controlX = midX - deltaY * this.curve; - - var controlY = midY + deltaX * this.curve; - - context.beginPath(); - context.moveTo(fromPos[0], fromPos[1]); - context.quadraticCurveTo(controlX, controlY, toPos[0], toPos[1]); - context.stroke(); - //context.closePath(); - - // Position of the edge label: First, we will place it right along the - // middle of the curve (or the middle of the line, for curve == 0) - var labelPosX = 0.25* fromPos[0] + 0.5*controlX + 0.25*toPos[0]; - var labelPosY = 0.25* fromPos[1] + 0.5*controlY + 0.25*toPos[1]; - - // Next, we push the edge position label out just a little in the direction of - // the curve, so that the label doesn't intersect the cuve (as long as the label - // is only a few characters, that is) - var midLen = Math.sqrt(deltaY*deltaY + deltaX*deltaX); - if (midLen != 0) - { - labelPosX += (- deltaY * this.sign(this.curve)) / midLen * 10 - labelPosY += ( deltaX * this.sign(this.curve)) / midLen * 10 - } - - - - context.textAlign = 'center'; - context.font = '10px sans-serif'; - context.textBaseline = 'middle'; - context.fillText(this.edgeLabel, labelPosX, labelPosY); - - if (this.directed) - { - var xVec = controlX - toPos[0]; - var yVec = controlY - toPos[1]; - var len = Math.sqrt(xVec * xVec + yVec*yVec); - - if (len > 0) - { - xVec = xVec / len - yVec = yVec / len; - - context.beginPath(); - context.moveTo(toPos[0], toPos[1]); - context.lineTo(toPos[0] + xVec*this.arrowHeight - yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight + xVec*this.arrowWidth); - context.lineTo(toPos[0] + xVec*this.arrowHeight + yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight - xVec*this.arrowWidth); - context.lineTo(toPos[0], toPos[1]); - context.closePath(); - context.stroke(); - context.fill(); - } - - } - - } - - - this.draw = function(ctx) - { - if (!this.addedToScene) - { - return; - } - ctx.globalAlpha = this.alpha; - - if (this.highlighted) - this.drawArrow(this.highlightDiff, "#FF0000", ctx); - this.drawArrow(1, this.edgeColor, ctx); - } - - -} - - - -function UndoConnect(from, to, createConnection, edgeColor, isDirected, cv, lab, anch) -{ - this.fromID = from; - this.toID = to; - this.connect = createConnection; - this.color = edgeColor; - this.directed = isDirected; - this.curve = cv; - this.edgeLabel = lab; - this.anchorPoint = anch; -} - - -UndoConnect.prototype.undoInitialStep = function(world) -{ - if (this.connect) - { - world.connectEdge(this.fromID, this.toID, this.color, this.curve, this.directed, this.edgeLabel,this.anchorPoint); - } - else - { - world.disconnect(this.fromID,this.toID); - } -} - - -UndoConnect.prototype.addUndoAnimation = function(animationList) -{ - return false; -} +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +// This class is somewhat poorly named -- it handles links between vertices in graphs, +// pointers in linked lists, and so on. + + +var LINE_maxHeightDiff = 5; +var LINE_minHeightDiff = 3; +var LINE_range= LINE_maxHeightDiff - LINE_minHeightDiff + 1; +var LINE_highlightDiff = 3; + + +function Line(n1, n2, color, cv, d, weight, anchorIndex) +{ + this.arrowHeight = 8; + this. arrowWidth = 4; + + this.Node1 = n1; + this.Node2 = n2; + this.Dirty = false; + this.directed = d; + this.edgeColor = color; + this.edgeLabel = weight; + this.highlighted = false; + this.addedToScene = true; + this.anchorPoint = anchorIndex; + this.highlightDiff = 0; + this.curve = cv; + + this.alpha = 1.0; + this.color = function color() + { + return this.edgeColor; + } + + this.setColor = function(newColor) + { + this.edgeColor = newColor; + Dirty = true; + } + + this.setHighlight = function(highlightVal) + { + this.highlighted = highlightVal; + } + + this.pulseHighlight = function(frameNum) + { + if (this.highlighted) + { + var frameMod = frameNum / 14.0; + var delta = Math.abs((frameMod) % (2 * LINE_range - 2) - LINE_range + 1) + this.highlightDiff = delta + LINE_minHeightDiff; + Dirty = true; + } + } + + + this.hasNode = function(n) + { + return ((this.Node1 == n) || (this.Node2 == n)); + } + + + this.createUndoDisconnect = function() + { + return new UndoConnect(this.Node1.objectID, this.Node2.objectID, true, this.edgeColor, this.directed, this.curve, this.edgeLabel, this.anchorPoint); + } + + + this.sign = function(n) + { + if (n > 0) + { + return 1; + } + else + { + return -1; + } + } + + + this.drawArrow = function(pensize, color, context) + { + context.strokeStyle = color; + context.fillStyle = color; + context.lineWidth = pensize; + var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint); + var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y); + + var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint); + var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y); + + var deltaX = toPos[0] - fromPos[0]; + var deltaY = toPos[1] - fromPos[1]; + var midX = (deltaX) / 2.0 + fromPos[0]; + var midY = (deltaY) / 2.0 + fromPos[1]; + var controlX = midX - deltaY * this.curve; + + var controlY = midY + deltaX * this.curve; + + context.beginPath(); + context.moveTo(fromPos[0], fromPos[1]); + context.quadraticCurveTo(controlX, controlY, toPos[0], toPos[1]); + context.stroke(); + //context.closePath(); + + // Position of the edge label: First, we will place it right along the + // middle of the curve (or the middle of the line, for curve == 0) + var labelPosX = 0.25* fromPos[0] + 0.5*controlX + 0.25*toPos[0]; + var labelPosY = 0.25* fromPos[1] + 0.5*controlY + 0.25*toPos[1]; + + // Next, we push the edge position label out just a little in the direction of + // the curve, so that the label doesn't intersect the cuve (as long as the label + // is only a few characters, that is) + var midLen = Math.sqrt(deltaY*deltaY + deltaX*deltaX); + if (midLen != 0) + { + labelPosX += (- deltaY * this.sign(this.curve)) / midLen * 10 + labelPosY += ( deltaX * this.sign(this.curve)) / midLen * 10 + } + + + + context.textAlign = 'center'; + context.font = '10px sans-serif'; + context.textBaseline = 'middle'; + context.fillText(this.edgeLabel, labelPosX, labelPosY); + + if (this.directed) + { + var xVec = controlX - toPos[0]; + var yVec = controlY - toPos[1]; + var len = Math.sqrt(xVec * xVec + yVec*yVec); + + if (len > 0) + { + xVec = xVec / len + yVec = yVec / len; + + context.beginPath(); + context.moveTo(toPos[0], toPos[1]); + context.lineTo(toPos[0] + xVec*this.arrowHeight - yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight + xVec*this.arrowWidth); + context.lineTo(toPos[0] + xVec*this.arrowHeight + yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight - xVec*this.arrowWidth); + context.lineTo(toPos[0], toPos[1]); + context.closePath(); + context.stroke(); + context.fill(); + } + + } + + } + + + this.draw = function(ctx) + { + if (!this.addedToScene) + { + return; + } + ctx.globalAlpha = this.alpha; + + if (this.highlighted) + this.drawArrow(this.highlightDiff, "#FF0000", ctx); + this.drawArrow(1, this.edgeColor, ctx); + } + + +} + + + +function UndoConnect(from, to, createConnection, edgeColor, isDirected, cv, lab, anch) +{ + this.fromID = from; + this.toID = to; + this.connect = createConnection; + this.color = edgeColor; + this.directed = isDirected; + this.curve = cv; + this.edgeLabel = lab; + this.anchorPoint = anch; +} + + +UndoConnect.prototype.undoInitialStep = function(world) +{ + if (this.connect) + { + world.connectEdge(this.fromID, this.toID, this.color, this.curve, this.directed, this.edgeLabel,this.anchorPoint); + } + else + { + world.disconnect(this.fromID,this.toID); + } +} + + +UndoConnect.prototype.addUndoAnimation = function(animationList) +{ + return false; +} diff --git a/AnimationLibrary/ObjectManager.js b/AnimationLibrary/ObjectManager.js index 7dd6b3d..23a8a84 100644 --- a/AnimationLibrary/ObjectManager.js +++ b/AnimationLibrary/ObjectManager.js @@ -1,858 +1,858 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -// Object Manager -// -// Manage all of our animated objects. Control any animated object should occur through -// this interface (not language enforced, because enforcing such things in Javascript is -// problematic.) -// -// This class is only accessed through: -// -// AnimationMain -// Undo objects (which are themselves controlled by AnimationMain - - -// TODO: -// 1. Add proper throws for all error conditions (perhaps guarded by -// an assert-like structure that can be turned off for production?) -// 2. Refactor this code so that it uses the same object syntax (with -// prototypes) as te rest of the code. (low priority) -function ObjectManager(canvas) -{ - this.Nodes = []; - this.Edges = []; - this.BackEdges = []; - this.activeLayers = []; - this.activeLayers[0] = true; - this.ctx = canvas.getContext('2d'); - this.framenum = 0; - this.width = 0; - this.height = 0; - this.statusReport = new AnimatedLabel(-1, "XXX", false, 30, this.ctx); - this.statusReport.x = 30; - - this.draw = function() - { - this.framenum++; - if (this.framenum > 1000) - this.framenum = 0; - - this.ctx.clearRect(0,0,this.width,this.height); // clear canvas - this.statusReport.y = this.height - 15; - - var i; - var j; - for (i = 0; i < this.Nodes.length; i++) - { - if (this.Nodes[i] != null && !this.Nodes[i].highlighted && this.Nodes[i].addedToScene && !this.Nodes[i].alwaysOnTop) - { - this.Nodes[i].draw(this.ctx); - } - } - for (i = 0; i < this.Nodes.length; i++) - { - if (this.Nodes[i] != null && (this.Nodes[i].highlighted && !this.Nodes[i].alwaysOnTop) && this.Nodes[i].addedToScene) - { - this.Nodes[i].pulseHighlight(this.framenum); - this.Nodes[i].draw(this.ctx); - } - } - - for (i = 0; i < this.Nodes.length; i++) - { - if (this.Nodes[i] != null && this.Nodes[i].alwaysOnTop && this.Nodes[i].addedToScene) - { - this.Nodes[i].pulseHighlight(this.framenum); - this.Nodes[i].draw(this.ctx); - } - } - - - for (i = 0; i < this.Edges.length; i++) - { - if (this.Edges[i] != null) - { - for (j = 0; j < this.Edges[i].length; j++) - { - if (this.Edges[i][j].addedToScene) - { - this.Edges[i][j].pulseHighlight(this.framenum); - this.Edges[i][j].draw(this.ctx); - } - - } - - } - } - this.statusReport.draw(this.ctx); - - } - - this.update = function () - { - - - } - - - this.setLayers = function(shown,layers) - { - for (var i = 0; i < layers.length; i++) - { - this.activeLayers[layers[i]] = shown; - } - this.resetLayers(); - - } - - - this.addHighlightCircleObject = function(objectID, objectColor, radius) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - throw "addHighlightCircleObject:Object with same ID (" + String(objectID) + ") already Exists!" - } - var newNode = new HighlightCircle(objectID, objectColor, radius) - this.Nodes[objectID] = newNode; - } - - this.setEdgeAlpha = function(fromID, toID, alphaVal) - { - var oldAlpha = 1.0; - if (this.Edges[fromID] != null && - this.Edges[fromID] != undefined) - { - var len = this.Edges[fromID].length; - for (var i = len - 1; i >= 0; i--) - { - if (this.Edges[fromID][i] != null && - this.Edges[fromID][i] != undefined && - this.Edges[fromID][i].Node2 == this.Nodes[toID]) - { - oldAlpha = this.Edges[fromID][i].alpha - this.Edges[fromID][i].alpha = alphaVal; - } - } - } - return oldAlpha; - - } - - this.setAlpha = function(nodeID, alphaVal) - { - if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) - { - this.Nodes[nodeID].setAlpha(alphaVal); - } - } - - this.getAlpha = function(nodeID) - { - if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) - { - return this.Nodes[nodeID].getAlpha(); - } - else - { - return -1; - } - } - - this.getTextColor = function(nodeID, index) - { - if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) - { - return this.Nodes[nodeID].getTextColor(index); - } - else - { - return "#000000"; - } - - } - - this.setTextColor = function(nodeID, color, index) - { - if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) - { - this.Nodes[nodeID].setTextColor(color, index); - } - } - - - this.setHighlightIndex = function(nodeID, index) - { - if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) - { - this.Nodes[nodeID].setHighlightIndex(index); - } - } - - - - - - this.setAllLayers = function(layers) - { - this.activeLayers = []; - for(var i = 0; i < layers.length; i++) - { - this.activeLayers[layers[i]] = true; - } - this.resetLayers(); - } - - this.resetLayers = function() - { - var i - for (i = 0; i = 0; i--) - { - if (this.Edges[i] != null && this.Edges[i] != undefined) - { - for (var j = 0; j < this.Edges[i].length; j++) - { - if (this.Edges[i][j] != null && this.Edges[i][j] != undefined) - { - this.Edges[i][j].addedToScene = - this.activeLayers[this.Edges[i][j].Node1.layer] == true && - this.activeLayers[this.Edges[i][j].Node2.layer] == true; - } - - } - - } - - } - - } - - - - this.setLayer = function(objectID, layer) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - this.Nodes[objectID].layer = layer; - if (this.activeLayers[layer]) - { - this.Nodes[objectID].addedToScene = true; - } - else - { - this.Nodes[objectID].addedToScene = false; - } - if (this.Edges[objectID] != null && this.Edges[objectID] != undefined) - { - for (var i = 0; i < this.Edges[objectID].length; i++) - { - var nextEdge = this.Edges[objectID][i]; - if (nextEdge != null && nextEdge != undefined) - { - nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) && - (nextEdge.Node2.addedToScene)); - - } - } - } - if (this.BackEdges[objectID] != null && this.BackEdges[objectID] != undefined) - { - for (var i = 0; i < this.BackEdges[objectID].length; i++) - { - var nextEdge = this.BackEdges[objectID][i]; - if (nextEdge != null && nextEdge != undefined) - { - nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) && - (nextEdge.Node2.addedToScene)); - - } - } - } - } - } - - this.clearAllObjects = function() - { - this.Nodes = []; - this.Edges = []; - this.BackEdges = []; - } - - - this.setForegroundColor = function(objectID, color) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - this.Nodes[objectID].setForegroundColor(color); - - } - } - - this.setBackgroundColor = function(objectID, color) - { - if (this.Nodes[objectID] != null) - { - this.Nodes[objectID].setBackgroundColor(color); - - } - } - - this.setHighlight = function(nodeID, val) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return; - } - this.Nodes[nodeID].setHighlight(val); - } - - - this.getHighlight = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return false; - } - return this.Nodes[nodeID].getHighlight(); - } - - - this.getHighlightIndex = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return false; - } - return this.Nodes[nodeID].getHighlightIndex(); - } - - this.setWidth = function(nodeID, val) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return; - } - this.Nodes[nodeID].setWidth(val); - } - - this.setHeight = function(nodeID, val) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return; - } - this.Nodes[nodeID].setHeight(val); - } - - - this.getHeight = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return -1; - } - return this.Nodes[nodeID].getHeight(); - } - - this.getWidth = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return -1; - } - return this.Nodes[nodeID].getWidth(); - } - - this.backgroundColor = function(objectID) - { - if (this.Nodes[objectID] != null) - { - return this.Nodes[objectID].backgroundColor; - } - else - { - return '#000000'; - } - } - - this.foregroundColor = function(objectID) - { - if (this.Nodes[objectID] != null) - { - return this.Nodes[objectID].foregroundColor; - } - else - { - return '#000000'; - } - } - - - this.disconnect = function(objectIDfrom,objectIDto) - { - var undo = null; - var i; - if (this.Edges[objectIDfrom] != null) - { - var len = this.Edges[objectIDfrom].length; - for (i = len - 1; i >= 0; i--) - { - if (this.Edges[objectIDfrom][i] != null && this.Edges[objectIDfrom][i].Node2 == this.Nodes[objectIDto]) - { - var deleted = this.Edges[objectIDfrom][i]; - undo = deleted.createUndoDisconnect(); - this.Edges[objectIDfrom][i] = this.Edges[objectIDfrom][len - 1]; - len -= 1; - this.Edges[objectIDfrom].pop(); - } - } - } - if (this.BackEdges[objectIDto] != null) - { - len = this.BackEdges[objectIDto].length; - for (i = len - 1; i >= 0; i--) - { - if (this.BackEdges[objectIDto][i] != null && this.BackEdges[objectIDto][i].Node1 == this.Nodes[objectIDfrom]) - { - deleted = this.BackEdges[objectIDto][i]; - // Note: Don't need to remove this child, did it above on the regular edge - this.BackEdges[objectIDto][i] = this.BackEdges[objectIDto][len - 1]; - len -= 1; - this.BackEdges[objectIDto].pop(); - } - } - } - return undo; - } - - this.deleteIncident = function(objectID) - { - var undoStack = []; - - if (this.Edges[objectID] != null) - { - var len = this.Edges[objectID].length; - for (var i = len - 1; i >= 0; i--) - { - var deleted = this.Edges[objectID][i]; - var node2ID = deleted.Node2.identifier(); - undoStack.push(deleted.createUndoDisconnect()); - - var len2 = this.BackEdges[node2ID].length; - for (var j = len2 - 1; j >=0; j--) - { - if (this.BackEdges[node2ID][j] == deleted) - { - this.BackEdges[node2ID][j] = this.BackEdges[node2ID][len2 - 1]; - len2 -= 1; - this.BackEdges[node2ID].pop(); - } - } - } - this.Edges[objectID] = null; - } - if (this.BackEdges[objectID] != null) - { - len = this.BackEdges[objectID].length; - for (i = len - 1; i >= 0; i--) - { - deleted = this.BackEdges[objectID][i]; - var node1ID = deleted.Node1.identifier(); - undoStack.push(deleted.createUndoDisconnect()); - - len2 = this.Edges[node1ID].length; - for (j = len2 - 1; j >=0; j--) - { - if (this.Edges[node1ID][j] == deleted) - { - this.Edges[node1ID][j] = this.Edges[node1ID][len2 - 1]; - len2 -= 1; - this.Edges[node1ID].pop(); - } - } - } - this.BackEdges[objectID] = null; - } - return undoStack; - } - - - this.removeObject = function(ObjectID) - { - var OldObject = this.Nodes[ObjectID]; - if (ObjectID == this.Nodes.length - 1) - { - this.Nodes.pop(); - } - else - { - this.Nodes[ObjectID] = null; - } - } - - this.getObject = function(objectID) - { - if (this.Nodes[objectID] == null || this.Nodes[objectID] == undefined) - { - throw "getObject:Object with ID (" + String(objectID) + ") does not exist" - } - return this.Nodes[objectID]; - - } - - - this.addCircleObject = function (objectID, objectLabel) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - throw "addCircleObject:Object with same ID (" + String(objectID) + ") already Exists!" - } - var newNode = new AnimatedCircle(objectID, objectLabel); - this.Nodes[objectID] = newNode; - } - - this.getNodeX = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - throw "getting x position of an object that does not exit"; - } - return this.Nodes[nodeID].x; - } - - this.getTextWidth = function(text) - { - // TODO: Need to make fonts more flexible, and less hardwired. - this.ctx.font = '10px sans-serif'; - if (text==undefined) - { - w = 3; - } - var strList = text.split("\n"); - var width = 0; - if (strList.length == 1) - { - width = this.ctx.measureText(text).width; - } - else - { - for (var i = 0; i < strList.length; i++) - { - width = Math.max(width, this.ctx.measureText(strList[i]).width); - } - } - - return width; - } - - this.setText = function(nodeID, text, index) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - return; - throw "setting text of an object that does not exit"; - } - this.Nodes[nodeID].setText(text, index, this.getTextWidth(text)); - - } - - this.getText = function(nodeID, index) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - throw "getting text of an object that does not exit"; - } - return this.Nodes[nodeID].getText(index); - - } - - this.getNodeY = function(nodeID) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - throw "getting y position of an object that does not exit"; - } - return this.Nodes[nodeID].y; - } - - - this.connectEdge = function(objectIDfrom, objectIDto, color, curve, directed, lab, connectionPoint) - { - var fromObj = this.Nodes[objectIDfrom]; - var toObj = this.Nodes[objectIDto]; - if (fromObj == null || toObj == null) - { - throw "Tried to connect two nodes, one didn't exist!"; - } - var l = new Line(fromObj,toObj, color, curve, directed, lab, connectionPoint); - if (this.Edges[objectIDfrom] == null || this.Edges[objectIDfrom] == undefined) - { - this.Edges[objectIDfrom] = []; - } - if (this.BackEdges[objectIDto] == null || this.BackEdges[objectIDto] == undefined) - { - this.BackEdges[objectIDto] = []; - } - l.addedToScene = fromObj.addedToScene && toObj.addedToScene; - this.Edges[objectIDfrom].push(l); - this.BackEdges[objectIDto].push(l); - - } - - - this.setNull = function(objectID, nullVal) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - this.Nodes[objectID].setNull(nullVal); - - } - } - - this.getNull = function(objectID) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - return this.Nodes[objectID].getNull(); - } - return false; // TODO: Error here? - } - - - - this.setEdgeColor = function(fromID, toID, color) // returns old color - { - var oldColor ="#000000"; - if (this.Edges[fromID] != null && - this.Edges[fromID] != undefined) - { - var len = this.Edges[fromID].length; - for (var i = len - 1; i >= 0; i--) - { - if (this.Edges[fromID][i] != null && - this.Edges[fromID][i] != undefined && - this.Edges[fromID][i].Node2 == this.Nodes[toID]) - { - oldColor = this.Edges[fromID][i].color(); - this.Edges[fromID][i].setColor(color); - } - } - } - return oldColor; - } - - this.alignTop = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - this.Nodes[id1].alignTop(this.Nodes[id2]); - } - - this.alignLeft = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - this.Nodes[id1].alignLeft(this.Nodes[id2]); - } - - this.alignRight = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - this.Nodes[id1].alignRight(this.Nodes[id2]); - } - - - - this.getAlignRightPos = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - return this.Nodes[id1].getAlignRightPos(this.Nodes[id2]); - } - - this.getAlignLeftPos = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - return this.Nodes[id1].getAlignLeftPos(this.Nodes[id2]); - } - - - - this.alignBottom = function(id1, id2) - { - if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || - this.Nodes[id2] == null || this.Nodes[id2] == undefined) - { - throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); - } - this.Nodes[id1].alignBottom(this.Nodes[id2]); - } - - - this.setEdgeHighlight = function(fromID, toID, val) // returns old color - { - var oldHighlight = false; - if (this.Edges[fromID] != null && - this.Edges[fromID] != undefined) - { - var len = this.Edges[fromID].length; - for (var i = len - 1; i >= 0; i--) - { - if (this.Edges[fromID][i] != null && - this.Edges[fromID][i] != undefined && - this.Edges[fromID][i].Node2 == this.Nodes[toID]) - { - oldHighlight = this.Edges[fromID][i].highlighted; - this.Edges[fromID][i].setHighlight(val); - } - } - } - return oldHighlight; - } - this.addLabelObject = function(objectID, objectLabel, centering) - { - if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) - { - throw new Error("addLabelObject: Object Already Exists!"); - } - - var newLabel = new AnimatedLabel(objectID, objectLabel, centering, this.getTextWidth(objectLabel),this.ctx); - this.Nodes[objectID] = newLabel; - } - - - this.addLinkedListObject = function(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor) - { - if (this.Nodes[objectID] != null) - { - throw new Error("addLinkedListObject:Object with same ID already Exists!"); - return; - } - var newNode = new AnimatedLinkedList(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor); - this.Nodes[objectID] = newNode; - } - - - this.getNumElements = function(objectID) - { - return this.Nodes[objectID].getNumElements(); - } - - - this.setNumElements = function(objectID, numElems) - { - this.Nodes[objectID].setNumElements(numElems); - } - this.addBTreeNode = function(objectID, widthPerElem, height, numElems, backgroundColor, foregroundColor) - { - backgroundColor = (backgroundColor == undefined) ? "#FFFFFF" : backgroundColor; - foregroundColor = (foregroundColor == undefined) ? "#FFFFFF" : foregroundColor; - - if (this.Nodes[objectID] != null && Nodes[objectID] != undefined) - { - throw "addBTreeNode:Object with same ID already Exists!"; - } - - var newNode = new AnimatedBTreeNode(objectID,widthPerElem, height, numElems, backgroundColor, foregroundColor); - this.Nodes[objectID] = newNode; - } - - this.addRectangleObject = function(objectID,nodeLabel, width, height, xJustify , yJustify , backgroundColor, foregroundColor) - { - if (this.Nodes[objectID] != null || this.Nodes[objectID] != undefined) - { - throw new Error("addRectangleObject:Object with same ID already Exists!"); - } - var newNode = new AnimatedRectangle(objectID, nodeLabel, width, height, xJustify, yJustify, backgroundColor, foregroundColor); - this.Nodes[objectID] = newNode; - - } - - - - - this.setNodePosition = function(nodeID, newX, newY) - { - if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) - { - // TODO: Error here? - return; - } - if (newX == undefined || newY == undefined) - { - - return; - } - this.Nodes[nodeID].x = newX; - this.Nodes[nodeID].y = newY; - /* Don't need to dirty anything, since we repaint everything every frame - (TODO: Revisit if we do conditional redraws) - }*/ - - } - -} - - - - - - - - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +// Object Manager +// +// Manage all of our animated objects. Control any animated object should occur through +// this interface (not language enforced, because enforcing such things in Javascript is +// problematic.) +// +// This class is only accessed through: +// +// AnimationMain +// Undo objects (which are themselves controlled by AnimationMain + + +// TODO: +// 1. Add proper throws for all error conditions (perhaps guarded by +// an assert-like structure that can be turned off for production?) +// 2. Refactor this code so that it uses the same object syntax (with +// prototypes) as te rest of the code. (low priority) +function ObjectManager(canvas) +{ + this.Nodes = []; + this.Edges = []; + this.BackEdges = []; + this.activeLayers = []; + this.activeLayers[0] = true; + this.ctx = canvas.getContext('2d'); + this.framenum = 0; + this.width = 0; + this.height = 0; + this.statusReport = new AnimatedLabel(-1, "XXX", false, 30, this.ctx); + this.statusReport.x = 30; + + this.draw = function() + { + this.framenum++; + if (this.framenum > 1000) + this.framenum = 0; + + this.ctx.clearRect(0,0,this.width,this.height); // clear canvas + this.statusReport.y = this.height - 15; + + var i; + var j; + for (i = 0; i < this.Nodes.length; i++) + { + if (this.Nodes[i] != null && !this.Nodes[i].highlighted && this.Nodes[i].addedToScene && !this.Nodes[i].alwaysOnTop) + { + this.Nodes[i].draw(this.ctx); + } + } + for (i = 0; i < this.Nodes.length; i++) + { + if (this.Nodes[i] != null && (this.Nodes[i].highlighted && !this.Nodes[i].alwaysOnTop) && this.Nodes[i].addedToScene) + { + this.Nodes[i].pulseHighlight(this.framenum); + this.Nodes[i].draw(this.ctx); + } + } + + for (i = 0; i < this.Nodes.length; i++) + { + if (this.Nodes[i] != null && this.Nodes[i].alwaysOnTop && this.Nodes[i].addedToScene) + { + this.Nodes[i].pulseHighlight(this.framenum); + this.Nodes[i].draw(this.ctx); + } + } + + + for (i = 0; i < this.Edges.length; i++) + { + if (this.Edges[i] != null) + { + for (j = 0; j < this.Edges[i].length; j++) + { + if (this.Edges[i][j].addedToScene) + { + this.Edges[i][j].pulseHighlight(this.framenum); + this.Edges[i][j].draw(this.ctx); + } + + } + + } + } + this.statusReport.draw(this.ctx); + + } + + this.update = function () + { + + + } + + + this.setLayers = function(shown,layers) + { + for (var i = 0; i < layers.length; i++) + { + this.activeLayers[layers[i]] = shown; + } + this.resetLayers(); + + } + + + this.addHighlightCircleObject = function(objectID, objectColor, radius) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + throw "addHighlightCircleObject:Object with same ID (" + String(objectID) + ") already Exists!" + } + var newNode = new HighlightCircle(objectID, objectColor, radius) + this.Nodes[objectID] = newNode; + } + + this.setEdgeAlpha = function(fromID, toID, alphaVal) + { + var oldAlpha = 1.0; + if (this.Edges[fromID] != null && + this.Edges[fromID] != undefined) + { + var len = this.Edges[fromID].length; + for (var i = len - 1; i >= 0; i--) + { + if (this.Edges[fromID][i] != null && + this.Edges[fromID][i] != undefined && + this.Edges[fromID][i].Node2 == this.Nodes[toID]) + { + oldAlpha = this.Edges[fromID][i].alpha + this.Edges[fromID][i].alpha = alphaVal; + } + } + } + return oldAlpha; + + } + + this.setAlpha = function(nodeID, alphaVal) + { + if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) + { + this.Nodes[nodeID].setAlpha(alphaVal); + } + } + + this.getAlpha = function(nodeID) + { + if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) + { + return this.Nodes[nodeID].getAlpha(); + } + else + { + return -1; + } + } + + this.getTextColor = function(nodeID, index) + { + if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) + { + return this.Nodes[nodeID].getTextColor(index); + } + else + { + return "#000000"; + } + + } + + this.setTextColor = function(nodeID, color, index) + { + if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) + { + this.Nodes[nodeID].setTextColor(color, index); + } + } + + + this.setHighlightIndex = function(nodeID, index) + { + if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined) + { + this.Nodes[nodeID].setHighlightIndex(index); + } + } + + + + + + this.setAllLayers = function(layers) + { + this.activeLayers = []; + for(var i = 0; i < layers.length; i++) + { + this.activeLayers[layers[i]] = true; + } + this.resetLayers(); + } + + this.resetLayers = function() + { + var i + for (i = 0; i = 0; i--) + { + if (this.Edges[i] != null && this.Edges[i] != undefined) + { + for (var j = 0; j < this.Edges[i].length; j++) + { + if (this.Edges[i][j] != null && this.Edges[i][j] != undefined) + { + this.Edges[i][j].addedToScene = + this.activeLayers[this.Edges[i][j].Node1.layer] == true && + this.activeLayers[this.Edges[i][j].Node2.layer] == true; + } + + } + + } + + } + + } + + + + this.setLayer = function(objectID, layer) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + this.Nodes[objectID].layer = layer; + if (this.activeLayers[layer]) + { + this.Nodes[objectID].addedToScene = true; + } + else + { + this.Nodes[objectID].addedToScene = false; + } + if (this.Edges[objectID] != null && this.Edges[objectID] != undefined) + { + for (var i = 0; i < this.Edges[objectID].length; i++) + { + var nextEdge = this.Edges[objectID][i]; + if (nextEdge != null && nextEdge != undefined) + { + nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) && + (nextEdge.Node2.addedToScene)); + + } + } + } + if (this.BackEdges[objectID] != null && this.BackEdges[objectID] != undefined) + { + for (var i = 0; i < this.BackEdges[objectID].length; i++) + { + var nextEdge = this.BackEdges[objectID][i]; + if (nextEdge != null && nextEdge != undefined) + { + nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) && + (nextEdge.Node2.addedToScene)); + + } + } + } + } + } + + this.clearAllObjects = function() + { + this.Nodes = []; + this.Edges = []; + this.BackEdges = []; + } + + + this.setForegroundColor = function(objectID, color) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + this.Nodes[objectID].setForegroundColor(color); + + } + } + + this.setBackgroundColor = function(objectID, color) + { + if (this.Nodes[objectID] != null) + { + this.Nodes[objectID].setBackgroundColor(color); + + } + } + + this.setHighlight = function(nodeID, val) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return; + } + this.Nodes[nodeID].setHighlight(val); + } + + + this.getHighlight = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return false; + } + return this.Nodes[nodeID].getHighlight(); + } + + + this.getHighlightIndex = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return false; + } + return this.Nodes[nodeID].getHighlightIndex(); + } + + this.setWidth = function(nodeID, val) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return; + } + this.Nodes[nodeID].setWidth(val); + } + + this.setHeight = function(nodeID, val) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return; + } + this.Nodes[nodeID].setHeight(val); + } + + + this.getHeight = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return -1; + } + return this.Nodes[nodeID].getHeight(); + } + + this.getWidth = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return -1; + } + return this.Nodes[nodeID].getWidth(); + } + + this.backgroundColor = function(objectID) + { + if (this.Nodes[objectID] != null) + { + return this.Nodes[objectID].backgroundColor; + } + else + { + return '#000000'; + } + } + + this.foregroundColor = function(objectID) + { + if (this.Nodes[objectID] != null) + { + return this.Nodes[objectID].foregroundColor; + } + else + { + return '#000000'; + } + } + + + this.disconnect = function(objectIDfrom,objectIDto) + { + var undo = null; + var i; + if (this.Edges[objectIDfrom] != null) + { + var len = this.Edges[objectIDfrom].length; + for (i = len - 1; i >= 0; i--) + { + if (this.Edges[objectIDfrom][i] != null && this.Edges[objectIDfrom][i].Node2 == this.Nodes[objectIDto]) + { + var deleted = this.Edges[objectIDfrom][i]; + undo = deleted.createUndoDisconnect(); + this.Edges[objectIDfrom][i] = this.Edges[objectIDfrom][len - 1]; + len -= 1; + this.Edges[objectIDfrom].pop(); + } + } + } + if (this.BackEdges[objectIDto] != null) + { + len = this.BackEdges[objectIDto].length; + for (i = len - 1; i >= 0; i--) + { + if (this.BackEdges[objectIDto][i] != null && this.BackEdges[objectIDto][i].Node1 == this.Nodes[objectIDfrom]) + { + deleted = this.BackEdges[objectIDto][i]; + // Note: Don't need to remove this child, did it above on the regular edge + this.BackEdges[objectIDto][i] = this.BackEdges[objectIDto][len - 1]; + len -= 1; + this.BackEdges[objectIDto].pop(); + } + } + } + return undo; + } + + this.deleteIncident = function(objectID) + { + var undoStack = []; + + if (this.Edges[objectID] != null) + { + var len = this.Edges[objectID].length; + for (var i = len - 1; i >= 0; i--) + { + var deleted = this.Edges[objectID][i]; + var node2ID = deleted.Node2.identifier(); + undoStack.push(deleted.createUndoDisconnect()); + + var len2 = this.BackEdges[node2ID].length; + for (var j = len2 - 1; j >=0; j--) + { + if (this.BackEdges[node2ID][j] == deleted) + { + this.BackEdges[node2ID][j] = this.BackEdges[node2ID][len2 - 1]; + len2 -= 1; + this.BackEdges[node2ID].pop(); + } + } + } + this.Edges[objectID] = null; + } + if (this.BackEdges[objectID] != null) + { + len = this.BackEdges[objectID].length; + for (i = len - 1; i >= 0; i--) + { + deleted = this.BackEdges[objectID][i]; + var node1ID = deleted.Node1.identifier(); + undoStack.push(deleted.createUndoDisconnect()); + + len2 = this.Edges[node1ID].length; + for (j = len2 - 1; j >=0; j--) + { + if (this.Edges[node1ID][j] == deleted) + { + this.Edges[node1ID][j] = this.Edges[node1ID][len2 - 1]; + len2 -= 1; + this.Edges[node1ID].pop(); + } + } + } + this.BackEdges[objectID] = null; + } + return undoStack; + } + + + this.removeObject = function(ObjectID) + { + var OldObject = this.Nodes[ObjectID]; + if (ObjectID == this.Nodes.length - 1) + { + this.Nodes.pop(); + } + else + { + this.Nodes[ObjectID] = null; + } + } + + this.getObject = function(objectID) + { + if (this.Nodes[objectID] == null || this.Nodes[objectID] == undefined) + { + throw "getObject:Object with ID (" + String(objectID) + ") does not exist" + } + return this.Nodes[objectID]; + + } + + + this.addCircleObject = function (objectID, objectLabel) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + throw "addCircleObject:Object with same ID (" + String(objectID) + ") already Exists!" + } + var newNode = new AnimatedCircle(objectID, objectLabel); + this.Nodes[objectID] = newNode; + } + + this.getNodeX = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + throw "getting x position of an object that does not exit"; + } + return this.Nodes[nodeID].x; + } + + this.getTextWidth = function(text) + { + // TODO: Need to make fonts more flexible, and less hardwired. + this.ctx.font = '10px sans-serif'; + if (text==undefined) + { + w = 3; + } + var strList = text.split("\n"); + var width = 0; + if (strList.length == 1) + { + width = this.ctx.measureText(text).width; + } + else + { + for (var i = 0; i < strList.length; i++) + { + width = Math.max(width, this.ctx.measureText(strList[i]).width); + } + } + + return width; + } + + this.setText = function(nodeID, text, index) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + return; + throw "setting text of an object that does not exit"; + } + this.Nodes[nodeID].setText(text, index, this.getTextWidth(text)); + + } + + this.getText = function(nodeID, index) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + throw "getting text of an object that does not exit"; + } + return this.Nodes[nodeID].getText(index); + + } + + this.getNodeY = function(nodeID) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + throw "getting y position of an object that does not exit"; + } + return this.Nodes[nodeID].y; + } + + + this.connectEdge = function(objectIDfrom, objectIDto, color, curve, directed, lab, connectionPoint) + { + var fromObj = this.Nodes[objectIDfrom]; + var toObj = this.Nodes[objectIDto]; + if (fromObj == null || toObj == null) + { + throw "Tried to connect two nodes, one didn't exist!"; + } + var l = new Line(fromObj,toObj, color, curve, directed, lab, connectionPoint); + if (this.Edges[objectIDfrom] == null || this.Edges[objectIDfrom] == undefined) + { + this.Edges[objectIDfrom] = []; + } + if (this.BackEdges[objectIDto] == null || this.BackEdges[objectIDto] == undefined) + { + this.BackEdges[objectIDto] = []; + } + l.addedToScene = fromObj.addedToScene && toObj.addedToScene; + this.Edges[objectIDfrom].push(l); + this.BackEdges[objectIDto].push(l); + + } + + + this.setNull = function(objectID, nullVal) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + this.Nodes[objectID].setNull(nullVal); + + } + } + + this.getNull = function(objectID) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + return this.Nodes[objectID].getNull(); + } + return false; // TODO: Error here? + } + + + + this.setEdgeColor = function(fromID, toID, color) // returns old color + { + var oldColor ="#000000"; + if (this.Edges[fromID] != null && + this.Edges[fromID] != undefined) + { + var len = this.Edges[fromID].length; + for (var i = len - 1; i >= 0; i--) + { + if (this.Edges[fromID][i] != null && + this.Edges[fromID][i] != undefined && + this.Edges[fromID][i].Node2 == this.Nodes[toID]) + { + oldColor = this.Edges[fromID][i].color(); + this.Edges[fromID][i].setColor(color); + } + } + } + return oldColor; + } + + this.alignTop = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + this.Nodes[id1].alignTop(this.Nodes[id2]); + } + + this.alignLeft = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + this.Nodes[id1].alignLeft(this.Nodes[id2]); + } + + this.alignRight = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + this.Nodes[id1].alignRight(this.Nodes[id2]); + } + + + + this.getAlignRightPos = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + return this.Nodes[id1].getAlignRightPos(this.Nodes[id2]); + } + + this.getAlignLeftPos = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + return this.Nodes[id1].getAlignLeftPos(this.Nodes[id2]); + } + + + + this.alignBottom = function(id1, id2) + { + if (this.Nodes[id1] == null || this.Nodes[id1] == undefined || + this.Nodes[id2] == null || this.Nodes[id2] == undefined) + { + throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2); + } + this.Nodes[id1].alignBottom(this.Nodes[id2]); + } + + + this.setEdgeHighlight = function(fromID, toID, val) // returns old color + { + var oldHighlight = false; + if (this.Edges[fromID] != null && + this.Edges[fromID] != undefined) + { + var len = this.Edges[fromID].length; + for (var i = len - 1; i >= 0; i--) + { + if (this.Edges[fromID][i] != null && + this.Edges[fromID][i] != undefined && + this.Edges[fromID][i].Node2 == this.Nodes[toID]) + { + oldHighlight = this.Edges[fromID][i].highlighted; + this.Edges[fromID][i].setHighlight(val); + } + } + } + return oldHighlight; + } + this.addLabelObject = function(objectID, objectLabel, centering) + { + if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined) + { + throw new Error("addLabelObject: Object Already Exists!"); + } + + var newLabel = new AnimatedLabel(objectID, objectLabel, centering, this.getTextWidth(objectLabel),this.ctx); + this.Nodes[objectID] = newLabel; + } + + + this.addLinkedListObject = function(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor) + { + if (this.Nodes[objectID] != null) + { + throw new Error("addLinkedListObject:Object with same ID already Exists!"); + return; + } + var newNode = new AnimatedLinkedList(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor); + this.Nodes[objectID] = newNode; + } + + + this.getNumElements = function(objectID) + { + return this.Nodes[objectID].getNumElements(); + } + + + this.setNumElements = function(objectID, numElems) + { + this.Nodes[objectID].setNumElements(numElems); + } + this.addBTreeNode = function(objectID, widthPerElem, height, numElems, backgroundColor, foregroundColor) + { + backgroundColor = (backgroundColor == undefined) ? "#FFFFFF" : backgroundColor; + foregroundColor = (foregroundColor == undefined) ? "#FFFFFF" : foregroundColor; + + if (this.Nodes[objectID] != null && Nodes[objectID] != undefined) + { + throw "addBTreeNode:Object with same ID already Exists!"; + } + + var newNode = new AnimatedBTreeNode(objectID,widthPerElem, height, numElems, backgroundColor, foregroundColor); + this.Nodes[objectID] = newNode; + } + + this.addRectangleObject = function(objectID,nodeLabel, width, height, xJustify , yJustify , backgroundColor, foregroundColor) + { + if (this.Nodes[objectID] != null || this.Nodes[objectID] != undefined) + { + throw new Error("addRectangleObject:Object with same ID already Exists!"); + } + var newNode = new AnimatedRectangle(objectID, nodeLabel, width, height, xJustify, yJustify, backgroundColor, foregroundColor); + this.Nodes[objectID] = newNode; + + } + + + + + this.setNodePosition = function(nodeID, newX, newY) + { + if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined) + { + // TODO: Error here? + return; + } + if (newX == undefined || newY == undefined) + { + + return; + } + this.Nodes[nodeID].x = newX; + this.Nodes[nodeID].y = newY; + /* Don't need to dirty anything, since we repaint everything every frame + (TODO: Revisit if we do conditional redraws) + }*/ + + } + +} + + + + + + + + + diff --git a/AnimationLibrary/UndoFunctions.js b/AnimationLibrary/UndoFunctions.js index 5019e5a..6397719 100644 --- a/AnimationLibrary/UndoFunctions.js +++ b/AnimationLibrary/UndoFunctions.js @@ -1,381 +1,381 @@ -// Copyright 2011 David Galles, University of San Francisco. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of the University of San Francisco - - -// Base "class": UndoBlock - -function UndoBlock() -{ - -} - -UndoBlock.prototype.addUndoAnimation = function(animationList) -{ - return false; -} - -UndoBlock.prototype.undoInitialStep = function(world) -{ - -} - -//////////////////////////////////////////////////////////// -// UndoMove -//////////////////////////////////////////////////////////// - -function UndoMove(id, fmX, fmy, tx, ty) -{ - this.objectID = id; - this.fromX = fmX; - this.fromY = fmy; - this.toX = tx; - this.toY = ty; -} - - -UndoMove.inheritFrom(UndoBlock); - -UndoMove.prototype.addUndoAnimation = function (animationList) -{ - var nextAnim = new SingleAnimation(this.objectID, this.fromX, this.fromY, this.toX, this.toY); - animationList.push(nextAnim); - return true; -} - -//////////////////////////////////////////////////////////// -// UndoCreate -//////////////////////////////////////////////////////////// - -function UndoCreate(id) -{ - this.objectID = id; -} - -UndoCreate.inheritFrom(UndoBlock); - - -UndoCreate.prototype.undoInitialStep = function(world) -{ - world.removeObject(this.objectID); -} - -//////////////////////////////////////////////////////////// -// UndoHighlight -//////////////////////////////////////////////////////////// - -function UndoHighlight(id, val) -{ - this.objectID = id; - this.highlightValue = val; -} - -UndoHighlight.inheritFrom(UndoBlock); - -UndoHighlight.prototype.undoInitialStep = function(world) -{ - world.setHighlight(this.objectID, this.highlightValue); -} - - -//////////////////////////////////////////////////////////// -// UndoSetHeight -//////////////////////////////////////////////////////////// - -function UndoSetHeight(id, val) -{ - this.objectID = id; - this.height = val; -} - -UndoSetHeight.inheritFrom(UndoBlock); - -UndoSetHeight.prototype.undoInitialStep = function(world) -{ - world.setHeight(this.objectID, this.height); -} - -//////////////////////////////////////////////////////////// -// UndoSetWidth -//////////////////////////////////////////////////////////// - -function UndoSetWidth(id, val) -{ - this.objectID = id; - this.width = val; -} - -UndoSetWidth.inheritFrom(UndoBlock); - -UndoSetWidth.prototype.undoInitialStep = function(world) -{ - world.setWidth(this.objectID, this.width); -} - - -//////////////////////////////////////////////////////////// -// UndoSetNumElements -//////////////////////////////////////////////////////////// -function UndoSetNumElements(obj, newNumElems) -{ - this.objectID = obj.objectID; - this.sizeBeforeChange = obj.getNumElements(); - this.sizeAfterChange = newNumElems; - if (this.sizeBeforeChange > this.sizeAfterChange) - { - this.labels = new Array(this.sizeBeforeChange - this.sizeAfterChange); - this.colors = new Array(this.sizeBeforeChange - this.sizeAfterChange); - for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++) - { - this.labels[i] = obj.getText(i+this.sizeAfterChange); - this.colors[i] = obj.getTextColor(i+this.sizeAfterChange); - } - - } -} - -UndoSetNumElements.inheritFrom(UndoBlock); - - -UndoSetNumElements.prototype.undoInitialStep = function(world) -{ - world.setNumElements(this.objectID, this.sizeBeforeChange); - if (this.sizeBeforeChange > this.sizeAfterChange) - { - for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++) - { - world.setText(this.objectID, this.labels[i], i+this.sizeAfterChange); - world.setTextColor(this.objectID, this.colors[i], i+this.sizeAfterChange); - } - } -} - - -//////////////////////////////////////////////////////////// -// UndoSetAlpha -//////////////////////////////////////////////////////////// - -function UndoSetAlpha(id, alph) -{ - this.objectID = id; - this.alphaVal = alph; -} - -UndoSetAlpha.inheritFrom(UndoBlock); - -UndoSetAlpha.prototype.undoInitialStep = function(world) -{ - world.setAlpha(this.objectID, this.alphaVal); -} - -//////////////////////////////////////////////////////////// -// UndoSetNull -//////////////////////////////////////////////////////////// - -function UndoSetNull(id, nv) -{ - this.objectID = id; - this.nullVal = nv; -} - -UndoSetNull.inheritFrom(UndoBlock); - -UndoSetNull.prototype.undoInitialStep = function(world) -{ - world.setNull(this.objectID, this.nullVal); -} - -//////////////////////////////////////////////////////////// -// UndoSetForegroundColor -//////////////////////////////////////////////////////////// - -function UndoSetForegroundColor(id, color) -{ - this.objectID = id; - this.color = color; -} - -UndoSetForegroundColor.inheritFrom(UndoBlock); - -UndoSetForegroundColor.prototype.undoInitialStep = function (world) -{ - world.setForegroundColor(this.objectID, this.color); -} - -//////////////////////////////////////////////////////////// -// UndoSetBackgroundColor -//////////////////////////////////////////////////////////// - -function UndoSetBackgroundColor(id, color) -{ - this.objectID = id; - this.color = color; -} - -UndoSetBackgroundColor.inheritFrom(UndoBlock); - -UndoSetBackgroundColor.prototype.undoInitialStep = function (world) -{ - world.setBackgroundColor(this.objectID, this.color); -} - - - -//////////////////////////////////////////////////////////// -// UndoSetHighlightIndex -//////////////////////////////////////////////////////////// - -function UndoSetHighlightIndex(id, index) -{ - this.objectID = id; - this.index = index; -} - -UndoSetHighlightIndex.inheritFrom(UndoBlock); - -UndoSetHighlightIndex.prototype.undoInitialStep = function (world) -{ - world.setHighlightIndex(this.objectID, this.index); -} - - - -//////////////////////////////////////////////////////////// -// UndoSetText -//////////////////////////////////////////////////////////// - - - -function UndoSetText(id, str, index) -{ - this.objectID = id; - this.newText = str; - this.labelIndex = index; -} - -UndoSetText.inheritFrom(UndoBlock); - -UndoSetText.prototype.undoInitialStep = function(world) -{ - world.setText(this.objectID, this.newText, this.labelIndex); -} -//////////////////////////////////////////////////////////// -// UndoSetTextColor -//////////////////////////////////////////////////////////// - - - -function UndoSetTextColor(id, color, index) -{ - this.objectID = id; - this.color = color; - this.index = index; -} - -UndoSetTextColor.inheritFrom(UndoBlock); - -UndoSetTextColor.prototype.undoInitialStep = function(world) -{ - world.setTextColor(this.objectID, this.color, this.index); -} - - - -//////////////////////////////////////////////////////////// -// UndoHighlightEdge -//////////////////////////////////////////////////////////// - -function UndoHighlightEdge(from, to, val) -{ - this.fromID = from; - this.toID = to; - this.highlightValue = val; -} - -UndoHighlightEdge.inheritFrom(UndoBlock); - -UndoHighlightEdge.prototype.undoInitialStep = function(world) -{ - world.setEdgeHighlight(this.fromID, this.toID, this.highlightValue); -} - - -//////////////////////////////////////////////////////////// -// UndoSetEdgeColor -//////////////////////////////////////////////////////////// - -function UndoSetEdgeColor(from, to, oldColor) -{ - this.fromID = from; - this.toID = to; - this.color = oldColor; -} - -UndoSetEdgeColor.inheritFrom(UndoBlock); - -UndoSetEdgeColor.prototype.undoInitialStep = function(world) -{ - world.setEdgeColor(this.fromID, this.toID, this.color); -} - - -//////////////////////////////////////////////////////////// -// UndoSetEdgeAlpha -//////////////////////////////////////////////////////////// - -function UndoSetEdgeAlpha(from, to, oldAplha) -{ - this.fromID = from; - this.toID = to; - this.alpha = oldAplha; -} - -UndoSetEdgeAlpha.inheritFrom(UndoBlock); - -UndoSetEdgeAlpha.prototype.undoInitialStep = function(world) -{ - world.setEdgeAlpha(this.fromID, this.toID, this.alpha); -} - -//////////////////////////////////////////////////////////// -// UndoSetPosition -//////////////////////////////////////////////////////////// - -function UndoSetPosition(id, x, y) -{ - this.objectID = id; - this.x = x; - this.y = y; -} - -UndoSetPosition.inheritFrom(UndoBlock); - - -UndoSetPosition.prototype.undoInitialStep = function(world) -{ - world.setNodePosition(this.objectID, this.x, this.y); -} - - +// Copyright 2011 David Galles, University of San Francisco. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of the University of San Francisco + + +// Base "class": UndoBlock + +function UndoBlock() +{ + +} + +UndoBlock.prototype.addUndoAnimation = function(animationList) +{ + return false; +} + +UndoBlock.prototype.undoInitialStep = function(world) +{ + +} + +//////////////////////////////////////////////////////////// +// UndoMove +//////////////////////////////////////////////////////////// + +function UndoMove(id, fmX, fmy, tx, ty) +{ + this.objectID = id; + this.fromX = fmX; + this.fromY = fmy; + this.toX = tx; + this.toY = ty; +} + + +UndoMove.inheritFrom(UndoBlock); + +UndoMove.prototype.addUndoAnimation = function (animationList) +{ + var nextAnim = new SingleAnimation(this.objectID, this.fromX, this.fromY, this.toX, this.toY); + animationList.push(nextAnim); + return true; +} + +//////////////////////////////////////////////////////////// +// UndoCreate +//////////////////////////////////////////////////////////// + +function UndoCreate(id) +{ + this.objectID = id; +} + +UndoCreate.inheritFrom(UndoBlock); + + +UndoCreate.prototype.undoInitialStep = function(world) +{ + world.removeObject(this.objectID); +} + +//////////////////////////////////////////////////////////// +// UndoHighlight +//////////////////////////////////////////////////////////// + +function UndoHighlight(id, val) +{ + this.objectID = id; + this.highlightValue = val; +} + +UndoHighlight.inheritFrom(UndoBlock); + +UndoHighlight.prototype.undoInitialStep = function(world) +{ + world.setHighlight(this.objectID, this.highlightValue); +} + + +//////////////////////////////////////////////////////////// +// UndoSetHeight +//////////////////////////////////////////////////////////// + +function UndoSetHeight(id, val) +{ + this.objectID = id; + this.height = val; +} + +UndoSetHeight.inheritFrom(UndoBlock); + +UndoSetHeight.prototype.undoInitialStep = function(world) +{ + world.setHeight(this.objectID, this.height); +} + +//////////////////////////////////////////////////////////// +// UndoSetWidth +//////////////////////////////////////////////////////////// + +function UndoSetWidth(id, val) +{ + this.objectID = id; + this.width = val; +} + +UndoSetWidth.inheritFrom(UndoBlock); + +UndoSetWidth.prototype.undoInitialStep = function(world) +{ + world.setWidth(this.objectID, this.width); +} + + +//////////////////////////////////////////////////////////// +// UndoSetNumElements +//////////////////////////////////////////////////////////// +function UndoSetNumElements(obj, newNumElems) +{ + this.objectID = obj.objectID; + this.sizeBeforeChange = obj.getNumElements(); + this.sizeAfterChange = newNumElems; + if (this.sizeBeforeChange > this.sizeAfterChange) + { + this.labels = new Array(this.sizeBeforeChange - this.sizeAfterChange); + this.colors = new Array(this.sizeBeforeChange - this.sizeAfterChange); + for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++) + { + this.labels[i] = obj.getText(i+this.sizeAfterChange); + this.colors[i] = obj.getTextColor(i+this.sizeAfterChange); + } + + } +} + +UndoSetNumElements.inheritFrom(UndoBlock); + + +UndoSetNumElements.prototype.undoInitialStep = function(world) +{ + world.setNumElements(this.objectID, this.sizeBeforeChange); + if (this.sizeBeforeChange > this.sizeAfterChange) + { + for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++) + { + world.setText(this.objectID, this.labels[i], i+this.sizeAfterChange); + world.setTextColor(this.objectID, this.colors[i], i+this.sizeAfterChange); + } + } +} + + +//////////////////////////////////////////////////////////// +// UndoSetAlpha +//////////////////////////////////////////////////////////// + +function UndoSetAlpha(id, alph) +{ + this.objectID = id; + this.alphaVal = alph; +} + +UndoSetAlpha.inheritFrom(UndoBlock); + +UndoSetAlpha.prototype.undoInitialStep = function(world) +{ + world.setAlpha(this.objectID, this.alphaVal); +} + +//////////////////////////////////////////////////////////// +// UndoSetNull +//////////////////////////////////////////////////////////// + +function UndoSetNull(id, nv) +{ + this.objectID = id; + this.nullVal = nv; +} + +UndoSetNull.inheritFrom(UndoBlock); + +UndoSetNull.prototype.undoInitialStep = function(world) +{ + world.setNull(this.objectID, this.nullVal); +} + +//////////////////////////////////////////////////////////// +// UndoSetForegroundColor +//////////////////////////////////////////////////////////// + +function UndoSetForegroundColor(id, color) +{ + this.objectID = id; + this.color = color; +} + +UndoSetForegroundColor.inheritFrom(UndoBlock); + +UndoSetForegroundColor.prototype.undoInitialStep = function (world) +{ + world.setForegroundColor(this.objectID, this.color); +} + +//////////////////////////////////////////////////////////// +// UndoSetBackgroundColor +//////////////////////////////////////////////////////////// + +function UndoSetBackgroundColor(id, color) +{ + this.objectID = id; + this.color = color; +} + +UndoSetBackgroundColor.inheritFrom(UndoBlock); + +UndoSetBackgroundColor.prototype.undoInitialStep = function (world) +{ + world.setBackgroundColor(this.objectID, this.color); +} + + + +//////////////////////////////////////////////////////////// +// UndoSetHighlightIndex +//////////////////////////////////////////////////////////// + +function UndoSetHighlightIndex(id, index) +{ + this.objectID = id; + this.index = index; +} + +UndoSetHighlightIndex.inheritFrom(UndoBlock); + +UndoSetHighlightIndex.prototype.undoInitialStep = function (world) +{ + world.setHighlightIndex(this.objectID, this.index); +} + + + +//////////////////////////////////////////////////////////// +// UndoSetText +//////////////////////////////////////////////////////////// + + + +function UndoSetText(id, str, index) +{ + this.objectID = id; + this.newText = str; + this.labelIndex = index; +} + +UndoSetText.inheritFrom(UndoBlock); + +UndoSetText.prototype.undoInitialStep = function(world) +{ + world.setText(this.objectID, this.newText, this.labelIndex); +} +//////////////////////////////////////////////////////////// +// UndoSetTextColor +//////////////////////////////////////////////////////////// + + + +function UndoSetTextColor(id, color, index) +{ + this.objectID = id; + this.color = color; + this.index = index; +} + +UndoSetTextColor.inheritFrom(UndoBlock); + +UndoSetTextColor.prototype.undoInitialStep = function(world) +{ + world.setTextColor(this.objectID, this.color, this.index); +} + + + +//////////////////////////////////////////////////////////// +// UndoHighlightEdge +//////////////////////////////////////////////////////////// + +function UndoHighlightEdge(from, to, val) +{ + this.fromID = from; + this.toID = to; + this.highlightValue = val; +} + +UndoHighlightEdge.inheritFrom(UndoBlock); + +UndoHighlightEdge.prototype.undoInitialStep = function(world) +{ + world.setEdgeHighlight(this.fromID, this.toID, this.highlightValue); +} + + +//////////////////////////////////////////////////////////// +// UndoSetEdgeColor +//////////////////////////////////////////////////////////// + +function UndoSetEdgeColor(from, to, oldColor) +{ + this.fromID = from; + this.toID = to; + this.color = oldColor; +} + +UndoSetEdgeColor.inheritFrom(UndoBlock); + +UndoSetEdgeColor.prototype.undoInitialStep = function(world) +{ + world.setEdgeColor(this.fromID, this.toID, this.color); +} + + +//////////////////////////////////////////////////////////// +// UndoSetEdgeAlpha +//////////////////////////////////////////////////////////// + +function UndoSetEdgeAlpha(from, to, oldAplha) +{ + this.fromID = from; + this.toID = to; + this.alpha = oldAplha; +} + +UndoSetEdgeAlpha.inheritFrom(UndoBlock); + +UndoSetEdgeAlpha.prototype.undoInitialStep = function(world) +{ + world.setEdgeAlpha(this.fromID, this.toID, this.alpha); +} + +//////////////////////////////////////////////////////////// +// UndoSetPosition +//////////////////////////////////////////////////////////// + +function UndoSetPosition(id, x, y) +{ + this.objectID = id; + this.x = x; + this.y = y; +} + +UndoSetPosition.inheritFrom(UndoBlock); + + +UndoSetPosition.prototype.undoInitialStep = function(world) +{ + world.setNodePosition(this.objectID, this.x, this.y); +} + + From 2bd78592ab884cff35d33799b93961901744b5d0 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 21:20:26 +0200 Subject: [PATCH 07/25] comment out unreachable statement --- AlgorithmLibrary/DPChange.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AlgorithmLibrary/DPChange.js b/AlgorithmLibrary/DPChange.js index 8791a12..6c6558e 100644 --- a/AlgorithmLibrary/DPChange.js +++ b/AlgorithmLibrary/DPChange.js @@ -817,9 +817,9 @@ DPChange.prototype.memoizedChange = function(value) this.cmd("SetText", functionCallID, "change(" + String(value)+ ", [" +String(DPChange.COINS[this.coinIndex]) +"]) = " + String(final[0])); return this.commands; - this.currentY = DPChange.RECURSIVE_START_Y; + // this.currentY = DPChange.RECURSIVE_START_Y; - return this.commands; + // return this.commands; } From 3db9eb3c27634d78def4582ac9a693fb49414495 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 12 Jan 2020 21:49:25 +0200 Subject: [PATCH 08/25] call AnimatedObject constructor before subclass' --- AnimationLibrary/AnimatedLinkedList.js | 7 +++---- AnimationLibrary/HighlightCircle.js | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/AnimationLibrary/AnimatedLinkedList.js b/AnimationLibrary/AnimatedLinkedList.js index 1ad192f..5c88bf9 100644 --- a/AnimationLibrary/AnimatedLinkedList.js +++ b/AnimationLibrary/AnimatedLinkedList.js @@ -26,6 +26,9 @@ function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor) { + // call superclass' constructor, which calls init + AnimatedLinkedList.superclass.constructor.call(this); + this.w = wth; this.h = hgt; this.backgroundColor = fillColor; @@ -38,11 +41,7 @@ function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, lin this.numLabels = numLab; this.objectID = id; - - // call superclass' constructor, which calls init - AnimatedLinkedList.superclass.constructor.call(this); } - AnimatedLinkedList.inheritFrom(AnimatedObject); diff --git a/AnimationLibrary/HighlightCircle.js b/AnimationLibrary/HighlightCircle.js index 53f32e1..fa4c3f9 100644 --- a/AnimationLibrary/HighlightCircle.js +++ b/AnimationLibrary/HighlightCircle.js @@ -29,6 +29,9 @@ var HighlightCircle = function(objectID, color, radius) { + // call superclass' constructor + HighlightCircle.superclass.constructor.call(this); + this.objectID = objectID; this.radius = radius; this.thickness = 4; @@ -36,9 +39,6 @@ var HighlightCircle = function(objectID, color, radius) this.x = 0; this.y = 0; this.alpha = 1; - - // call superclass' constructor - HighlightCircle.superclass.constructor.call(this); } HighlightCircle.inheritFrom(AnimatedObject); From 04fef2a47c05b221595f29e336f41deaab1f1af7 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Mon, 13 Jan 2020 01:03:15 +0200 Subject: [PATCH 09/25] AnimationManager: small bugfix --- AnimationLibrary/AnimationMain.js | 4 ++-- AnimationLibrary/ObjectManager.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AnimationLibrary/AnimationMain.js b/AnimationLibrary/AnimationMain.js index e27390e..bdbe00b 100644 --- a/AnimationLibrary/AnimationMain.js +++ b/AnimationLibrary/AnimationMain.js @@ -355,7 +355,7 @@ function initCanvas(canvas, generalControlBar, algorithmControlBar) animationManager.widthEntry = animationManager.addControlToAnimationBar("Text", canvas.width); animationManager.widthEntry.size = 4; - animationManager.widthEntry.onkeydown = this.returnSubmit(animationManager.widthEntry, animationManager.changeSize.bind(animationManager), 4, true); + animationManager.widthEntry.onkeydown = returnSubmit(animationManager.widthEntry, animationManager.changeSize.bind(animationManager), 4, true); tableEntry = document.createElement("td"); @@ -365,7 +365,7 @@ function initCanvas(canvas, generalControlBar, algorithmControlBar) generalControlBar.appendChild(tableEntry); animationManager.heightEntry = animationManager.addControlToAnimationBar("Text", canvas.height); - animationManager.heightEntry.onkeydown = this.returnSubmit(animationManager.heightEntry, animationManager.changeSize.bind(animationManager), 4, true); + animationManager.heightEntry.onkeydown = returnSubmit(animationManager.heightEntry, animationManager.changeSize.bind(animationManager), 4, true); // heightEntry.size = 4; animationManager.sizeButton = animationManager.addControlToAnimationBar("Button", "Change Canvas Size"); diff --git a/AnimationLibrary/ObjectManager.js b/AnimationLibrary/ObjectManager.js index 23a8a84..ed43437 100644 --- a/AnimationLibrary/ObjectManager.js +++ b/AnimationLibrary/ObjectManager.js @@ -842,7 +842,7 @@ function ObjectManager(canvas) this.Nodes[nodeID].y = newY; /* Don't need to dirty anything, since we repaint everything every frame (TODO: Revisit if we do conditional redraws) - }*/ + */ } From 544ad5dbd928dc912808ec5eeb69d757a521db39 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Mon, 13 Jan 2020 12:54:33 +0200 Subject: [PATCH 10/25] StackLL: remove global vars --- AlgorithmLibrary/StackLL.js | 86 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/AlgorithmLibrary/StackLL.js b/AlgorithmLibrary/StackLL.js index f633afd..5fc6755 100644 --- a/AlgorithmLibrary/StackLL.js +++ b/AlgorithmLibrary/StackLL.js @@ -24,41 +24,41 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco -var LINKED_LIST_START_X = 100; -var LINKED_LIST_START_Y = 200; -var LINKED_LIST_ELEM_WIDTH = 70; -var LINKED_LIST_ELEM_HEIGHT = 30; +function StackLL(am, w, h) +{ + this.init(am, w, h); + +} +StackLL.inheritFrom(Algorithm); -var LINKED_LIST_INSERT_X = 250; -var LINKED_LIST_INSERT_Y = 50; +StackLL.LINKED_LIST_START_X = 100; +StackLL.LINKED_LIST_START_Y = 200; +StackLL.LINKED_LIST_ELEM_WIDTH = 70; +StackLL.LINKED_LIST_ELEM_HEIGHT = 30; -var LINKED_LIST_ELEMS_PER_LINE = 8; -var LINKED_LIST_ELEM_SPACING = 100; -var LINKED_LIST_LINE_SPACING = 100; -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; +StackLL.LINKED_LIST_INSERT_X = 250; +StackLL.LINKED_LIST_INSERT_Y = 50; -var TOP_ELEM_WIDTH = 30; -var TOP_ELEM_HEIGHT = 30; +StackLL.LINKED_LIST_ELEMS_PER_LINE = 8; +StackLL.LINKED_LIST_ELEM_SPACING = 100; +StackLL.LINKED_LIST_LINE_SPACING = 100; -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; +StackLL.TOP_POS_X = 180; +StackLL.TOP_POS_Y = 100; +StackLL.TOP_LABEL_X = 130; +StackLL.TOP_LABEL_Y = 100; -var SIZE = 32; +StackLL.TOP_ELEM_WIDTH = 30; +StackLL.TOP_ELEM_HEIGHT = 30; -function StackLL(am, w, h) -{ - this.init(am, w, h); - -} +StackLL.PUSH_LABEL_X = 50; +StackLL.PUSH_LABEL_Y = 30; +StackLL.PUSH_ELEMENT_X = 120; +StackLL.PUSH_ELEMENT_Y = 30; -StackLL.inheritFrom(Algorithm); +StackLL.SIZE = 32; StackLL.prototype.init = function(am, w, h) @@ -113,8 +113,8 @@ StackLL.prototype.disableUI = function(event) StackLL.prototype.setup = function() { - this.linkedListElemID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) + this.linkedListElemID = new Array(StackLL.SIZE); + for (var i = 0; i < StackLL.SIZE; i++) { this.linkedListElemID[i]= this.nextIndex++; @@ -122,15 +122,15 @@ StackLL.prototype.setup = function() this.topID = this.nextIndex++; this.topLabelID = this.nextIndex++; - this.arrayData = new Array(SIZE); + this.arrayData = new Array(StackLL.SIZE); this.top = 0; this.leftoverLabelID = this.nextIndex++; - this.cmd("CreateLabel", this.topLabelID, "Top", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.topID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + this.cmd("CreateLabel", this.topLabelID, "Top", StackLL.TOP_LABEL_X, StackLL.TOP_LABEL_Y); + this.cmd("CreateRectangle", this.topID, "", StackLL.TOP_ELEM_WIDTH, StackLL.TOP_ELEM_HEIGHT, StackLL.TOP_POS_X, StackLL.TOP_POS_Y); this.cmd("SetNull", this.topID, 1); - this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", this.leftoverLabelID, "", StackLL.PUSH_LABEL_X, StackLL.PUSH_LABEL_Y); this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); @@ -142,8 +142,8 @@ StackLL.prototype.resetLinkedListPositions = function() { for (var i = this.top - 1; i >= 0; i--) { - var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; - var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; + var nextX = (this.top - 1 - i) % StackLL.LINKED_LIST_ELEMS_PER_LINE * StackLL.LINKED_LIST_ELEM_SPACING + StackLL.LINKED_LIST_START_X; + var nextY = Math.floor((this.top - 1 - i) / StackLL.LINKED_LIST_ELEMS_PER_LINE) * StackLL.LINKED_LIST_LINE_SPACING + StackLL.LINKED_LIST_START_Y; this.cmd("Move", this.linkedListElemID[i], nextX, nextY); } @@ -162,7 +162,7 @@ StackLL.prototype.reset = function() StackLL.prototype.pushCallback = function(event) { - if (this.top < SIZE && this.pushField.value != "") + if (this.top < StackLL.SIZE && this.pushField.value != "") { var pushVal = this.pushField.value; this.pushField.value = "" @@ -197,17 +197,17 @@ StackLL.prototype.push = function(elemToPush) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLinkedList",this.linkedListElemID[this.top], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, - LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); + this.cmd("CreateLinkedList",this.linkedListElemID[this.top], "" ,StackLL.LINKED_LIST_ELEM_WIDTH, StackLL.LINKED_LIST_ELEM_HEIGHT, + StackLL.LINKED_LIST_INSERT_X, StackLL.LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); - this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("CreateLabel", labPushID, "Pushing Value: ", StackLL.PUSH_LABEL_X, StackLL.PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, StackLL.PUSH_ELEMENT_X, StackLL.PUSH_ELEMENT_Y); this.cmd("Step"); - this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); + this.cmd("Move", labPushValID, StackLL.LINKED_LIST_INSERT_X, StackLL.LINKED_LIST_INSERT_Y); this.cmd("Step"); this.cmd("SetText", this.linkedListElemID[this.top], elemToPush); @@ -245,10 +245,10 @@ StackLL.prototype.pop = function(ignored) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); + this.cmd("CreateLabel", labPopID, "Popped Value: ", StackLL.PUSH_LABEL_X, StackLL.PUSH_LABEL_Y); + this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], StackLL.LINKED_LIST_START_X, StackLL.LINKED_LIST_START_Y); - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Move", labPopValID, StackLL.PUSH_ELEMENT_X, StackLL.PUSH_ELEMENT_Y); this.cmd("Step"); this.cmd("Disconnect", this.topID, this.linkedListElemID[this.top - 1]); From a87ba83399ff43baa3ae6bac4b83ad7a63a3f1c1 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Mon, 13 Jan 2020 12:56:15 +0200 Subject: [PATCH 11/25] StackArray: remove global variables --- AlgorithmLibrary/StackArray.js | 93 +++++++++++++++++----------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/AlgorithmLibrary/StackArray.js b/AlgorithmLibrary/StackArray.js index e19518e..11a7200 100644 --- a/AlgorithmLibrary/StackArray.js +++ b/AlgorithmLibrary/StackArray.js @@ -24,36 +24,35 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco - -var ARRAY_START_X = 100; -var ARRAY_START_Y = 200; -var ARRAY_ELEM_WIDTH = 50; -var ARRAY_ELEM_HEIGHT = 50; - -var ARRRAY_ELEMS_PER_LINE = 15; -var ARRAY_LINE_SPACING = 130; - -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; - -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; - -var SIZE = 30; - function StackArray(am, w, h) { this.init(am, w, h); } - StackArray.inheritFrom(Algorithm); +StackArray.ARRAY_START_X = 100; +StackArray.ARRAY_START_Y = 200; +StackArray.ARRAY_ELEM_WIDTH = 50; +StackArray.ARRAY_ELEM_HEIGHT = 50; + +StackArray.ARRRAY_ELEMS_PER_LINE = 15; +StackArray.ARRAY_LINE_SPACING = 130; + +StackArray.TOP_POS_X = 180; +StackArray.TOP_POS_Y = 100; +StackArray.TOP_LABEL_X = 130; +StackArray.TOP_LABEL_Y = 100; + +StackArray.PUSH_LABEL_X = 50; +StackArray.PUSH_LABEL_Y = 30; +StackArray.PUSH_ELEMENT_X = 120; +StackArray.PUSH_ELEMENT_Y = 30; + +StackArray.SIZE = 30; + + StackArray.prototype.init = function(am, w, h) { StackArray.superclass.init.call(this, am, w, h); @@ -107,9 +106,9 @@ StackArray.prototype.setup = function() { this.nextIndex = 0; - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) + this.arrayID = new Array(StackArray.SIZE); + this.arrayLabelID = new Array(StackArray.SIZE); + for (var i = 0; i < StackArray.SIZE; i++) { this.arrayID[i]= this.nextIndex++; @@ -118,24 +117,24 @@ StackArray.prototype.setup = function() this.topID = this.nextIndex++; this.topLabelID = this.nextIndex++; - this.arrayData = new Array(SIZE); + this.arrayData = new Array(StackArray.SIZE); this.top = 0; this.leftoverLabelID = this.nextIndex++; this.commands = new Array(); - for (var i = 0; i < SIZE; i++) + for (var i = 0; i < StackArray.SIZE; i++) { - var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); - this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); + var xpos = (i % StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_ELEM_WIDTH + StackArray.ARRAY_START_X; + var ypos = Math.floor(i / StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_LINE_SPACING + StackArray.ARRAY_START_Y; + this.cmd("CreateRectangle", this.arrayID[i],"", StackArray.ARRAY_ELEM_WIDTH, StackArray.ARRAY_ELEM_HEIGHT,xpos, ypos); + this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + StackArray.ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); } - this.cmd("CreateLabel", this.topLabelID, "top", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.topID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + this.cmd("CreateLabel", this.topLabelID, "top", StackArray.TOP_LABEL_X, StackArray.TOP_LABEL_Y); + this.cmd("CreateRectangle", this.topID, 0, StackArray.ARRAY_ELEM_WIDTH, StackArray.ARRAY_ELEM_HEIGHT, StackArray.TOP_POS_X, StackArray.TOP_POS_Y); - this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", this.leftoverLabelID, "", StackArray.PUSH_LABEL_X, StackArray.PUSH_LABEL_Y); this.highlight1ID = this.nextIndex++; this.highlight2ID = this.nextIndex++; @@ -158,7 +157,7 @@ StackArray.prototype.reset = function() StackArray.prototype.pushCallback = function(event) { - if (this.top < SIZE && this.pushField.value != "") + if (this.top < StackArray.SIZE && this.pushField.value != "") { var pushVal = this.pushField.value; this.pushField.value = "" @@ -199,17 +198,17 @@ StackArray.prototype.push = function(elemToPush) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labPushID, "Pushing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("CreateLabel", labPushID, "Pushing Value: ", StackArray.PUSH_LABEL_X, StackArray.PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, StackArray.PUSH_ELEMENT_X, StackArray.PUSH_ELEMENT_Y); this.cmd("Step"); - this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); + this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", StackArray.TOP_POS_X, StackArray.TOP_POS_Y); this.cmd("Step"); - var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + var xpos = (this.top % StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_ELEM_WIDTH + StackArray.ARRAY_START_X; + var ypos = Math.floor(this.top / StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_LINE_SPACING + StackArray.ARRAY_START_Y; - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Move", this.highlight1ID, xpos, ypos + StackArray.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("Move", labPushValID, xpos, ypos); @@ -241,7 +240,7 @@ StackArray.prototype.pop = function(ignored) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labPopID, "Popped Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); + this.cmd("CreateLabel", labPopID, "Popped Value: ", StackArray.PUSH_LABEL_X, StackArray.PUSH_LABEL_Y); this.cmd("SetHighlight", this.topID, 1); @@ -251,18 +250,18 @@ StackArray.prototype.pop = function(ignored) this.cmd("Step"); this.cmd("SetHighlight", this.topID, 0); - this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", TOP_POS_X, TOP_POS_Y); + this.cmd("CreateHighlightCircle", this.highlight1ID, "#0000FF", StackArray.TOP_POS_X, StackArray.TOP_POS_Y); this.cmd("Step"); - var xpos = (this.top % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.top / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + var xpos = (this.top % StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_ELEM_WIDTH + StackArray.ARRAY_START_X; + var ypos = Math.floor(this.top / StackArray.ARRRAY_ELEMS_PER_LINE) * StackArray.ARRAY_LINE_SPACING + StackArray.ARRAY_START_Y; - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Move", this.highlight1ID, xpos, ypos + StackArray.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("CreateLabel", labPopValID,this.arrayData[this.top], xpos, ypos); this.cmd("Settext", this.arrayID[this.top], ""); - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Move", labPopValID, StackArray.PUSH_ELEMENT_X, StackArray.PUSH_ELEMENT_Y); this.cmd("Step"); this.cmd("Delete", labPopValID) this.cmd("Delete", labPopID); From 9a182b31072ed224711ae93c74e52c4c3ee2a1d7 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Mon, 13 Jan 2020 12:59:51 +0200 Subject: [PATCH 12/25] BFS: remove global vars --- AlgorithmLibrary/BFS.js | 67 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/AlgorithmLibrary/BFS.js b/AlgorithmLibrary/BFS.js index 3dd3456..44e8ed0 100644 --- a/AlgorithmLibrary/BFS.js +++ b/AlgorithmLibrary/BFS.js @@ -24,22 +24,6 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco -var AUX_ARRAY_WIDTH = 25; -var AUX_ARRAY_HEIGHT = 25; -var AUX_ARRAY_START_Y = 50; - -var VISITED_START_X = 475; -var PARENT_START_X = 400; - -var HIGHLIGHT_CIRCLE_COLOR = "#000000"; -var BFS_TREE_COLOR = "#0000FF"; -var BFS_QUEUE_HEAD_COLOR = "#0000FF"; - - -var QUEUE_START_X = 30; -var QUEUE_START_Y = 50; -var QUEUE_SPACING = 30; - function BFS(am, w, h) { @@ -49,6 +33,23 @@ function BFS(am, w, h) BFS.inheritFrom(Graph); +BFS.AUX_ARRAY_WIDTH = 25; +BFS.AUX_ARRAY_HEIGHT = 25; +BFS.AUX_ARRAY_START_Y = 50; + +BFS.VISITED_START_X = 475; +BFS.PARENT_START_X = 400; + +BFS.HIGHLIGHT_CIRCLE_COLOR = "#000000"; +BFS.BFS_TREE_COLOR = "#0000FF"; +BFS.BFS_QUEUE_HEAD_COLOR = "#0000FF"; + + +BFS.QUEUE_START_X = 30; +BFS.QUEUE_START_Y = 50; +BFS.QUEUE_SPACING = 30; + + BFS.prototype.addControls = function() { this.addLabelToAlgorithmBar("Start Vertex: "); @@ -85,17 +86,17 @@ BFS.prototype.setup = function() this.visitedIndexID[i] = this.nextIndex++; this.parentID[i] = this.nextIndex++; this.parentIndexID[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.visitedID[i], "f", AUX_ARRAY_WIDTH, AUX_ARRAY_HEIGHT, VISITED_START_X, AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("CreateLabel", this.visitedIndexID[i], i, VISITED_START_X - AUX_ARRAY_WIDTH , AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("SetForegroundColor", this.visitedIndexID[i], VERTEX_INDEX_COLOR); - this.cmd("CreateRectangle", this.parentID[i], "", AUX_ARRAY_WIDTH, AUX_ARRAY_HEIGHT, PARENT_START_X, AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("CreateLabel", this.parentIndexID[i], i, PARENT_START_X - AUX_ARRAY_WIDTH , AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("SetForegroundColor", this.parentIndexID[i], VERTEX_INDEX_COLOR); + this.cmd("CreateRectangle", this.visitedID[i], "f", BFS.AUX_ARRAY_WIDTH, BFS.AUX_ARRAY_HEIGHT, BFS.VISITED_START_X, BFS.AUX_ARRAY_START_Y + i*BFS.AUX_ARRAY_HEIGHT); + this.cmd("CreateLabel", this.visitedIndexID[i], i, BFS.VISITED_START_X - BFS.AUX_ARRAY_WIDTH , BFS.AUX_ARRAY_START_Y + i*BFS.AUX_ARRAY_HEIGHT); + this.cmd("SetForegroundColor", this.visitedIndexID[i], BFS.VERTEX_INDEX_COLOR); + this.cmd("CreateRectangle", this.parentID[i], "", BFS.AUX_ARRAY_WIDTH, BFS.AUX_ARRAY_HEIGHT, BFS.PARENT_START_X, BFS.AUX_ARRAY_START_Y + i*BFS.AUX_ARRAY_HEIGHT); + this.cmd("CreateLabel", this.parentIndexID[i], i, BFS.PARENT_START_X - BFS.AUX_ARRAY_WIDTH , BFS.AUX_ARRAY_START_Y + i*BFS.AUX_ARRAY_HEIGHT); + this.cmd("SetForegroundColor", this.parentIndexID[i], BFS.VERTEX_INDEX_COLOR); } - this.cmd("CreateLabel", this.nextIndex++, "Parent", PARENT_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); - this.cmd("CreateLabel", this.nextIndex++, "Visited", VISITED_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); - this.cmd("CreateLabel", this.nextIndex++, "BFS Queue", QUEUE_START_X, QUEUE_START_Y - 30, 0); + this.cmd("CreateLabel", this.nextIndex++, "Parent", BFS.PARENT_START_X - BFS.AUX_ARRAY_WIDTH, BFS.AUX_ARRAY_START_Y - BFS.AUX_ARRAY_HEIGHT * 1.5, 0); + this.cmd("CreateLabel", this.nextIndex++, "Visited", BFS.VISITED_START_X - BFS.AUX_ARRAY_WIDTH, BFS.AUX_ARRAY_START_Y - BFS.AUX_ARRAY_HEIGHT * 1.5, 0); + this.cmd("CreateLabel", this.nextIndex++, "BFS Queue", BFS.QUEUE_START_X, BFS.QUEUE_START_Y - 30, 0); this.animationManager.setAllLayers([0, this.currentLayer]); this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); @@ -151,7 +152,7 @@ BFS.prototype.doBFS = function(startVetex) var vertex = parseInt(startVetex); this.visited[vertex] = true; this.queue[tail] = vertex; - this.cmd("CreateLabel", queueID[tail], vertex, QUEUE_START_X + queueSize * QUEUE_SPACING, QUEUE_START_Y); + this.cmd("CreateLabel", queueID[tail], vertex, BFS.QUEUE_START_X + queueSize * BFS.QUEUE_SPACING, BFS.QUEUE_START_Y); queueSize = queueSize + 1; tail = (tail + 1) % (this.size); @@ -159,14 +160,14 @@ BFS.prototype.doBFS = function(startVetex) while (queueSize > 0) { vertex = this.queue[head]; - this.cmd("CreateHighlightCircle", this.highlightCircleL, HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); + this.cmd("CreateHighlightCircle", this.highlightCircleL, BFS.HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); this.cmd("SetLayer", this.highlightCircleL, 1); - this.cmd("CreateHighlightCircle", this.highlightCircleAL, HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAL, BFS.HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); this.cmd("SetLayer", this.highlightCircleAL, 2); - this.cmd("CreateHighlightCircle", this.highlightCircleAM, HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAM, BFS.HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); this.cmd("SetLayer", this.highlightCircleAM, 3); - this.cmd("SetTextColor", queueID[head], BFS_QUEUE_HEAD_COLOR); + this.cmd("SetTextColor", queueID[head], BFS.BFS_QUEUE_HEAD_COLOR); for (var neighbor = 0; neighbor < this.size; neighbor++) @@ -183,9 +184,9 @@ BFS.prototype.doBFS = function(startVetex) this.cmd("SetText", this.parentID[neighbor], vertex); this.highlightEdge(vertex, neighbor, 0); this.cmd("Disconnect", this.circleID[vertex], this.circleID[neighbor]); - this.cmd("Connect", this.circleID[vertex], this.circleID[neighbor], BFS_TREE_COLOR, this.curve[vertex][neighbor], 1, ""); + this.cmd("Connect", this.circleID[vertex], this.circleID[neighbor], BFS.BFS_TREE_COLOR, this.curve[vertex][neighbor], 1, ""); this.queue[tail] = neighbor; - this.cmd("CreateLabel", queueID[tail], neighbor, QUEUE_START_X + queueSize * QUEUE_SPACING, QUEUE_START_Y); + this.cmd("CreateLabel", queueID[tail], neighbor, BFS.QUEUE_START_X + queueSize * BFS.QUEUE_SPACING, BFS.QUEUE_START_Y); tail = (tail + 1) % (this.size); queueSize = queueSize + 1; } @@ -204,7 +205,7 @@ BFS.prototype.doBFS = function(startVetex) for (i = 0; i < queueSize; i++) { var nextQueueIndex = (i + head) % this.size; - this.cmd("Move", queueID[nextQueueIndex], QUEUE_START_X + i * QUEUE_SPACING, QUEUE_START_Y); + this.cmd("Move", queueID[nextQueueIndex], BFS.QUEUE_START_X + i * BFS.QUEUE_SPACING, BFS.QUEUE_START_Y); } this.cmd("Delete", this.highlightCircleL); From b839fa6f9d62c8e2afae899a15dfdf5441bb6cb0 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 11:29:46 +0200 Subject: [PATCH 13/25] replace init() by the constructor in Animated* classes --- AnimationLibrary/AnimatedBTreeNode.js | 22 ++++++++-------------- AnimationLibrary/AnimatedLinkedList.js | 9 +-------- AnimationLibrary/AnimatedObject.js | 11 +++-------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/AnimationLibrary/AnimatedBTreeNode.js b/AnimationLibrary/AnimatedBTreeNode.js index 3bfdb1d..a9cbdc7 100644 --- a/AnimationLibrary/AnimatedBTreeNode.js +++ b/AnimationLibrary/AnimatedBTreeNode.js @@ -27,6 +27,8 @@ function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor) { + AnimatedBTreeNode.superclass.constructor.call(this); + this.objectID = id; this.widthPerElement = widthPerElem; this.nodeHeight = h; @@ -34,19 +36,6 @@ function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor) this.backgroundColor = (fillColor == undefined)? "#FFFFFF" : fillColor; this.foregroundColor = (edgeColor == undefined)? "#000000" : edgeColor; - // call superclass' constructor, which calls init - AnimatedBTreeNode.superclass.constructor.call(this); -} -AnimatedBTreeNode.inheritFrom(AnimatedObject); - -AnimatedBTreeNode.MIN_WIDTH = 10; -AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; - - -AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fillColor, edgeColor) -{ - AnimatedBTreeNode.superclass.init.call(this); - this.labels = new Array(this.numLabels); this.labelColors = new Array(this.numLabels); for (var i = 0; i < this.numLabels; i++) @@ -54,7 +43,12 @@ AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fill this.labelColors[i] = this.foregroundColor; } } - +AnimatedBTreeNode.inheritFrom(AnimatedObject); + +AnimatedBTreeNode.MIN_WIDTH = 10; +AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5; + + AnimatedBTreeNode.prototype.getNumElements = function() { return this.numLabels; diff --git a/AnimationLibrary/AnimatedLinkedList.js b/AnimationLibrary/AnimatedLinkedList.js index 5c88bf9..6339b08 100644 --- a/AnimationLibrary/AnimatedLinkedList.js +++ b/AnimationLibrary/AnimatedLinkedList.js @@ -41,13 +41,6 @@ function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, lin this.numLabels = numLab; this.objectID = id; -} -AnimatedLinkedList.inheritFrom(AnimatedObject); - - -AnimatedLinkedList.prototype.init = function() -{ - AnimatedLinkedList.superclass.init.call(this); this.labels = []; this.labelPosX = []; @@ -70,7 +63,7 @@ AnimatedLinkedList.prototype.init = function() this.labels[0] = this.val; this.highlighted = false; } - +AnimatedLinkedList.inheritFrom(AnimatedObject); AnimatedLinkedList.prototype.left = function() diff --git a/AnimationLibrary/AnimatedObject.js b/AnimationLibrary/AnimatedObject.js index b4eef56..9213407 100644 --- a/AnimationLibrary/AnimatedObject.js +++ b/AnimationLibrary/AnimatedObject.js @@ -25,11 +25,6 @@ // or implied, of the University of San Francisco function AnimatedObject() -{ - this.init(); -} - -AnimatedObject.prototype.init = function() { this.backgroundColor = "#FFFFFF"; this.foregroundColor = "#000000"; @@ -44,9 +39,9 @@ AnimatedObject.prototype.init = function() this.y = 0; this.minHeightDiff = 3; this.range = 5; - this.highlightIndex = -1; - this.highlightIndexDirty = true; - this.textHeight = 10; + this.highlightIndex = -1; + this.highlightIndexDirty = true; + this.textHeight = 10; } AnimatedObject.prototype.alwaysOnTop = false; From 91ba69ae1eb7341c61d203e75a5f932953b7048f Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 11:46:24 +0200 Subject: [PATCH 14/25] QueueArray: remove global variables --- AlgorithmLibrary/QueueArray.js | 117 ++++++++++++++++----------------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/AlgorithmLibrary/QueueArray.js b/AlgorithmLibrary/QueueArray.js index 4fd20b9..5d28dda 100644 --- a/AlgorithmLibrary/QueueArray.js +++ b/AlgorithmLibrary/QueueArray.js @@ -24,41 +24,40 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco +function QueueArray(am, w, h) +{ + this.init(am, w, h); + +} +QueueArray.inheritFrom(Algorithm); -var ARRAY_START_X = 100; -var ARRAY_START_Y = 200; -var ARRAY_ELEM_WIDTH = 50; -var ARRAY_ELEM_HEIGHT = 50; -var ARRRAY_ELEMS_PER_LINE = 15; -var ARRAY_LINE_SPACING = 130; +QueueArray.ARRAY_START_X = 100; +QueueArray.ARRAY_START_Y = 200; +QueueArray.ARRAY_ELEM_WIDTH = 50; +QueueArray.ARRAY_ELEM_HEIGHT = 50; -var HEAD_POS_X = 180; -var HEAD_POS_Y = 100; -var HEAD_LABEL_X = 130; -var HEAD_LABEL_Y = 100; +QueueArray.ARRRAY_ELEMS_PER_LINE = 15; +QueueArray.ARRAY_LINE_SPACING = 130; -var TAIL_POS_X = 280; -var TAIL_POS_Y = 100; -var TAIL_LABEL_X = 230; -var TAIL_LABEL_Y = 100; +QueueArray.HEAD_POS_X = 180; +QueueArray.HEAD_POS_Y = 100; +QueueArray.HEAD_LABEL_X = 130; +QueueArray.HEAD_LABEL_Y = 100; -var QUEUE_LABEL_X = 50; -var QUEUE_LABEL_Y = 30; -var QUEUE_ELEMENT_X = 120; -var QUEUE_ELEMENT_Y = 30; +QueueArray.TAIL_POS_X = 280; +QueueArray.TAIL_POS_Y = 100; +QueueArray.TAIL_LABEL_X = 230; +QueueArray.TAIL_LABEL_Y = 100; -var INDEX_COLOR = "#0000FF" +QueueArray.QUEUE_LABEL_X = 50; +QueueArray.QUEUE_LABEL_Y = 30; +QueueArray.QUEUE_ELEMENT_X = 120; +QueueArray.QUEUE_ELEMENT_Y = 30; -var SIZE = 15; +QueueArray.INDEX_COLOR = "#0000FF" -function QueueArray(am, w, h) -{ - this.init(am, w, h); - -} - -QueueArray.inheritFrom(Algorithm); +QueueArray.SIZE = 15; QueueArray.prototype.init = function(am, w, h) @@ -67,7 +66,7 @@ QueueArray.prototype.init = function(am, w, h) this.addControls(); this.nextIndex = 0; this.commands = []; - //this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; + //this.tail_pos_y = h - QueueArray.LINKED_LIST_ELEM_HEIGHT; // this.tail_label_y = this.tail_pos_y; this.setup(); this.initialIndex = this.nextIndex; @@ -117,9 +116,9 @@ QueueArray.prototype.setup = function() this.nextIndex = 0; - this.arrayID = new Array(SIZE); - this.arrayLabelID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) + this.arrayID = new Array(QueueArray.SIZE); + this.arrayLabelID = new Array(QueueArray.SIZE); + for (var i = 0; i < QueueArray.SIZE; i++) { this.arrayID[i]= this.nextIndex++; @@ -130,30 +129,30 @@ QueueArray.prototype.setup = function() this.tailID = this.nextIndex++; tailLabelID = this.nextIndex++; - this.arrayData = new Array(SIZE); + this.arrayData = new Array(QueueArray.SIZE); this.head = 0; this.tail = 0; this.leftoverLabelID = this.nextIndex++; - for (var i = 0; i < SIZE; i++) + for (var i = 0; i < QueueArray.SIZE; i++) { - var xpos = (i % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(i / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; - this.cmd("CreateRectangle", this.arrayID[i],"", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xpos, ypos); - this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + ARRAY_ELEM_HEIGHT); - this.cmd("SetForegroundColor", this.arrayLabelID[i], INDEX_COLOR); + var xpos = (i % QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_ELEM_WIDTH + QueueArray.ARRAY_START_X; + var ypos = Math.floor(i / QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_LINE_SPACING + QueueArray.ARRAY_START_Y; + this.cmd("CreateRectangle", this.arrayID[i],"", QueueArray.ARRAY_ELEM_WIDTH, QueueArray.ARRAY_ELEM_HEIGHT,xpos, ypos); + this.cmd("CreateLabel",this.arrayLabelID[i], i, xpos, ypos + QueueArray.ARRAY_ELEM_HEIGHT); + this.cmd("SetForegroundColor", this.arrayLabelID[i], QueueArray.INDEX_COLOR); } - this.cmd("CreateLabel", headLabelID, "Head", HEAD_LABEL_X, HEAD_LABEL_Y); - this.cmd("CreateRectangle", this.headID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, HEAD_POS_X, HEAD_POS_Y); + this.cmd("CreateLabel", headLabelID, "Head", QueueArray.HEAD_LABEL_X, QueueArray.HEAD_LABEL_Y); + this.cmd("CreateRectangle", this.headID, 0, QueueArray.ARRAY_ELEM_WIDTH, QueueArray.ARRAY_ELEM_HEIGHT, QueueArray.HEAD_POS_X, QueueArray.HEAD_POS_Y); - this.cmd("CreateLabel", tailLabelID, "Tail", TAIL_LABEL_X, TAIL_LABEL_Y); - this.cmd("CreateRectangle", this.tailID, 0, ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, TAIL_POS_X, TAIL_POS_Y); + this.cmd("CreateLabel", tailLabelID, "Tail", QueueArray.TAIL_LABEL_X, QueueArray.TAIL_LABEL_Y); + this.cmd("CreateRectangle", this.tailID, 0, QueueArray.ARRAY_ELEM_WIDTH, QueueArray.ARRAY_ELEM_HEIGHT, QueueArray.TAIL_POS_X, QueueArray.TAIL_POS_Y); - this.cmd("CreateLabel", this.leftoverLabelID, "", QUEUE_LABEL_X, QUEUE_LABEL_Y); + this.cmd("CreateLabel", this.leftoverLabelID, "", QueueArray.QUEUE_LABEL_X, QueueArray.QUEUE_LABEL_Y); this.initialIndex = this.nextIndex; @@ -179,7 +178,7 @@ QueueArray.prototype.reset = function() QueueArray.prototype.enqueueCallback = function(event) { - if ((this.tail + 1) % SIZE != this.head && this.enqueueField.value != "") + if ((this.tail + 1) % QueueArray.SIZE != this.head && this.enqueueField.value != "") { var pushVal = this.enqueueField.value; this.enqueueField.value = "" @@ -213,17 +212,17 @@ QueueArray.prototype.enqueue = function(elemToEnqueue) this.arrayData[this.tail] = elemToEnqueue; this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labEnqueueID, "Enqueuing Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); - this.cmd("CreateLabel", labEnqueueValID,elemToEnqueue, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); + this.cmd("CreateLabel", labEnqueueID, "Enqueuing Value: ", QueueArray.QUEUE_LABEL_X, QueueArray.QUEUE_LABEL_Y); + this.cmd("CreateLabel", labEnqueueValID,elemToEnqueue, QueueArray.QUEUE_ELEMENT_X, QueueArray.QUEUE_ELEMENT_Y); this.cmd("Step"); - this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, TAIL_POS_X, TAIL_POS_Y); + this.cmd("CreateHighlightCircle", this.highlight1ID, QueueArray.INDEX_COLOR, QueueArray.TAIL_POS_X, QueueArray.TAIL_POS_Y); this.cmd("Step"); - var xpos = (this.tail % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.tail / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + var xpos = (this.tail % QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_ELEM_WIDTH + QueueArray.ARRAY_START_X; + var ypos = Math.floor(this.tail / QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_LINE_SPACING + QueueArray.ARRAY_START_Y; - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Move", this.highlight1ID, xpos, ypos + QueueArray.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("Move", labEnqueueValID, xpos, ypos); @@ -236,7 +235,7 @@ QueueArray.prototype.enqueue = function(elemToEnqueue) this.cmd("SetHighlight", this.tailID, 1); this.cmd("Step"); - this.tail = (this.tail + 1) % SIZE; + this.tail = (this.tail + 1) % QueueArray.SIZE; this.cmd("SetText", this.tailID, this.tail) this.cmd("Step"); this.cmd("SetHighlight", this.tailID, 0); @@ -255,15 +254,15 @@ QueueArray.prototype.dequeue = function(ignored) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labDequeueID, "Dequeued Value: ", QUEUE_LABEL_X, QUEUE_LABEL_Y); + this.cmd("CreateLabel", labDequeueID, "Dequeued Value: ", QueueArray.QUEUE_LABEL_X, QueueArray.QUEUE_LABEL_Y); - this.cmd("CreateHighlightCircle", this.highlight1ID, INDEX_COLOR, HEAD_POS_X, HEAD_POS_Y); + this.cmd("CreateHighlightCircle", this.highlight1ID, QueueArray.INDEX_COLOR, QueueArray.HEAD_POS_X, QueueArray.HEAD_POS_Y); this.cmd("Step"); - var xpos = (this.head % ARRRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; - var ypos = Math.floor(this.head / ARRRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y; + var xpos = (this.head % QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_ELEM_WIDTH + QueueArray.ARRAY_START_X; + var ypos = Math.floor(this.head / QueueArray.ARRRAY_ELEMS_PER_LINE) * QueueArray.ARRAY_LINE_SPACING + QueueArray.ARRAY_START_Y; - this.cmd("Move", this.highlight1ID, xpos, ypos + ARRAY_ELEM_HEIGHT); + this.cmd("Move", this.highlight1ID, xpos, ypos + QueueArray.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("Delete", this.highlight1ID); @@ -272,12 +271,12 @@ QueueArray.prototype.dequeue = function(ignored) var dequeuedVal = this.arrayData[this.head] this.cmd("CreateLabel", labDequeueValID,dequeuedVal, xpos, ypos); this.cmd("Settext", this.arrayID[this.head], ""); - this.cmd("Move", labDequeueValID, QUEUE_ELEMENT_X, QUEUE_ELEMENT_Y); + this.cmd("Move", labDequeueValID, QueueArray.QUEUE_ELEMENT_X, QueueArray.QUEUE_ELEMENT_Y); this.cmd("Step"); this.cmd("SetHighlight", this.headID, 1); this.cmd("Step"); - this.head = (this.head + 1 ) % SIZE; + this.head = (this.head + 1 ) % QueueArray.SIZE; this.cmd("SetText", this.headID, this.head) this.cmd("Step"); this.cmd("SetHighlight", this.headID, 0); @@ -300,7 +299,7 @@ QueueArray.prototype.clearAll = function() this.commands = new Array(); this.cmd("SetText", this.leftoverLabelID, ""); - for (var i = 0; i < SIZE; i++) + for (var i = 0; i < QueueArray.SIZE; i++) { this.cmd("SetText", this.arrayID[i], ""); } From 03176291c5aaa1e980d9f1dbc23fc56992cbdca7 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 11:48:08 +0200 Subject: [PATCH 15/25] QueueLL: remove global vars --- AlgorithmLibrary/QueueLL.js | 96 ++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/AlgorithmLibrary/QueueLL.js b/AlgorithmLibrary/QueueLL.js index b29647d..dd86cc3 100644 --- a/AlgorithmLibrary/QueueLL.js +++ b/AlgorithmLibrary/QueueLL.js @@ -24,45 +24,43 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco - -var LINKED_LIST_START_X = 100; -var LINKED_LIST_START_Y = 200; -var LINKED_LIST_ELEM_WIDTH = 70; -var LINKED_LIST_ELEM_HEIGHT = 30; +function QueueLL(am, w, h) +{ + this.init(am, w, h); +} +QueueLL.inheritFrom(Algorithm); -var LINKED_LIST_INSERT_X = 250; -var LINKED_LIST_INSERT_Y = 50; +QueueLL.LINKED_LIST_START_X = 100; +QueueLL.LINKED_LIST_START_Y = 200; +QueueLL.LINKED_LIST_ELEM_WIDTH = 70; +QueueLL.LINKED_LIST_ELEM_HEIGHT = 30; -var LINKED_LIST_ELEMS_PER_LINE = 8; -var LINKED_LIST_ELEM_SPACING = 100; -var LINKED_LIST_LINE_SPACING = 100; -var TOP_POS_X = 180; -var TOP_POS_Y = 100; -var TOP_LABEL_X = 130; -var TOP_LABEL_Y = 100; +QueueLL.LINKED_LIST_INSERT_X = 250; +QueueLL.LINKED_LIST_INSERT_Y = 50; -var TOP_ELEM_WIDTH = 30; -var TOP_ELEM_HEIGHT = 30; +QueueLL.LINKED_LIST_ELEMS_PER_LINE = 8; +QueueLL.LINKED_LIST_ELEM_SPACING = 100; +QueueLL.LINKED_LIST_LINE_SPACING = 100; -var TAIL_POS_X = 180; -var TAIL_LABEL_X = 130; +QueueLL.TOP_POS_X = 180; +QueueLL.TOP_POS_Y = 100; +QueueLL.TOP_LABEL_X = 130; +QueueLL.TOP_LABEL_Y = 100; -var PUSH_LABEL_X = 50; -var PUSH_LABEL_Y = 30; -var PUSH_ELEMENT_X = 120; -var PUSH_ELEMENT_Y = 30; +QueueLL.TOP_ELEM_WIDTH = 30; +QueueLL.TOP_ELEM_HEIGHT = 30; -var SIZE = 32; +QueueLL.TAIL_POS_X = 180; +QueueLL.TAIL_LABEL_X = 130; -function QueueLL(am, w, h) -{ - this.init(am, w, h); - -} +QueueLL.PUSH_LABEL_X = 50; +QueueLL.PUSH_LABEL_Y = 30; +QueueLL.PUSH_ELEMENT_X = 120; +QueueLL.PUSH_ELEMENT_Y = 30; -QueueLL.inheritFrom(Algorithm); +QueueLL.SIZE = 32; QueueLL.prototype.init = function(am, w, h) @@ -71,7 +69,7 @@ QueueLL.prototype.init = function(am, w, h) this.addControls(); this.nextIndex = 0; this.commands = []; - this.tail_pos_y = h - LINKED_LIST_ELEM_HEIGHT; + this.tail_pos_y = h - QueueLL.LINKED_LIST_ELEM_HEIGHT; this.tail_label_y = this.tail_pos_y; this.setup(); this.initialIndex = this.nextIndex; @@ -119,8 +117,8 @@ QueueLL.prototype.disableUI = function(event) QueueLL.prototype.setup = function() { - this.linkedListElemID = new Array(SIZE); - for (var i = 0; i < SIZE; i++) + this.linkedListElemID = new Array(QueueLL.SIZE); + for (var i = 0; i < QueueLL.SIZE; i++) { this.linkedListElemID[i]= this.nextIndex++; @@ -132,20 +130,20 @@ QueueLL.prototype.setup = function() this.tailLabelID = this.nextIndex++; - this.arrayData = new Array(SIZE); + this.arrayData = new Array(QueueLL.SIZE); this.top = 0; this.leftoverLabelID = this.nextIndex++; - this.cmd("CreateLabel", this.headLabelID, "Head", TOP_LABEL_X, TOP_LABEL_Y); - this.cmd("CreateRectangle", this.headID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TOP_POS_X, TOP_POS_Y); + this.cmd("CreateLabel", this.headLabelID, "Head", QueueLL.TOP_LABEL_X, QueueLL.TOP_LABEL_Y); + this.cmd("CreateRectangle", this.headID, "", QueueLL.TOP_ELEM_WIDTH, QueueLL.TOP_ELEM_HEIGHT, QueueLL.TOP_POS_X, QueueLL.TOP_POS_Y); this.cmd("SetNull", this.headID, 1); - this.cmd("CreateLabel", this.tailLabelID, "Tail", TAIL_LABEL_X, this.tail_label_y); - this.cmd("CreateRectangle", this.tailID, "", TOP_ELEM_WIDTH, TOP_ELEM_HEIGHT, TAIL_POS_X, this.tail_pos_y); + this.cmd("CreateLabel", this.tailLabelID, "Tail", QueueLL.TAIL_LABEL_X, this.tail_label_y); + this.cmd("CreateRectangle", this.tailID, "", QueueLL.TOP_ELEM_WIDTH, QueueLL.TOP_ELEM_HEIGHT, QueueLL.TAIL_POS_X, this.tail_pos_y); this.cmd("SetNull", this.tailID, 1); - this.cmd("CreateLabel", this.leftoverLabelID, "", 5, PUSH_LABEL_Y,0); + this.cmd("CreateLabel", this.leftoverLabelID, "", 5, QueueLL.PUSH_LABEL_Y,0); this.animationManager.StartNewAnimation(this.commands); @@ -158,8 +156,8 @@ QueueLL.prototype.resetLinkedListPositions = function() { for (var i = this.top - 1; i >= 0; i--) { - var nextX = (this.top - 1 - i) % LINKED_LIST_ELEMS_PER_LINE * LINKED_LIST_ELEM_SPACING + LINKED_LIST_START_X; - var nextY = Math.floor((this.top - 1 - i) / LINKED_LIST_ELEMS_PER_LINE) * LINKED_LIST_LINE_SPACING + LINKED_LIST_START_Y; + var nextX = (this.top - 1 - i) % QueueLL.LINKED_LIST_ELEMS_PER_LINE * QueueLL.LINKED_LIST_ELEM_SPACING + QueueLL.LINKED_LIST_START_X; + var nextY = Math.floor((this.top - 1 - i) / QueueLL.LINKED_LIST_ELEMS_PER_LINE) * QueueLL.LINKED_LIST_LINE_SPACING + QueueLL.LINKED_LIST_START_Y; this.cmd("Move", this.linkedListElemID[i], nextX, nextY); } @@ -178,7 +176,7 @@ QueueLL.prototype.reset = function() QueueLL.prototype.enqueueCallback = function(event) { - if (this.top < SIZE && this.enqueueField.value != "") + if (this.top < QueueLL.SIZE && this.enqueueField.value != "") { var pushVal = this.enqueueField.value; this.enqueueField.value = "" @@ -221,18 +219,18 @@ QueueLL.prototype.enqueue = function(elemToPush) var labPushID = this.nextIndex++; var labPushValID = this.nextIndex++; - this.cmd("CreateLinkedList",this.linkedListElemID[0], "" ,LINKED_LIST_ELEM_WIDTH, LINKED_LIST_ELEM_HEIGHT, - LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); + this.cmd("CreateLinkedList",this.linkedListElemID[0], "" ,QueueLL.LINKED_LIST_ELEM_WIDTH, QueueLL.LINKED_LIST_ELEM_HEIGHT, + QueueLL.LINKED_LIST_INSERT_X, QueueLL.LINKED_LIST_INSERT_Y, 0.25, 0, 1, 1); this.cmd("SetNull", this.linkedListElemID[0], 1); - this.cmd("CreateLabel", labPushID, "Enqueuing Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPushValID,elemToPush, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("CreateLabel", labPushID, "Enqueuing Value: ", QueueLL.PUSH_LABEL_X, QueueLL.PUSH_LABEL_Y); + this.cmd("CreateLabel", labPushValID,elemToPush, QueueLL.PUSH_ELEMENT_X, QueueLL.PUSH_ELEMENT_Y); this.cmd("Step"); - this.cmd("Move", labPushValID, LINKED_LIST_INSERT_X, LINKED_LIST_INSERT_Y); + this.cmd("Move", labPushValID, QueueLL.LINKED_LIST_INSERT_X, QueueLL.LINKED_LIST_INSERT_Y); this.cmd("Step"); this.cmd("SetText", this.linkedListElemID[0], elemToPush); @@ -273,10 +271,10 @@ QueueLL.prototype.dequeue = function(ignored) this.cmd("SetText", this.leftoverLabelID, ""); - this.cmd("CreateLabel", labPopID, "Dequeued Value: ", PUSH_LABEL_X, PUSH_LABEL_Y); - this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], LINKED_LIST_START_X, LINKED_LIST_START_Y); + this.cmd("CreateLabel", labPopID, "Dequeued Value: ", QueueLL.PUSH_LABEL_X, QueueLL.PUSH_LABEL_Y); + this.cmd("CreateLabel", labPopValID,this.arrayData[this.top - 1], QueueLL.LINKED_LIST_START_X, QueueLL.LINKED_LIST_START_Y); - this.cmd("Move", labPopValID, PUSH_ELEMENT_X, PUSH_ELEMENT_Y); + this.cmd("Move", labPopValID, QueueLL.PUSH_ELEMENT_X, QueueLL.PUSH_ELEMENT_Y); this.cmd("Step"); this.cmd("Disconnect", this.headID, this.linkedListElemID[this.top - 1]); From 677c54cf5e7eaf93bfa1a92f360643dd9ca05fb2 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 12:22:27 +0200 Subject: [PATCH 16/25] Algorithm*: remove global vars --- AlgorithmLibrary/BPlusTree.js | 122 ++++++------- AlgorithmLibrary/BTree.js | 156 ++++++++--------- AlgorithmLibrary/BinomialQueue.js | 112 ++++++------ AlgorithmLibrary/BucketSort.js | 90 +++++----- AlgorithmLibrary/ClosedHash.js | 42 ++--- AlgorithmLibrary/ClosedHashBucket.js | 94 +++++----- AlgorithmLibrary/ComparisonSort.js | 230 ++++++++++++------------- AlgorithmLibrary/ConnectedComponent.js | 60 +++---- AlgorithmLibrary/CountingSort.js | 114 ++++++------ AlgorithmLibrary/DFS.js | 46 ++--- AlgorithmLibrary/DijkstraPrim.js | 54 +++--- AlgorithmLibrary/DisjointSet.js | 48 +++--- AlgorithmLibrary/Floyd.js | 8 +- AlgorithmLibrary/Graph.js | 158 ++++++++--------- AlgorithmLibrary/Hash.js | 100 +++++------ AlgorithmLibrary/Heap.js | 46 ++--- AlgorithmLibrary/HeapSort.js | 52 +++--- AlgorithmLibrary/Kruskal.js | 4 +- AlgorithmLibrary/OpenHash.js | 54 +++--- AlgorithmLibrary/RadixSort.js | 136 +++++++-------- AlgorithmLibrary/RedBlack.js | 186 ++++++++++---------- AlgorithmLibrary/Search.js | 202 +++++++++++----------- AlgorithmLibrary/TopoSortIndegree.js | 6 +- 23 files changed, 1060 insertions(+), 1060 deletions(-) diff --git a/AlgorithmLibrary/BPlusTree.js b/AlgorithmLibrary/BPlusTree.js index 743df48..45d7b6d 100644 --- a/AlgorithmLibrary/BPlusTree.js +++ b/AlgorithmLibrary/BPlusTree.js @@ -24,28 +24,28 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of the University of San Francisco -var FIRST_PRINT_POS_X = 50; -var PRINT_VERTICAL_GAP = 20; -var PRINT_MAX = 990; -var PRINT_HORIZONTAL_GAP = 50; +BPlusTree.FIRST_PRINT_POS_X = 50; +BPlusTree.PRINT_VERTICAL_GAP = 20; +BPlusTree.PRINT_MAX = 990; +BPlusTree.PRINT_HORIZONTAL_GAP = 50; -var MIN_MAX_DEGREE = 3; -var MAX_MAX_DEGREE = 7; +BPlusTree.MIN_MAX_DEGREE = 3; +BPlusTree.MAX_MAX_DEGREE = 7; -var HEIGHT_DELTA = 50; -var NODE_SPACING = 15; -var STARTING_Y = 30; -var WIDTH_PER_ELEM = 40; -var NODE_HEIGHT = 20; +BPlusTree.HEIGHT_DELTA = 50; +BPlusTree.NODE_SPACING = 15; +BPlusTree.STARTING_Y = 30; +BPlusTree.WIDTH_PER_ELEM = 40; +BPlusTree.NODE_HEIGHT = 20; -var MESSAGE_X = 5; -var MESSAGE_Y = 10; +BPlusTree.MESSAGE_X = 5; +BPlusTree.MESSAGE_Y = 10; -var LINK_COLOR = "#007700"; -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var PRINT_COLOR = FOREGROUND_COLOR; +BPlusTree.LINK_COLOR = "#007700"; +BPlusTree.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +BPlusTree.FOREGROUND_COLOR = "#007700"; +BPlusTree.BACKGROUND_COLOR = "#EEFFEE"; +BPlusTree.PRINT_COLOR = BPlusTree.FOREGROUND_COLOR; @@ -83,7 +83,7 @@ BPlusTree.prototype.init = function(am, w, h) this.messageID = this.nextIndex++; - this.cmd("CreateLabel", this.messageID, "", MESSAGE_X, MESSAGE_Y, 0); + this.cmd("CreateLabel", this.messageID, "", BPlusTree.MESSAGE_X, BPlusTree.MESSAGE_Y, 0); this.moveLabel1ID = this.nextIndex++; this.moveLabel2ID = this.nextIndex++; @@ -92,7 +92,7 @@ BPlusTree.prototype.init = function(am, w, h) this.animationManager.clearHistory(); this.commands = new Array(); - this.first_print_pos_y = h - 3 * PRINT_VERTICAL_GAP; + this.first_print_pos_y = h - 3 * BPlusTree.PRINT_VERTICAL_GAP; this.xPosOfNextLabel = 100; @@ -137,7 +137,7 @@ BPlusTree.prototype.addControls = function() var i; radioButtonNames = []; - for (i = MIN_MAX_DEGREE; i <= MAX_MAX_DEGREE; i++) + for (i = BPlusTree.MIN_MAX_DEGREE; i <= BPlusTree.MAX_MAX_DEGREE; i++) { radioButtonNames.push("Max. Degree = " + String(i)); } @@ -147,7 +147,7 @@ BPlusTree.prototype.addControls = function() this.maxDegreeRadioButtons[0].checked = true; for(i = 0; i < this.maxDegreeRadioButtons.length; i++) { - this.maxDegreeRadioButtons[i].onclick = this.maxDegreeChangedHandler.bind(this,i+MIN_MAX_DEGREE); + this.maxDegreeRadioButtons[i].onclick = this.maxDegreeChangedHandler.bind(this,i+BPlusTree.MIN_MAX_DEGREE); } @@ -283,7 +283,7 @@ BPlusTree.prototype.printTree = function(unused) if (this.treeRoot != null) { - this.xPosOfNextLabel = FIRST_PRINT_POS_X; + this.xPosOfNextLabel = BPlusTree.FIRST_PRINT_POS_X; this.yPosOfNextLabel = this.first_print_pos_y; var tmp = this.treeRoot; @@ -308,14 +308,14 @@ BPlusTree.prototype.printTree = function(unused) { var nextLabelID = this.nextIndex++; this.cmd("CreateLabel", nextLabelID, tmp.keys[i], this.getLabelX(tmp, i), tmp.y); - this.cmd("SetForegroundColor", nextLabelID, PRINT_COLOR); + this.cmd("SetForegroundColor", nextLabelID, BPlusTree.PRINT_COLOR); this.cmd("Move", nextLabelID, this.xPosOfNextLabel, this.yPosOfNextLabel); this.cmd("Step"); - this.xPosOfNextLabel += PRINT_HORIZONTAL_GAP; - if (this.xPosOfNextLabel > PRINT_MAX) + this.xPosOfNextLabel += BPlusTree.PRINT_HORIZONTAL_GAP; + if (this.xPosOfNextLabel > BPlusTree.PRINT_MAX) { - this.xPosOfNextLabel = FIRST_PRINT_POS_X; - this.yPosOfNextLabel += PRINT_VERTICAL_GAP; + this.xPosOfNextLabel = BPlusTree.FIRST_PRINT_POS_X; + this.yPosOfNextLabel += BPlusTree.PRINT_VERTICAL_GAP; } } if (tmp.next != null) @@ -381,7 +381,7 @@ BPlusTree.prototype.changeDegree = function(degree) var newDegree = degree; this.ignoreInputs = true; //TODO: Check me! - this.maxDegreeRadioButtons[newDegree - MIN_MAX_DEGREE].checked = true; + this.maxDegreeRadioButtons[newDegree - BPlusTree.MIN_MAX_DEGREE].checked = true; this.ignoreInputs = false; this.max_degree = newDegree; @@ -468,7 +468,7 @@ BPlusTree.prototype.findInTree = function(tree, val) this.cmd("SetTextColor", tree.graphicID, "#FF0000", i); this.cmd("SetText", this.messageID, "Element " + val + " found"); this.cmd("Step"); - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BPlusTree.FOREGROUND_COLOR, i); this.cmd("SetHighlight", tree.graphicID, 0); this.cmd("Step"); @@ -499,8 +499,8 @@ BPlusTree.prototype.insertElement = function(insertedValue) if (this.treeRoot == null) { - this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, STARTING_Y); - this.cmd("CreateBTreeNode",this.treeRoot.graphicID, WIDTH_PER_ELEM, NODE_HEIGHT, 1, this.starting_x, STARTING_Y, BACKGROUND_COLOR, FOREGROUND_COLOR); + this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, BPlusTree.STARTING_Y); + this.cmd("CreateBTreeNode",this.treeRoot.graphicID, BPlusTree.WIDTH_PER_ELEM, BPlusTree.NODE_HEIGHT, 1, this.starting_x, BPlusTree.STARTING_Y, BPlusTree.BACKGROUND_COLOR, BPlusTree.FOREGROUND_COLOR); this.treeRoot.keys[0] = insertedValue; this.cmd("SetText", this.treeRoot.graphicID, insertedValue, 0); } @@ -546,7 +546,7 @@ BPlusTree.prototype.insert = function(tree, insertValue) this.cmd("Disconnect", tree.graphicID, tree.next.graphicID); this.cmd("Connect", tree.graphicID, tree.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -615,7 +615,7 @@ BPlusTree.prototype.split = function(tree) { currentParent.children[i+1] = currentParent.children[i]; this.cmd("Disconnect", currentParent.graphicID, currentParent.children[i].graphicID); - this.cmd("Connect", currentParent.graphicID, currentParent.children[i].graphicID, FOREGROUND_COLOR, + this.cmd("Connect", currentParent.graphicID, currentParent.children[i].graphicID, BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -653,7 +653,7 @@ BPlusTree.prototype.split = function(tree) rightNode.numKeys = tree.numKeys - rightSplit; - this.cmd("CreateBTreeNode",rightNode.graphicID, WIDTH_PER_ELEM, NODE_HEIGHT, tree.numKeys -rightSplit, tree.x, tree.y, BACKGROUND_COLOR, FOREGROUND_COLOR); + this.cmd("CreateBTreeNode",rightNode.graphicID, BPlusTree.WIDTH_PER_ELEM, BPlusTree.NODE_HEIGHT, tree.numKeys -rightSplit, tree.x, tree.y, BPlusTree.BACKGROUND_COLOR, BPlusTree.FOREGROUND_COLOR); if (tree.isLeaf) { @@ -663,7 +663,7 @@ BPlusTree.prototype.split = function(tree) this.cmd("Disconnect", tree.graphicID, rightNode.next.graphicID); this.cmd("Connect", rightNode.graphicID, rightNode.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -673,7 +673,7 @@ BPlusTree.prototype.split = function(tree) } this.cmd("Connect", tree.graphicID, rightNode.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -691,7 +691,7 @@ BPlusTree.prototype.split = function(tree) this.cmd("Connect", rightNode.graphicID, rightNode.children[i - rightSplit].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -721,7 +721,7 @@ BPlusTree.prototype.split = function(tree) if (tree.parent != null) { - this.cmd("Connect", currentParent.graphicID, rightNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", currentParent.graphicID, rightNode.graphicID, BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -734,20 +734,20 @@ BPlusTree.prototype.split = function(tree) } else // if (tree.parent == null) { - this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, STARTING_Y); - this.cmd("CreateBTreeNode",this.treeRoot.graphicID, WIDTH_PER_ELEM, NODE_HEIGHT, 1, this.starting_x, STARTING_Y,BACKGROUND_COLOR, FOREGROUND_COLOR); + this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, BPlusTree.STARTING_Y); + this.cmd("CreateBTreeNode",this.treeRoot.graphicID, BPlusTree.WIDTH_PER_ELEM, BPlusTree.NODE_HEIGHT, 1, this.starting_x, BPlusTree.STARTING_Y,BPlusTree.BACKGROUND_COLOR, BPlusTree.FOREGROUND_COLOR); this.treeRoot.keys[0] = risingNode; this.cmd("SetText", this.treeRoot.graphicID, risingNode, 0); this.treeRoot.children[0] = leftNode; this.treeRoot.children[1] = rightNode; leftNode.parent = this.treeRoot; rightNode.parent = this.treeRoot; - this.cmd("Connect", this.treeRoot.graphicID, leftNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", this.treeRoot.graphicID, leftNode.graphicID, BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label 0); // Connection Point - this.cmd("Connect", this.treeRoot.graphicID, rightNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", this.treeRoot.graphicID, rightNode.graphicID, BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -824,7 +824,7 @@ BPlusTree.prototype.doDelete = function(tree, val) { this.cmd("SetTextColor", tree.graphicID, 0xFF0000, i); this.cmd("Step"); - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BPlusTree.FOREGROUND_COLOR, i); for (var j = i; j < tree.numKeys - 1; j++) { tree.keys[j] = tree.keys[j+1]; @@ -840,7 +840,7 @@ BPlusTree.prototype.doDelete = function(tree, val) this.cmd("Disconnect", tree.graphicID, tree.next.graphicID); this.cmd("Connect", tree.graphicID, tree.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -948,7 +948,7 @@ BPlusTree.prototype.mergeRight = function(tree) tree.children[tree.numKeys + 1 + i].parent = tree; this.cmd("Connect", tree.graphicID, tree.children[tree.numKeys + 1 + i].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -966,7 +966,7 @@ BPlusTree.prototype.mergeRight = function(tree) { this.cmd("Connect", tree.graphicID, tree.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -981,7 +981,7 @@ BPlusTree.prototype.mergeRight = function(tree) parentNode.children[i] = parentNode.children[i+1]; this.cmd("Connect", parentNode.graphicID, parentNode.children[i].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1030,7 +1030,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", tree.graphicID, tree.next.graphicID); this.cmd("Connect", tree.graphicID, tree.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -1078,7 +1078,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", rightSib.graphicID, rightSib.children[0].graphicID); this.cmd("Connect", tree.graphicID, tree.children[tree.numKeys].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1091,7 +1091,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) rightSib.children[i-1] = rightSib.children[i]; this.cmd("Connect", rightSib.graphicID, rightSib.children[i-1].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1118,7 +1118,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", rightSib.graphicID, rightSib.next.graphicID); this.cmd("Connect", rightSib.graphicID, rightSib.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -1144,7 +1144,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", tree.graphicID, tree.next.graphicID); this.cmd("Connect", tree.graphicID, tree.next.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -1196,7 +1196,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) tree.children[i] =tree.children[i-1]; this.cmd("Connect", tree.graphicID, tree.children[i].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1206,7 +1206,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", leftSib.graphicID, leftSib.children[leftSib.numKeys].graphicID); this.cmd("Connect", tree.graphicID, tree.children[0].graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1231,7 +1231,7 @@ BPlusTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", leftSib.graphicID, tree.graphicID); this.cmd("Connect", leftSib.graphicID, tree.graphicID, - FOREGROUND_COLOR, + BPlusTree.FOREGROUND_COLOR, 0, // Curve 1, // Directed "", // Label @@ -1309,13 +1309,13 @@ BPlusTree.prototype.repairAfterDelete = function(tree) BPlusTree.prototype.getLabelX = function(tree, index) { - return tree.x - WIDTH_PER_ELEM * tree.numKeys / 2 + WIDTH_PER_ELEM / 2 + index * WIDTH_PER_ELEM; + return tree.x - BPlusTree.WIDTH_PER_ELEM * tree.numKeys / 2 + BPlusTree.WIDTH_PER_ELEM / 2 + index * BPlusTree.WIDTH_PER_ELEM; } BPlusTree.prototype.resizeTree = function() { this.resizeWidths(this.treeRoot); - this.setNewPositions(this.treeRoot, this.starting_x, STARTING_Y); + this.setNewPositions(this.treeRoot, this.starting_x, BPlusTree.STARTING_Y); this.animateNewPositions(this.treeRoot); } @@ -1331,7 +1331,7 @@ BPlusTree.prototype.setNewPositions = function(tree, xPosition, yPosition) var priorWidth = 0; for (var i = 0; i < tree.numKeys+1; i++) { - this.setNewPositions(tree.children[i], leftEdge + priorWidth + tree.widths[i] / 2, yPosition+HEIGHT_DELTA); + this.setNewPositions(tree.children[i], leftEdge + priorWidth + tree.widths[i] / 2, yPosition+BPlusTree.HEIGHT_DELTA); priorWidth += tree.widths[i]; } } @@ -1364,7 +1364,7 @@ BPlusTree.prototype.resizeWidths = function(tree) { tree.widths[i] = 0; } - tree.width = tree.numKeys * WIDTH_PER_ELEM + NODE_SPACING; + tree.width = tree.numKeys * BPlusTree.WIDTH_PER_ELEM + BPlusTree.NODE_SPACING; return tree.width; } else @@ -1375,7 +1375,7 @@ BPlusTree.prototype.resizeWidths = function(tree) tree.widths[i] = this.resizeWidths(tree.children[i]); treeWidth = treeWidth + tree.widths[i]; } - treeWidth = Math.max(treeWidth, tree.numKeys * WIDTH_PER_ELEM + NODE_SPACING); + treeWidth = Math.max(treeWidth, tree.numKeys * BPlusTree.WIDTH_PER_ELEM + BPlusTree.NODE_SPACING); tree.width = treeWidth; return treeWidth; } diff --git a/AlgorithmLibrary/BTree.js b/AlgorithmLibrary/BTree.js index af1e1ec..8292de9 100644 --- a/AlgorithmLibrary/BTree.js +++ b/AlgorithmLibrary/BTree.js @@ -26,28 +26,28 @@ -var FIRST_PRINT_POS_X = 50; -var PRINT_VERTICAL_GAP = 20; -var PRINT_MAX = 990; -var PRINT_HORIZONTAL_GAP = 50; +BTree.FIRST_PRINT_POS_X = 50; +BTree.PRINT_VERTICAL_GAP = 20; +BTree.PRINT_MAX = 990; +BTree.PRINT_HORIZONTAL_GAP = 50; -var MIN_MAX_DEGREE = 3; -var MAX_MAX_DEGREE = 7; +BTree.MIN_MAX_DEGREE = 3; +BTree.MAX_MAX_DEGREE = 7; -var HEIGHT_DELTA = 50; -var NODE_SPACING = 3; -var STARTING_Y = 30; -var WIDTH_PER_ELEM = 40; -var NODE_HEIGHT = 20; +BTree.HEIGHT_DELTA = 50; +BTree.NODE_SPACING = 3; +BTree.STARTING_Y = 30; +BTree.WIDTH_PER_ELEM = 40; +BTree.NODE_HEIGHT = 20; -var MESSAGE_X = 5; -var MESSAGE_Y = 10; +BTree.MESSAGE_X = 5; +BTree.MESSAGE_Y = 10; -var LINK_COLOR = "#007700"; -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var PRINT_COLOR = FOREGROUND_COLOR; +BTree.LINK_COLOR = "#007700"; +BTree.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +BTree.FOREGROUND_COLOR = "#007700"; +BTree.BACKGROUND_COLOR = "#EEFFEE"; +BTree.PRINT_COLOR = BTree.FOREGROUND_COLOR; @@ -86,7 +86,7 @@ BTree.prototype.init = function(am, w, h) this.messageID = this.nextIndex++; - this.cmd("CreateLabel", this.messageID, "", MESSAGE_X, MESSAGE_Y, 0); + this.cmd("CreateLabel", this.messageID, "", BTree.MESSAGE_X, BTree.MESSAGE_Y, 0); this.moveLabel1ID = this.nextIndex++; this.moveLabel2ID = this.nextIndex++; @@ -95,7 +95,7 @@ BTree.prototype.init = function(am, w, h) this.animationManager.clearHistory(); this.commands = new Array(); - this.first_print_pos_y = h - 3 * PRINT_VERTICAL_GAP; + this.first_print_pos_y = h - 3 * BTree.PRINT_VERTICAL_GAP; this.xPosOfNextLabel = 100; @@ -140,7 +140,7 @@ BTree.prototype.addControls = function() var i; radioButtonNames = []; - for (i = MIN_MAX_DEGREE; i <= MAX_MAX_DEGREE; i++) + for (i = BTree.MIN_MAX_DEGREE; i <= BTree.MAX_MAX_DEGREE; i++) { radioButtonNames.push("Max. Degree = " + String(i)); } @@ -150,7 +150,7 @@ BTree.prototype.addControls = function() this.maxDegreeRadioButtons[0].checked = true; for(i = 0; i < this.maxDegreeRadioButtons.length; i++) { - this.maxDegreeRadioButtons[i].onclick = this.maxDegreeChangedHandler.bind(this,i+MIN_MAX_DEGREE); + this.maxDegreeRadioButtons[i].onclick = this.maxDegreeChangedHandler.bind(this,i+BTree.MIN_MAX_DEGREE); } @@ -193,9 +193,9 @@ BTree.prototype.enableUI = function(event) if (this.preemptiveSplit) { - var initialEven = MIN_MAX_DEGREE % 2; + var initialEven = BTree.MIN_MAX_DEGREE % 2; var i; - for (i = initialEven; i <= MAX_MAX_DEGREE - MIN_MAX_DEGREE; i+= 2) + for (i = initialEven; i <= BTree.MAX_MAX_DEGREE - BTree.MIN_MAX_DEGREE; i+= 2) { this.maxDegreeRadioButtons[i].disabled = false; } @@ -314,7 +314,7 @@ BTree.prototype.printTree = function(unused) this.cmd("SetText", this.messageID, "Printing tree"); var firstLabel = this.nextIndex; - this.xPosOfNextLabel = FIRST_PRINT_POS_X; + this.xPosOfNextLabel = BTree.FIRST_PRINT_POS_X; this.yPosOfNextLabel = this.first_print_pos_y; this.printTreeRec(this.treeRoot); @@ -338,14 +338,14 @@ BTree.prototype.printTreeRec =function (tree) { nextLabelID = this.nextIndex++; this.cmd("CreateLabel", nextLabelID, tree.keys[i], this.getLabelX(tree, i), tree.y); - this.cmd("SetForegroundColor", nextLabelID, PRINT_COLOR); + this.cmd("SetForegroundColor", nextLabelID, BTree.PRINT_COLOR); this.cmd("Move", nextLabelID, this.xPosOfNextLabel, this.yPosOfNextLabel); this.cmd("Step"); - this.xPosOfNextLabel += PRINT_HORIZONTAL_GAP; - if (this.xPosOfNextLabel > PRINT_MAX) + this.xPosOfNextLabel += BTree.PRINT_HORIZONTAL_GAP; + if (this.xPosOfNextLabel > BTree.PRINT_MAX) { - this.xPosOfNextLabel = FIRST_PRINT_POS_X; - this.yPosOfNextLabel += PRINT_VERTICAL_GAP; + this.xPosOfNextLabel = BTree.FIRST_PRINT_POS_X; + this.yPosOfNextLabel += BTree.PRINT_VERTICAL_GAP; } } this.cmd("SetHighlight", tree.graphicID, 0); @@ -362,14 +362,14 @@ BTree.prototype.printTreeRec =function (tree) this.cmd("SetHighlight", tree.graphicID, 1); nextLabelID = this.nextIndex++; this.cmd("CreateLabel", nextLabelID, tree.keys[i], this.getLabelX(tree, i), tree.y); - this.cmd("SetForegroundColor", nextLabelID, PRINT_COLOR); + this.cmd("SetForegroundColor", nextLabelID, BTree.PRINT_COLOR); this.cmd("Move", nextLabelID, this.xPosOfNextLabel, this.yPosOfNextLabel); this.cmd("Step"); - this.xPosOfNextLabel += PRINT_HORIZONTAL_GAP; - if (this.xPosOfNextLabel > PRINT_MAX) + this.xPosOfNextLabel += BTree.PRINT_HORIZONTAL_GAP; + if (this.xPosOfNextLabel > BTree.PRINT_MAX) { - this.xPosOfNextLabel = FIRST_PRINT_POS_X; - this.yPosOfNextLabel += PRINT_VERTICAL_GAP; + this.xPosOfNextLabel = BTree.FIRST_PRINT_POS_X; + this.yPosOfNextLabel += BTree.PRINT_VERTICAL_GAP; } this.cmd("SetEdgeHighlight", tree.graphicID, tree.children[i+1].graphicID, 1); this.cmd("Step"); @@ -422,7 +422,7 @@ BTree.prototype.changeDegree = function(degree) var newDegree = degree; this.ignoreInputs = true; //TODO: Check me! - this.maxDegreeRadioButtons[newDegree - MIN_MAX_DEGREE].checked = true; + this.maxDegreeRadioButtons[newDegree - BTree.MIN_MAX_DEGREE].checked = true; this.ignoreInputs = false; this.max_degree = newDegree; @@ -505,7 +505,7 @@ BTree.prototype.findInTree = function(tree, val) this.cmd("SetTextColor", tree.graphicID, "#FF0000", i); this.cmd("SetText", this.messageID, "Element " + val + " found"); this.cmd("Step"); - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); this.cmd("SetHighlight", tree.graphicID, 0); this.cmd("Step"); @@ -527,15 +527,15 @@ BTree.prototype.insertElement = function(insertedValue) if (this.treeRoot == null) { - this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, STARTING_Y); + this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, BTree.STARTING_Y); this.cmd("CreateBTreeNode", this.treeRoot.graphicID, - WIDTH_PER_ELEM, NODE_HEIGHT, + BTree.WIDTH_PER_ELEM, BTree.NODE_HEIGHT, 1, this.starting_x, - STARTING_Y, - BACKGROUND_COLOR, - FOREGROUND_COLOR); + BTree.STARTING_Y, + BTree.BACKGROUND_COLOR, + BTree.FOREGROUND_COLOR); this.treeRoot.keys[0] = insertedValue; this.cmd("SetText", this.treeRoot.graphicID, insertedValue, 0); } @@ -695,7 +695,7 @@ BTree.prototype.split = function(tree) { currentParent.children[i+1] = currentParent.children[i]; this.cmd("Disconnect", currentParent.graphicID, currentParent.children[i].graphicID); - this.cmd("Connect", currentParent.graphicID, currentParent.children[i].graphicID, FOREGROUND_COLOR, + this.cmd("Connect", currentParent.graphicID, currentParent.children[i].graphicID, BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -709,7 +709,7 @@ BTree.prototype.split = function(tree) this.cmd("SetText", currentParent.graphicID, "", parentIndex); this.moveLabel1ID = this.nextIndex++; this.cmd("CreateLabel", this.moveLabel1ID, risingNode, this.getLabelX(tree, this.split_index), tree.y) - this.cmd("SetForegroundColor", this.moveLabel1ID, FOREGROUND_COLOR); + this.cmd("SetForegroundColor", this.moveLabel1ID, BTree.FOREGROUND_COLOR); this.cmd("Move", this.moveLabel1ID, this.getLabelX(currentParent, parentIndex), currentParent.y) @@ -724,12 +724,12 @@ BTree.prototype.split = function(tree) this.cmd("CreateBTreeNode", rightNode.graphicID, - WIDTH_PER_ELEM, NODE_HEIGHT, + BTree.WIDTH_PER_ELEM, BTree.NODE_HEIGHT, tree.numKeys - this.split_index - 1, tree.x, tree.y, - BACKGROUND_COLOR, - FOREGROUND_COLOR); + BTree.BACKGROUND_COLOR, + BTree.FOREGROUND_COLOR); var i; for (i = this.split_index + 1; i < tree.numKeys + 1; i++) @@ -742,7 +742,7 @@ BTree.prototype.split = function(tree) this.cmd("Connect", rightNode.graphicID, rightNode.children[i - this.split_index - 1].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -772,7 +772,7 @@ BTree.prototype.split = function(tree) if (tree.parent != null) { - this.cmd("Connect", currentParent.graphicID, rightNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", currentParent.graphicID, rightNode.graphicID, BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -785,28 +785,28 @@ BTree.prototype.split = function(tree) } else // if (tree.parent == null) { - this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, STARTING_Y); + this.treeRoot = new BTreeNode(this.nextIndex++, this.starting_x, BTree.STARTING_Y); this.cmd("CreateBTreeNode", this.treeRoot.graphicID, - WIDTH_PER_ELEM, - NODE_HEIGHT, + BTree.WIDTH_PER_ELEM, + BTree.NODE_HEIGHT, 1, this.starting_x, - STARTING_Y, - BACKGROUND_COLOR, - FOREGROUND_COLOR); + BTree.STARTING_Y, + BTree.BACKGROUND_COLOR, + BTree.FOREGROUND_COLOR); this.treeRoot.keys[0] = risingNode; this.cmd("SetText", this.treeRoot.graphicID, risingNode, 0); this.treeRoot.children[0] = leftNode; this.treeRoot.children[1] = rightNode; leftNode.parent = this.treeRoot; rightNode.parent = this.treeRoot; - this.cmd("Connect", this.treeRoot.graphicID, leftNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", this.treeRoot.graphicID, leftNode.graphicID, BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label 0); // Connection Point - this.cmd("Connect", this.treeRoot.graphicID, rightNode.graphicID, FOREGROUND_COLOR, + this.cmd("Connect", this.treeRoot.graphicID, rightNode.graphicID, BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -927,7 +927,7 @@ BTree.prototype.doDeleteNotEmpty = function(tree, val) this.cmd("Step"); if (tree.isLeaf) { - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); for (var j = i; j < tree.numKeys - 1; j++) { tree.keys[j] = tree.keys[j+1]; @@ -967,7 +967,7 @@ BTree.prototype.doDeleteNotEmpty = function(tree, val) this.cmd("SetText", this.messageID, "Neither subtree has extra nodes. Mergeing around the key to delete, \nand recursively deleting ..."); this.cmd("Step"); - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); nextNode = this.mergeRight(tree.children[i]); this.doDeleteNotEmpty(nextNode, val); return; @@ -1004,7 +1004,7 @@ BTree.prototype.doDeleteNotEmpty = function(tree, val) this.cmd("SetHighlight", minNode.graphicID, 1); tree.keys[i] = minNode.keys[0]; - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); this.cmd("SetText", tree.graphicID, "", i); this.cmd("SetText", minNode.graphicID, "", 0); @@ -1059,7 +1059,7 @@ BTree.prototype.doDeleteNotEmpty = function(tree, val) } this.cmd("SetHighlight", maxNode.graphicID, 1); tree.keys[i] = maxNode.keys[maxNode.numKeys - 1]; - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); this.cmd("SetText", tree.graphicID, "", i); this.cmd("SetText", maxNode.graphicID, "", maxNode.numKeys - 1); this.cmd("CreateLabel", this.moveLabel1ID, tree.keys[i], this.getLabelX(maxNode, maxNode.numKeys - 1), maxNode.y) @@ -1128,7 +1128,7 @@ BTree.prototype.doDelete = function(tree, val) this.cmd("Step"); if (tree.isLeaf) { - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); for (var j = i; j < tree.numKeys - 1; j++) { tree.keys[j] = tree.keys[j+1]; @@ -1152,7 +1152,7 @@ BTree.prototype.doDelete = function(tree, val) } this.cmd("SetHighlight", maxNode.graphicID, 1); tree.keys[i] = maxNode.keys[maxNode.numKeys - 1]; - this.cmd("SetTextColor", tree.graphicID, FOREGROUND_COLOR, i); + this.cmd("SetTextColor", tree.graphicID, BTree.FOREGROUND_COLOR, i); this.cmd("SetText", tree.graphicID, "", i); this.cmd("SetText", maxNode.graphicID, "", maxNode.numKeys - 1); this.cmd("CreateLabel", this.moveLabel1ID, tree.keys[i], this.getLabelX(maxNode, maxNode.numKeys - 1), maxNode.y) @@ -1213,7 +1213,7 @@ BTree.prototype.mergeRight = function(tree) tree.children[tree.numKeys + 1 + i].parent = tree; this.cmd("Connect", tree.graphicID, tree.children[tree.numKeys + 1 + i].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1227,7 +1227,7 @@ BTree.prototype.mergeRight = function(tree) parentNode.children[i] = parentNode.children[i+1]; this.cmd("Connect", parentNode.graphicID, parentNode.children[i].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1287,8 +1287,8 @@ BTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("CreateLabel", tmpLabel1, rightSib.keys[0], this.getLabelX(rightSib, 0), rightSib.y) this.cmd("CreateLabel", tmpLabel2, parentNode.keys[parentIndex], this.getLabelX(parentNode, parentIndex), parentNode.y) - this.cmd("SetForegroundColor", tmpLabel1, FOREGROUND_COLOR); - this.cmd("SetForegroundColor", tmpLabel2, FOREGROUND_COLOR); + this.cmd("SetForegroundColor", tmpLabel1, BTree.FOREGROUND_COLOR); + this.cmd("SetForegroundColor", tmpLabel2, BTree.FOREGROUND_COLOR); this.cmd("Move", tmpLabel1, this.getLabelX(parentNode, parentIndex), parentNode.y); this.cmd("Move", tmpLabel2, this.getLabelX(tree, tree.numKeys - 1), tree.y); @@ -1310,7 +1310,7 @@ BTree.prototype.stealFromRight = function(tree, parentIndex) this.cmd("Disconnect", rightSib.graphicID, rightSib.children[0].graphicID); this.cmd("Connect", tree.graphicID, tree.children[tree.numKeys].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1323,7 +1323,7 @@ BTree.prototype.stealFromRight = function(tree, parentIndex) rightSib.children[i-1] = rightSib.children[i]; this.cmd("Connect", rightSib.graphicID, rightSib.children[i-1].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1370,8 +1370,8 @@ BTree.prototype.stealFromLeft = function(tree, parentIndex) this.cmd("CreateLabel", tmpLabel1, leftSib.keys[leftSib.numKeys - 1], this.getLabelX(leftSib, leftSib.numKeys - 1), leftSib.y) this.cmd("CreateLabel", tmpLabel2, parentNode.keys[parentIndex - 1], this.getLabelX(parentNode, parentIndex - 1), parentNode.y) - this.cmd("SetForegroundColor", tmpLabel1, FOREGROUND_COLOR); - this.cmd("SetForegroundColor", tmpLabel2, FOREGROUND_COLOR); + this.cmd("SetForegroundColor", tmpLabel1, BTree.FOREGROUND_COLOR); + this.cmd("SetForegroundColor", tmpLabel2, BTree.FOREGROUND_COLOR); this.cmd("Move", tmpLabel1, this.getLabelX(parentNode, parentIndex - 1), parentNode.y); @@ -1390,7 +1390,7 @@ BTree.prototype.stealFromLeft = function(tree, parentIndex) tree.children[i] =tree.children[i-1]; this.cmd("Connect", tree.graphicID, tree.children[i].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1400,7 +1400,7 @@ BTree.prototype.stealFromLeft = function(tree, parentIndex) this.cmd("Disconnect", leftSib.graphicID, leftSib.children[leftSib.numKeys].graphicID); this.cmd("Connect", tree.graphicID, tree.children[0].graphicID, - FOREGROUND_COLOR, + BTree.FOREGROUND_COLOR, 0, // Curve 0, // Directed "", // Label @@ -1475,13 +1475,13 @@ BTree.prototype.repairAfterDelete = function(tree) BTree.prototype.getLabelX = function(tree, index) { - return tree.x - WIDTH_PER_ELEM * tree.numKeys / 2 + WIDTH_PER_ELEM / 2 + index * WIDTH_PER_ELEM; + return tree.x - BTree.WIDTH_PER_ELEM * tree.numKeys / 2 + BTree.WIDTH_PER_ELEM / 2 + index * BTree.WIDTH_PER_ELEM; } BTree.prototype.resizeTree = function() { this.resizeWidths(this.treeRoot); - this.setNewPositions(this.treeRoot, this.starting_x, STARTING_Y); + this.setNewPositions(this.treeRoot, this.starting_x, BTree.STARTING_Y); this.animateNewPositions(this.treeRoot); } @@ -1497,7 +1497,7 @@ BTree.prototype.setNewPositions = function(tree, xPosition, yPosition) var priorWidth = 0; for (var i = 0; i < tree.numKeys+1; i++) { - this.setNewPositions(tree.children[i], leftEdge + priorWidth + tree.widths[i] / 2, yPosition+HEIGHT_DELTA); + this.setNewPositions(tree.children[i], leftEdge + priorWidth + tree.widths[i] / 2, yPosition+BTree.HEIGHT_DELTA); priorWidth += tree.widths[i]; } } @@ -1530,7 +1530,7 @@ BTree.prototype.resizeWidths = function(tree) { tree.widths[i] = 0; } - tree.width = tree.numKeys * WIDTH_PER_ELEM + NODE_SPACING; + tree.width = tree.numKeys * BTree.WIDTH_PER_ELEM + BTree.NODE_SPACING; return tree.width; } else @@ -1541,7 +1541,7 @@ BTree.prototype.resizeWidths = function(tree) tree.widths[i] = this.resizeWidths(tree.children[i]); treeWidth = treeWidth + tree.widths[i]; } - treeWidth = Math.max(treeWidth, tree.numKeys * WIDTH_PER_ELEM + NODE_SPACING); + treeWidth = Math.max(treeWidth, tree.numKeys * BTree.WIDTH_PER_ELEM + BTree.NODE_SPACING); tree.width = treeWidth; return treeWidth; } diff --git a/AlgorithmLibrary/BinomialQueue.js b/AlgorithmLibrary/BinomialQueue.js index 50c1294..c725369 100644 --- a/AlgorithmLibrary/BinomialQueue.js +++ b/AlgorithmLibrary/BinomialQueue.js @@ -25,26 +25,26 @@ // or implied, of the University of San Francisco -var LINK_COLOR = "#007700"; -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var MERGE_SEPARATING_LINE_COLOR = "#0000FF"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var DEGREE_OFFSET_X = -20; -var DEGREE_OFFSET_Y = -20; +BinomialQueue.LINK_COLOR = "#007700"; +BinomialQueue.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +BinomialQueue.MERGE_SEPARATING_LINE_COLOR = "#0000FF"; +BinomialQueue.FOREGROUND_COLOR = "#007700"; +BinomialQueue.BACKGROUND_COLOR = "#EEFFEE"; +BinomialQueue.DEGREE_OFFSET_X = -20; +BinomialQueue.DEGREE_OFFSET_Y = -20; -var DELETE_LAB_X = 30; -var DELETE_LAB_Y = 50; +BinomialQueue.DELETE_LAB_X = 30; +BinomialQueue.DELETE_LAB_Y = 50; -var NODE_WIDTH = 60; -var NODE_HEIGHT = 70 +BinomialQueue.NODE_WIDTH = 60; +BinomialQueue.NODE_HEIGHT = 70 -var STARTING_X = 70; -var STARTING_Y = 80; +BinomialQueue.STARTING_X = 70; +BinomialQueue.STARTING_Y = 80; -var INSERT_X = 30; -var INSERT_Y = 25 +BinomialQueue.INSERT_X = 30; +BinomialQueue.INSERT_Y = 25 function BinomialQueue(am, w, h) @@ -124,22 +124,22 @@ BinomialQueue.prototype.setPositions = function(tree, xPosition, yPosition) { tree.x = xPosition; tree.y = yPosition; - return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); + return this.setPositions(tree.rightSib, xPosition + BinomialQueue.NODE_WIDTH, yPosition); } else if (tree.degree == 1) { tree.x = xPosition; tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + NODE_WIDTH, yPosition); + this.setPositions(tree.leftChild, xPosition, yPosition + BinomialQueue.NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + BinomialQueue.NODE_WIDTH, yPosition); } else { var treeWidth = Math.pow(2, tree.degree - 1); - tree.x = xPosition + (treeWidth - 1) * NODE_WIDTH; + tree.x = xPosition + (treeWidth - 1) * BinomialQueue.NODE_WIDTH; tree.y = yPosition; - this.setPositions(tree.leftChild, xPosition, yPosition + NODE_HEIGHT); - return this.setPositions(tree.rightSib, xPosition + treeWidth * NODE_WIDTH, yPosition); + this.setPositions(tree.leftChild, xPosition, yPosition + BinomialQueue.NODE_HEIGHT); + return this.setPositions(tree.rightSib, xPosition + treeWidth * BinomialQueue.NODE_WIDTH, yPosition); } } return xPosition; @@ -151,7 +151,7 @@ BinomialQueue.prototype.moveTree = function(tree) { this.cmd("Move", tree.graphicID, tree.x, tree.y); this.cmd("Move", tree.internalGraphicID, tree.x, tree.y); - this.cmd("Move", tree.degreeID, tree.x + DEGREE_OFFSET_X, tree.y + DEGREE_OFFSET_Y); + this.cmd("Move", tree.degreeID, tree.x + BinomialQueue.DEGREE_OFFSET_X, tree.y + BinomialQueue.DEGREE_OFFSET_Y); this.moveTree(tree.leftChild); this.moveTree(tree.rightSib); @@ -245,13 +245,13 @@ BinomialQueue.prototype.removeSmallest = function(dummy) this.cmd("SetText", smallest.graphicID, ""); this.cmd("SetText", smallest.internalGraphicID, ""); this.cmd("CreateLabel", moveLabel, smallest.data, smallest.x, smallest.y); - this.cmd("Move", moveLabel, DELETE_LAB_X, DELETE_LAB_Y); + this.cmd("Move", moveLabel, BinomialQueue.DELETE_LAB_X, BinomialQueue.DELETE_LAB_Y); this.cmd("Step"); if (prev != null && prev.rightSib != null) { this.cmd("Connect", prev.internalGraphicID, prev.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -281,7 +281,7 @@ BinomialQueue.prototype.reverse = function(tree) this.cmd("Disconnect", tree.internalGraphicID, tree.rightSib.internalGraphicID); this.cmd("Connect", tree.rightSib.internalGraphicID, tree.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -300,18 +300,18 @@ BinomialQueue.prototype.insertElement = function(insertedValue) { this.commands = new Array(); - var insertNode = new BinomialNode(insertedValue, this.nextIndex++, INSERT_X, INSERT_Y); + var insertNode = new BinomialNode(insertedValue, this.nextIndex++, BinomialQueue.INSERT_X, BinomialQueue.INSERT_Y); insertNode.internalGraphicID = this.nextIndex++; insertNode.degreeID= this.nextIndex++; - this.cmd("CreateCircle", insertNode.graphicID, insertedValue, INSERT_X, INSERT_Y); - this.cmd("SetForegroundColor", insertNode.graphicID, FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.graphicID, BACKGROUND_COLOR); + this.cmd("CreateCircle", insertNode.graphicID, insertedValue, BinomialQueue.INSERT_X, BinomialQueue.INSERT_Y); + this.cmd("SetForegroundColor", insertNode.graphicID, BinomialQueue.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.graphicID, BinomialQueue.BACKGROUND_COLOR); this.cmd("SetLayer", insertNode.graphicID, 1); - this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, INSERT_X, INSERT_Y); - this.cmd("SetForegroundColor", insertNode.internalGraphicID, FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", insertNode.internalGraphicID, BACKGROUND_COLOR); + this.cmd("CreateCircle", insertNode.internalGraphicID, insertedValue, BinomialQueue.INSERT_X, BinomialQueue.INSERT_Y); + this.cmd("SetForegroundColor", insertNode.internalGraphicID, BinomialQueue.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", insertNode.internalGraphicID, BinomialQueue.BACKGROUND_COLOR); this.cmd("SetLayer", insertNode.internalGraphicID, 2); - this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + DEGREE_OFFSET_X, insertNode.y + DEGREE_OFFSET_Y); + this.cmd("CreateLabel", insertNode.degreeID, insertNode.degree, insertNode.x + BinomialQueue.DEGREE_OFFSET_X, insertNode.y + BinomialQueue.DEGREE_OFFSET_Y); this.cmd("SetTextColor", insertNode.degreeID, "#0000FF"); this.cmd("SetLayer", insertNode.degreeID, 2); this.cmd("Step"); @@ -319,7 +319,7 @@ BinomialQueue.prototype.insertElement = function(insertedValue) if (this.treeRoot == null) { this.treeRoot = insertNode; - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.setPositions(this.treeRoot, BinomialQueue.STARTING_X, BinomialQueue.STARTING_Y); this.moveTree(this.treeRoot); } else @@ -336,13 +336,13 @@ BinomialQueue.prototype.merge = function() { if (this.treeRoot != null) { - var leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); + var leftSize = this.setPositions(this.treeRoot, BinomialQueue.STARTING_X, BinomialQueue.STARTING_Y); + this.setPositions(this.secondaryTreeRoot, leftSize + BinomialQueue.NODE_WIDTH, BinomialQueue.STARTING_Y); this.moveTree(this.secondaryTreeRoot); this.moveTree(this.treeRoot); var lineID = this.nextIndex++; this.cmd("CreateRectangle", lineID, "", 0, 200, leftSize, 50,"left","top"); - this.cmd("SetForegroundColor", lineID, MERGE_SEPARATING_LINE_COLOR); + this.cmd("SetForegroundColor", lineID, BinomialQueue.MERGE_SEPARATING_LINE_COLOR); this.cmd("SetLayer", lineID, 0); this.cmd("Step"); } @@ -350,7 +350,7 @@ BinomialQueue.prototype.merge = function() { this.treeRoot = this.secondaryTreeRoot; this.secondaryTreeRoot = null; - this.setPositions(this.treeRoot, NODE_WIDTH, STARTING_Y); + this.setPositions(this.treeRoot, BinomialQueue.NODE_WIDTH, BinomialQueue.STARTING_Y); this.moveTree(this.treeRoot); return; } @@ -368,7 +368,7 @@ BinomialQueue.prototype.merge = function() this.treeRoot = tmp; this.cmd("Connect", this.treeRoot.internalGraphicID, this.treeRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -385,7 +385,7 @@ BinomialQueue.prototype.merge = function() this.cmd("Disconnect", tmp2.internalGraphicID, tmp2.rightSib.internalGraphicID); this.cmd("Connect", tmp.internalGraphicID, tmp2.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -394,13 +394,13 @@ BinomialQueue.prototype.merge = function() tmp2.rightSib = tmp; this.cmd("Connect", tmp2.internalGraphicID, tmp.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label } - leftSize = this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); - this.setPositions(this.secondaryTreeRoot, leftSize + NODE_WIDTH, STARTING_Y); + leftSize = this.setPositions(this.treeRoot, BinomialQueue.STARTING_X, BinomialQueue.STARTING_Y); + this.setPositions(this.secondaryTreeRoot, leftSize + BinomialQueue.NODE_WIDTH, BinomialQueue.STARTING_Y); this.moveTree(this.secondaryTreeRoot); this.moveTree(this.treeRoot); this.cmd("Move", lineID, leftSize, 50); @@ -441,7 +441,7 @@ BinomialQueue.prototype.combineNodes = function() } this.cmd("Connect", this.treeRoot.graphicID, this.treeRoot.leftChild.graphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 0, // Directed ""); // Label @@ -449,14 +449,14 @@ BinomialQueue.prototype.combineNodes = function() this.cmd("Connect", this.treeRoot.internalGraphicID, this.treeRoot.leftChild.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0.15, // Curve 1, // Directed ""); // Label this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, this.treeRoot.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -465,7 +465,7 @@ BinomialQueue.prototype.combineNodes = function() this.cmd("Disconnect", this.treeRoot.internalGraphicID, this.treeRoot.leftChild.rightSib.internalGraphicID); this.cmd("Connect", this.treeRoot.leftChild.internalGraphicID, this.treeRoot.leftChild.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -474,7 +474,7 @@ BinomialQueue.prototype.combineNodes = function() { this.cmd("Connect", this.treeRoot.internalGraphicID, this.treeRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -485,7 +485,7 @@ BinomialQueue.prototype.combineNodes = function() this.cmd("SetText", this.treeRoot.degreeID, this.treeRoot.degree); - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.setPositions(this.treeRoot, BinomialQueue.STARTING_X, BinomialQueue.STARTING_Y); this.moveTree(this.treeRoot); this.cmd("Step"); } @@ -537,28 +537,28 @@ BinomialQueue.prototype.combineNodes = function() } this.cmd("Connect", tempRoot.graphicID, tempRoot.leftChild.graphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 0, // Directed ""); // Label this.cmd("Connect", tempRoot.internalGraphicID, tempRoot.leftChild.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0.15, // Curve 1, // Directed ""); // Label this.cmd("Connect", tempRoot.leftChild.internalGraphicID, tempRoot.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label this.cmd("Connect", tmp2.internalGraphicID, tempRoot.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -568,7 +568,7 @@ BinomialQueue.prototype.combineNodes = function() this.cmd("Disconnect",tempRoot.internalGraphicID, tempRoot.leftChild.rightSib.internalGraphicID); this.cmd("Connect",tempRoot.leftChild.internalGraphicID, tempRoot.leftChild.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label); @@ -577,7 +577,7 @@ BinomialQueue.prototype.combineNodes = function() { this.cmd("Connect",tempRoot.internalGraphicID, tempRoot.rightSib.internalGraphicID, - FOREGROUND_COLOR, + BinomialQueue.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label); @@ -586,7 +586,7 @@ BinomialQueue.prototype.combineNodes = function() - this.setPositions(this.treeRoot, STARTING_X, STARTING_Y); + this.setPositions(this.treeRoot, BinomialQueue.STARTING_X, BinomialQueue.STARTING_Y); this.moveTree(this.treeRoot); this.cmd("Step"); } diff --git a/AlgorithmLibrary/BucketSort.js b/AlgorithmLibrary/BucketSort.js index b46c482..193da28 100644 --- a/AlgorithmLibrary/BucketSort.js +++ b/AlgorithmLibrary/BucketSort.js @@ -33,27 +33,27 @@ function BucketSort(am, w, h) } -var ARRAY_ELEM_WIDTH_SMALL = 30; -var ARRAY_ELEM_HEIGHT_SMALL = 30; -var ARRAY_ELEM_START_X_SMALL = 20; +BucketSort.ARRAY_ELEM_WIDTH_SMALL = 30; +BucketSort.ARRAY_ELEM_HEIGHT_SMALL = 30; +BucketSort.ARRAY_ELEM_START_X_SMALL = 20; -var ARRAY_ELEMENT_Y_SMALL = 150; +BucketSort.ARRAY_ELEMENT_Y_SMALL = 150; -var POINTER_ARRAY_ELEM_WIDTH_SMALL = 30; -var POINTER_ARRAY_ELEM_HEIGHT_SMALL = 30; -var POINTER_ARRAY_ELEM_START_X_SMALL = 20; +BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL = 30; +BucketSort.POINTER_ARRAY_ELEM_HEIGHT_SMALL = 30; +BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL = 20; -var LINKED_ITEM_HEIGHT_SMALL = 30; -var LINKED_ITEM_WIDTH_SMALL = 24; +BucketSort.LINKED_ITEM_HEIGHT_SMALL = 30; +BucketSort.LINKED_ITEM_WIDTH_SMALL = 24; -var LINKED_ITEM_Y_DELTA_SMALL = 50; -var LINKED_ITEM_POINTER_PERCENT_SMALL = 0.25; +BucketSort.LINKED_ITEM_Y_DELTA_SMALL = 50; +BucketSort.LINKED_ITEM_POINTER_PERCENT_SMALL = 0.25; -var MAX_DATA_VALUE = 999; +BucketSort.MAX_DATA_VALUE = 999; -var ARRAY_SIZE_SMALL = 30; +BucketSort.ARRAY_SIZE_SMALL = 30; -var ARRAY_Y_POS = 350; +BucketSort.ARRAY_Y_POS = 350; BucketSort.inheritFrom(Algorithm); @@ -85,34 +85,34 @@ BucketSort.prototype.addControls = function() BucketSort.prototype.setup = function() { - this.arrayData = new Array(ARRAY_SIZE_SMALL); - this.arrayRects= new Array(ARRAY_SIZE_SMALL); - this.linkedListRects = new Array(ARRAY_SIZE_SMALL); - this.linkedListData = new Array(ARRAY_SIZE_SMALL); - this.upperIndices = new Array(ARRAY_SIZE_SMALL); - this.lowerIndices = new Array(ARRAY_SIZE_SMALL); + this.arrayData = new Array(BucketSort.ARRAY_SIZE_SMALL); + this.arrayRects= new Array(BucketSort.ARRAY_SIZE_SMALL); + this.linkedListRects = new Array(BucketSort.ARRAY_SIZE_SMALL); + this.linkedListData = new Array(BucketSort.ARRAY_SIZE_SMALL); + this.upperIndices = new Array(BucketSort.ARRAY_SIZE_SMALL); + this.lowerIndices = new Array(BucketSort.ARRAY_SIZE_SMALL); this.commands = new Array(); - this.oldData = new Array(ARRAY_SIZE_SMALL); + this.oldData = new Array(BucketSort.ARRAY_SIZE_SMALL); - for (var i = 0; i < ARRAY_SIZE_SMALL; i++) + for (var i = 0; i < BucketSort.ARRAY_SIZE_SMALL; i++) { var nextID = this.nextIndex++; - this.arrayData[i] = Math.floor(Math.random()*MAX_DATA_VALUE); + this.arrayData[i] = Math.floor(Math.random()*BucketSort.MAX_DATA_VALUE); this.oldData[i] = this.arrayData[i]; - this.cmd("CreateRectangle", nextID, this.arrayData[i], ARRAY_ELEM_WIDTH_SMALL, ARRAY_ELEM_HEIGHT_SMALL, ARRAY_ELEM_START_X_SMALL + i *ARRAY_ELEM_WIDTH_SMALL, ARRAY_ELEMENT_Y_SMALL) + this.cmd("CreateRectangle", nextID, this.arrayData[i], BucketSort.ARRAY_ELEM_WIDTH_SMALL, BucketSort.ARRAY_ELEM_HEIGHT_SMALL, BucketSort.ARRAY_ELEM_START_X_SMALL + i *BucketSort.ARRAY_ELEM_WIDTH_SMALL, BucketSort.ARRAY_ELEMENT_Y_SMALL) this.arrayRects[i] = nextID; nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID, "", POINTER_ARRAY_ELEM_WIDTH_SMALL, POINTER_ARRAY_ELEM_HEIGHT_SMALL, POINTER_ARRAY_ELEM_START_X_SMALL + i *POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small) + this.cmd("CreateRectangle", nextID, "", BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL, BucketSort.POINTER_ARRAY_ELEM_HEIGHT_SMALL, BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL + i *BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small) this.linkedListRects[i] = nextID; this.cmd("SetNull", this.linkedListRects[i], 1); nextID = this.nextIndex++; this.upperIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, ARRAY_ELEM_START_X_SMALL + i *ARRAY_ELEM_WIDTH_SMALL, ARRAY_ELEMENT_Y_SMALL + ARRAY_ELEM_HEIGHT_SMALL); + this.cmd("CreateLabel",nextID, i, BucketSort.ARRAY_ELEM_START_X_SMALL + i *BucketSort.ARRAY_ELEM_WIDTH_SMALL, BucketSort.ARRAY_ELEMENT_Y_SMALL + BucketSort.ARRAY_ELEM_HEIGHT_SMALL); this.cmd("SetForegroundColor", nextID, "#0000FF"); nextID = this.nextIndex++; this.lowerIndices[i] = nextID; - this.cmd("CreateLabel", nextID, i, POINTER_ARRAY_ELEM_START_X_SMALL + i *POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small + POINTER_ARRAY_ELEM_HEIGHT_SMALL); + this.cmd("CreateLabel", nextID, i, BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL + i *BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small + BucketSort.POINTER_ARRAY_ELEM_HEIGHT_SMALL); this.cmd("SetForegroundColor", nextID, "#0000FF"); } this.animationManager.StartNewAnimation(this.commands); @@ -125,30 +125,30 @@ BucketSort.prototype.bucketSortCallback = function(event) { var savedIndex = this.nextIndex; this.commands = new Array(); - linkedListData = new Array(ARRAY_SIZE_SMALL); + linkedListData = new Array(BucketSort.ARRAY_SIZE_SMALL); var i; - for (i= 0; i < ARRAY_SIZE_SMALL; i++) + for (i= 0; i < BucketSort.ARRAY_SIZE_SMALL; i++) { var labelID = this.nextIndex++; var label2ID = this.nextIndex++; var label3ID = this.nextIndex++; var label4ID = this.nextIndex++; var node = new LinkedListNode(this.arrayData[i],this.nextIndex++, 100, 75); - this.cmd("CreateLinkedList", node.graphicID, "", LINKED_ITEM_WIDTH_SMALL, LINKED_ITEM_HEIGHT_SMALL, 100, 75); + this.cmd("CreateLinkedList", node.graphicID, "", BucketSort.LINKED_ITEM_WIDTH_SMALL, BucketSort.LINKED_ITEM_HEIGHT_SMALL, 100, 75); this.cmd("SetNull", node.graphicID, 1); - this.cmd("CreateLabel", labelID, this.arrayData[i], ARRAY_ELEM_START_X_SMALL + i *ARRAY_ELEM_WIDTH_SMALL, ARRAY_ELEMENT_Y_SMALL); + this.cmd("CreateLabel", labelID, this.arrayData[i], BucketSort.ARRAY_ELEM_START_X_SMALL + i *BucketSort.ARRAY_ELEM_WIDTH_SMALL, BucketSort.ARRAY_ELEMENT_Y_SMALL); this.cmd("SetText", node.graphicID, "") this.cmd("SetText", this.arrayRects[i], "") this.cmd("Move", labelID, 100,75); this.cmd("Step"); this.cmd("SetText", node.graphicID, this.arrayData[i]); this.cmd("Delete", labelID); - var index = Math.floor((this.arrayData[i] * ARRAY_SIZE_SMALL) / (MAX_DATA_VALUE + 1)); + var index = Math.floor((this.arrayData[i] * BucketSort.ARRAY_SIZE_SMALL) / (BucketSort.MAX_DATA_VALUE + 1)); this.cmd("CreateLabel", labelID, "Linked List Array index = " , 300, 20, 0); - this.cmd("CreateLabel", label2ID, "Value * NUMBER_OF_ELEMENTS / (MAXIMUM_ARRAY_VALUE + 1)) = ", 300, 40, 0); - this.cmd("CreateLabel", label3ID, "("+ String(this.arrayData[i]) + " * " + String(ARRAY_SIZE_SMALL) + ") / " + String(MAX_DATA_VALUE+1) + " = " , 300, 60, 0); + this.cmd("CreateLabel", label2ID, "Value * BucketSort.NUMBER_OF_ELEMENTS / (BucketSort.MAXIMUM_ARRAY_VALUE + 1)) = ", 300, 40, 0); + this.cmd("CreateLabel", label3ID, "("+ String(this.arrayData[i]) + " * " + String(BucketSort.ARRAY_SIZE_SMALL) + ") / " + String(BucketSort.MAX_DATA_VALUE+1) + " = " , 300, 60, 0); this.cmd("CreateLabel", label4ID, index, 305, 85); this.cmd("SetForegroundColor", labelID, "#000000"); this.cmd("SetForegroundColor", label2ID, "#000000"); @@ -158,7 +158,7 @@ BucketSort.prototype.bucketSortCallback = function(event) var highlightCircle = this.nextIndex++; this.cmd("CreateHighlightCircle", highlightCircle, "#0000FF", 305, 100); - this.cmd("Move", highlightCircle, POINTER_ARRAY_ELEM_START_X_SMALL + index *POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small + POINTER_ARRAY_ELEM_HEIGHT_SMALL); + this.cmd("Move", highlightCircle, BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL + index *BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL, this.pointer_array_elem_y_small + BucketSort.POINTER_ARRAY_ELEM_HEIGHT_SMALL); this.cmd("Step"); this.cmd("Delete", labelID); this.cmd("Delete", label2ID); @@ -174,8 +174,8 @@ BucketSort.prototype.bucketSortCallback = function(event) this.cmd("Connect", this.linkedListRects[index], node.graphicID); this.cmd("SetNull",this.linkedListRects[index], 0); - node.x = POINTER_ARRAY_ELEM_START_X_SMALL + index *POINTER_ARRAY_ELEM_WIDTH_SMALL; - node.y = this.pointer_array_elem_y_small - LINKED_ITEM_Y_DELTA_SMALL; + node.x = BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL + index *BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL; + node.y = this.pointer_array_elem_y_small - BucketSort.LINKED_ITEM_Y_DELTA_SMALL; this.cmd("Move", node.graphicID, node.x, node.y); } else @@ -236,21 +236,21 @@ BucketSort.prototype.bucketSortCallback = function(event) this.cmd("Connect", tmp.graphicID, node.graphicID); } tmp = linkedListData[index]; - var startX = POINTER_ARRAY_ELEM_START_X_SMALL + index *POINTER_ARRAY_ELEM_WIDTH_SMALL; - var startY = this.pointer_array_elem_y_small - LINKED_ITEM_Y_DELTA_SMALL; + var startX = BucketSort.POINTER_ARRAY_ELEM_START_X_SMALL + index *BucketSort.POINTER_ARRAY_ELEM_WIDTH_SMALL; + var startY = this.pointer_array_elem_y_small - BucketSort.LINKED_ITEM_Y_DELTA_SMALL; while (tmp != null) { tmp.x = startX; tmp.y = startY; this.cmd("Move", tmp.graphicID, tmp.x, tmp.y); - startY = startY - LINKED_ITEM_Y_DELTA_SMALL; + startY = startY - BucketSort.LINKED_ITEM_Y_DELTA_SMALL; tmp = tmp.next; } } this.cmd("Step"); } var insertIndex = 0; - for (i = 0; i < ARRAY_SIZE_SMALL; i++) + for (i = 0; i < BucketSort.ARRAY_SIZE_SMALL; i++) { for (tmp = linkedListData[i]; tmp != null; tmp = tmp.next) { @@ -258,7 +258,7 @@ BucketSort.prototype.bucketSortCallback = function(event) this.cmd("SetText", tmp.graphicID, ""); this.cmd("SetText", this.arrayRects[insertIndex], ""); this.cmd("CreateLabel", moveLabelID, tmp.data, tmp.x, tmp.y); - this.cmd("Move", moveLabelID, ARRAY_ELEM_START_X_SMALL + insertIndex *ARRAY_ELEM_WIDTH_SMALL, ARRAY_ELEMENT_Y_SMALL); + this.cmd("Move", moveLabelID, BucketSort.ARRAY_ELEM_START_X_SMALL + insertIndex *BucketSort.ARRAY_ELEM_WIDTH_SMALL, BucketSort.ARRAY_ELEMENT_Y_SMALL); this.cmd("Step"); this.cmd("Delete", moveLabelID); this.cmd("SetText", this.arrayRects[insertIndex], tmp.data); @@ -284,9 +284,9 @@ BucketSort.prototype.bucketSortCallback = function(event) BucketSort.prototype.randomizeArray = function() { this.commands = new Array(); - for (var i = 0; i < ARRAY_SIZE_SMALL; i++) + for (var i = 0; i < BucketSort.ARRAY_SIZE_SMALL; i++) { - this.arrayData[i] = Math.floor(1 + Math.random()*MAX_DATA_VALUE); + this.arrayData[i] = Math.floor(1 + Math.random()*BucketSort.MAX_DATA_VALUE); this.oldData[i] = this.arrayData[i]; this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); } @@ -305,7 +305,7 @@ BucketSort.prototype.randomizeArray = function() BucketSort.prototype.reset = function() { this.commands = new Array(); - for (var i = 0; i < ARRAY_SIZE_SMALL; i++) + for (var i = 0; i < BucketSort.ARRAY_SIZE_SMALL; i++) { this.arrayData[i] = this.oldData[i]; } diff --git a/AlgorithmLibrary/ClosedHash.js b/AlgorithmLibrary/ClosedHash.js index 2078f4b..c1e777c 100644 --- a/AlgorithmLibrary/ClosedHash.js +++ b/AlgorithmLibrary/ClosedHash.js @@ -32,30 +32,30 @@ function ClosedHash(am, w, h) } ClosedHash.inheritFrom(Hash); -var ARRAY_ELEM_WIDTH = 90; -var ARRAY_ELEM_HEIGHT = 30; -var ARRAY_ELEM_START_X = 50; -var ARRAY_ELEM_START_Y = 100; -var ARRAY_VERTICAL_SEPARATION = 100; +ClosedHash.ARRAY_ELEM_WIDTH = 90; +ClosedHash.ARRAY_ELEM_HEIGHT = 30; +ClosedHash.ARRAY_ELEM_START_X = 50; +ClosedHash.ARRAY_ELEM_START_Y = 100; +ClosedHash.ARRAY_VERTICAL_SEPARATION = 100; -var CLOSED_HASH_TABLE_SIZE = 29; +ClosedHash.CLOSED_HASH_TABLE_SIZE = 29; -var ARRAY_Y_POS = 350; +ClosedHash.ARRAY_Y_POS = 350; -var INDEX_COLOR = "#0000FF"; +ClosedHash.INDEX_COLOR = "#0000FF"; -var MAX_DATA_VALUE = 999; +ClosedHash.MAX_DATA_VALUE = 999; -var HASH_TABLE_SIZE = 13; +ClosedHash.HASH_TABLE_SIZE = 13; -var ARRAY_Y_POS = 350; +ClosedHash.ARRAY_Y_POS = 350; -var INDEX_COLOR = "#0000FF"; +ClosedHash.INDEX_COLOR = "#0000FF"; @@ -64,13 +64,13 @@ ClosedHash.prototype.init = function(am, w, h) { var sc = ClosedHash.superclass; var fn = sc.init; - this.elements_per_row = Math.floor(w / ARRAY_ELEM_WIDTH); + this.elements_per_row = Math.floor(w / ClosedHash.ARRAY_ELEM_WIDTH); fn.call(this,am, w, h); //Change me! this.nextIndex = 0; - //this.POINTER_ARRAY_ELEM_Y = h - POINTER_ARRAY_ELEM_WIDTH; + //this.POINTER_ARRAY_ELEM_Y = h - ClosedHash.POINTER_ARRAY_ELEM_WIDTH; this.setup(); } @@ -175,7 +175,7 @@ ClosedHash.prototype.insertElement = function(elem) { var labID = this.nextIndex++; this.cmd("CreateLabel", labID, elem, 20, 25); - this.cmd("Move", labID, this.indexXPos[index], this.indexYPos[index] - ARRAY_ELEM_HEIGHT); + this.cmd("Move", labID, this.indexXPos[index], this.indexYPos[index] - ClosedHash.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("Delete", labID); this.cmd("SetText", this.hashTableVisual[index], elem); @@ -303,7 +303,7 @@ ClosedHash.prototype.findElement = function(elem) ClosedHash.prototype.setup = function() { - this.table_size = CLOSED_HASH_TABLE_SIZE; + this.table_size = ClosedHash.CLOSED_HASH_TABLE_SIZE; this.skipDist = new Array(this.table_size); this.hashTableVisual = new Array(this.table_size); this.hashTableIndices = new Array(this.table_size); @@ -326,17 +326,17 @@ ClosedHash.prototype.setup = function() this.empty[i] = true; this.deleted[i] = false; - var nextXPos = ARRAY_ELEM_START_X + (i % this.elements_per_row) * ARRAY_ELEM_WIDTH; - var nextYPos = ARRAY_ELEM_START_Y + Math.floor(i / this.elements_per_row) * ARRAY_VERTICAL_SEPARATION; - this.cmd("CreateRectangle", nextID, "", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,nextXPos, nextYPos) + var nextXPos = ClosedHash.ARRAY_ELEM_START_X + (i % this.elements_per_row) * ClosedHash.ARRAY_ELEM_WIDTH; + var nextYPos = ClosedHash.ARRAY_ELEM_START_Y + Math.floor(i / this.elements_per_row) * ClosedHash.ARRAY_VERTICAL_SEPARATION; + this.cmd("CreateRectangle", nextID, "", ClosedHash.ARRAY_ELEM_WIDTH, ClosedHash.ARRAY_ELEM_HEIGHT,nextXPos, nextYPos) this.hashTableVisual[i] = nextID; nextID = this.nextIndex++; this.hashTableIndices[i] = nextID; this.indexXPos[i] = nextXPos; - this.indexYPos[i] = nextYPos + ARRAY_ELEM_HEIGHT + this.indexYPos[i] = nextYPos + ClosedHash.ARRAY_ELEM_HEIGHT this.cmd("CreateLabel", nextID, i,this.indexXPos[i],this.indexYPos[i]); - this.cmd("SetForegroundColor", nextID, INDEX_COLOR); + this.cmd("SetForegroundColor", nextID, ClosedHash.INDEX_COLOR); } this.cmd("CreateLabel", this.ExplainLabel, "", 10, 25, 0); this.animationManager.StartNewAnimation(this.commands); diff --git a/AlgorithmLibrary/ClosedHashBucket.js b/AlgorithmLibrary/ClosedHashBucket.js index 6d1693e..d5b4f44 100644 --- a/AlgorithmLibrary/ClosedHashBucket.js +++ b/AlgorithmLibrary/ClosedHashBucket.js @@ -32,36 +32,36 @@ function ClosedHashBucket(am, w, h) } ClosedHashBucket.inheritFrom(Hash); -var ARRAY_ELEM_WIDTH = 90; -var ARRAY_ELEM_HEIGHT = 30; -var ARRAY_ELEM_START_X = 50; -var ARRAY_ELEM_START_Y = 100; -var ARRAY_VERTICAL_SEPARATION = 100; +ClosedHashBucket.ARRAY_ELEM_WIDTH = 90; +ClosedHashBucket.ARRAY_ELEM_HEIGHT = 30; +ClosedHashBucket.ARRAY_ELEM_START_X = 50; +ClosedHashBucket.ARRAY_ELEM_START_Y = 100; +ClosedHashBucket.ARRAY_VERTICAL_SEPARATION = 100; -var CLOSED_HASH_TABLE_SIZE = 29; +ClosedHashBucket.CLOSED_HASH_TABLE_SIZE = 29; -var BUCKET_SIZE = 3; -var NUM_BUCKETS = 11; -var CLOSED_HASH_TABLE_SIZE = 40; +ClosedHashBucket.BUCKET_SIZE = 3; +ClosedHashBucket.NUM_BUCKETS = 11; +ClosedHashBucket.CLOSED_HASH_TABLE_SIZE = 40; -var ARRAY_Y_POS = 350; +ClosedHashBucket.ARRAY_Y_POS = 350; -var INDEX_COLOR = "#0000FF"; +ClosedHashBucket.INDEX_COLOR = "#0000FF"; -var MAX_DATA_VALUE = 999; +ClosedHashBucket.MAX_DATA_VALUE = 999; -var HASH_TABLE_SIZE = 13; +ClosedHashBucket.HASH_TABLE_SIZE = 13; -var ARRAY_Y_POS = 350; +ClosedHashBucket.ARRAY_Y_POS = 350; -var INDEX_COLOR = "#0000FF"; +ClosedHashBucket.INDEX_COLOR = "#0000FF"; @@ -73,12 +73,12 @@ ClosedHashBucket.prototype.init = function(am, w, h) var fn = sc.init; fn.call(this,am, w, h); - this.elements_per_row = Math.floor(w / ARRAY_ELEM_WIDTH) ; + this.elements_per_row = Math.floor(w / ClosedHashBucket.ARRAY_ELEM_WIDTH) ; //Change me! this.nextIndex = 0; - //this.POINTER_ARRAY_ELEM_Y = h - POINTER_ARRAY_ELEM_WIDTH; + //this.POINTER_ARRAY_ELEM_Y = h - ClosedHashBucket.POINTER_ARRAY_ELEM_WIDTH; this.setup(); } @@ -103,7 +103,7 @@ ClosedHashBucket.prototype.insertElement = function(elem) var index = this.doHash(elem); var foundIndex = -1; - for (var candidateIndex = index * BUCKET_SIZE; candidateIndex < index * BUCKET_SIZE + BUCKET_SIZE; candidateIndex++) + for (var candidateIndex = index * ClosedHashBucket.BUCKET_SIZE; candidateIndex < index * ClosedHashBucket.BUCKET_SIZE + ClosedHashBucket.BUCKET_SIZE; candidateIndex++) { this.cmd("SetHighlight", this.hashTableVisual[candidateIndex], 1); this.cmd("Step"); @@ -116,7 +116,7 @@ ClosedHashBucket.prototype.insertElement = function(elem) } if (foundIndex == -1) { - for (candidateIndex = BUCKET_SIZE * NUM_BUCKETS; candidateIndex < CLOSED_HASH_TABLE_SIZE; candidateIndex++) + for (candidateIndex = ClosedHashBucket.BUCKET_SIZE * ClosedHashBucket.NUM_BUCKETS; candidateIndex < ClosedHashBucket.CLOSED_HASH_TABLE_SIZE; candidateIndex++) { this.cmd("SetHighlight", this.hashTableVisual[candidateIndex], 1); this.cmd("Step"); @@ -135,7 +135,7 @@ ClosedHashBucket.prototype.insertElement = function(elem) { var labID = this.nextIndex++; this.cmd("CreateLabel", labID, elem, 20, 25); - this.cmd("Move", labID, this.indexXPos2[foundIndex], this.indexYPos2[foundIndex] - ARRAY_ELEM_HEIGHT); + this.cmd("Move", labID, this.indexXPos2[foundIndex], this.indexYPos2[foundIndex] - ClosedHashBucket.ARRAY_ELEM_HEIGHT); this.cmd("Step"); this.cmd("Delete", labID); this.cmd("SetText", this.hashTableVisual[foundIndex], elem); @@ -159,7 +159,7 @@ ClosedHashBucket.prototype.getElemIndex = function(elem) var foundIndex = -1; var initialIndex = this.doHash(elem); - for (var candidateIndex = initialIndex * BUCKET_SIZE; candidateIndex < initialIndex* BUCKET_SIZE + BUCKET_SIZE; candidateIndex++) + for (var candidateIndex = initialIndex * ClosedHashBucket.BUCKET_SIZE; candidateIndex < initialIndex* ClosedHashBucket.BUCKET_SIZE + ClosedHashBucket.BUCKET_SIZE; candidateIndex++) { this.cmd("SetHighlight", this.hashTableVisual[candidateIndex], 1); this.cmd("Step"); @@ -175,7 +175,7 @@ ClosedHashBucket.prototype.getElemIndex = function(elem) } // Can only get this far if we didn't find the element we are looking for, // *and* the bucekt was full -- look at overflow bucket. - for (candidateIndex = BUCKET_SIZE * NUM_BUCKETS; candidateIndex < CLOSED_HASH_TABLE_SIZE; candidateIndex++) + for (candidateIndex = ClosedHashBucket.BUCKET_SIZE * ClosedHashBucket.NUM_BUCKETS; candidateIndex < ClosedHashBucket.CLOSED_HASH_TABLE_SIZE; candidateIndex++) { this.cmd("SetHighlight", this.hashTableVisual[candidateIndex], 1); this.cmd("Step"); @@ -236,59 +236,59 @@ ClosedHashBucket.prototype.findElement = function(elem) ClosedHashBucket.prototype.setup = function() { - this.table_size = NUM_BUCKETS; - this.hashTableVisual = new Array(CLOSED_HASH_TABLE_SIZE); - this.hashTableIndices = new Array(CLOSED_HASH_TABLE_SIZE); - this.hashTableValues = new Array(CLOSED_HASH_TABLE_SIZE); + this.table_size = ClosedHashBucket.NUM_BUCKETS; + this.hashTableVisual = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); + this.hashTableIndices = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); + this.hashTableValues = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); - this.indexXPos = new Array(NUM_BUCKETS); - this.indexYPos = new Array(NUM_BUCKETS); + this.indexXPos = new Array(ClosedHashBucket.NUM_BUCKETS); + this.indexYPos = new Array(ClosedHashBucket.NUM_BUCKETS); - this.indexXPos2 = new Array(CLOSED_HASH_TABLE_SIZE); - this.indexYPos2 = new Array(CLOSED_HASH_TABLE_SIZE); + this.indexXPos2 = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); + this.indexYPos2 = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); - this.empty = new Array(CLOSED_HASH_TABLE_SIZE); - this.deleted = new Array(CLOSED_HASH_TABLE_SIZE); + this.empty = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); + this.deleted = new Array(ClosedHashBucket.CLOSED_HASH_TABLE_SIZE); this.ExplainLabel = this.nextIndex++; this.commands = []; - for (var i = 0; i < CLOSED_HASH_TABLE_SIZE; i++) + for (var i = 0; i < ClosedHashBucket.CLOSED_HASH_TABLE_SIZE; i++) { var nextID = this.nextIndex++; this.empty[i] = true; this.deleted[i] = false; - var nextXPos = ARRAY_ELEM_START_X + (i % this.elements_per_row) * ARRAY_ELEM_WIDTH; - var nextYPos = ARRAY_ELEM_START_Y + Math.floor(i / this.elements_per_row) * ARRAY_VERTICAL_SEPARATION; - this.cmd("CreateRectangle", nextID, "", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,nextXPos, nextYPos) + var nextXPos = ClosedHashBucket.ARRAY_ELEM_START_X + (i % this.elements_per_row) * ClosedHashBucket.ARRAY_ELEM_WIDTH; + var nextYPos = ClosedHashBucket.ARRAY_ELEM_START_Y + Math.floor(i / this.elements_per_row) * ClosedHashBucket.ARRAY_VERTICAL_SEPARATION; + this.cmd("CreateRectangle", nextID, "", ClosedHashBucket.ARRAY_ELEM_WIDTH, ClosedHashBucket.ARRAY_ELEM_HEIGHT,nextXPos, nextYPos) this.hashTableVisual[i] = nextID; nextID = this.nextIndex++; this.hashTableIndices[i] = nextID; this.indexXPos2[i] = nextXPos; - this.indexYPos2[i] = nextYPos + ARRAY_ELEM_HEIGHT + this.indexYPos2[i] = nextYPos + ClosedHashBucket.ARRAY_ELEM_HEIGHT this.cmd("CreateLabel", nextID, i,this.indexXPos2[i],this.indexYPos2[i]); - this.cmd("SetForegroundColor", nextID, INDEX_COLOR); + this.cmd("SetForegroundColor", nextID, ClosedHashBucket.INDEX_COLOR); } - for (i = 0; i <= NUM_BUCKETS; i++) + for (i = 0; i <= ClosedHashBucket.NUM_BUCKETS; i++) { nextID = this.nextIndex++; - nextXPos = ARRAY_ELEM_START_X + (i * 3 % this.elements_per_row) * ARRAY_ELEM_WIDTH - ARRAY_ELEM_WIDTH / 2; - nextYPos = ARRAY_ELEM_START_Y + Math.floor((i * 3) / this.elements_per_row) * ARRAY_VERTICAL_SEPARATION + ARRAY_ELEM_HEIGHT; - this.cmd("CreateRectangle", nextID, "", 0, ARRAY_ELEM_HEIGHT * 2,nextXPos, nextYPos) + nextXPos = ClosedHashBucket.ARRAY_ELEM_START_X + (i * 3 % this.elements_per_row) * ClosedHashBucket.ARRAY_ELEM_WIDTH - ClosedHashBucket.ARRAY_ELEM_WIDTH / 2; + nextYPos = ClosedHashBucket.ARRAY_ELEM_START_Y + Math.floor((i * 3) / this.elements_per_row) * ClosedHashBucket.ARRAY_VERTICAL_SEPARATION + ClosedHashBucket.ARRAY_ELEM_HEIGHT; + this.cmd("CreateRectangle", nextID, "", 0, ClosedHashBucket.ARRAY_ELEM_HEIGHT * 2,nextXPos, nextYPos) nextID = this.nextIndex++; - if (i == NUM_BUCKETS) + if (i == ClosedHashBucket.NUM_BUCKETS) { - this.cmd("CreateLabel", nextID, "Overflow", nextXPos + 3, nextYPos + ARRAY_ELEM_HEIGHT / 2 , 0); + this.cmd("CreateLabel", nextID, "Overflow", nextXPos + 3, nextYPos + ClosedHashBucket.ARRAY_ELEM_HEIGHT / 2 , 0); } else { this.indexXPos[i] = nextXPos + 5; - this.indexYPos[i] = nextYPos + ARRAY_ELEM_HEIGHT / 2; + this.indexYPos[i] = nextYPos + ClosedHashBucket.ARRAY_ELEM_HEIGHT / 2; this.cmd("CreateLabel", nextID, i, this.indexXPos[i],this.indexYPos[i], 0); } } @@ -310,7 +310,7 @@ ClosedHashBucket.prototype.resetAll = function() { this.commands = ClosedHashBucket.superclass.resetAll.call(this); - for (var i = 0; i < CLOSED_HASH_TABLE_SIZE; i++) + for (var i = 0; i < ClosedHashBucket.CLOSED_HASH_TABLE_SIZE; i++) { this.empty[i] = true; this.deleted[i] = false; @@ -325,7 +325,7 @@ ClosedHashBucket.prototype.resetAll = function() // NEED TO OVERRIDE IN PARENT ClosedHashBucket.prototype.reset = function() { - for (var i = 0; i < CLOSED_HASH_TABLE_SIZE; i++) + for (var i = 0; i < ClosedHashBucket.CLOSED_HASH_TABLE_SIZE; i++) { this.empty[i]= true; this.deleted[i] = false; diff --git a/AlgorithmLibrary/ComparisonSort.js b/AlgorithmLibrary/ComparisonSort.js index 9fbd585..8653182 100644 --- a/AlgorithmLibrary/ComparisonSort.js +++ b/AlgorithmLibrary/ComparisonSort.js @@ -32,31 +32,31 @@ function ComparisonSort(am, w, h) } -var ARRAY_SIZE_SMALL = 50; -var ARRAY_WIDTH_SMALL = 17; -var ARRAY_BAR_WIDTH_SMALL = 10; -var ARRAY_INITIAL_X_SMALL = 15; +ComparisonSort.ARRAY_SIZE_SMALL = 50; +ComparisonSort.ARRAY_WIDTH_SMALL = 17; +ComparisonSort.ARRAY_BAR_WIDTH_SMALL = 10; +ComparisonSort.ARRAY_INITIAL_X_SMALL = 15; -var ARRAY_Y_POS = 250; -var ARRAY_LABEL_Y_POS = 260; +ComparisonSort.ARRAY_Y_POS = 250; +ComparisonSort.ARRAY_LABEL_Y_POS = 260; -var LOWER_ARRAY_Y_POS = 500; -var LOWER_ARRAY_LABEL_Y_POS = 510; +ComparisonSort.LOWER_ARRAY_Y_POS = 500; +ComparisonSort.LOWER_ARRAY_LABEL_Y_POS = 510; -var SCALE_FACTOR = 2.0; +ComparisonSort.SCALE_FACTOR = 2.0; -var ARRAY_SIZE_LARGE = 200; -var ARRAY_WIDTH_LARGE = 4; -var ARRAY_BAR_WIDTH_LARGE = 2; -var ARRAY_INITIAL_X_LARGE = 15; +ComparisonSort.ARRAY_SIZE_LARGE = 200; +ComparisonSort.ARRAY_WIDTH_LARGE = 4; +ComparisonSort.ARRAY_BAR_WIDTH_LARGE = 2; +ComparisonSort.ARRAY_INITIAL_X_LARGE = 15; -var BAR_FOREGROUND_COLOR = "#0000FF"; -var BAR_BACKGROUND_COLOR ="#AAAAFF"; -var INDEX_COLOR = "#0000FF"; -var HIGHLIGHT_BAR_COLOR = "#FF0000"; -var HIGHLIGHT_BAR_BACKGROUND_COLOR = "#FFAAAA"; +ComparisonSort.BAR_FOREGROUND_COLOR = "#0000FF"; +ComparisonSort.BAR_BACKGROUND_COLOR ="#AAAAFF"; +ComparisonSort.INDEX_COLOR = "#0000FF"; +ComparisonSort.HIGHLIGHT_BAR_COLOR = "#FF0000"; +ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR = "#FFAAAA"; -var QUICKSORT_LINE_COLOR = "#FF0000"; +ComparisonSort.QUICKSORT_LINE_COLOR = "#FF0000"; @@ -71,10 +71,10 @@ ComparisonSort.prototype.init = function(am, w, h) this.nextIndex = 0; this.setArraySize(true); - this.arrayData = new Array(ARRAY_SIZE_LARGE); - this.arraySwap = new Array(ARRAY_SIZE_LARGE); - this.labelsSwap = new Array(ARRAY_SIZE_LARGE); - this.objectsSwap = new Array(ARRAY_SIZE_LARGE); + this.arrayData = new Array(ComparisonSort.ARRAY_SIZE_LARGE); + this.arraySwap = new Array(ComparisonSort.ARRAY_SIZE_LARGE); + this.labelsSwap = new Array(ComparisonSort.ARRAY_SIZE_LARGE); + this.objectsSwap = new Array(ComparisonSort.ARRAY_SIZE_LARGE); this.createVisualObjects(); } @@ -113,22 +113,22 @@ ComparisonSort.prototype.setArraySize = function (small) { if (small) { - this.array_size = ARRAY_SIZE_SMALL; - this.array_width = ARRAY_WIDTH_SMALL; - this.array_bar_width = ARRAY_BAR_WIDTH_SMALL; - this.array_initial_x = ARRAY_INITIAL_X_SMALL; - this.array_y_pos = ARRAY_Y_POS; - this.array_label_y_pos = ARRAY_LABEL_Y_POS; + this.array_size = ComparisonSort.ARRAY_SIZE_SMALL; + this.array_width = ComparisonSort.ARRAY_WIDTH_SMALL; + this.array_bar_width = ComparisonSort.ARRAY_BAR_WIDTH_SMALL; + this.array_initial_x = ComparisonSort.ARRAY_INITIAL_X_SMALL; + this.array_y_pos = ComparisonSort.ARRAY_Y_POS; + this.array_label_y_pos = ComparisonSort.ARRAY_LABEL_Y_POS; this.showLabels = true; } else { - this.array_size = ARRAY_SIZE_LARGE; - this.array_width = ARRAY_WIDTH_LARGE; - this.array_bar_width = ARRAY_BAR_WIDTH_LARGE; - this.array_initial_x = ARRAY_INITIAL_X_LARGE; - this.array_y_pos = ARRAY_Y_POS; - this.array_label_y_pos = ARRAY_LABEL_Y_POS; + this.array_size = ComparisonSort.ARRAY_SIZE_LARGE; + this.array_width = ComparisonSort.ARRAY_WIDTH_LARGE; + this.array_bar_width = ComparisonSort.ARRAY_BAR_WIDTH_LARGE; + this.array_initial_x = ComparisonSort.ARRAY_INITIAL_X_LARGE; + this.array_y_pos = ComparisonSort.ARRAY_Y_POS; + this.array_label_y_pos = ComparisonSort.ARRAY_LABEL_Y_POS; this.showLabels = false; } @@ -159,7 +159,7 @@ ComparisonSort.prototype.randomizeArray = function() { this.cmd("SetText", this.barLabels[i], ""); } - this.cmd("SetHeight", this.barObjects[i], this.arrayData[i] * SCALE_FACTOR); + this.cmd("SetHeight", this.barObjects[i], this.arrayData[i] * ComparisonSort.SCALE_FACTOR); } this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); @@ -213,8 +213,8 @@ ComparisonSort.prototype.createVisualObjects = function() xPos = xPos + this.array_width; this.barPositionsX[i] = xPos; this.cmd("CreateRectangle", this.nextIndex, "", this.array_bar_width, 200, xPos, yPos,"center","bottom"); - this.cmd("SetForegroundColor", this.nextIndex, BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.nextIndex, BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.nextIndex, ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.nextIndex, ComparisonSort.BAR_BACKGROUND_COLOR); this.barObjects[i] = this.nextIndex; this.oldBarObjects[i] = this.barObjects[i]; this.nextIndex += 1; @@ -226,7 +226,7 @@ ComparisonSort.prototype.createVisualObjects = function() { this.cmd("CreateLabel", this.nextIndex, "", xPos, yLabelPos); } - this.cmd("SetForegroundColor", this.nextIndex, INDEX_COLOR); + this.cmd("SetForegroundColor", this.nextIndex, ComparisonSort.INDEX_COLOR); this.barLabels[i] = this.nextIndex; this.oldbarLabels[i] = this.barLabels[i]; @@ -291,7 +291,7 @@ ComparisonSort.prototype.reset = function() { this.cmd("SetText", this.barLabels[i], ""); } - this.cmd("SetHeight", this.barObjects[i], this.arrayData[i] * SCALE_FACTOR); + this.cmd("SetHeight", this.barObjects[i], this.arrayData[i] * ComparisonSort.SCALE_FACTOR); } this.commands = new Array(); } @@ -327,31 +327,31 @@ ComparisonSort.prototype.selectSortCallback = function(event) for (var i = 0; i < this.array_size - 1; i++) { var smallestIndex = i; - this.cmd("SetForegroundColor", this.barObjects[smallestIndex], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[smallestIndex], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[smallestIndex], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[smallestIndex], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); for (var j = i+1; j < this.array_size; j++) { - this.cmd("SetForegroundColor", this.barObjects[j], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); if (this.arrayData[j] < this.arrayData[smallestIndex]) { - this.cmd("SetForegroundColor", this.barObjects[smallestIndex], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[smallestIndex], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[smallestIndex], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[smallestIndex], ComparisonSort.BAR_BACKGROUND_COLOR); smallestIndex = j; } else { - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); } } if (smallestIndex != i) { this.swap(smallestIndex, i); } - this.cmd("SetForegroundColor", this.barObjects[i], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.BAR_BACKGROUND_COLOR); } this.animationManager.StartNewAnimation(this.commands); } @@ -364,21 +364,21 @@ ComparisonSort.prototype.bubbleSortCallback = function(event) { for (var j = 0; j < i; j++) { - this.cmd("SetForegroundColor", this.barObjects[j], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[j+1], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j+1], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j+1], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j+1], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); if (this.arrayData[j] > this.arrayData[j+1]) { this.swap(j,j+1); } - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[j+1], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j+1], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j+1], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j+1], ComparisonSort.BAR_BACKGROUND_COLOR); } } @@ -393,10 +393,10 @@ ComparisonSort.prototype.quickSortCallback = function(event) this.jID= this.nextIndex++; this.cmd("CreateLabel", this.iID, "i", this.barObjects[0], this.array_label_y_pos + 20); this.cmd("CreateLabel", this.jID, "j", this.barObjects[this.array_size - 1], this.array_label_y_pos + 20); - this.cmd("SetForegroundColor", this.iID, HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.iID, HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.jID, HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.jID, HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.iID, ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.iID, ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.jID, ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.jID, ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.doQuickSort(0, this.array_size - 1); this.cmd("Delete", this.iID); this.cmd("Delete", this.jID); @@ -412,7 +412,7 @@ ComparisonSort.prototype.doQuickSort = function(low, high) var lineID = this.nextIndex; var pivot = this.arrayData[low]; this.cmd("CreateRectangle", lineID, "", (this.array_size + 1) * this.array_width, 0, this.array_initial_x, this.array_y_pos - pivot * 2,"left","bottom"); - this.cmd("SetForegroundColor", lineID, QUICKSORT_LINE_COLOR); + this.cmd("SetForegroundColor", lineID, ComparisonSort.QUICKSORT_LINE_COLOR); var i = low+1; var j = high; @@ -423,61 +423,61 @@ ComparisonSort.prototype.doQuickSort = function(low, high) while (i <= j) { - this.cmd("SetForegroundColor", this.barObjects[i], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[low], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[low], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[i], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.BAR_BACKGROUND_COLOR); while (i <= j && this.arrayData[i] < pivot) { ++i; this.cmd("Move", this.iID, this.barPositionsX[i], this.array_label_y_pos + 20); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[low], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[i], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[low], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[i], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.BAR_BACKGROUND_COLOR); } - this.cmd("SetForegroundColor", this.barObjects[j], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[low], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[low], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.BAR_BACKGROUND_COLOR); while (j >= i && this.arrayData[j] > pivot) { --j; this.cmd("Move", this.jID, this.barPositionsX[j], this.array_label_y_pos + 20); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[j], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[low], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[low], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[low], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[low], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[low], ComparisonSort.BAR_BACKGROUND_COLOR); } if (i <= j) { @@ -491,14 +491,14 @@ ComparisonSort.prototype.doQuickSort = function(low, high) } if (i >= low) { - this.cmd("SetForegroundColor", this.barObjects[i], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[i], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[i], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[i], ComparisonSort.BAR_BACKGROUND_COLOR); } if (j <= high) { - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); } this.swap(low, j); @@ -538,8 +538,8 @@ ComparisonSort.prototype.doMergeSort = function(low,high) if (leftIndex <= mid && (rightIndex > high || this.arrayData[leftIndex] <= this.arrayData[rightIndex])) { this.arraySwap[insertIndex] = this.arrayData[leftIndex]; - this.cmd("Move", this.barObjects[leftIndex], this.barPositionsX[insertIndex], LOWER_ARRAY_Y_POS); - this.cmd("Move", this.barLabels[leftIndex], this.barPositionsX[insertIndex], LOWER_ARRAY_LABEL_Y_POS); + this.cmd("Move", this.barObjects[leftIndex], this.barPositionsX[insertIndex], ComparisonSort.LOWER_ARRAY_Y_POS); + this.cmd("Move", this.barLabels[leftIndex], this.barPositionsX[insertIndex], ComparisonSort.LOWER_ARRAY_LABEL_Y_POS); this.cmd("Step"); this.labelsSwap[insertIndex] = this.barLabels[leftIndex]; this.objectsSwap[insertIndex] = this.barObjects[leftIndex]; @@ -549,8 +549,8 @@ ComparisonSort.prototype.doMergeSort = function(low,high) else { this.arraySwap[insertIndex] = this.arrayData[rightIndex]; - this.cmd("Move", this.barLabels[rightIndex], this.barPositionsX[insertIndex], LOWER_ARRAY_LABEL_Y_POS); - this.cmd("Move", this.barObjects[rightIndex], this.barPositionsX[insertIndex], LOWER_ARRAY_Y_POS); + this.cmd("Move", this.barLabels[rightIndex], this.barPositionsX[insertIndex], ComparisonSort.LOWER_ARRAY_LABEL_Y_POS); + this.cmd("Move", this.barObjects[rightIndex], this.barPositionsX[insertIndex], ComparisonSort.LOWER_ARRAY_Y_POS); this.cmd("Step"); this.labelsSwap[insertIndex] = this.barLabels[rightIndex]; this.objectsSwap[insertIndex] = this.barObjects[rightIndex]; @@ -625,24 +625,24 @@ ComparisonSort.prototype.insertionSortSkip = function(inc, offset) var j = i; while (j > inc - 1) { - this.cmd("SetForegroundColor", this.barObjects[j], HIGHLIGHT_BAR_COLOR); - this.cmd("SetForegroundColor", this.barObjects[j-inc], HIGHLIGHT_BAR_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], HIGHLIGHT_BAR_BACKGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j - inc], HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j-inc], ComparisonSort.HIGHLIGHT_BAR_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j - inc], ComparisonSort.HIGHLIGHT_BAR_BACKGROUND_COLOR); this.cmd("Step"); if (this.arrayData[j-inc] <= this.arrayData[j]) { - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[j-inc], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j - inc], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j-inc], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j - inc], ComparisonSort.BAR_BACKGROUND_COLOR); break; } this.swap(j,j-inc); - this.cmd("SetForegroundColor", this.barObjects[j], BAR_FOREGROUND_COLOR); - this.cmd("SetForegroundColor", this.barObjects[j-inc], BAR_FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j], BAR_BACKGROUND_COLOR); - this.cmd("SetBackgroundColor", this.barObjects[j - inc], BAR_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetForegroundColor", this.barObjects[j-inc], ComparisonSort.BAR_FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j], ComparisonSort.BAR_BACKGROUND_COLOR); + this.cmd("SetBackgroundColor", this.barObjects[j - inc], ComparisonSort.BAR_BACKGROUND_COLOR); j = j - inc; } diff --git a/AlgorithmLibrary/ConnectedComponent.js b/AlgorithmLibrary/ConnectedComponent.js index 7da2962..8d9ab53 100644 --- a/AlgorithmLibrary/ConnectedComponent.js +++ b/AlgorithmLibrary/ConnectedComponent.js @@ -25,29 +25,29 @@ // or implied, of the University of San Francisco -var AUX_ARRAY_WIDTH = 25; -var AUX_ARRAY_HEIGHT = 25; -var AUX_ARRAY_START_Y = 100; +ConnectedComponent.AUX_ARRAY_WIDTH = 25; +ConnectedComponent.AUX_ARRAY_HEIGHT = 25; +ConnectedComponent.AUX_ARRAY_START_Y = 100; -var VISITED_START_X = 475; -var PARENT_START_X = 400; +ConnectedComponent.VISITED_START_X = 475; +ConnectedComponent.PARENT_START_X = 400; -var D_X_POS_SMALL = [760, 685, 915, 610, 910, 685, 915, 760]; -var F_X_POS_SMALL = [760, 685, 915, 610, 910, 685, 915, 760]; +ConnectedComponent.D_X_POS_SMALL = [760, 685, 915, 610, 910, 685, 915, 760]; +ConnectedComponent.F_X_POS_SMALL = [760, 685, 915, 610, 910, 685, 915, 760]; -var D_Y_POS_SMALL = [18, 118, 118, 218, 218, 318, 318, 418]; -var F_Y_POS_SMALL = [32, 132, 132, 232, 232, 332, 332, 432]; +ConnectedComponent.D_Y_POS_SMALL = [18, 118, 118, 218, 218, 318, 318, 418]; +ConnectedComponent.F_Y_POS_SMALL = [32, 132, 132, 232, 232, 332, 332, 432]; -var D_X_POS_LARGE = [560, 660, 760, 860, +ConnectedComponent.D_X_POS_LARGE = [560, 660, 760, 860, 610, 710, 810, 560, 660, 760, 860, 610, 710, 810, 560, 660, 760, 860]; -var F_X_POS_LARGE = [560, 660, 760, 860, +ConnectedComponent.F_X_POS_LARGE = [560, 660, 760, 860, 610, 710, 810, 560, 660, 760, 860, 610, 710, 810, @@ -55,21 +55,21 @@ var F_X_POS_LARGE = [560, 660, 760, 860, -var D_Y_POS_LARGE = [037, 037, 037, 037, +ConnectedComponent.D_Y_POS_LARGE = [037, 037, 037, 037, 137, 137, 137, 237, 237, 237, 237, 337, 337, 337, 437, 437, 437, 437]; -var F_Y_POS_LARGE = [62, 62, 62, 62, +ConnectedComponent.F_Y_POS_LARGE = [62, 62, 62, 62, 162, 162, 162, 262, 262, 262, 262, 362, 362, 362, 462, 462, 462, 462]; -var HIGHLIGHT_CIRCLE_COLOR = "#000000"; -var DFS_TREE_COLOR = "#0000FF"; +ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR = "#000000"; +ConnectedComponent.DFS_TREE_COLOR = "#0000FF"; function ConnectedComponent(am, w, h) @@ -190,12 +190,12 @@ ConnectedComponent.prototype.doCC = function(ignored) { if (!this.visited[vertex]) { - this.cmd("CreateHighlightCircle", this.highlightCircleL, HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); + this.cmd("CreateHighlightCircle", this.highlightCircleL, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); this.cmd("SetLayer", this.highlightCircleL, 1); - this.cmd("CreateHighlightCircle", this.highlightCircleAL, HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAL, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); this.cmd("SetLayer", this.highlightCircleAL, 2); - this.cmd("CreateHighlightCircle", this.highlightCircleAM, HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAM, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); this.cmd("SetLayer", this.highlightCircleAM, 3); if (vertex > 0) @@ -300,12 +300,12 @@ ConnectedComponent.prototype.doCC = function(ignored) this.cmd("SetForegroundColor",breakID2 ,"#004B00"); this.messageY = this.messageY + 20; - this.cmd("CreateHighlightCircle", this.highlightCircleL, HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); + this.cmd("CreateHighlightCircle", this.highlightCircleL, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); this.cmd("SetLayer", this.highlightCircleL, 1); - this.cmd("CreateHighlightCircle", this.highlightCircleAL, HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAL, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); this.cmd("SetLayer", this.highlightCircleAL, 2); - this.cmd("CreateHighlightCircle", this.highlightCircleAM, HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAM, ConnectedComponent.HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); this.cmd("SetLayer", this.highlightCircleAM, 3); @@ -335,20 +335,20 @@ ConnectedComponent.prototype.doCC = function(ignored) ConnectedComponent.prototype.setup_large = function() { - this.d_x_pos = D_X_POS_LARGE; - this.d_y_pos = D_Y_POS_LARGE; - this.f_x_pos = F_X_POS_LARGE; - this.f_y_pos = F_Y_POS_LARGE; + this.d_x_pos = ConnectedComponent.D_X_POS_LARGE; + this.d_y_pos = ConnectedComponent.D_Y_POS_LARGE; + this.f_x_pos = ConnectedComponent.F_X_POS_LARGE; + this.f_y_pos = ConnectedComponent.F_Y_POS_LARGE; ConnectedComponent.superclass.setup_large.call(this); } ConnectedComponent.prototype.setup_small = function() { - this.d_x_pos = D_X_POS_SMALL; - this.d_y_pos = D_Y_POS_SMALL; - this.f_x_pos = F_X_POS_SMALL; - this.f_y_pos = F_Y_POS_SMALL; + this.d_x_pos = ConnectedComponent.D_X_POS_SMALL; + this.d_y_pos = ConnectedComponent.D_Y_POS_SMALL; + this.f_x_pos = ConnectedComponent.F_X_POS_SMALL; + this.f_y_pos = ConnectedComponent.F_Y_POS_SMALL; ConnectedComponent.superclass.setup_small.call(this); } @@ -397,7 +397,7 @@ ConnectedComponent.prototype.dfsVisit = function(startVertex, messageX, printCCN if (!this.visited[neighbor]) { this.cmd("Disconnect", this.circleID[startVertex], this.circleID[neighbor]); - this.cmd("Connect", this.circleID[startVertex], this.circleID[neighbor], DFS_TREE_COLOR, this.curve[startVertex][neighbor], 1, ""); + this.cmd("Connect", this.circleID[startVertex], this.circleID[neighbor], ConnectedComponent.DFS_TREE_COLOR, this.curve[startVertex][neighbor], 1, ""); this.cmd("Move", this.highlightCircleL, this.x_pos_logical[neighbor], this.y_pos_logical[neighbor]); this.cmd("Move", this.highlightCircleAL, this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + neighbor*this.adj_list_height); this.cmd("Move", this.highlightCircleAM, this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + neighbor*this.adj_matrix_height); diff --git a/AlgorithmLibrary/CountingSort.js b/AlgorithmLibrary/CountingSort.js index 4117731..8a5f15e 100644 --- a/AlgorithmLibrary/CountingSort.js +++ b/AlgorithmLibrary/CountingSort.js @@ -32,31 +32,31 @@ function CountingSort(am, w, h) } -var ARRAY_ELEM_WIDTH = 30; -var ARRAY_ELEM_HEIGHT = 30; -var ARRAY_ELEM_START_X = 20; +CountingSort.ARRAY_ELEM_WIDTH = 30; +CountingSort.ARRAY_ELEM_HEIGHT = 30; +CountingSort.ARRAY_ELEM_START_X = 20; -var COUNTER_ARRAY_ELEM_WIDTH = 30; -var COUNTER_ARRAY_ELEM_HEIGHT = 30; -var COUNTER_ARRAY_ELEM_START_X = 20; +CountingSort.COUNTER_ARRAY_ELEM_WIDTH = 30; +CountingSort.COUNTER_ARRAY_ELEM_HEIGHT = 30; +CountingSort.COUNTER_ARRAY_ELEM_START_X = 20; -var MAX_DATA_VALUE = 30; -var COUNTER_ARRAY_SIZE = MAX_DATA_VALUE + 1; +CountingSort.MAX_DATA_VALUE = 30; +CountingSort.COUNTER_ARRAY_SIZE = CountingSort.MAX_DATA_VALUE + 1; -var ARRAY_SIZE = 30; +CountingSort.ARRAY_SIZE = 30; CountingSort.inheritFrom(Algorithm); CountingSort.prototype.init = function(am, w, h) { - this.ARRAY_ELEM_Y = 3 * COUNTER_ARRAY_ELEM_HEIGHT; + this.ARRAY_ELEM_Y = 3 * CountingSort.COUNTER_ARRAY_ELEM_HEIGHT; this.COUNTER_ARRAY_ELEM_Y = Math.floor(h / 2); - this.SWAP_ARRAY_ELEM_Y = h - 3 * COUNTER_ARRAY_ELEM_HEIGHT + this.SWAP_ARRAY_ELEM_Y = h - 3 * CountingSort.COUNTER_ARRAY_ELEM_HEIGHT var sc = CountingSort.superclass; var fn = sc.init; @@ -73,9 +73,9 @@ CountingSort.prototype.init = function(am, w, h) CountingSort.prototype.sizeChanged = function(newWidth, newHeight) { - this.ARRAY_ELEM_Y = 3 * COUNTER_ARRAY_ELEM_HEIGHT; + this.ARRAY_ELEM_Y = 3 * CountingSort.COUNTER_ARRAY_ELEM_HEIGHT; this.COUNTER_ARRAY_ELEM_Y = Math.floor(newHeight / 2); - this.SWAP_ARRAY_ELEM_Y = newHeight - 3 * COUNTER_ARRAY_ELEM_HEIGHT + this.SWAP_ARRAY_ELEM_Y = newHeight - 3 * CountingSort.COUNTER_ARRAY_ELEM_HEIGHT this.setup(); } @@ -94,50 +94,50 @@ CountingSort.prototype.addControls = function() CountingSort.prototype.setup = function() { - this.arrayData = new Array(ARRAY_SIZE); - this. arrayRects= new Array(ARRAY_SIZE); - this. arrayIndices = new Array(ARRAY_SIZE); + this.arrayData = new Array(CountingSort.ARRAY_SIZE); + this. arrayRects= new Array(CountingSort.ARRAY_SIZE); + this. arrayIndices = new Array(CountingSort.ARRAY_SIZE); - this. counterData = new Array(COUNTER_ARRAY_SIZE); - this. counterRects= new Array(COUNTER_ARRAY_SIZE); - this. counterIndices = new Array(COUNTER_ARRAY_SIZE); + this. counterData = new Array(CountingSort.COUNTER_ARRAY_SIZE); + this. counterRects= new Array(CountingSort.COUNTER_ARRAY_SIZE); + this. counterIndices = new Array(CountingSort.COUNTER_ARRAY_SIZE); - this. swapData = new Array(ARRAY_SIZE); - this. swapRects= new Array(ARRAY_SIZE); - this. swapIndices = new Array(ARRAY_SIZE); + this. swapData = new Array(CountingSort.ARRAY_SIZE); + this. swapRects= new Array(CountingSort.ARRAY_SIZE); + this. swapIndices = new Array(CountingSort.ARRAY_SIZE); this. commands = new Array(); this.animationManager.resetAll(); - for (var i = 0; i < ARRAY_SIZE; i++) + for (var i = 0; i < CountingSort.ARRAY_SIZE; i++) { var nextID = this.nextIndex++; - this.arrayData[i] = Math.floor(Math.random()*MAX_DATA_VALUE); - this.cmd("CreateRectangle", nextID, this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y) + this.arrayData[i] = Math.floor(Math.random()*CountingSort.MAX_DATA_VALUE); + this.cmd("CreateRectangle", nextID, this.arrayData[i], CountingSort.ARRAY_ELEM_WIDTH, CountingSort.ARRAY_ELEM_HEIGHT, CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y) this. arrayRects[i] = nextID; nextID = this.nextIndex++; this. arrayIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y + ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y + CountingSort.ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID, "", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y) + this.cmd("CreateRectangle", nextID, "", CountingSort.ARRAY_ELEM_WIDTH, CountingSort.ARRAY_ELEM_HEIGHT, CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y) this. swapRects[i] = nextID; nextID = this.nextIndex++; this. swapIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + CountingSort.ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); } - for (i = COUNTER_ARRAY_SIZE - 1; i >= 0; i--) + for (i = CountingSort.COUNTER_ARRAY_SIZE - 1; i >= 0; i--) { nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID,"", COUNTER_ARRAY_ELEM_WIDTH, COUNTER_ARRAY_ELEM_HEIGHT, COUNTER_ARRAY_ELEM_START_X + i *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y) + this.cmd("CreateRectangle", nextID,"", CountingSort.COUNTER_ARRAY_ELEM_WIDTH, CountingSort.COUNTER_ARRAY_ELEM_HEIGHT, CountingSort.COUNTER_ARRAY_ELEM_START_X + i *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y) this. counterRects[i] = nextID; nextID = this.nextIndex++; this. counterIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, COUNTER_ARRAY_ELEM_START_X + i *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, CountingSort.COUNTER_ARRAY_ELEM_START_X + i *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + CountingSort.COUNTER_ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); } this.animationManager.StartNewAnimation(this. commands); @@ -161,17 +161,17 @@ CountingSort.prototype.countingSortCallback = function(event) var animatedCircleID2 = this.nextIndex++; var animatedCircleID3 = this.nextIndex++; var animatedCircleID4 = this.nextIndex++; - for (var i = 0; i < COUNTER_ARRAY_SIZE; i++) + for (var i = 0; i < CountingSort.COUNTER_ARRAY_SIZE; i++) { this. counterData[i] = 0; this.cmd("SetText", this. counterRects[i], 0); } - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < CountingSort.ARRAY_SIZE; i++) { - this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); var index = this.arrayData[i]; - this.cmd("Move", animatedCircleID, COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID, CountingSort.COUNTER_ARRAY_ELEM_START_X + index *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + CountingSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); this. counterData[index]++; this.cmd("SetText", this. counterRects[this.arrayData[i]], this. counterData[this.arrayData[i]]); @@ -180,7 +180,7 @@ CountingSort.prototype.countingSortCallback = function(event) this.cmd("Delete", animatedCircleID); this.cmd("Delete", animatedCircleID2); } - for (i=1; i < COUNTER_ARRAY_SIZE; i++) + for (i=1; i < CountingSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetHighlight", this. counterRects[i-1], 1); this.cmd("SetHighlight", this. counterRects[i], 1); @@ -191,33 +191,33 @@ CountingSort.prototype.countingSortCallback = function(event) this.cmd("SetHighlight", this. counterRects[i-1], 0); this.cmd("SetHighlight", this. counterRects[i], 0); } - for (i=ARRAY_SIZE - 1; i >= 0; i--) + for (i=CountingSort.ARRAY_SIZE - 1; i >= 0; i--) { this.cmd("SetAlpha", this. arrayRects[i], 1.0); } - for (i=ARRAY_SIZE - 1; i >= 0; i--) + for (i=CountingSort.ARRAY_SIZE - 1; i >= 0; i--) { - this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); index = this.arrayData[i]; - this.cmd("Move", animatedCircleID2, COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID2, CountingSort.COUNTER_ARRAY_ELEM_START_X + index *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + CountingSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); var insertIndex = --this. counterData[this.arrayData[i]]; this.cmd("SetText", this. counterRects[this.arrayData[i]], this. counterData[this.arrayData[i]]); this.cmd("Step"); - this.cmd("CreateHighlightCircle", animatedCircleID3, "#AAAAFF", COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID4, "#AAAAFF", COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID3, "#AAAAFF", CountingSort.COUNTER_ARRAY_ELEM_START_X + index *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID4, "#AAAAFF", CountingSort.COUNTER_ARRAY_ELEM_START_X + index *CountingSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); - this.cmd("Move", animatedCircleID4, ARRAY_ELEM_START_X + insertIndex * ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID4, CountingSort.ARRAY_ELEM_START_X + insertIndex * CountingSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + CountingSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); var moveLabel = this.nextIndex++; this.cmd("SetText", this. arrayRects[i], ""); - this.cmd("CreateLabel", moveLabel, this.arrayData[i], ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("Move", moveLabel, ARRAY_ELEM_START_X + insertIndex *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); + this.cmd("CreateLabel", moveLabel, this.arrayData[i], CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("Move", moveLabel, CountingSort.ARRAY_ELEM_START_X + insertIndex *CountingSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); this. swapData[insertIndex] = this.arrayData[i]; this.cmd("Step"); this.cmd("Delete", moveLabel); @@ -229,12 +229,12 @@ CountingSort.prototype.countingSortCallback = function(event) this.cmd("Delete", animatedCircleID4); } - for (i= 0; i < ARRAY_SIZE; i++) + for (i= 0; i < CountingSort.ARRAY_SIZE; i++) { this.cmd("SetText", this. arrayRects[i], ""); } - for (i= 0; i < COUNTER_ARRAY_SIZE; i++) + for (i= 0; i < CountingSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetAlpha", this. counterRects[i], 0.05); this.cmd("SetAlpha", this. counterIndices[i], 0.05); @@ -242,21 +242,21 @@ CountingSort.prototype.countingSortCallback = function(event) this.cmd("Step"); var startLab = this.nextIndex; - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < CountingSort.ARRAY_SIZE; i++) { - this.cmd("CreateLabel", startLab+i, this. swapData[i], ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); - this.cmd("Move", startLab+i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateLabel", startLab+i, this. swapData[i], CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); + this.cmd("Move", startLab+i, CountingSort.ARRAY_ELEM_START_X + i *CountingSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); this.cmd("SetText", this. swapRects[i], ""); } this.cmd("Step"); - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < CountingSort.ARRAY_SIZE; i++) { this.arrayData[i] = this. swapData[i]; this.cmd("SetText", this. arrayRects[i], this.arrayData[i]); this.cmd("Delete", startLab + i); } - for (i= 0; i < COUNTER_ARRAY_SIZE; i++) + for (i= 0; i < CountingSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetAlpha", this. counterRects[i], 1); this.cmd("SetAlpha", this. counterIndices[i], 1); @@ -268,13 +268,13 @@ CountingSort.prototype.countingSortCallback = function(event) CountingSort.prototype.randomizeArray = function() { this. commands = new Array(); - for (var i = 0; i < ARRAY_SIZE; i++) + for (var i = 0; i < CountingSort.ARRAY_SIZE; i++) { - this.arrayData[i] = Math.floor(1 + Math.random()*MAX_DATA_VALUE); + this.arrayData[i] = Math.floor(1 + Math.random()*CountingSort.MAX_DATA_VALUE); this.cmd("SetText", this. arrayRects[i], this.arrayData[i]); } - for (i = 0; i < COUNTER_ARRAY_SIZE; i++) + for (i = 0; i < CountingSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetText", this. counterRects[i], ""); } diff --git a/AlgorithmLibrary/DFS.js b/AlgorithmLibrary/DFS.js index abe64da..605cf4a 100644 --- a/AlgorithmLibrary/DFS.js +++ b/AlgorithmLibrary/DFS.js @@ -25,21 +25,21 @@ // or implied, of the University of San Francisco -var AUX_ARRAY_WIDTH = 25; -var AUX_ARRAY_HEIGHT = 25; -var AUX_ARRAY_START_Y = 50; +DFS.AUX_ARRAY_WIDTH = 25; +DFS.AUX_ARRAY_HEIGHT = 25; +DFS.AUX_ARRAY_START_Y = 50; -var VISITED_START_X = 475; -var PARENT_START_X = 400; +DFS.VISITED_START_X = 475; +DFS.PARENT_START_X = 400; -var HIGHLIGHT_CIRCLE_COLOR = "#000000"; -var DFS_TREE_COLOR = "#0000FF"; -var BFS_QUEUE_HEAD_COLOR = "#0000FF"; +DFS.HIGHLIGHT_CIRCLE_COLOR = "#000000"; +DFS.DFS_TREE_COLOR = "#0000FF"; +DFS.BFS_QUEUE_HEAD_COLOR = "#0000FF"; -var QUEUE_START_X = 30; -var QUEUE_START_Y = 50; -var QUEUE_SPACING = 30; +DFS.QUEUE_START_X = 30; +DFS.QUEUE_START_Y = 50; +DFS.QUEUE_SPACING = 30; function DFS(am, w, h) @@ -84,16 +84,16 @@ DFS.prototype.setup = function() this.visitedIndexID[i] = this.nextIndex++; this.parentID[i] = this.nextIndex++; this.parentIndexID[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.visitedID[i], "f", AUX_ARRAY_WIDTH, AUX_ARRAY_HEIGHT, VISITED_START_X, AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("CreateLabel", this.visitedIndexID[i], i, VISITED_START_X - AUX_ARRAY_WIDTH , AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("SetForegroundColor", this.visitedIndexID[i], VERTEX_INDEX_COLOR); - this.cmd("CreateRectangle", this.parentID[i], "", AUX_ARRAY_WIDTH, AUX_ARRAY_HEIGHT, PARENT_START_X, AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("CreateLabel", this.parentIndexID[i], i, PARENT_START_X - AUX_ARRAY_WIDTH , AUX_ARRAY_START_Y + i*AUX_ARRAY_HEIGHT); - this.cmd("SetForegroundColor", this.parentIndexID[i], VERTEX_INDEX_COLOR); + this.cmd("CreateRectangle", this.visitedID[i], "f", DFS.AUX_ARRAY_WIDTH, DFS.AUX_ARRAY_HEIGHT, DFS.VISITED_START_X, DFS.AUX_ARRAY_START_Y + i*DFS.AUX_ARRAY_HEIGHT); + this.cmd("CreateLabel", this.visitedIndexID[i], i, DFS.VISITED_START_X - DFS.AUX_ARRAY_WIDTH , DFS.AUX_ARRAY_START_Y + i*DFS.AUX_ARRAY_HEIGHT); + this.cmd("SetForegroundColor", this.visitedIndexID[i], DFS.VERTEX_INDEX_COLOR); + this.cmd("CreateRectangle", this.parentID[i], "", DFS.AUX_ARRAY_WIDTH, DFS.AUX_ARRAY_HEIGHT, DFS.PARENT_START_X, DFS.AUX_ARRAY_START_Y + i*DFS.AUX_ARRAY_HEIGHT); + this.cmd("CreateLabel", this.parentIndexID[i], i, DFS.PARENT_START_X - DFS.AUX_ARRAY_WIDTH , DFS.AUX_ARRAY_START_Y + i*DFS.AUX_ARRAY_HEIGHT); + this.cmd("SetForegroundColor", this.parentIndexID[i], DFS.VERTEX_INDEX_COLOR); } - this.cmd("CreateLabel", this.nextIndex++, "Parent", PARENT_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); - this.cmd("CreateLabel", this.nextIndex++, "Visited", VISITED_START_X - AUX_ARRAY_WIDTH, AUX_ARRAY_START_Y - AUX_ARRAY_HEIGHT * 1.5, 0); + this.cmd("CreateLabel", this.nextIndex++, "Parent", DFS.PARENT_START_X - DFS.AUX_ARRAY_WIDTH, DFS.AUX_ARRAY_START_Y - DFS.AUX_ARRAY_HEIGHT * 1.5, 0); + this.cmd("CreateLabel", this.nextIndex++, "Visited", DFS.VISITED_START_X - DFS.AUX_ARRAY_WIDTH, DFS.AUX_ARRAY_START_Y - DFS.AUX_ARRAY_HEIGHT * 1.5, 0); this.animationManager.setAllLayers([0, this.currentLayer]); this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); @@ -138,12 +138,12 @@ DFS.prototype.doDFS = function(startVetex) this.visited[i] = false; } var vertex = parseInt(startVetex); - this.cmd("CreateHighlightCircle", this.highlightCircleL, HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); + this.cmd("CreateHighlightCircle", this.highlightCircleL, DFS.HIGHLIGHT_CIRCLE_COLOR, this.x_pos_logical[vertex], this.y_pos_logical[vertex]); this.cmd("SetLayer", this.highlightCircleL, 1); - this.cmd("CreateHighlightCircle", this.highlightCircleAL, HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAL, DFS.HIGHLIGHT_CIRCLE_COLOR,this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + vertex*this.adj_list_height); this.cmd("SetLayer", this.highlightCircleAL, 2); - this.cmd("CreateHighlightCircle", this.highlightCircleAM, HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); + this.cmd("CreateHighlightCircle", this.highlightCircleAM, DFS.HIGHLIGHT_CIRCLE_COLOR,this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + vertex*this.adj_matrix_height); this.cmd("SetLayer", this.highlightCircleAM, 3); this.messageY = 30; @@ -190,7 +190,7 @@ DFS.prototype.dfsVisit = function(startVertex, messageX) if (!this.visited[neighbor]) { this.cmd("Disconnect", this.circleID[startVertex], this.circleID[neighbor]); - this.cmd("Connect", this.circleID[startVertex], this.circleID[neighbor], DFS_TREE_COLOR, this.curve[startVertex][neighbor], 1, ""); + this.cmd("Connect", this.circleID[startVertex], this.circleID[neighbor], DFS.DFS_TREE_COLOR, this.curve[startVertex][neighbor], 1, ""); this.cmd("Move", this.highlightCircleL, this.x_pos_logical[neighbor], this.y_pos_logical[neighbor]); this.cmd("Move", this.highlightCircleAL, this.adj_list_x_start - this.adj_list_width, this.adj_list_y_start + neighbor*this.adj_list_height); this.cmd("Move", this.highlightCircleAM, this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + neighbor*this.adj_matrix_height); diff --git a/AlgorithmLibrary/DijkstraPrim.js b/AlgorithmLibrary/DijkstraPrim.js index 417bf0d..b476cb6 100644 --- a/AlgorithmLibrary/DijkstraPrim.js +++ b/AlgorithmLibrary/DijkstraPrim.js @@ -25,17 +25,17 @@ // or implied, of the University of San Francisco -var TABLE_ENTRY_WIDTH = 50; -var TABLE_ENTRY_HEIGHT = 25; -var TABLE_START_X = 50; -var TABLE_START_Y = 80; +DijkstraPrim.TABLE_ENTRY_WIDTH = 50; +DijkstraPrim.TABLE_ENTRY_HEIGHT = 25; +DijkstraPrim.TABLE_START_X = 50; +DijkstraPrim.TABLE_START_Y = 80; -var MESSAGE_LABEL_1_X = 20; -var MESSAGE_LABEL_1_Y = 10; +DijkstraPrim.MESSAGE_LABEL_1_X = 20; +DijkstraPrim.MESSAGE_LABEL_1_Y = 10; -var HIGHLIGHT_CIRCLE_COLOR = "#000000"; +DijkstraPrim.HIGHLIGHT_CIRCLE_COLOR = "#000000"; @@ -84,7 +84,7 @@ DijkstraPrim.prototype.setup = function() DijkstraPrim.superclass.setup.call(this); this.commands = new Array(); - this.cmd("CreateLabel", this.message1ID, "", MESSAGE_LABEL_1_X, MESSAGE_LABEL_1_Y, 0); + this.cmd("CreateLabel", this.message1ID, "", DijkstraPrim.MESSAGE_LABEL_1_X, DijkstraPrim.MESSAGE_LABEL_1_Y, 0); this.vertexID = new Array(this.size); @@ -103,17 +103,17 @@ DijkstraPrim.prototype.setup = function() this.knownID[i] = this.nextIndex++; this.distanceID[i] = this.nextIndex++; this.pathID[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.vertexID[i], i, TABLE_ENTRY_WIDTH, TABLE_ENTRY_HEIGHT, TABLE_START_X, TABLE_START_Y + i*TABLE_ENTRY_HEIGHT); - this.cmd("CreateRectangle", this.knownID[i], "", TABLE_ENTRY_WIDTH, TABLE_ENTRY_HEIGHT, TABLE_START_X + TABLE_ENTRY_WIDTH, TABLE_START_Y + i*TABLE_ENTRY_HEIGHT); - this.cmd("CreateRectangle", this.distanceID[i], "", TABLE_ENTRY_WIDTH, TABLE_ENTRY_HEIGHT, TABLE_START_X + 2 * TABLE_ENTRY_WIDTH, TABLE_START_Y + i*TABLE_ENTRY_HEIGHT); - this.cmd("CreateRectangle", this.pathID[i], "", TABLE_ENTRY_WIDTH, TABLE_ENTRY_HEIGHT, TABLE_START_X+ 3 * TABLE_ENTRY_WIDTH, TABLE_START_Y + i*TABLE_ENTRY_HEIGHT); - this.cmd("SetTextColor", this.vertexID[i], VERTEX_INDEX_COLOR); + this.cmd("CreateRectangle", this.vertexID[i], i, DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_ENTRY_HEIGHT, DijkstraPrim.TABLE_START_X, DijkstraPrim.TABLE_START_Y + i*DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateRectangle", this.knownID[i], "", DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_ENTRY_HEIGHT, DijkstraPrim.TABLE_START_X + DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y + i*DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateRectangle", this.distanceID[i], "", DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_ENTRY_HEIGHT, DijkstraPrim.TABLE_START_X + 2 * DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y + i*DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateRectangle", this.pathID[i], "", DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_ENTRY_HEIGHT, DijkstraPrim.TABLE_START_X+ 3 * DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y + i*DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("SetTextColor", this.vertexID[i], DijkstraPrim.VERTEX_INDEX_COLOR); } - this.cmd("CreateLabel", this.nextIndex++, "Vertex", TABLE_START_X, TABLE_START_Y - TABLE_ENTRY_HEIGHT); - this.cmd("CreateLabel", this.nextIndex++, "Known", TABLE_START_X + TABLE_ENTRY_WIDTH, TABLE_START_Y - TABLE_ENTRY_HEIGHT); - this.cmd("CreateLabel", this.nextIndex++, "Cost", TABLE_START_X + 2 * TABLE_ENTRY_WIDTH, TABLE_START_Y - TABLE_ENTRY_HEIGHT); - this.cmd("CreateLabel", this.nextIndex++, "Path", TABLE_START_X + 3 * TABLE_ENTRY_WIDTH, TABLE_START_Y - TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", this.nextIndex++, "Vertex", DijkstraPrim.TABLE_START_X, DijkstraPrim.TABLE_START_Y - DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", this.nextIndex++, "Known", DijkstraPrim.TABLE_START_X + DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y - DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", this.nextIndex++, "Cost", DijkstraPrim.TABLE_START_X + 2 * DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y - DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", this.nextIndex++, "Path", DijkstraPrim.TABLE_START_X + 3 * DijkstraPrim.TABLE_ENTRY_WIDTH, DijkstraPrim.TABLE_START_Y - DijkstraPrim.TABLE_ENTRY_HEIGHT); this.animationManager.setAllLayers([0, this.currentLayer]); this.animationManager.StartNewAnimation(this.commands); @@ -225,7 +225,7 @@ DijkstraPrim.prototype.doDijkstraPrim = function(startVertex) { this.cmd("CreateLabel", this.comparisonMessageID,"Vertex " + String(neighbor) + " known", - TABLE_START_X + 5 * TABLE_ENTRY_WIDTH,TABLE_START_Y + neighbor*TABLE_ENTRY_HEIGHT); + DijkstraPrim.TABLE_START_X + 5 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + neighbor*DijkstraPrim.TABLE_ENTRY_HEIGHT); this.cmd("SetHighlight", this.knownID[neighbor], 1); } else @@ -242,12 +242,12 @@ DijkstraPrim.prototype.doDijkstraPrim = function(startVertex) if (this.distance[neighbor] < 0 || this.distance[neighbor] > this.distance[current] + this.adj_matrix[current][neighbor]) { this.cmd("CreateLabel", this.comparisonMessageID, distString + " > " + String(this.distance[current]) + " + " + String(this.adj_matrix[current][neighbor]), - TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + neighbor*TABLE_ENTRY_HEIGHT); + DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + neighbor*DijkstraPrim.TABLE_ENTRY_HEIGHT); } else { this.cmd("CreateLabel", this.comparisonMessageID,"!(" + String(this.distance[neighbor]) + " > " + String(this.distance[current]) + " + " + String(this.adj_matrix[current][neighbor]) + ")", - TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + neighbor*TABLE_ENTRY_HEIGHT); + DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + neighbor*DijkstraPrim.TABLE_ENTRY_HEIGHT); } } @@ -256,12 +256,12 @@ DijkstraPrim.prototype.doDijkstraPrim = function(startVertex) if (this.distance[neighbor] < 0 || this.distance[neighbor] > this.adj_matrix[current][neighbor]) { this.cmd("CreateLabel", this.comparisonMessageID, distString + " > " + String(this.adj_matrix[current][neighbor]), - TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + neighbor*TABLE_ENTRY_HEIGHT); + DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + neighbor*DijkstraPrim.TABLE_ENTRY_HEIGHT); } else { this.cmd("CreateLabel", this.comparisonMessageID,"!(" + String(this.distance[neighbor]) + " > " + String(this.adj_matrix[current][neighbor]) + ")", - TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + neighbor*TABLE_ENTRY_HEIGHT); + DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + neighbor*DijkstraPrim.TABLE_ENTRY_HEIGHT); } @@ -329,12 +329,12 @@ DijkstraPrim.prototype.createPaths = function() var nextLabelID = this.nextIndex++; if (this.distance[vertex] < 0) { - this.cmd("CreateLabel", nextLabelID, "No Path", TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + vertex*TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", nextLabelID, "No Path", DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + vertex*DijkstraPrim.TABLE_ENTRY_HEIGHT); this.messageID.push(nextLabelID); } else { - this.cmd("CreateLabel", nextLabelID, vertex, TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + vertex*TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", nextLabelID, vertex, DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + vertex*DijkstraPrim.TABLE_ENTRY_HEIGHT); this.messageID.push(nextLabelID); var pathList = [nextLabelID]; var nextInPath = vertex; @@ -345,12 +345,12 @@ DijkstraPrim.prototype.createPaths = function() if (this.path[nextInPath] != -1) { nextLabelID = this.nextIndex++; - this.cmd("CreateLabel", nextLabelID, this.path[nextInPath], TABLE_START_X + 3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + nextInPath*TABLE_ENTRY_HEIGHT); - this.cmd("Move", nextLabelID, TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH,TABLE_START_Y + vertex*TABLE_ENTRY_HEIGHT); + this.cmd("CreateLabel", nextLabelID, this.path[nextInPath], DijkstraPrim.TABLE_START_X + 3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + nextInPath*DijkstraPrim.TABLE_ENTRY_HEIGHT); + this.cmd("Move", nextLabelID, DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH,DijkstraPrim.TABLE_START_Y + vertex*DijkstraPrim.TABLE_ENTRY_HEIGHT); this.messageID.push(nextLabelID); for (var i = pathList.length - 1; i >= 0; i--) { - this.cmd("Move", pathList[i], TABLE_START_X + 4.3 * TABLE_ENTRY_WIDTH + (pathList.length - i) * 17,TABLE_START_Y + vertex*TABLE_ENTRY_HEIGHT) + this.cmd("Move", pathList[i], DijkstraPrim.TABLE_START_X + 4.3 * DijkstraPrim.TABLE_ENTRY_WIDTH + (pathList.length - i) * 17,DijkstraPrim.TABLE_START_Y + vertex*DijkstraPrim.TABLE_ENTRY_HEIGHT) } this.cmd("Step"); diff --git a/AlgorithmLibrary/DisjointSet.js b/AlgorithmLibrary/DisjointSet.js index a6a5cc1..621d022 100644 --- a/AlgorithmLibrary/DisjointSet.js +++ b/AlgorithmLibrary/DisjointSet.js @@ -25,25 +25,25 @@ // or implied, of the University of San Francisco -var ARRAY_START_X = 50; -var ARRAY_WIDTH = 30; -var ARRAY_HEIGHT = 30; +DisjointSet.ARRAY_START_X = 50; +DisjointSet.ARRAY_WIDTH = 30; +DisjointSet.ARRAY_HEIGHT = 30; -var TREE_START_X = 50; -var TREE_ELEM_WIDTH = 50; -var TREE_ELEM_HEIGHT = 50; +DisjointSet.TREE_START_X = 50; +DisjointSet.TREE_ELEM_WIDTH = 50; +DisjointSet.TREE_ELEM_HEIGHT = 50; var SIZE = 16; -var LINK_COLOR = "#007700" -var HIGHLIGHT_CIRCLE_COLOR = "#007700"; -var FOREGROUND_COLOR = "#007700"; -var BACKGROUND_COLOR = "#EEFFEE"; -var PRINT_COLOR = FOREGROUND_COLOR; +DisjointSet.LINK_COLOR = "#007700" +DisjointSet.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +DisjointSet.FOREGROUND_COLOR = "#007700"; +DisjointSet.BACKGROUND_COLOR = "#EEFFEE"; +DisjointSet.PRINT_COLOR = DisjointSet.FOREGROUND_COLOR; function DisjointSet(am, w, h) { - this.array_start_y = h - 2 * ARRAY_HEIGHT; + this.array_start_y = h - 2 * DisjointSet.ARRAY_HEIGHT; this.tree_start_y = this.array_start_y - 50; this.init(am); @@ -155,13 +155,13 @@ DisjointSet.prototype.setup = function() for (var i = 0; i < SIZE; i++) { - this.cmd("CreateRectangle", this.arrayID[i], this.setData[i], ARRAY_WIDTH, ARRAY_HEIGHT, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y); - this.cmd("CreateLabel",this.arrayLabelID[i], i, ARRAY_START_X + i *ARRAY_WIDTH, this.array_start_y + ARRAY_HEIGHT); + this.cmd("CreateRectangle", this.arrayID[i], this.setData[i], DisjointSet.ARRAY_WIDTH, DisjointSet.ARRAY_HEIGHT, DisjointSet.ARRAY_START_X + i *DisjointSet.ARRAY_WIDTH, this.array_start_y); + this.cmd("CreateLabel",this.arrayLabelID[i], i, DisjointSet.ARRAY_START_X + i *DisjointSet.ARRAY_WIDTH, this.array_start_y + DisjointSet.ARRAY_HEIGHT); this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); - this.cmd("CreateCircle", this.treeID[i], i, TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); - this.cmd("SetForegroundColor", this.treeID[i], FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.treeID[i], BACKGROUND_COLOR); + this.cmd("CreateCircle", this.treeID[i], i, DisjointSet.TREE_START_X + this.treeIndexToLocation[i] * DisjointSet.TREE_ELEM_WIDTH, this.treeY[i]); + this.cmd("SetForegroundColor", this.treeID[i], DisjointSet.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.treeID[i], DisjointSet.BACKGROUND_COLOR); } @@ -416,7 +416,7 @@ DisjointSet.prototype.clearAll = function() this.treeIndexToLocation[i] = i; this.locationToTreeIndex[i] = i; this.treeY[i] = this.tree_start_y; - this.cmd("SetPosition", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); + this.cmd("SetPosition", this.treeID[i], DisjointSet.TREE_START_X + this.treeIndexToLocation[i] * DisjointSet.TREE_ELEM_WIDTH, this.treeY[i]); } @@ -462,7 +462,7 @@ DisjointSet.prototype.doFind = function(elem) this.cmd("SetText", this.arrayID[elem], this.setData[elem]); this.cmd("Connect", this.treeID[elem], this.treeID[treeRoot], - FOREGROUND_COLOR, + DisjointSet.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -551,11 +551,11 @@ DisjointSet.prototype.doUnion = function(value) var args = value.split(";"); var arg1 = this.doFind(parseInt(args[0])); - this.cmd("CreateHighlightCircle", this.highlight1ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg1] * TREE_ELEM_WIDTH, this.treeY[arg1]); + this.cmd("CreateHighlightCircle", this.highlight1ID, DisjointSet.HIGHLIGHT_CIRCLE_COLOR, DisjointSet.TREE_START_X + this.treeIndexToLocation[arg1] * DisjointSet.TREE_ELEM_WIDTH, this.treeY[arg1]); var arg2 = this.doFind(parseInt(args[1])); - this.cmd("CreateHighlightCircle", this.highlight2ID, HIGHLIGHT_CIRCLE_COLOR, TREE_START_X + this.treeIndexToLocation[arg2] * TREE_ELEM_WIDTH, this.treeY[arg2]); + this.cmd("CreateHighlightCircle", this.highlight2ID, DisjointSet.HIGHLIGHT_CIRCLE_COLOR, DisjointSet.TREE_START_X + this.treeIndexToLocation[arg2] * DisjointSet.TREE_ELEM_WIDTH, this.treeY[arg2]); if (arg1 == arg2) @@ -603,7 +603,7 @@ DisjointSet.prototype.doUnion = function(value) this.cmd("Connect", this.treeID[arg1], this.treeID[arg2], - FOREGROUND_COLOR, + DisjointSet.FOREGROUND_COLOR, 0, // Curve 1, // Directed ""); // Label @@ -662,7 +662,7 @@ DisjointSet.prototype.adjustHeights = function() } for (i = 0; i < SIZE; i++) { - var newY = this.tree_start_y - this.heights[i] * TREE_ELEM_HEIGHT; + var newY = this.tree_start_y - this.heights[i] * DisjointSet.TREE_ELEM_HEIGHT; if (this.treeY[i] != newY) { this.treeY[i] = newY; @@ -677,7 +677,7 @@ DisjointSet.prototype.animateNewPositions = function() { for (var i = 0; i < SIZE; i++) { - this.cmd("Move", this.treeID[i], TREE_START_X + this.treeIndexToLocation[i] * TREE_ELEM_WIDTH, this.treeY[i]); + this.cmd("Move", this.treeID[i], DisjointSet.TREE_START_X + this.treeIndexToLocation[i] * DisjointSet.TREE_ELEM_WIDTH, this.treeY[i]); } } diff --git a/AlgorithmLibrary/Floyd.js b/AlgorithmLibrary/Floyd.js index d1d4d19..df66de3 100644 --- a/AlgorithmLibrary/Floyd.js +++ b/AlgorithmLibrary/Floyd.js @@ -120,7 +120,7 @@ Floyd.prototype.reset = function() Floyd.prototype.smallGraphCallback = function (event) { - if (this.size != SMALL_SIZE) + if (this.size != Graph.SMALL_SIZE) { this.animationManager.resetAll(); this.animationManager.setAllLayers([0,this.currentLayer]); @@ -133,7 +133,7 @@ Floyd.prototype.smallGraphCallback = function (event) Graph.prototype.largeGraphCallback = function (event) { - if (this.size != LARGE_SIZE) + if (this.size != Graph.LARGE_SIZE) { this.animationManager.resetAll(); //this.animationManager.setAllLayers([0]); @@ -154,7 +154,7 @@ Floyd.prototype.getCostLabel = function(value, alwaysUseINF) { return String(value); } - else if (this.size == SMALL_SIZE || alwaysUseINF) + else if (this.size == Graph.SMALL_SIZE || alwaysUseINF) { return "INF"; } @@ -283,7 +283,7 @@ Floyd.prototype.setup = function() this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); this.animationManager.clearHistory(); - if (this.size == LARGE_SIZE) + if (this.size == Graph.LARGE_SIZE) { this.animationManager.setAllLayers([0]); } diff --git a/AlgorithmLibrary/Graph.js b/AlgorithmLibrary/Graph.js index e547e1c..e5237f8 100644 --- a/AlgorithmLibrary/Graph.js +++ b/AlgorithmLibrary/Graph.js @@ -38,7 +38,7 @@ function Graph(am, w, h, dir, dag) Graph.inheritFrom(Algorithm); -var LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, false, false, false, false, false, true, false, false, false], +Graph.LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, false, false, false, false, false, true, false, false, false], [true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false], [true, true, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false], [false, false, true, false, false,false, true, false, false, false, true, false, false, false, false, false, false, true], @@ -57,7 +57,7 @@ var LARGE_ALLOWED = [[false, true, true, false, true, false, false, true, false, [false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true], [false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, true, true, false]]; -var LARGE_CURVE = [[0, 0, -0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, 0, 0, 0], +Graph.LARGE_CURVE = [[0, 0, -0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.25], @@ -78,21 +78,21 @@ var LARGE_CURVE = [[0, 0, -0.4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, 0, 0, 0] -var LARGE_X_POS_LOGICAL = [600, 700, 800, 900, +Graph.LARGE_X_POS_LOGICAL = [600, 700, 800, 900, 650, 750, 850, 600, 700, 800, 900, 650, 750, 850, 600, 700, 800, 900]; -var LARGE_Y_POS_LOGICAL = [50, 50, 50, 50, +Graph.LARGE_Y_POS_LOGICAL = [50, 50, 50, 50, 150, 150, 150, 250, 250, 250, 250, 350, 350, 350, 450, 450, 450, 450]; -var SMALL_ALLLOWED = [[false, true, true, true, true, false, false, false], +Graph.SMALL_ALLLOWED = [[false, true, true, true, true, false, false, false], [true, false, true, true, false, true, true, false], [true, true, false, false, true, true, true, false], [true, true, false, false, false, true, false, true], @@ -101,7 +101,7 @@ var SMALL_ALLLOWED = [[false, true, true, true, true, false, false, false], [false, true, true, false, true, true, false, true], [false, false, false, true, true, true, true, false]]; -var SMALL_CURVE = [[0, 0.001, 0, 0.5, -0.5, 0, 0, 0], +Graph.SMALL_CURVE = [[0, 0.001, 0, 0.5, -0.5, 0, 0, 0], [0, 0, 0, 0.001, 0, 0.001, -0.2, 0], [0, 0.001, 0, 0, 0, 0.2, 0, 0], [-0.5, 0, 0, 0, 0, 0.001, 0, 0.5], @@ -110,52 +110,52 @@ var SMALL_CURVE = [[0, 0.001, 0, 0.5, -0.5, 0, 0, 0], [0, 0.2, 0, 0, 0, 0, 0, 0], [0, 0, 0, -0.5, 0.5, 0, 0, 0]] -var SMALL_X_POS_LOGICAL = [800, 725, 875, 650, 950, 725, 875, 800]; -var SMALL_Y_POS_LOGICAL = [25, 125, 125, 225, 225, 325, 325, 425]; +Graph.SMALL_X_POS_LOGICAL = [800, 725, 875, 650, 950, 725, 875, 800]; +Graph.SMALL_Y_POS_LOGICAL = [25, 125, 125, 225, 225, 325, 325, 425]; -var SMALL_ADJ_MATRIX_X_START = 700; -var SMALL_ADJ_MATRIX_Y_START = 40; -var SMALL_ADJ_MATRIX_WIDTH = 30; -var SMALL_ADJ_MATRIX_HEIGHT = 30; +Graph.SMALL_ADJ_MATRIX_X_START = 700; +Graph.SMALL_ADJ_MATRIX_Y_START = 40; +Graph.SMALL_ADJ_MATRIX_WIDTH = 30; +Graph.SMALL_ADJ_MATRIX_HEIGHT = 30; -var SMALL_ADJ_LIST_X_START = 600; -var SMALL_ADJ_LIST_Y_START = 30; +Graph.SMALL_ADJ_LIST_X_START = 600; +Graph.SMALL_ADJ_LIST_Y_START = 30; -var SMALL_ADJ_LIST_ELEM_WIDTH = 50; -var SMALL_ADJ_LIST_ELEM_HEIGHT = 30; +Graph.SMALL_ADJ_LIST_ELEM_WIDTH = 50; +Graph.SMALL_ADJ_LIST_ELEM_HEIGHT = 30; -var SMALL_ADJ_LIST_HEIGHT = 36; -var SMALL_ADJ_LIST_WIDTH = 36; +Graph.SMALL_ADJ_LIST_HEIGHT = 36; +Graph.SMALL_ADJ_LIST_WIDTH = 36; -var SMALL_ADJ_LIST_SPACING = 10; +Graph.SMALL_ADJ_LIST_SPACING = 10; -var LARGE_ADJ_MATRIX_X_START = 575; -var LARGE_ADJ_MATRIX_Y_START = 30; -var LARGE_ADJ_MATRIX_WIDTH = 23; -var LARGE_ADJ_MATRIX_HEIGHT = 23; +Graph.LARGE_ADJ_MATRIX_X_START = 575; +Graph.LARGE_ADJ_MATRIX_Y_START = 30; +Graph.LARGE_ADJ_MATRIX_WIDTH = 23; +Graph.LARGE_ADJ_MATRIX_HEIGHT = 23; -var LARGE_ADJ_LIST_X_START = 600; -var LARGE_ADJ_LIST_Y_START = 30; +Graph.LARGE_ADJ_LIST_X_START = 600; +Graph.LARGE_ADJ_LIST_Y_START = 30; -var LARGE_ADJ_LIST_ELEM_WIDTH = 50; -var LARGE_ADJ_LIST_ELEM_HEIGHT = 26; +Graph.LARGE_ADJ_LIST_ELEM_WIDTH = 50; +Graph.LARGE_ADJ_LIST_ELEM_HEIGHT = 26; -var LARGE_ADJ_LIST_HEIGHT = 30; -var LARGE_ADJ_LIST_WIDTH = 30; +Graph.LARGE_ADJ_LIST_HEIGHT = 30; +Graph.LARGE_ADJ_LIST_WIDTH = 30; -var LARGE_ADJ_LIST_SPACING = 10; +Graph.LARGE_ADJ_LIST_SPACING = 10; -var VERTEX_INDEX_COLOR ="#0000FF"; -var EDGE_COLOR = "#000000"; +Graph.VERTEX_INDEX_COLOR ="#0000FF"; +Graph.EDGE_COLOR = "#000000"; -var SMALL_SIZE = 8; -var LARGE_SIZE = 18; +Graph.SMALL_SIZE = 8; +Graph.LARGE_SIZE = 18; -var HIGHLIGHT_COLOR = "#0000FF"; +Graph.HIGHLIGHT_COLOR = "#0000FF"; @@ -235,7 +235,7 @@ Graph.prototype.directedGraphCallback = function (newDirected, event) Graph.prototype.smallGraphCallback = function (event) { - if (this.size != SMALL_SIZE) + if (this.size != Graph.SMALL_SIZE) { this.animationManager.resetAll(); this.setup_small(); @@ -244,7 +244,7 @@ Graph.prototype.smallGraphCallback = function (event) Graph.prototype.largeGraphCallback = function (event) { - if (this.size != LARGE_SIZE) + if (this.size != Graph.LARGE_SIZE) { this.animationManager.resetAll(); this.setup_large(); @@ -275,7 +275,7 @@ Graph.prototype.recolorGraph = function() { if (this.adj_matrix[i][j] >= 0) { - this.setEdgeColor(i, j, EDGE_COLOR); + this.setEdgeColor(i, j, Graph.EDGE_COLOR); } } } @@ -348,11 +348,11 @@ Graph.prototype.buildEdges = function() } if (this.directed) { - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.adjustCurveForDirectedEdges(this.curve[i][j], this.adj_matrix[j][i] >= 0), 1, edgeLabel); + this.cmd("Connect", this.circleID[i], this.circleID[j], Graph.EDGE_COLOR, this.adjustCurveForDirectedEdges(this.curve[i][j], this.adj_matrix[j][i] >= 0), 1, edgeLabel); } else if (i < j) { - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); + this.cmd("Connect", this.circleID[i], this.circleID[j], Graph.EDGE_COLOR, this.curve[i][j], 0, edgeLabel); } } } @@ -362,43 +362,43 @@ Graph.prototype.buildEdges = function() Graph.prototype.setup_small = function() { - this.allowed = SMALL_ALLLOWED; - this.curve = SMALL_CURVE; - this. x_pos_logical = SMALL_X_POS_LOGICAL; - this. y_pos_logical = SMALL_Y_POS_LOGICAL; - this.adj_matrix_x_start = SMALL_ADJ_MATRIX_X_START; - this.adj_matrix_y_start = SMALL_ADJ_MATRIX_Y_START; - this.adj_matrix_width = SMALL_ADJ_MATRIX_WIDTH; - this.adj_matrix_height = SMALL_ADJ_MATRIX_HEIGHT; - this.adj_list_x_start = SMALL_ADJ_LIST_X_START; - this.adj_list_y_start = SMALL_ADJ_LIST_Y_START; - this.adj_list_elem_width = SMALL_ADJ_LIST_ELEM_WIDTH; - this.adj_list_elem_height = SMALL_ADJ_LIST_ELEM_HEIGHT; - this.adj_list_height = SMALL_ADJ_LIST_HEIGHT; - this.adj_list_width = SMALL_ADJ_LIST_WIDTH; - this.adj_list_spacing = SMALL_ADJ_LIST_SPACING; - this.size = SMALL_SIZE; + this.allowed = Graph.SMALL_ALLLOWED; + this.curve = Graph.SMALL_CURVE; + this. x_pos_logical = Graph.SMALL_X_POS_LOGICAL; + this. y_pos_logical = Graph.SMALL_Y_POS_LOGICAL; + this.adj_matrix_x_start = Graph.SMALL_ADJ_MATRIX_X_START; + this.adj_matrix_y_start = Graph.SMALL_ADJ_MATRIX_Y_START; + this.adj_matrix_width = Graph.SMALL_ADJ_MATRIX_WIDTH; + this.adj_matrix_height = Graph.SMALL_ADJ_MATRIX_HEIGHT; + this.adj_list_x_start = Graph.SMALL_ADJ_LIST_X_START; + this.adj_list_y_start = Graph.SMALL_ADJ_LIST_Y_START; + this.adj_list_elem_width = Graph.SMALL_ADJ_LIST_ELEM_WIDTH; + this.adj_list_elem_height = Graph.SMALL_ADJ_LIST_ELEM_HEIGHT; + this.adj_list_height = Graph.SMALL_ADJ_LIST_HEIGHT; + this.adj_list_width = Graph.SMALL_ADJ_LIST_WIDTH; + this.adj_list_spacing = Graph.SMALL_ADJ_LIST_SPACING; + this.size = Graph.SMALL_SIZE; this.setup(); } Graph.prototype.setup_large = function() { - this.allowed = LARGE_ALLOWED; - this.curve = LARGE_CURVE; - this. x_pos_logical = LARGE_X_POS_LOGICAL; - this. y_pos_logical = LARGE_Y_POS_LOGICAL; - this.adj_matrix_x_start = LARGE_ADJ_MATRIX_X_START; - this.adj_matrix_y_start = LARGE_ADJ_MATRIX_Y_START; - this.adj_matrix_width = LARGE_ADJ_MATRIX_WIDTH; - this.adj_matrix_height = LARGE_ADJ_MATRIX_HEIGHT; - this.adj_list_x_start = LARGE_ADJ_LIST_X_START; - this.adj_list_y_start = LARGE_ADJ_LIST_Y_START; - this.adj_list_elem_width = LARGE_ADJ_LIST_ELEM_WIDTH; - this.adj_list_elem_height = LARGE_ADJ_LIST_ELEM_HEIGHT; - this.adj_list_height = LARGE_ADJ_LIST_HEIGHT; - this.adj_list_width = LARGE_ADJ_LIST_WIDTH; - this.adj_list_spacing = LARGE_ADJ_LIST_SPACING; - this.size = LARGE_SIZE; + this.allowed = Graph.LARGE_ALLOWED; + this.curve = Graph.LARGE_CURVE; + this. x_pos_logical = Graph.LARGE_X_POS_LOGICAL; + this. y_pos_logical = Graph.LARGE_Y_POS_LOGICAL; + this.adj_matrix_x_start = Graph.LARGE_ADJ_MATRIX_X_START; + this.adj_matrix_y_start = Graph.LARGE_ADJ_MATRIX_Y_START; + this.adj_matrix_width = Graph.LARGE_ADJ_MATRIX_WIDTH; + this.adj_matrix_height = Graph.LARGE_ADJ_MATRIX_HEIGHT; + this.adj_list_x_start = Graph.LARGE_ADJ_LIST_X_START; + this.adj_list_y_start = Graph.LARGE_ADJ_LIST_Y_START; + this.adj_list_elem_width = Graph.LARGE_ADJ_LIST_ELEM_WIDTH; + this.adj_list_elem_height = Graph.LARGE_ADJ_LIST_ELEM_HEIGHT; + this.adj_list_height = Graph.LARGE_ADJ_LIST_HEIGHT; + this.adj_list_width = Graph.LARGE_ADJ_LIST_WIDTH; + this.adj_list_spacing = Graph.LARGE_ADJ_LIST_SPACING; + this.size = Graph.LARGE_SIZE; this.setup(); } @@ -423,7 +423,7 @@ Graph.prototype.setup = function() { this.circleID[i] = this.nextIndex++; this.cmd("CreateCircle", this.circleID[i], i, this. x_pos_logical[i], this. y_pos_logical[i]); - this.cmd("SetTextColor", this.circleID[i], VERTEX_INDEX_COLOR, 0); + this.cmd("SetTextColor", this.circleID[i], Graph.VERTEX_INDEX_COLOR, 0); this.cmd("SetLayer", this.circleID[i], 1); } @@ -437,7 +437,7 @@ Graph.prototype.setup = function() } var edgePercent; - if (this.size == SMALL_SIZE) + if (this.size == Graph.SMALL_SIZE) { if (this.directed) { @@ -522,7 +522,7 @@ Graph.prototype.setup = function() { edgeLabel = ""; } - this.cmd("Connect", this.circleID[i], this.circleID[j], EDGE_COLOR, this.curve[i][j], 0, edgeLabel); + this.cmd("Connect", this.circleID[i], this.circleID[j], Graph.EDGE_COLOR, this.curve[i][j], 0, edgeLabel); } else { @@ -578,9 +578,9 @@ Graph.prototype.buildAdjMatrix = function() this.adj_matrix_index_x[i] = this.nextIndex++; this.adj_matrix_index_y[i] = this.nextIndex++; this.cmd("CreateLabel", this.adj_matrix_index_x[i], i, this.adj_matrix_x_start + i*this.adj_matrix_width, this.adj_matrix_y_start - this.adj_matrix_height); - this.cmd("SetForegroundColor", this.adj_matrix_index_x[i], VERTEX_INDEX_COLOR); + this.cmd("SetForegroundColor", this.adj_matrix_index_x[i], Graph.VERTEX_INDEX_COLOR); this.cmd("CreateLabel", this.adj_matrix_index_y[i], i, this.adj_matrix_x_start - this.adj_matrix_width, this.adj_matrix_y_start + i* this.adj_matrix_height); - this.cmd("SetForegroundColor", this.adj_matrix_index_y[i], VERTEX_INDEX_COLOR); + this.cmd("SetForegroundColor", this.adj_matrix_index_y[i], Graph.VERTEX_INDEX_COLOR); this.cmd("SetLayer", this.adj_matrix_index_x[i], 3); this.cmd("SetLayer", this.adj_matrix_index_y[i], 3); @@ -639,7 +639,7 @@ Graph.prototype.buildAdjList = function() this.cmd("CreateRectangle", this.adj_list_list[i], "", this.adj_list_width, this.adj_list_height, this.adj_list_x_start, this.adj_list_y_start + i*this.adj_list_height); this.cmd("SetLayer", this.adj_list_list[i], 2); this.cmd("CreateLabel", this.adj_list_index[i], i, this.adj_list_x_start - this.adj_list_width , this.adj_list_y_start + i*this.adj_list_height); - this.cmd("SetForegroundColor", this.adj_list_index[i], VERTEX_INDEX_COLOR); + this.cmd("SetForegroundColor", this.adj_list_index[i], Graph.VERTEX_INDEX_COLOR); this.cmd("SetLayer", this.adj_list_index[i], 2); var lastElem = this.adj_list_list[i]; var nextXPos = this.adj_list_x_start + this.adj_list_width + this.adj_list_spacing; @@ -654,7 +654,7 @@ Graph.prototype.buildAdjList = function() nextXPos, this.adj_list_y_start + i*this.adj_list_height, 0.25, 0, 1, 2); this.cmd("SetNull", this.adj_list_edges[i][j], 1); this.cmd("SetText", this.adj_list_edges[i][j], this.adj_matrix[i][j], 1); - this.cmd("SetTextColor", this.adj_list_edges[i][j], VERTEX_INDEX_COLOR, 0); + this.cmd("SetTextColor", this.adj_list_edges[i][j], Graph.VERTEX_INDEX_COLOR, 0); this.cmd("SetLayer", this.adj_list_edges[i][j], 2); nextXPos = nextXPos + this.adj_list_elem_width + this.adj_list_spacing; diff --git a/AlgorithmLibrary/Hash.js b/AlgorithmLibrary/Hash.js index bdda260..9114fae 100644 --- a/AlgorithmLibrary/Hash.js +++ b/AlgorithmLibrary/Hash.js @@ -35,25 +35,25 @@ function Hash(am, w, h) } Hash.inheritFrom(Algorithm); -var MAX_HASH_LENGTH = 10; +Hash.MAX_HASH_LENGTH = 10; -var HASH_NUMBER_START_X = 200; -var HASH_X_DIFF = 7; -var HASH_NUMBER_START_Y = 10; -var HASH_ADD_START_Y = 30; -var HASH_INPUT_START_X = 60; -var HASH_INPUT_X_DIFF = 7; -var HASH_INPUT_START_Y = 45; -var HASH_ADD_LINE_Y = 42; -var HASH_RESULT_Y = 50; -var ELF_HASH_SHIFT = 10; +Hash.HASH_NUMBER_START_X = 200; +Hash.HASH_X_DIFF = 7; +Hash.HASH_NUMBER_START_Y = 10; +Hash.HASH_ADD_START_Y = 30; +Hash.HASH_INPUT_START_X = 60; +Hash.HASH_INPUT_X_DIFF = 7; +Hash.HASH_INPUT_START_Y = 45; +Hash.HASH_ADD_LINE_Y = 42; +Hash.HASH_RESULT_Y = 50; +Hash.ELF_HASH_SHIFT = 10; -var HASH_LABEL_X = 300; -var HASH_LABEL_Y = 30; -var HASH_LABEL_DELTA_X = 50; +Hash.HASH_LABEL_X = 300; +Hash.HASH_LABEL_Y = 30; +Hash.HASH_LABEL_DELTA_X = 50; -var HIGHLIGHT_COLOR = "#0000FF"; +Hash.HIGHLIGHT_COLOR = "#0000FF"; @@ -71,21 +71,21 @@ Hash.prototype.init = function(am, w, h) Hash.prototype.addControls = function() { this.insertField = this.addControlToAlgorithmBar("Text", ""); - this.insertField.size = MAX_HASH_LENGTH; - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), MAX_HASH_LENGTH, true); + this.insertField.size = Hash.MAX_HASH_LENGTH; + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), Hash.MAX_HASH_LENGTH, true); this.insertButton = this.addControlToAlgorithmBar("Button", "Insert"); this.insertButton.onclick = this.insertCallback.bind(this); this.deleteField = this.addControlToAlgorithmBar("Text", ""); - this.deleteField.size = MAX_HASH_LENGTH; - this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), MAX_HASH_LENGTH, true); + this.deleteField.size = Hash.MAX_HASH_LENGTH; + this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), Hash.MAX_HASH_LENGTH, true); this.deleteButton = this.addControlToAlgorithmBar("Button", "Delete"); this.deleteButton.onclick = this.deleteCallback.bind(this); this.findField = this.addControlToAlgorithmBar("Text", ""); - this.findField.size = MAX_HASH_LENGTH; - this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), MAX_HASH_LENGTH, true); + this.findField.size = Hash.MAX_HASH_LENGTH; + this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), Hash.MAX_HASH_LENGTH, true); this.findButton = this.addControlToAlgorithmBar("Button", "Find"); this.findButton.onclick = this.findCallback.bind(this); @@ -120,16 +120,16 @@ Hash.prototype.changeHashType = function(newHashingIntegerValue) if (this.hashingIntegers) { this.hashIntegerButton.checked = true; - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), MAX_HASH_LENGTH, true); - this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), MAX_HASH_LENGTH, true); - this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), MAX_HASH_LENGTH, true); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), Hash.MAX_HASH_LENGTH, true); + this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), Hash.MAX_HASH_LENGTH, true); + this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), Hash.MAX_HASH_LENGTH, true); } else { this.hashStringButton.checked = true; - this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), MAX_HASH_LENGTH, false); - this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), MAX_HASH_LENGTH, false); - this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), MAX_HASH_LENGTH, false); + this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), Hash.MAX_HASH_LENGTH, false); + this.deleteField.onkeydown = this.returnSubmit(this.insertField, this.deleteCallback.bind(this), Hash.MAX_HASH_LENGTH, false); + this.findField.onkeydown = this.returnSubmit(this.insertField, this.findCallback.bind(this), Hash.MAX_HASH_LENGTH, false); } return this.resetAll(); } @@ -145,10 +145,10 @@ Hash.prototype.doHash = function(input) var index = parseInt(input) % this.table_size; this.currHash = parseInt(input); - this.cmd("CreateLabel", labelID1, input + " % " + String(this.table_size) + " = " , HASH_LABEL_X, HASH_LABEL_Y); - this.cmd("CreateLabel", labelID2,index, HASH_LABEL_X + HASH_LABEL_DELTA_X, HASH_LABEL_Y); + this.cmd("CreateLabel", labelID1, input + " % " + String(this.table_size) + " = " , Hash.HASH_LABEL_X, Hash.HASH_LABEL_Y); + this.cmd("CreateLabel", labelID2,index, Hash.HASH_LABEL_X + Hash.HASH_LABEL_DELTA_X, Hash.HASH_LABEL_Y); this.cmd("Step"); - this.cmd("CreateHighlightCircle", highlightID, HIGHLIGHT_COLOR, HASH_LABEL_X + HASH_LABEL_DELTA_X, HASH_LABEL_Y); + this.cmd("CreateHighlightCircle", highlightID, Hash.HIGHLIGHT_COLOR, Hash.HASH_LABEL_X + Hash.HASH_LABEL_DELTA_X, Hash.HASH_LABEL_Y); this.cmd("Move", highlightID, this.indexXPos[index], this.indexYPos[index]); this.cmd("Step"); this.cmd("Delete", labelID1); @@ -170,7 +170,7 @@ Hash.prototype.doHash = function(input) { wordToHashID[i] = this.nextIndex++; wordToHash[i] = input.charAt(i); - this.cmd("CreateLabel", wordToHashID[i], wordToHash[i], HASH_INPUT_START_X + i * HASH_INPUT_X_DIFF, HASH_INPUT_START_Y, 0); + this.cmd("CreateLabel", wordToHashID[i], wordToHash[i], Hash.HASH_INPUT_START_X + i * Hash.HASH_INPUT_X_DIFF, Hash.HASH_INPUT_START_Y, 0); } var digits = new Array(32); var hashValue = new Array(32); @@ -201,7 +201,7 @@ Hash.prototype.doHash = function(input) { for (j = 0; j < 32; j++) { - this.cmd("CreateLabel", digits[j],hashValue[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_NUMBER_START_Y, 0); + this.cmd("CreateLabel", digits[j],hashValue[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y, 0); } this.cmd("Delete", wordToHashID[i]); var nextChar = wordToHash[i].charCodeAt(0); @@ -209,12 +209,12 @@ Hash.prototype.doHash = function(input) { nextByte[j] = nextChar % 2; nextChar = Math.floor((nextChar / 2)); - this.cmd("CreateLabel", nextByteID[j], nextByte[j], HASH_INPUT_START_X + i*HASH_INPUT_X_DIFF, HASH_INPUT_START_Y, 0); - this.cmd("Move", nextByteID[j], HASH_NUMBER_START_X + (j + 24) * HASH_X_DIFF, HASH_ADD_START_Y); + this.cmd("CreateLabel", nextByteID[j], nextByte[j], Hash.HASH_INPUT_START_X + i*Hash.HASH_INPUT_X_DIFF, Hash.HASH_INPUT_START_Y, 0); + this.cmd("Move", nextByteID[j], Hash.HASH_NUMBER_START_X + (j + 24) * Hash.HASH_X_DIFF, Hash.HASH_ADD_START_Y); } this.cmd("Step"); - this.cmd("CreateRectangle", barID, "", 32 * HASH_X_DIFF, 0, HASH_NUMBER_START_X, HASH_ADD_LINE_Y,"left","bottom"); - this.cmd("CreateLabel", operatorID, "+", HASH_NUMBER_START_X, HASH_ADD_START_Y, 0); + this.cmd("CreateRectangle", barID, "", 32 * Hash.HASH_X_DIFF, 0, Hash.HASH_NUMBER_START_X, Hash.HASH_ADD_LINE_Y,"left","bottom"); + this.cmd("CreateLabel", operatorID, "+", Hash.HASH_NUMBER_START_X, Hash.HASH_ADD_START_Y, 0); this.cmd("Step"); var carry = 0; @@ -246,7 +246,7 @@ Hash.prototype.doHash = function(input) } for (j = 0; j < 32; j++) { - this.cmd("CreateLabel", resultDigits[j], hashValue[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_RESULT_Y, 0); + this.cmd("CreateLabel", resultDigits[j], hashValue[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_RESULT_Y, 0); } this.cmd("Step"); @@ -259,14 +259,14 @@ Hash.prototype.doHash = function(input) for (j = 0; j<32; j++) { this.cmd("Delete", digits[j]); - this.cmd("Move", resultDigits[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_NUMBER_START_Y) + this.cmd("Move", resultDigits[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y) } this.cmd("Step"); if (i > 0) { for (j = 0; j < 32; j++) { - this.cmd("Move", resultDigits[j], HASH_NUMBER_START_X + (j - 4) * HASH_X_DIFF, HASH_NUMBER_START_Y) + this.cmd("Move", resultDigits[j], Hash.HASH_NUMBER_START_X + (j - 4) * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y) } this.cmd("Step"); for (j = 0; j < 28; j++) @@ -277,20 +277,20 @@ Hash.prototype.doHash = function(input) for (j = 0; j < 4; j++) { - this.cmd("Move", resultDigits[j], HASH_NUMBER_START_X + (j + ELF_HASH_SHIFT) * HASH_X_DIFF, HASH_ADD_START_Y); + this.cmd("Move", resultDigits[j], Hash.HASH_NUMBER_START_X + (j + Hash.ELF_HASH_SHIFT) * Hash.HASH_X_DIFF, Hash.HASH_ADD_START_Y); hashValue[j+28] = 0; - this.cmd("CreateLabel", floatingDigits[j],0, HASH_NUMBER_START_X + (j + 28) * HASH_X_DIFF, HASH_NUMBER_START_Y,0); + this.cmd("CreateLabel", floatingDigits[j],0, Hash.HASH_NUMBER_START_X + (j + 28) * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y,0); if (floatingVals[j]) { - hashValue[j + ELF_HASH_SHIFT] = 1 - hashValue[j + ELF_HASH_SHIFT]; + hashValue[j + Hash.ELF_HASH_SHIFT] = 1 - hashValue[j + Hash.ELF_HASH_SHIFT]; } } - this.cmd("CreateRectangle", barID, "", 32 * HASH_X_DIFF, 0, HASH_NUMBER_START_X, HASH_ADD_LINE_Y,"left","bottom"); - this.cmd("CreateLabel", operatorID, "XOR", HASH_NUMBER_START_X, HASH_ADD_START_Y, 0); + this.cmd("CreateRectangle", barID, "", 32 * Hash.HASH_X_DIFF, 0, Hash.HASH_NUMBER_START_X, Hash.HASH_ADD_LINE_Y,"left","bottom"); + this.cmd("CreateLabel", operatorID, "XOR", Hash.HASH_NUMBER_START_X, Hash.HASH_ADD_START_Y, 0); this.cmd("Step"); for (j = 0; j < 32; j++) { - this.cmd("CreateLabel", digits[j], hashValue[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_RESULT_Y, 0); + this.cmd("CreateLabel", digits[j], hashValue[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_RESULT_Y, 0); } this.cmd("Step"); @@ -299,7 +299,7 @@ Hash.prototype.doHash = function(input) for (j = 0; j<32; j++) { this.cmd("Delete", resultDigits[j]); - this.cmd("Move", digits[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_NUMBER_START_Y) + this.cmd("Move", digits[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y) } for (j = 0; j < 4; j++) { @@ -323,14 +323,14 @@ Hash.prototype.doHash = function(input) this.cmd("Delete", label1); for (j = 0; j < 32; j++) { - this.cmd("CreateLabel", digits[j],hashValue[j], HASH_NUMBER_START_X + j * HASH_X_DIFF, HASH_NUMBER_START_Y, 0); + this.cmd("CreateLabel", digits[j],hashValue[j], Hash.HASH_NUMBER_START_X + j * Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y, 0); } this.currHash = 0; for (j=0; j < 32; j++) { this.currHash = this.currHash * 2 + hashValue[j]; } - this.cmd("CreateLabel", label1, " = " + String(this.currHash), HASH_NUMBER_START_X + 32*HASH_X_DIFF, HASH_NUMBER_START_Y, 0); + this.cmd("CreateLabel", label1, " = " + String(this.currHash), Hash.HASH_NUMBER_START_X + 32*Hash.HASH_X_DIFF, Hash.HASH_NUMBER_START_Y, 0); this.cmd("Step"); for (j = 0; j < 32; j++) { @@ -340,10 +340,10 @@ Hash.prototype.doHash = function(input) var label2 = this.nextIndex++; this.cmd("SetText", label1, String(this.currHash) + " % " + String(this.table_size) + " = "); index = this.currHash % this.table_size; - this.cmd("CreateLabel", label2, index, HASH_NUMBER_START_X + 32*HASH_X_DIFF + 105, HASH_NUMBER_START_Y, 0); + this.cmd("CreateLabel", label2, index, Hash.HASH_NUMBER_START_X + 32*Hash.HASH_X_DIFF + 105, Hash.HASH_NUMBER_START_Y, 0); this.cmd("Step"); highlightID = this.nextIndex++; - this.cmd("CreateHighlightCircle", highlightID, HIGHLIGHT_COLOR, HASH_NUMBER_START_X + 30*HASH_X_DIFF + 120, HASH_NUMBER_START_Y+ 15); + this.cmd("CreateHighlightCircle", highlightID, Hash.HIGHLIGHT_COLOR, Hash.HASH_NUMBER_START_X + 30*Hash.HASH_X_DIFF + 120, Hash.HASH_NUMBER_START_Y+ 15); this.cmd("Move", highlightID, this.indexXPos[index], this.indexYPos[index]); this.cmd("Step"); this.cmd("Delete", highlightID); diff --git a/AlgorithmLibrary/Heap.js b/AlgorithmLibrary/Heap.js index 531bf90..d14f967 100644 --- a/AlgorithmLibrary/Heap.js +++ b/AlgorithmLibrary/Heap.js @@ -34,13 +34,13 @@ Heap.inheritFrom(Algorithm); -var ARRAY_SIZE = 32; -var ARRAY_ELEM_WIDTH = 30; -var ARRAY_ELEM_HEIGHT = 25; -var ARRAY_INITIAL_X = 30; +Heap.ARRAY_SIZE = 32; +Heap.ARRAY_ELEM_WIDTH = 30; +Heap.ARRAY_ELEM_HEIGHT = 25; +Heap.ARRAY_INITIAL_X = 30; -var ARRAY_Y_POS = 50; -var ARRAY_LABEL_Y_POS = 70; +Heap.ARRAY_Y_POS = 50; +Heap.ARRAY_LABEL_Y_POS = 70; Heap.prototype.init = function(am) @@ -87,21 +87,21 @@ Heap.prototype.addControls = function() Heap.prototype.createArray = function() { - this.arrayData = new Array(ARRAY_SIZE); - this.arrayLabels = new Array(ARRAY_SIZE); - this.arrayRects = new Array(ARRAY_SIZE); - this.circleObjs = new Array(ARRAY_SIZE); - this.ArrayXPositions = new Array(ARRAY_SIZE); + this.arrayData = new Array(Heap.ARRAY_SIZE); + this.arrayLabels = new Array(Heap.ARRAY_SIZE); + this.arrayRects = new Array(Heap.ARRAY_SIZE); + this.circleObjs = new Array(Heap.ARRAY_SIZE); + this.ArrayXPositions = new Array(Heap.ARRAY_SIZE); this.currentHeapSize = 0; - for (var i = 0; i < ARRAY_SIZE; i++) + for (var i = 0; i < Heap.ARRAY_SIZE; i++) { - this.ArrayXPositions[i] = ARRAY_INITIAL_X + i *ARRAY_ELEM_WIDTH; + this.ArrayXPositions[i] = Heap.ARRAY_INITIAL_X + i *Heap.ARRAY_ELEM_WIDTH; this.arrayLabels[i] = this.nextIndex++; this.arrayRects[i] = this.nextIndex++; this.circleObjs[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.arrayRects[i], "", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, this.ArrayXPositions[i] , ARRAY_Y_POS) - this.cmd("CreateLabel", this.arrayLabels[i], i, this.ArrayXPositions[i], ARRAY_LABEL_Y_POS); + this.cmd("CreateRectangle", this.arrayRects[i], "", Heap.ARRAY_ELEM_WIDTH, Heap.ARRAY_ELEM_HEIGHT, this.ArrayXPositions[i] , Heap.ARRAY_Y_POS) + this.cmd("CreateLabel", this.arrayLabels[i], i, this.ArrayXPositions[i], Heap.ARRAY_LABEL_Y_POS); this.cmd("SetForegroundColor", this.arrayLabels[i], "#0000FF"); } this.cmd("SetText", this.arrayRects[0], "-INF"); @@ -169,12 +169,12 @@ Heap.prototype.swap = function(index1, index2) this.cmd("SetText", this.arrayRects[index2], ""); this.cmd("SetText", this.circleObjs[index1], ""); this.cmd("SetText", this.circleObjs[index2], ""); - this.cmd("CreateLabel", this.swapLabel1, this.arrayData[index1], this.ArrayXPositions[index1],ARRAY_Y_POS); - this.cmd("CreateLabel", this.swapLabel2, this.arrayData[index2], this.ArrayXPositions[index2],ARRAY_Y_POS); + this.cmd("CreateLabel", this.swapLabel1, this.arrayData[index1], this.ArrayXPositions[index1],Heap.ARRAY_Y_POS); + this.cmd("CreateLabel", this.swapLabel2, this.arrayData[index2], this.ArrayXPositions[index2],Heap.ARRAY_Y_POS); this.cmd("CreateLabel", this.swapLabel3, this.arrayData[index1], this.HeapXPositions[index1],this.HeapYPositions[index1]); this.cmd("CreateLabel", this.swapLabel4, this.arrayData[index2], this.HeapXPositions[index2],this.HeapYPositions[index2]); - this.cmd("Move", this.swapLabel1, this.ArrayXPositions[index2],ARRAY_Y_POS) - this.cmd("Move", this.swapLabel2, this.ArrayXPositions[index1],ARRAY_Y_POS) + this.cmd("Move", this.swapLabel1, this.ArrayXPositions[index2],Heap.ARRAY_Y_POS) + this.cmd("Move", this.swapLabel2, this.ArrayXPositions[index1],Heap.ARRAY_Y_POS) this.cmd("Move", this.swapLabel3, this.HeapXPositions[index2],this.HeapYPositions[index2]) this.cmd("Move", this.swapLabel4, this.HeapXPositions[index1],this.HeapYPositions[index1]) var tmp = this.arrayData[index1]; @@ -292,9 +292,9 @@ Heap.prototype.buildHeap = function(ignored) { this.commands = []; this.clear(); - for (var i = 1; i 1) @@ -304,7 +304,7 @@ Heap.prototype.buildHeap = function(ignored) } this.cmd("Step"); - this.currentHeapSize = ARRAY_SIZE - 1; + this.currentHeapSize = Heap.ARRAY_SIZE - 1; var nextElem = this.currentHeapSize; while(nextElem > 0) { @@ -318,7 +318,7 @@ Heap.prototype.insertElement = function(insertedValue) { this.commands = new Array(); - if (this.currentHeapSize >= ARRAY_SIZE - 1) + if (this.currentHeapSize >= Heap.ARRAY_SIZE - 1) { this.cmd("SetText", this.descriptLabel1, "Heap Full!"); return this.commands; diff --git a/AlgorithmLibrary/HeapSort.js b/AlgorithmLibrary/HeapSort.js index c4dbe59..fa6b34e 100644 --- a/AlgorithmLibrary/HeapSort.js +++ b/AlgorithmLibrary/HeapSort.js @@ -34,13 +34,13 @@ HeapSort.inheritFrom(Algorithm); -var ARRAY_SIZE = 32; -var ARRAY_ELEM_WIDTH = 30; -var ARRAY_ELEM_HEIGHT = 25; -var ARRAY_INITIAL_X = 30; +HeapSort.ARRAY_SIZE = 32; +HeapSort.ARRAY_ELEM_WIDTH = 30; +HeapSort.ARRAY_ELEM_HEIGHT = 25; +HeapSort.ARRAY_INITIAL_X = 30; -var ARRAY_Y_POS = 50; -var ARRAY_LABEL_Y_POS = 70; +HeapSort.ARRAY_Y_POS = 50; +HeapSort.ARRAY_LABEL_Y_POS = 70; HeapSort.prototype.init = function(am) @@ -82,25 +82,25 @@ HeapSort.prototype.addControls = function() HeapSort.prototype.createArray = function() { - this.arrayData = new Array(ARRAY_SIZE); - this.arrayLabels = new Array(ARRAY_SIZE); - this.arrayRects = new Array(ARRAY_SIZE); - this.circleObjs = new Array(ARRAY_SIZE); - this.ArrayXPositions = new Array(ARRAY_SIZE); - this.oldData = new Array(ARRAY_SIZE); + this.arrayData = new Array(HeapSort.ARRAY_SIZE); + this.arrayLabels = new Array(HeapSort.ARRAY_SIZE); + this.arrayRects = new Array(HeapSort.ARRAY_SIZE); + this.circleObjs = new Array(HeapSort.ARRAY_SIZE); + this.ArrayXPositions = new Array(HeapSort.ARRAY_SIZE); + this.oldData = new Array(HeapSort.ARRAY_SIZE); this.currentHeapSize = 0; - for (var i = 1; i < ARRAY_SIZE; i++) + for (var i = 1; i < HeapSort.ARRAY_SIZE; i++) { this.arrayData[i] = Math.floor(1 + Math.random()*999); this.oldData[i] = this.arrayData[i]; - this.ArrayXPositions[i] = ARRAY_INITIAL_X + i *ARRAY_ELEM_WIDTH; + this.ArrayXPositions[i] = HeapSort.ARRAY_INITIAL_X + i *HeapSort.ARRAY_ELEM_WIDTH; this.arrayLabels[i] = this.nextIndex++; this.arrayRects[i] = this.nextIndex++; this.circleObjs[i] = this.nextIndex++; - this.cmd("CreateRectangle", this.arrayRects[i], this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, this.ArrayXPositions[i] , ARRAY_Y_POS) - this.cmd("CreateLabel", this.arrayLabels[i], i - 1, this.ArrayXPositions[i], ARRAY_LABEL_Y_POS); + this.cmd("CreateRectangle", this.arrayRects[i], this.arrayData[i], HeapSort.ARRAY_ELEM_WIDTH, HeapSort.ARRAY_ELEM_HEIGHT, this.ArrayXPositions[i] , HeapSort.ARRAY_Y_POS) + this.cmd("CreateLabel", this.arrayLabels[i], i - 1, this.ArrayXPositions[i], HeapSort.ARRAY_LABEL_Y_POS); this.cmd("SetForegroundColor", this.arrayLabels[i], "#0000FF"); } this.swapLabel1 = this.nextIndex++; @@ -121,7 +121,7 @@ HeapSort.prototype.createArray = function() HeapSort.prototype.heapsortCallback = function(event) { this.commands = this.buildHeap(""); - for (var i = ARRAY_SIZE - 1; i > 1; i--) + for (var i = HeapSort.ARRAY_SIZE - 1; i > 1; i--) { this.swap(i, 1); this.cmd("SetAlpha", this.arrayRects[i], 0.2); @@ -129,7 +129,7 @@ HeapSort.prototype.heapsortCallback = function(event) this.currentHeapSize = i-1; this.pushDown(1); } - for (i = 1; i < ARRAY_SIZE; i++) + for (i = 1; i < HeapSort.ARRAY_SIZE; i++) { this.cmd("SetAlpha", this.arrayRects[i], 1); } @@ -146,7 +146,7 @@ HeapSort.prototype.randomizeCallback = function(ignored) HeapSort.prototype.randomizeArray = function() { this.commands = new Array(); - for (var i = 1; i < ARRAY_SIZE; i++) + for (var i = 1; i < HeapSort.ARRAY_SIZE; i++) { this.arrayData[i] = Math.floor(1 + Math.random()*999); this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); @@ -161,7 +161,7 @@ HeapSort.prototype.randomizeArray = function() HeapSort.prototype.reset = function() { - for (var i = 1; i < ARRAY_SIZE; i++) + for (var i = 1; i < HeapSort.ARRAY_SIZE; i++) { this.arrayData[i]= this.oldData[i]; @@ -177,12 +177,12 @@ HeapSort.prototype.swap = function(index1, index2) this.cmd("SetText", this.arrayRects[index2], ""); this.cmd("SetText", this.circleObjs[index1], ""); this.cmd("SetText", this.circleObjs[index2], ""); - this.cmd("CreateLabel", this.swapLabel1, this.arrayData[index1], this.ArrayXPositions[index1],ARRAY_Y_POS); - this.cmd("CreateLabel", this.swapLabel2, this.arrayData[index2], this.ArrayXPositions[index2],ARRAY_Y_POS); + this.cmd("CreateLabel", this.swapLabel1, this.arrayData[index1], this.ArrayXPositions[index1],HeapSort.ARRAY_Y_POS); + this.cmd("CreateLabel", this.swapLabel2, this.arrayData[index2], this.ArrayXPositions[index2],HeapSort.ARRAY_Y_POS); this.cmd("CreateLabel", this.swapLabel3, this.arrayData[index1], this.HeapXPositions[index1],this.HeapYPositions[index1]); this.cmd("CreateLabel", this.swapLabel4, this.arrayData[index2], this.HeapXPositions[index2],this.HeapYPositions[index2]); - this.cmd("Move", this.swapLabel1, this.ArrayXPositions[index2],ARRAY_Y_POS) - this.cmd("Move", this.swapLabel2, this.ArrayXPositions[index1],ARRAY_Y_POS) + this.cmd("Move", this.swapLabel1, this.ArrayXPositions[index2],HeapSort.ARRAY_Y_POS) + this.cmd("Move", this.swapLabel2, this.ArrayXPositions[index1],HeapSort.ARRAY_Y_POS) this.cmd("Move", this.swapLabel3, this.HeapXPositions[index2],this.HeapYPositions[index2]) this.cmd("Move", this.swapLabel4, this.HeapXPositions[index1],this.HeapYPositions[index1]) var tmp = this.arrayData[index1]; @@ -257,7 +257,7 @@ HeapSort.prototype.pushDown = function(index) HeapSort.prototype.buildHeap = function(ignored) { this.commands = new Array(); - for (var i = 1; i < ARRAY_SIZE; i++) + for (var i = 1; i < HeapSort.ARRAY_SIZE; i++) { this.cmd("CreateCircle", this.circleObjs[i], this.arrayData[i], this.HeapXPositions[i], this.HeapYPositions[i]); this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); @@ -268,7 +268,7 @@ HeapSort.prototype.buildHeap = function(ignored) } this.cmd("Step"); - this.currentHeapSize = ARRAY_SIZE - 1; + this.currentHeapSize = HeapSort.ARRAY_SIZE - 1; var nextElem = this.currentHeapSize; while(nextElem > 0) { diff --git a/AlgorithmLibrary/Kruskal.js b/AlgorithmLibrary/Kruskal.js index a84b288..1154f6e 100644 --- a/AlgorithmLibrary/Kruskal.js +++ b/AlgorithmLibrary/Kruskal.js @@ -99,7 +99,7 @@ Kruskal.prototype.setup = function() this.setIndexID[i] = this.nextIndex++; this.cmd("CreateRectangle", this.setID[i], "-1", Kruskal.SET_ARRAY_ELEM_WIDTH, Kruskal.SET_ARRAY_ELEM_HEIGHT, Kruskal.SET_ARRAY_START_X, Kruskal.SET_ARRAY_START_Y + i*Kruskal.SET_ARRAY_ELEM_HEIGHT); this.cmd("CreateLabel", this.setIndexID[i], i, Kruskal.SET_ARRAY_START_X - Kruskal.SET_ARRAY_ELEM_WIDTH ,Kruskal.SET_ARRAY_START_Y + i*Kruskal.SET_ARRAY_ELEM_HEIGHT); - this.cmd("SetForegroundColor", this.setIndexID[i], VERTEX_INDEX_COLOR); + this.cmd("SetForegroundColor", this.setIndexID[i], Graph.VERTEX_INDEX_COLOR); } this.cmd("CreateLabel", this.nextIndex++, "Disjoint Set", Kruskal.SET_ARRAY_START_X - 1 * Kruskal.SET_ARRAY_ELEM_WIDTH, Kruskal.SET_ARRAY_START_Y - Kruskal.SET_ARRAY_ELEM_HEIGHT * 1.5, 0); this.animationManager.setAllLayers([0, this.currentLayer]); @@ -172,7 +172,7 @@ Kruskal.prototype.doKruskal = function(ignored) Kruskal.EDGE_LIST_START_Y + (top % Kruskal.EDGE_LIST_MAX_PER_COLUMN) * Kruskal.EDGE_LIST_ELEM_HEIGHT); this.cmd("CreateLabel", this.edgesListRightID[top], j, Kruskal.EDGE_LIST_START_X +Kruskal.EDGE_LIST_ELEM_WIDTH + Math.floor(top / Kruskal.EDGE_LIST_MAX_PER_COLUMN) * Kruskal.EDGE_LIST_COLUMN_WIDTH, Kruskal.EDGE_LIST_START_Y + (top % Kruskal.EDGE_LIST_MAX_PER_COLUMN) * Kruskal.EDGE_LIST_ELEM_HEIGHT); - this.cmd("Connect", this.edgesListLeftID[top], this.edgesListRightID[top], EDGE_COLOR, 0, 0, this.adj_matrix[i][j]) + this.cmd("Connect", this.edgesListLeftID[top], this.edgesListRightID[top], Graph.EDGE_COLOR, 0, 0, this.adj_matrix[i][j]) } } } diff --git a/AlgorithmLibrary/OpenHash.js b/AlgorithmLibrary/OpenHash.js index ee4c883..e5694b6 100644 --- a/AlgorithmLibrary/OpenHash.js +++ b/AlgorithmLibrary/OpenHash.js @@ -34,24 +34,24 @@ function OpenHash(am, w, h) OpenHash.inheritFrom(Hash); -var POINTER_ARRAY_ELEM_WIDTH = 70; -var POINTER_ARRAY_ELEM_HEIGHT = 30; -var POINTER_ARRAY_ELEM_START_X = 50; +OpenHash.POINTER_ARRAY_ELEM_WIDTH = 70; +OpenHash.POINTER_ARRAY_ELEM_HEIGHT = 30; +OpenHash.POINTER_ARRAY_ELEM_START_X = 50; -var LINKED_ITEM_HEIGHT = 30; -var LINKED_ITEM_WIDTH = 65; +OpenHash.LINKED_ITEM_HEIGHT = 30; +OpenHash.LINKED_ITEM_WIDTH = 65; -var LINKED_ITEM_Y_DELTA = 50; -var LINKED_ITEM_POINTER_PERCENT = 0.25; +OpenHash.LINKED_ITEM_Y_DELTA = 50; +OpenHash.LINKED_ITEM_POINTER_PERCENT = 0.25; -var MAX_DATA_VALUE = 999; +OpenHash.MAX_DATA_VALUE = 999; -var HASH_TABLE_SIZE = 13; +OpenHash.HASH_TABLE_SIZE = 13; -var ARRAY_Y_POS = 350; +OpenHash.ARRAY_Y_POS = 350; -var INDEX_COLOR = "#0000FF"; +OpenHash.INDEX_COLOR = "#0000FF"; @@ -63,7 +63,7 @@ OpenHash.prototype.init = function(am, w, h) var fn = sc.init; fn.call(this,am, w, h); this.nextIndex = 0; - this.POINTER_ARRAY_ELEM_Y = h - POINTER_ARRAY_ELEM_WIDTH; + this.POINTER_ARRAY_ELEM_Y = h - OpenHash.POINTER_ARRAY_ELEM_WIDTH; this.setup(); } @@ -81,7 +81,7 @@ OpenHash.prototype.insertElement = function(elem) this.cmd("SetText", this.ExplainLabel, "Inserting element: " + String(elem)); var index = this.doHash(elem); var node = new LinkedListNode(elem,this.nextIndex++, 100, 75); - this.cmd("CreateLinkedList", node.graphicID, elem, LINKED_ITEM_WIDTH, LINKED_ITEM_HEIGHT, 100, 75); + this.cmd("CreateLinkedList", node.graphicID, elem, OpenHash.LINKED_ITEM_WIDTH, OpenHash.LINKED_ITEM_HEIGHT, 100, 75); if (this.hashTableValues[index] != null && this.hashTableValues[index] != undefined) { this.cmd("connect", node.graphicID, this.hashTableValues[index].graphicID); @@ -107,15 +107,15 @@ OpenHash.prototype.insertElement = function(elem) OpenHash.prototype.repositionList = function(index) { - var startX = POINTER_ARRAY_ELEM_START_X + index *POINTER_ARRAY_ELEM_WIDTH; - var startY = this.POINTER_ARRAY_ELEM_Y - LINKED_ITEM_Y_DELTA; + var startX = OpenHash.POINTER_ARRAY_ELEM_START_X + index *OpenHash.POINTER_ARRAY_ELEM_WIDTH; + var startY = this.POINTER_ARRAY_ELEM_Y - OpenHash.LINKED_ITEM_Y_DELTA; var tmp = this.hashTableValues[index]; while (tmp != null) { tmp.x = startX; tmp.y = startY; this.cmd("Move", tmp.graphicID, tmp.x, tmp.y); - startY = startY - LINKED_ITEM_Y_DELTA; + startY = startY - OpenHash.LINKED_ITEM_Y_DELTA; tmp = tmp.next; } } @@ -231,34 +231,34 @@ OpenHash.prototype.findElement = function(elem) OpenHash.prototype.setup = function() { - this.hashTableVisual = new Array(HASH_TABLE_SIZE); - this.hashTableIndices = new Array(HASH_TABLE_SIZE); - this.hashTableValues = new Array(HASH_TABLE_SIZE); + this.hashTableVisual = new Array(OpenHash.HASH_TABLE_SIZE); + this.hashTableIndices = new Array(OpenHash.HASH_TABLE_SIZE); + this.hashTableValues = new Array(OpenHash.HASH_TABLE_SIZE); - this.indexXPos = new Array(HASH_TABLE_SIZE); - this.indexYPos = new Array(HASH_TABLE_SIZE); + this.indexXPos = new Array(OpenHash.HASH_TABLE_SIZE); + this.indexYPos = new Array(OpenHash.HASH_TABLE_SIZE); this.ExplainLabel = this.nextIndex++; - this.table_size = HASH_TABLE_SIZE; + this.table_size = OpenHash.HASH_TABLE_SIZE; this.commands = []; - for (var i = 0; i < HASH_TABLE_SIZE; i++) + for (var i = 0; i < OpenHash.HASH_TABLE_SIZE; i++) { var nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID, "", POINTER_ARRAY_ELEM_WIDTH, POINTER_ARRAY_ELEM_HEIGHT, POINTER_ARRAY_ELEM_START_X + i *POINTER_ARRAY_ELEM_WIDTH, this.POINTER_ARRAY_ELEM_Y) + this.cmd("CreateRectangle", nextID, "", OpenHash.POINTER_ARRAY_ELEM_WIDTH, OpenHash.POINTER_ARRAY_ELEM_HEIGHT, OpenHash.POINTER_ARRAY_ELEM_START_X + i *OpenHash.POINTER_ARRAY_ELEM_WIDTH, this.POINTER_ARRAY_ELEM_Y) this.hashTableVisual[i] = nextID; this.cmd("SetNull", this.hashTableVisual[i], 1); nextID = this.nextIndex++; this.hashTableIndices[i] = nextID; - this.indexXPos[i] = POINTER_ARRAY_ELEM_START_X + i *POINTER_ARRAY_ELEM_WIDTH; - this.indexYPos[i] = this.POINTER_ARRAY_ELEM_Y + POINTER_ARRAY_ELEM_HEIGHT + this.indexXPos[i] = OpenHash.POINTER_ARRAY_ELEM_START_X + i *OpenHash.POINTER_ARRAY_ELEM_WIDTH; + this.indexYPos[i] = this.POINTER_ARRAY_ELEM_Y + OpenHash.POINTER_ARRAY_ELEM_HEIGHT this.hashTableValues[i] = null; this.cmd("CreateLabel", nextID, i,this.indexXPos[i],this.indexYPos[i] ); - this.cmd("SetForegroundColor", nextID, INDEX_COLOR); + this.cmd("SetForegroundColor", nextID, OpenHash.INDEX_COLOR); } this.cmd("CreateLabel", this.ExplainLabel, "", 10, 25, 0); this.animationManager.StartNewAnimation(this.commands); diff --git a/AlgorithmLibrary/RadixSort.js b/AlgorithmLibrary/RadixSort.js index 7b210fe..e6a71e6 100644 --- a/AlgorithmLibrary/RadixSort.js +++ b/AlgorithmLibrary/RadixSort.js @@ -32,22 +32,22 @@ function RadixSort(am, w, h) } -var ARRAY_ELEM_WIDTH = 30; -var ARRAY_ELEM_HEIGHT = 30; -var ARRAY_ELEM_START_X = 20; +RadixSort.ARRAY_ELEM_WIDTH = 30; +RadixSort.ARRAY_ELEM_HEIGHT = 30; +RadixSort.ARRAY_ELEM_START_X = 20; -var ARRAY_SIZE = 30; -var COUNTER_ARRAY_SIZE = 10; +RadixSort.ARRAY_SIZE = 30; +RadixSort.COUNTER_ARRAY_SIZE = 10; -var COUNTER_ARRAY_ELEM_WIDTH = 30; -var COUNTER_ARRAY_ELEM_HEIGHT = 30; -//var COUNTER_ARRAY_ELEM_START_X = 20; -var COUNTER_ARRAY_ELEM_START_X = (ARRAY_ELEM_WIDTH * ARRAY_SIZE- COUNTER_ARRAY_ELEM_WIDTH * COUNTER_ARRAY_SIZE) / 2 + ARRAY_ELEM_START_X; -var NUM_DIGITS = 3; +RadixSort.COUNTER_ARRAY_ELEM_WIDTH = 30; +RadixSort.COUNTER_ARRAY_ELEM_HEIGHT = 30; +//RadixSort.COUNTER_ARRAY_ELEM_START_X = 20; +RadixSort.COUNTER_ARRAY_ELEM_START_X = (RadixSort.ARRAY_ELEM_WIDTH * RadixSort.ARRAY_SIZE- RadixSort.COUNTER_ARRAY_ELEM_WIDTH * RadixSort.COUNTER_ARRAY_SIZE) / 2 + RadixSort.ARRAY_ELEM_START_X; +RadixSort.NUM_DIGITS = 3; -var MAX_DATA_VALUE = 999; +RadixSort.MAX_DATA_VALUE = 999; @@ -55,9 +55,9 @@ RadixSort.inheritFrom(Algorithm); RadixSort.prototype.init = function(am, w, h) { - this.ARRAY_ELEM_Y = 3 * COUNTER_ARRAY_ELEM_HEIGHT; + this.ARRAY_ELEM_Y = 3 * RadixSort.COUNTER_ARRAY_ELEM_HEIGHT; this.COUNTER_ARRAY_ELEM_Y = Math.floor(h / 2); - this.SWAP_ARRAY_ELEM_Y = h - 3 * COUNTER_ARRAY_ELEM_HEIGHT + this.SWAP_ARRAY_ELEM_Y = h - 3 * RadixSort.COUNTER_ARRAY_ELEM_HEIGHT var sc = RadixSort.superclass; var fn = sc.init; @@ -71,9 +71,9 @@ RadixSort.prototype.init = function(am, w, h) RadixSort.prototype.sizeChanged = function(newWidth, newHeight) { - this.ARRAY_ELEM_Y = 3 * COUNTER_ARRAY_ELEM_HEIGHT; + this.ARRAY_ELEM_Y = 3 * RadixSort.COUNTER_ARRAY_ELEM_HEIGHT; this.COUNTER_ARRAY_ELEM_Y = Math.floor(newHeight / 2); - this.SWAP_ARRAY_ELEM_Y = newHeight - 3 * COUNTER_ARRAY_ELEM_HEIGHT + this.SWAP_ARRAY_ELEM_Y = newHeight - 3 * RadixSort.COUNTER_ARRAY_ELEM_HEIGHT this.setup(); } @@ -91,49 +91,49 @@ RadixSort.prototype.addControls = function() RadixSort.prototype.setup = function() { - this.arrayData = new Array(ARRAY_SIZE); - this.arrayRects= new Array(ARRAY_SIZE); - this.arrayIndices = new Array(ARRAY_SIZE); + this.arrayData = new Array(RadixSort.ARRAY_SIZE); + this.arrayRects= new Array(RadixSort.ARRAY_SIZE); + this.arrayIndices = new Array(RadixSort.ARRAY_SIZE); - this.counterData = new Array(COUNTER_ARRAY_SIZE); - this.counterRects= new Array(COUNTER_ARRAY_SIZE); - this.counterIndices = new Array(COUNTER_ARRAY_SIZE); + this.counterData = new Array(RadixSort.COUNTER_ARRAY_SIZE); + this.counterRects= new Array(RadixSort.COUNTER_ARRAY_SIZE); + this.counterIndices = new Array(RadixSort.COUNTER_ARRAY_SIZE); - this.swapData = new Array(ARRAY_SIZE); - this.swapRects= new Array(ARRAY_SIZE); - this.swapIndices = new Array(ARRAY_SIZE); + this.swapData = new Array(RadixSort.ARRAY_SIZE); + this.swapRects= new Array(RadixSort.ARRAY_SIZE); + this.swapIndices = new Array(RadixSort.ARRAY_SIZE); this.commands = new Array(); - for (var i = 0; i < ARRAY_SIZE; i++) + for (var i = 0; i < RadixSort.ARRAY_SIZE; i++) { var nextID = this.nextIndex++; - this.arrayData[i] = Math.floor(Math.random()*MAX_DATA_VALUE); - this.cmd("CreateRectangle", nextID, this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y) + this.arrayData[i] = Math.floor(Math.random()*RadixSort.MAX_DATA_VALUE); + this.cmd("CreateRectangle", nextID, this.arrayData[i], RadixSort.ARRAY_ELEM_WIDTH, RadixSort.ARRAY_ELEM_HEIGHT, RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y) this.arrayRects[i] = nextID; nextID = this.nextIndex++; this.arrayIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y + ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y + RadixSort.ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID, "", ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y) + this.cmd("CreateRectangle", nextID, "", RadixSort.ARRAY_ELEM_WIDTH, RadixSort.ARRAY_ELEM_HEIGHT, RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y) this.swapRects[i] = nextID; nextID = this.nextIndex++; this.swapIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + RadixSort.ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); } - for (i = COUNTER_ARRAY_SIZE - 1; i >= 0; i--) + for (i = RadixSort.COUNTER_ARRAY_SIZE - 1; i >= 0; i--) { nextID = this.nextIndex++; - this.cmd("CreateRectangle", nextID,"", COUNTER_ARRAY_ELEM_WIDTH, COUNTER_ARRAY_ELEM_HEIGHT, COUNTER_ARRAY_ELEM_START_X + i *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y) + this.cmd("CreateRectangle", nextID,"", RadixSort.COUNTER_ARRAY_ELEM_WIDTH, RadixSort.COUNTER_ARRAY_ELEM_HEIGHT, RadixSort.COUNTER_ARRAY_ELEM_START_X + i *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y) this.counterRects[i] = nextID; nextID = this.nextIndex++; this.counterIndices[i] = nextID; - this.cmd("CreateLabel",nextID, i, COUNTER_ARRAY_ELEM_START_X + i *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT); + this.cmd("CreateLabel",nextID, i, RadixSort.COUNTER_ARRAY_ELEM_START_X + i *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + RadixSort.COUNTER_ARRAY_ELEM_HEIGHT); this.cmd("SetForegroundColor", nextID, "#0000FF"); } this.animationManager.StartNewAnimation(this.commands); @@ -158,31 +158,31 @@ RadixSort.prototype.radixSortCallback = function(event) var animatedCircleID3 = this.nextIndex++; var animatedCircleID4 = this.nextIndex++; - var digits = new Array(NUM_DIGITS); - for (var k = 0; k < NUM_DIGITS; k++) + var digits = new Array(RadixSort.NUM_DIGITS); + for (var k = 0; k < RadixSort.NUM_DIGITS; k++) { digits[k] = this.nextIndex++; } - for (var radix = 0; radix < NUM_DIGITS; radix++) + for (var radix = 0; radix < RadixSort.NUM_DIGITS; radix++) { - for (var i = 0; i < COUNTER_ARRAY_SIZE; i++) + for (var i = 0; i < RadixSort.COUNTER_ARRAY_SIZE; i++) { this.counterData[i] = 0; this.cmd("SetText", this.counterRects[i], 0); } - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < RadixSort.ARRAY_SIZE; i++) { - this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); this.cmd("SetText", this.arrayRects[i], ""); - for (k = 0; k < NUM_DIGITS; k++) + for (k = 0; k < RadixSort.NUM_DIGITS; k++) { - var digitXPos = ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH - ARRAY_ELEM_WIDTH/2 + (NUM_DIGITS - k ) * (ARRAY_ELEM_WIDTH / NUM_DIGITS - 3); + var digitXPos = RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH - RadixSort.ARRAY_ELEM_WIDTH/2 + (RadixSort.NUM_DIGITS - k ) * (RadixSort.ARRAY_ELEM_WIDTH / RadixSort.NUM_DIGITS - 3); var digitYPos = this.ARRAY_ELEM_Y; this.cmd("CreateLabel", digits[k], Math.floor(this.arrayData[i] / Math.pow(10,k)) % 10, digitXPos, digitYPos); if (k != radix) @@ -197,7 +197,7 @@ RadixSort.prototype.radixSortCallback = function(event) var index = Math.floor(this.arrayData[i] / Math.pow(10,radix)) % 10; - this.cmd("Move", animatedCircleID, COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID, RadixSort.COUNTER_ARRAY_ELEM_START_X + index *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + RadixSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); this.counterData[index]++; this.cmd("SetText", this.counterRects[index], this.counterData[index]); @@ -206,12 +206,12 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("Delete", animatedCircleID); this.cmd("Delete", animatedCircleID2); this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); - for (k = 0; k < NUM_DIGITS; k++) + for (k = 0; k < RadixSort.NUM_DIGITS; k++) { this.cmd("Delete", digits[k]); } } - for (i=1; i < COUNTER_ARRAY_SIZE; i++) + for (i=1; i < RadixSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetHighlight", this.counterRects[i-1], 1); this.cmd("SetHighlight", this.counterRects[i], 1); @@ -222,22 +222,22 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("SetHighlight", this.counterRects[i-1], 0); this.cmd("SetHighlight", this.counterRects[i], 0); } - // for (i=ARRAY_SIZE - 1; i >= 0; i--) + // for (i=RadixSort.ARRAY_SIZE - 1; i >= 0; i--) // { // this.cmd("SetAlpha", this.arrayRects[i], 1.0); // } - for (i=ARRAY_SIZE - 1; i >= 0; i--) + for (i=RadixSort.ARRAY_SIZE - 1; i >= 0; i--) { - this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID, "#0000FF", RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID2, "#0000FF", RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); this.cmd("SetText", this.arrayRects[i], ""); - for (k = 0; k < NUM_DIGITS; k++) + for (k = 0; k < RadixSort.NUM_DIGITS; k++) { digits[k] = this.nextIndex++; - digitXPos = ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH - ARRAY_ELEM_WIDTH/2 + (NUM_DIGITS - k ) * (ARRAY_ELEM_WIDTH / NUM_DIGITS - 3); + digitXPos = RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH - RadixSort.ARRAY_ELEM_WIDTH/2 + (RadixSort.NUM_DIGITS - k ) * (RadixSort.ARRAY_ELEM_WIDTH / RadixSort.NUM_DIGITS - 3); digitYPos = this.ARRAY_ELEM_Y; this.cmd("CreateLabel", digits[k], Math.floor(this.arrayData[i] / Math.pow(10,k)) % 10, digitXPos, digitYPos); if (k != radix) @@ -250,7 +250,7 @@ RadixSort.prototype.radixSortCallback = function(event) index = Math.floor(this.arrayData[i] / Math.pow(10,radix)) % 10; - this.cmd("Move", animatedCircleID2, COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID2, RadixSort.COUNTER_ARRAY_ELEM_START_X + index *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y + RadixSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); var insertIndex = --this.counterData[index]; @@ -258,19 +258,19 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("Step"); - this.cmd("CreateHighlightCircle", animatedCircleID3, "#AAAAFF", COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); - this.cmd("CreateHighlightCircle", animatedCircleID4, "#AAAAFF", COUNTER_ARRAY_ELEM_START_X + index *COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID3, "#AAAAFF", RadixSort.COUNTER_ARRAY_ELEM_START_X + index *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); + this.cmd("CreateHighlightCircle", animatedCircleID4, "#AAAAFF", RadixSort.COUNTER_ARRAY_ELEM_START_X + index *RadixSort.COUNTER_ARRAY_ELEM_WIDTH, this.COUNTER_ARRAY_ELEM_Y); - this.cmd("Move", animatedCircleID4, ARRAY_ELEM_START_X + insertIndex * ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + COUNTER_ARRAY_ELEM_HEIGHT) + this.cmd("Move", animatedCircleID4, RadixSort.ARRAY_ELEM_START_X + insertIndex * RadixSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y + RadixSort.COUNTER_ARRAY_ELEM_HEIGHT) this.cmd("Step"); var moveLabel = this.nextIndex++; this.cmd("SetText", this.arrayRects[i], ""); - this.cmd("CreateLabel", moveLabel, this.arrayData[i], ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); - this.cmd("Move", moveLabel, ARRAY_ELEM_START_X + insertIndex *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); + this.cmd("CreateLabel", moveLabel, this.arrayData[i], RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("Move", moveLabel, RadixSort.ARRAY_ELEM_START_X + insertIndex *RadixSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); this.swapData[insertIndex] = this.arrayData[i]; - for (k = 0; k < NUM_DIGITS; k++) + for (k = 0; k < RadixSort.NUM_DIGITS; k++) { this.cmd("Delete", digits[k]); } @@ -284,12 +284,12 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("Delete", animatedCircleID4); } - for (i= 0; i < ARRAY_SIZE; i++) + for (i= 0; i < RadixSort.ARRAY_SIZE; i++) { this.cmd("SetText", this.arrayRects[i], ""); } - for (i= 0; i < COUNTER_ARRAY_SIZE; i++) + for (i= 0; i < RadixSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetAlpha", this.counterRects[i], 0.05); this.cmd("SetAlpha", this.counterIndices[i], 0.05); @@ -297,21 +297,21 @@ RadixSort.prototype.radixSortCallback = function(event) this.cmd("Step"); var startLab = this.nextIndex; - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < RadixSort.ARRAY_SIZE; i++) { - this.cmd("CreateLabel", startLab+i, this.swapData[i], ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); - this.cmd("Move", startLab+i, ARRAY_ELEM_START_X + i *ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); + this.cmd("CreateLabel", startLab+i, this.swapData[i], RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.SWAP_ARRAY_ELEM_Y); + this.cmd("Move", startLab+i, RadixSort.ARRAY_ELEM_START_X + i *RadixSort.ARRAY_ELEM_WIDTH, this.ARRAY_ELEM_Y); this.cmd("SetText", this.swapRects[i], ""); } this.cmd("Step"); - for (i = 0; i < ARRAY_SIZE; i++) + for (i = 0; i < RadixSort.ARRAY_SIZE; i++) { this.arrayData[i] = this.swapData[i]; this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); this.cmd("Delete", startLab + i); } - for (i= 0; i < COUNTER_ARRAY_SIZE; i++) + for (i= 0; i < RadixSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetAlpha", this.counterRects[i], 1); this.cmd("SetAlpha", this.counterIndices[i], 1); @@ -326,13 +326,13 @@ RadixSort.prototype.radixSortCallback = function(event) RadixSort.prototype.randomizeArray = function() { this.commands = new Array(); - for (var i = 0; i < ARRAY_SIZE; i++) + for (var i = 0; i < RadixSort.ARRAY_SIZE; i++) { - this.arrayData[i] = Math.floor(1 + Math.random()*MAX_DATA_VALUE); + this.arrayData[i] = Math.floor(1 + Math.random()*RadixSort.MAX_DATA_VALUE); this.cmd("SetText", this.arrayRects[i], this.arrayData[i]); } - for (i = 0; i < COUNTER_ARRAY_SIZE; i++) + for (i = 0; i < RadixSort.COUNTER_ARRAY_SIZE; i++) { this.cmd("SetText", this.counterRects[i], ""); } diff --git a/AlgorithmLibrary/RedBlack.js b/AlgorithmLibrary/RedBlack.js index 044a558..9a1266d 100644 --- a/AlgorithmLibrary/RedBlack.js +++ b/AlgorithmLibrary/RedBlack.js @@ -40,11 +40,11 @@ RedBlack.prototype.init = function(am, w, h) this.nextIndex = 1; this.commands = []; this.startingX = w / 2; - this.print_max = w - PRINT_HORIZONTAL_GAP; - this.first_print_pos_y = h - 2 * PRINT_VERTICAL_GAP; + this.print_max = w - RedBlack.PRINT_HORIZONTAL_GAP; + this.first_print_pos_y = h - 2 * RedBlack.PRINT_VERTICAL_GAP; - this.cmd("CreateLabel", 0, "", EXPLANITORY_TEXT_X, EXPLANITORY_TEXT_Y, 0); + this.cmd("CreateLabel", 0, "", RedBlack.EXPLANITORY_TEXT_X, RedBlack.EXPLANITORY_TEXT_Y, 0); this.animationManager.StartNewAnimation(this.commands); this.animationManager.skipForward(); this.animationManager.clearHistory(); @@ -80,44 +80,44 @@ RedBlack.prototype.reset = function() this.treeRoot = null; } -var FIRST_PRINT_POS_X = 50; -var PRINT_VERTICAL_GAP = 20; -var PRINT_HORIZONTAL_GAP = 50; +RedBlack.FIRST_PRINT_POS_X = 50; +RedBlack.PRINT_VERTICAL_GAP = 20; +RedBlack.PRINT_HORIZONTAL_GAP = 50; -var FOREGROUND_RED = "#AA0000"; -var BACKGROUND_RED = "#FFAAAA"; +RedBlack.FOREGROUND_RED = "#AA0000"; +RedBlack.BACKGROUND_RED = "#FFAAAA"; -var FOREGROUND_BLACK = "#000000" -var BACKGROUND_BLACK = "#AAAAAA"; -var BACKGROUND_DOUBLE_BLACK = "#777777"; +RedBlack.FOREGROUND_BLACK = "#000000" +RedBlack.BACKGROUND_BLACK = "#AAAAAA"; +RedBlack.BACKGROUND_DOUBLE_BLACK = "#777777"; -// var HIGHLIGHT_LABEL_COLOR = RED -// var HIGHLIGHT_LINK_COLOR = RED +// var RedBlack.HIGHLIGHT_LABEL_COLOR = RED +// var RedBlack.HIGHLIGHT_LINK_COLOR = RED -var HIGHLIGHT_LABEL_COLOR = "#FF0000" -var HIGHLIGHT_LINK_COLOR = "#FF0000" +RedBlack.HIGHLIGHT_LABEL_COLOR = "#FF0000" +RedBlack.HIGHLIGHT_LINK_COLOR = "#FF0000" var BLUE = "#0000FF"; -var LINK_COLOR = "#000000" -var BACKGROUND_COLOR = BACKGROUND_BLACK; -var HIGHLIGHT_COLOR = "#007700"; -var FOREGROUND_COLOR = FOREGROUND_BLACK; -var PRINT_COLOR = FOREGROUND_COLOR +RedBlack.LINK_COLOR = "#000000" +RedBlack.BACKGROUND_COLOR = RedBlack.BACKGROUND_BLACK; +RedBlack.HIGHLIGHT_COLOR = "#007700"; +RedBlack.FOREGROUND_COLOR = RedBlack.FOREGROUND_BLACK; +RedBlack.PRINT_COLOR = RedBlack.FOREGROUND_COLOR var widthDelta = 50; var heightDelta = 50; var startingY = 50; -var FIRST_PRINT_POS_X = 40; -var PRINT_VERTICAL_GAP = 20; -var PRINT_HORIZONTAL_GAP = 50; -var EXPLANITORY_TEXT_X = 10; -var EXPLANITORY_TEXT_Y = 10; +RedBlack.FIRST_PRINT_POS_X = 40; +RedBlack.PRINT_VERTICAL_GAP = 20; +RedBlack.PRINT_HORIZONTAL_GAP = 50; +RedBlack.EXPLANITORY_TEXT_X = 10; +RedBlack.EXPLANITORY_TEXT_Y = 10; RedBlack.prototype.insertCallback = function(event) { @@ -181,8 +181,8 @@ RedBlack.prototype.printTree = function(unused) { this.highlightID = this.nextIndex++; var firstLabel = this.nextIndex; - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, this.treeRoot.x, this.treeRoot.y); - this.xPosOfNextLabel = FIRST_PRINT_POS_X; + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, this.treeRoot.x, this.treeRoot.y); + this.xPosOfNextLabel = RedBlack.FIRST_PRINT_POS_X; this.yPosOfNextLabel = this.first_print_pos_y; this.printTreeRec(this.treeRoot); this.cmd("Delete",this.highlightID); @@ -206,15 +206,15 @@ RedBlack.prototype.printTreeRec = function(tree) } var nextLabelID = this.nextIndex++; this.cmd("CreateLabel", nextLabelID, tree.data, tree.x, tree.y); - this.cmd("SetForegroundColor", nextLabelID, PRINT_COLOR); + this.cmd("SetForegroundColor", nextLabelID, RedBlack.PRINT_COLOR); this.cmd("Move", nextLabelID, this.xPosOfNextLabel, this.yPosOfNextLabel); this.cmd("Step"); - this.xPosOfNextLabel += PRINT_HORIZONTAL_GAP; + this.xPosOfNextLabel += RedBlack.PRINT_HORIZONTAL_GAP; if (this.xPosOfNextLabel > this.print_max) { - this.xPosOfNextLabel = FIRST_PRINT_POS_X; - this.yPosOfNextLabel += PRINT_VERTICAL_GAP; + this.xPosOfNextLabel = RedBlack.FIRST_PRINT_POS_X; + this.yPosOfNextLabel += RedBlack.PRINT_VERTICAL_GAP; } if (tree.right != null && !tree.right.phantomLeaf) @@ -263,7 +263,7 @@ RedBlack.prototype.doFind = function(tree, value) this.cmd("SetHighlight", tree.graphicID, 0); if (tree.left!= null) { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.left.x, tree.left.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -277,7 +277,7 @@ RedBlack.prototype.doFind = function(tree, value) this.cmd("SetHighlight", tree.graphicID, 0); if (tree.right!= null) { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.right.x, tree.right.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -343,13 +343,13 @@ RedBlack.prototype.attachLeftNullLeaf = function(node) // Add phantom left leaf var treeNodeID = this.nextIndex++; this.cmd("CreateCircle", treeNodeID, "NULL\nLEAF", node.x, node.y); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_BLACK); node.left = new RedBlackNode("", treeNodeID, this.startingX, startingY); node.left.phantomLeaf = true; this.cmd("SetLayer", treeNodeID, 1); node.left.blackLevel = 1; - this.cmd("Connect",node.graphicID, treeNodeID, LINK_COLOR); + this.cmd("Connect",node.graphicID, treeNodeID, RedBlack.LINK_COLOR); } RedBlack.prototype.attachRightNullLeaf = function(node) @@ -357,14 +357,14 @@ RedBlack.prototype.attachRightNullLeaf = function(node) // Add phantom right leaf treeNodeID = this.nextIndex++; this.cmd("CreateCircle", treeNodeID, "NULL\nLEAF", node.x, node.y); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_BLACK); node.right = new RedBlackNode("", treeNodeID, this.startingX, startingY); this.cmd("SetLayer", treeNodeID, 1); node.right.phantomLeaf = true; node.right.blackLevel = 1; - this.cmd("Connect", node.graphicID, treeNodeID, LINK_COLOR); + this.cmd("Connect", node.graphicID, treeNodeID, RedBlack.LINK_COLOR); } RedBlack.prototype.attachNullLeaves = function(node) @@ -383,8 +383,8 @@ RedBlack.prototype.insertElement = function(insertedValue) { treeNodeID = this.nextIndex++; this.cmd("CreateCircle", treeNodeID, insertedValue, this.startingX, startingY); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_BLACK); this.treeRoot = new RedBlackNode(insertedValue, treeNodeID, this.startingX, startingY); this.treeRoot.blackLevel = 1; @@ -397,8 +397,8 @@ RedBlack.prototype.insertElement = function(insertedValue) treeNodeID = this.nextIndex++; this.cmd("CreateCircle", treeNodeID, insertedValue, 30, startingY); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_RED); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_RED); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_RED); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_RED); this.cmd("Step"); var insertElem = new RedBlackNode(insertedValue, treeNodeID, 100, 100) @@ -429,11 +429,11 @@ RedBlack.prototype.singleRotateRight = function(tree) if (t2 != null) { this.cmd("Disconnect", A.graphicID, t2.graphicID); - this.cmd("Connect", B.graphicID, t2.graphicID, LINK_COLOR); + this.cmd("Connect", B.graphicID, t2.graphicID, RedBlack.LINK_COLOR); t2.parent = B; } this.cmd("Disconnect", B.graphicID, A.graphicID); - this.cmd("Connect", A.graphicID, B.graphicID, LINK_COLOR); + this.cmd("Connect", A.graphicID, B.graphicID, RedBlack.LINK_COLOR); A.parent = B.parent; if (this.treeRoot == B) @@ -442,8 +442,8 @@ RedBlack.prototype.singleRotateRight = function(tree) } else { - this.cmd("Disconnect", B.parent.graphicID, B.graphicID, LINK_COLOR); - this.cmd("Connect", B.parent.graphicID, A.graphicID, LINK_COLOR) + this.cmd("Disconnect", B.parent.graphicID, B.graphicID, RedBlack.LINK_COLOR); + this.cmd("Connect", B.parent.graphicID, A.graphicID, RedBlack.LINK_COLOR) if (B.isLeftChild()) { B.parent.left = A; @@ -479,11 +479,11 @@ RedBlack.prototype.singleRotateLeft = function(tree) if (t2 != null) { this.cmd("Disconnect", B.graphicID, t2.graphicID); - this.cmd("Connect", A.graphicID, t2.graphicID, LINK_COLOR); + this.cmd("Connect", A.graphicID, t2.graphicID, RedBlack.LINK_COLOR); t2.parent = A; } this.cmd("Disconnect", A.graphicID, B.graphicID); - this.cmd("Connect", B.graphicID, A.graphicID, LINK_COLOR); + this.cmd("Connect", B.graphicID, A.graphicID, RedBlack.LINK_COLOR); B.parent = A.parent; if (this.treeRoot == A) { @@ -491,8 +491,8 @@ RedBlack.prototype.singleRotateLeft = function(tree) } else { - this.cmd("Disconnect", A.parent.graphicID, A.graphicID, LINK_COLOR); - this.cmd("Connect", A.parent.graphicID, B.graphicID, LINK_COLOR) + this.cmd("Disconnect", A.parent.graphicID, A.graphicID, RedBlack.LINK_COLOR); + this.cmd("Connect", A.parent.graphicID, B.graphicID, RedBlack.LINK_COLOR) if (A.isLeftChild()) { @@ -566,7 +566,7 @@ RedBlack.prototype.insert = function(elem, tree) this.cmd("SetHighlight", elem.graphicID, 0); tree.left=elem; elem.parent = tree; - this.cmd("Connect", tree.graphicID, elem.graphicID, LINK_COLOR); + this.cmd("Connect", tree.graphicID, elem.graphicID, RedBlack.LINK_COLOR); this.attachNullLeaves(elem); this.resizeTree(); @@ -581,7 +581,7 @@ RedBlack.prototype.insert = function(elem, tree) } else { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.left.x, tree.left.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -602,7 +602,7 @@ RedBlack.prototype.insert = function(elem, tree) this.cmd("SetHighlight", elem.graphicID, 0); tree.right=elem; elem.parent = tree; - this.cmd("Connect", tree.graphicID, elem.graphicID, LINK_COLOR); + this.cmd("Connect", tree.graphicID, elem.graphicID, RedBlack.LINK_COLOR); elem.x = tree.x + widthDelta/2; elem.y = tree.y + heightDelta this.cmd("Move", elem.graphicID, elem.x, elem.y); @@ -617,7 +617,7 @@ RedBlack.prototype.insert = function(elem, tree) } else { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.right.x, tree.right.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -642,8 +642,8 @@ RedBlack.prototype.fixDoubleRed = function(tree) this.cmd("SetText", 0, "Tree root is red, color it black."); this.cmd("Step"); tree.parent.blackLevel = 1; - this.cmd("SetForegroundColor", tree.parent.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", tree.parent.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", tree.parent.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", tree.parent.graphicID, RedBlack.BACKGROUND_BLACK); return; } var uncle = this.findUncle(tree); @@ -652,17 +652,17 @@ RedBlack.prototype.fixDoubleRed = function(tree) this.cmd("SetText", 0, "Node and parent are both red. Uncle of node is red -- push blackness down from grandparent"); this.cmd("Step"); - this.cmd("SetForegroundColor", uncle.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor",uncle.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", uncle.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor",uncle.graphicID, RedBlack.BACKGROUND_BLACK); uncle.blackLevel = 1; tree.parent.blackLevel = 1; - this.cmd("SetForegroundColor", tree.parent.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor",tree.parent.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", tree.parent.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor",tree.parent.graphicID, RedBlack.BACKGROUND_BLACK); tree.parent.parent.blackLevel = 0; - this.cmd("SetForegroundColor", tree.parent.parent.graphicID, FOREGROUND_RED); - this.cmd("SetBackgroundColor",tree.parent.parent.graphicID, BACKGROUND_RED); + this.cmd("SetForegroundColor", tree.parent.parent.graphicID, RedBlack.FOREGROUND_RED); + this.cmd("SetBackgroundColor",tree.parent.parent.graphicID, RedBlack.BACKGROUND_RED); this.cmd("Step"); this.fixDoubleRed(tree.parent.parent); } @@ -693,12 +693,12 @@ RedBlack.prototype.fixDoubleRed = function(tree) this.singleRotateRight(tree.parent.parent); tree.parent.blackLevel = 1; - this.cmd("SetForegroundColor", tree.parent.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor",tree.parent.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", tree.parent.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor",tree.parent.graphicID, RedBlack.BACKGROUND_BLACK); tree.parent.right.blackLevel = 0; - this.cmd("SetForegroundColor", tree.parent.right.graphicID, FOREGROUND_RED); - this.cmd("SetBackgroundColor",tree.parent.right.graphicID, BACKGROUND_RED); + this.cmd("SetForegroundColor", tree.parent.right.graphicID, RedBlack.FOREGROUND_RED); + this.cmd("SetBackgroundColor",tree.parent.right.graphicID, RedBlack.BACKGROUND_RED); } @@ -709,12 +709,12 @@ RedBlack.prototype.fixDoubleRed = function(tree) this.singleRotateLeft(tree.parent.parent); tree.parent.blackLevel = 1; - this.cmd("SetForegroundColor", tree.parent.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor",tree.parent.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", tree.parent.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor",tree.parent.graphicID, RedBlack.BACKGROUND_BLACK); tree.parent.left.blackLevel = 0; - this.cmd("SetForegroundColor", tree.parent.left.graphicID, FOREGROUND_RED); - this.cmd("SetBackgroundColor",tree.parent.left.graphicID, BACKGROUND_RED); + this.cmd("SetForegroundColor", tree.parent.left.graphicID, RedBlack.FOREGROUND_RED); + this.cmd("SetBackgroundColor",tree.parent.left.graphicID, RedBlack.BACKGROUND_RED); } } @@ -728,8 +728,8 @@ RedBlack.prototype.fixDoubleRed = function(tree) this.cmd("Step"); tree.blackLevel = 1; - this.cmd("SetForegroundColor", tree.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", tree.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", tree.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", tree.graphicID, RedBlack.BACKGROUND_BLACK); } } @@ -756,14 +756,14 @@ RedBlack.prototype.fixLeftNull = function(tree) this.cmd("SetText", 0, "Coloring 'Null Leaf' double black"); this.cmd("CreateCircle", treeNodeID, "NULL\nLEAF", tree.x, tree.y); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_DOUBLE_BLACK); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_DOUBLE_BLACK); nullLeaf = new RedBlackNode("NULL\nLEAF", treeNodeID, tree.x, tree.x); nullLeaf.blackLevel = 2; nullLeaf.parent = tree; nullLeaf.phantomLeaf = true; tree.left = nullLeaf; - this.cmd("Connect", tree.graphicID, nullLeaf.graphicID, LINK_COLOR); + this.cmd("Connect", tree.graphicID, nullLeaf.graphicID, RedBlack.LINK_COLOR); this.resizeTree(); this.fixExtraBlackChild(tree, true); @@ -780,14 +780,14 @@ RedBlack.prototype.fixRightNull = function(tree) this.cmd("SetText", 0, "Coloring 'Null Leaf' double black"); this.cmd("CreateCircle", treeNodeID, "NULL\nLEAF", tree.x, tree.y); - this.cmd("SetForegroundColor", treeNodeID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", treeNodeID, BACKGROUND_DOUBLE_BLACK); + this.cmd("SetForegroundColor", treeNodeID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", treeNodeID, RedBlack.BACKGROUND_DOUBLE_BLACK); nullLeaf = new RedBlackNode("NULL\nLEAF", treeNodeID, tree.x, tree.x); nullLeaf.parent = tree; nullLeaf.phantomLeaf = true; nullLeaf.blackLevel = 2; tree.right = nullLeaf; - this.cmd("Connect", tree.graphicID, nullLeaf.graphicID, LINK_COLOR); + this.cmd("Connect", tree.graphicID, nullLeaf.graphicID, RedBlack.LINK_COLOR); this.resizeTree(); @@ -949,7 +949,7 @@ RedBlack.prototype.fixExtraBlack = function(tree) this.cmd("Step"); tree.blackLevel = 1; - this.cmd("SetBackgroundColor", tree.graphicID, BACKGROUND_BLACK); + this.cmd("SetBackgroundColor", tree.graphicID, RedBlack.BACKGROUND_BLACK); } else if (tree.parent.left == tree) { @@ -1060,7 +1060,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) if (tree.parent != null) { this.cmd("Disconnect", tree.parent.graphicID, tree.graphicID); - this.cmd("Connect", tree.parent.graphicID, tree.right.graphicID, LINK_COLOR); + this.cmd("Connect", tree.parent.graphicID, tree.right.graphicID, RedBlack.LINK_COLOR); this.cmd("Step"); this.cmd("Delete", tree.graphicID); if (leftchild) @@ -1096,8 +1096,8 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) if (this.treeRoot.blackLevel == 0) { this.treeRoot.blackLevel = 1; - this.cmd("SetForegroundColor", this.treeRoot.graphicID, FOREGROUND_BLACK); - this.cmd("SetBackgroundColor", this.treeRoot.graphicID, BACKGROUND_BLACK); + this.cmd("SetForegroundColor", this.treeRoot.graphicID, RedBlack.FOREGROUND_BLACK); + this.cmd("SetBackgroundColor", this.treeRoot.graphicID, RedBlack.BACKGROUND_BLACK); } } this.resizeTree(); @@ -1113,7 +1113,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) if (tree.parent != null) { this.cmd("Disconnect", tree.parent.graphicID, tree.graphicID); - this.cmd("Connect", tree.parent.graphicID, tree.left.graphicID, LINK_COLOR); + this.cmd("Connect", tree.parent.graphicID, tree.left.graphicID, RedBlack.LINK_COLOR); this.cmd("Step"); this.cmd("Delete", tree.graphicID); if (leftchild) @@ -1169,7 +1169,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) this.highlightID = this.nextIndex; this.nextIndex += 1; - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); var tmp = tree; tmp = tree.left; this.cmd("Move", this.highlightID, tmp.x, tmp.y); @@ -1239,7 +1239,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) else { this.cmd("Disconnect", tmp.parent.graphicID, tmp.graphicID); - this.cmd("Connect", tmp.parent.graphicID, tmp.left.graphicID, LINK_COLOR); + this.cmd("Connect", tmp.parent.graphicID, tmp.left.graphicID, RedBlack.LINK_COLOR); this.cmd("Step"); this.cmd("Delete", tmp.graphicID); @@ -1310,7 +1310,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) { if (tree.left != null) { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.left.x, tree.left.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -1321,7 +1321,7 @@ RedBlack.prototype.treeDelete = function(tree, valueToDelete) { if (tree.right != null) { - this.cmd("CreateHighlightCircle", this.highlightID, HIGHLIGHT_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, RedBlack.HIGHLIGHT_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.right.x, tree.right.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -1341,19 +1341,19 @@ RedBlack.prototype.fixNodeColor = function(tree) { if (tree.blackLevel == 0) { - this.cmd("SetForegroundColor", tree.graphicID, FOREGROUND_RED); - this.cmd("SetBackgroundColor", tree.graphicID, BACKGROUND_RED); + this.cmd("SetForegroundColor", tree.graphicID, RedBlack.FOREGROUND_RED); + this.cmd("SetBackgroundColor", tree.graphicID, RedBlack.BACKGROUND_RED); } else { - this.cmd("SetForegroundColor", tree.graphicID, FOREGROUND_BLACK); + this.cmd("SetForegroundColor", tree.graphicID, RedBlack.FOREGROUND_BLACK); if (tree.blackLevel > 1) { - this.cmd("SetBackgroundColor",tree.graphicID, BACKGROUND_DOUBLE_BLACK); + this.cmd("SetBackgroundColor",tree.graphicID, RedBlack.BACKGROUND_DOUBLE_BLACK); } else { - this.cmd("SetBackgroundColor",tree.graphicID, BACKGROUND_BLACK); + this.cmd("SetBackgroundColor",tree.graphicID, RedBlack.BACKGROUND_BLACK); } } } diff --git a/AlgorithmLibrary/Search.js b/AlgorithmLibrary/Search.js index 9097df0..0d9a6ee 100644 --- a/AlgorithmLibrary/Search.js +++ b/AlgorithmLibrary/Search.js @@ -32,74 +32,74 @@ Search.CODE_LINE_HEIGHT = 14; Search.CODE_HIGHLIGHT_COLOR = "#FF0000"; Search.CODE_STANDARD_COLOR = "#000000"; -var SMALL_SIZE = 0; -var LARGE_SIZE = 1; +Search.SMALL_SIZE = 0; +Search.LARGE_SIZE = 1; -var EXTRA_FIELD_WIDTH = 50; -var EXTRA_FIELD_HEIGHT = 50; +Search.EXTRA_FIELD_WIDTH = 50; +Search.EXTRA_FIELD_HEIGHT = 50; -var SEARCH_FOR_X = 450; -var SEARCH_FOR_Y = 30; +Search.SEARCH_FOR_X = 450; +Search.SEARCH_FOR_Y = 30; -var RESULT_X = 550; -var RESULT_Y = 30; +Search.RESULT_X = 550; +Search.RESULT_Y = 30; -var INDEX_X = 450; -var INDEX_Y = 130; +Search.INDEX_X = 450; +Search.INDEX_Y = 130; -var HIGHLIGHT_CIRCLE_SIZE_SMALL = 20; -var HIGHLIGHT_CIRCLE_SIZE_LARGE = 10; -var HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; +Search.HIGHLIGHT_CIRCLE_SIZE_SMALL = 20; +Search.HIGHLIGHT_CIRCLE_SIZE_LARGE = 10; +Search.HIGHLIGHT_CIRCLE_SIZE = Search.HIGHLIGHT_CIRCLE_SIZE_SMALL; -var LOW_CIRCLE_COLOR = "#1010FF"; -var LOW_BACKGROUND_COLOR = "#F0F0FF"; -var MID_CIRCLE_COLOR = "#118C4E"; -var MID_BACKGROUND_COLOR = "#F0FFF0"; -var HIGH_CIRCLE_COLOR = "#FF9009"; -var HIGH_BACKGROUND_COLOR = "#FFFFF0"; +Search.LOW_CIRCLE_COLOR = "#1010FF"; +Search.LOW_BACKGROUND_COLOR = "#F0F0FF"; +Search.MID_CIRCLE_COLOR = "#118C4E"; +Search.MID_BACKGROUND_COLOR = "#F0FFF0"; +Search.HIGH_CIRCLE_COLOR = "#FF9009"; +Search.HIGH_BACKGROUND_COLOR = "#FFFFF0"; -var LOW_POS_X = 350; -var LOW_POS_Y = 130; +Search.LOW_POS_X = 350; +Search.LOW_POS_Y = 130; -var MID_POS_X = 450; -var MID_POS_Y = 130; +Search.MID_POS_X = 450; +Search.MID_POS_Y = 130; -var HIGH_POS_X = 550; -var HIGH_POS_Y = 130; +Search.HIGH_POS_X = 550; +Search.HIGH_POS_Y = 130; -var ARRAY_START_X_SMALL = 100; -var ARRAY_START_X_LARGE = 100; -var ARRAY_START_X = ARRAY_START_X_SMALL; -var ARRAY_START_Y_SMALL = 240; -var ARRAY_START_Y_LARGE = 200; -var ARRAY_START_Y = ARRAY_START_Y_SMALL; -var ARRAY_ELEM_WIDTH_SMALL = 50; -var ARRAY_ELEM_WIDTH_LARGE = 25; -var ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; +Search.ARRAY_START_X_SMALL = 100; +Search.ARRAY_START_X_LARGE = 100; +Search.ARRAY_START_X = Search.ARRAY_START_X_SMALL; +Search.ARRAY_START_Y_SMALL = 240; +Search.ARRAY_START_Y_LARGE = 200; +Search.ARRAY_START_Y = Search.ARRAY_START_Y_SMALL; +Search.ARRAY_ELEM_WIDTH_SMALL = 50; +Search.ARRAY_ELEM_WIDTH_LARGE = 25; +Search.ARRAY_ELEM_WIDTH = Search.ARRAY_ELEM_WIDTH_SMALL; -var ARRAY_ELEM_HEIGHT_SMALL = 50; -var ARRAY_ELEM_HEIGHT_LARGE = 20; -var ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; +Search.ARRAY_ELEM_HEIGHT_SMALL = 50; +Search.ARRAY_ELEM_HEIGHT_LARGE = 20; +Search.ARRAY_ELEM_HEIGHT = Search.ARRAY_ELEM_HEIGHT_SMALL; -var ARRAY_ELEMS_PER_LINE_SMALL = 16; -var ARRAY_ELEMS_PER_LINE_LARGE = 30; -var ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; +Search.ARRAY_ELEMS_PER_LINE_SMALL = 16; +Search.ARRAY_ELEMS_PER_LINE_LARGE = 30; +Search.ARRAY_ELEMS_PER_LINE = Search.ARRAY_ELEMS_PER_LINE_SMALL; -var ARRAY_LINE_SPACING_LARGE = 40; -var ARRAY_LINE_SPACING_SMALL = 130; -var ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; +Search.ARRAY_LINE_SPACING_LARGE = 40; +Search.ARRAY_LINE_SPACING_SMALL = 130; +Search.ARRAY_LINE_SPACING = Search.ARRAY_LINE_SPACING_SMALL; -var SIZE_SMALL = 32; -var SIZE_LARGE = 180; -var SIZE = SIZE_SMALL; +Search.SIZE_SMALL = 32; +Search.SIZE_LARGE = 180; +var SIZE = Search.SIZE_SMALL; function Search(am, w, h) { @@ -172,7 +172,7 @@ Search.prototype.addControls = function() Search.prototype.smallListCallback = function (event) { - if (this.size != SMALL_SIZE) + if (this.size != Search.SMALL_SIZE) { this.animationManager.resetAll(); this.setup_small(); @@ -182,7 +182,7 @@ Search.prototype.smallListCallback = function (event) Search.prototype.largeListCallback = function (event) { - if (this.size != LARGE_SIZE) + if (this.size != Search.LARGE_SIZE) { this.animationManager.resetAll(); this.setup_large(); @@ -211,7 +211,7 @@ Search.prototype.disableUI = function(event) Search.prototype.getIndexX = function(index) { - var xpos = (index % ARRAY_ELEMS_PER_LINE) * ARRAY_ELEM_WIDTH + ARRAY_START_X; + var xpos = (index % Search.ARRAY_ELEMS_PER_LINE) * Search.ARRAY_ELEM_WIDTH + Search.ARRAY_START_X; return xpos; } @@ -220,7 +220,7 @@ Search.prototype.getIndexY = function(index) { if (index == -1) { index = 0; } - var ypos = Math.floor(index / ARRAY_ELEMS_PER_LINE) * ARRAY_LINE_SPACING + ARRAY_START_Y + ARRAY_ELEM_HEIGHT; + var ypos = Math.floor(index / Search.ARRAY_ELEMS_PER_LINE) * Search.ARRAY_LINE_SPACING + Search.ARRAY_START_Y + Search.ARRAY_ELEM_HEIGHT; return ypos; } @@ -257,7 +257,7 @@ Search.prototype.setup = function() { var xLabelpos = this.getIndexX(i); var yLabelpos = this.getIndexY(i); - this.cmd("CreateRectangle", this.arrayID[i],this.arrayData[i], ARRAY_ELEM_WIDTH, ARRAY_ELEM_HEIGHT,xLabelpos, yLabelpos - ARRAY_ELEM_HEIGHT); + this.cmd("CreateRectangle", this.arrayID[i],this.arrayData[i], Search.ARRAY_ELEM_WIDTH, Search.ARRAY_ELEM_HEIGHT,xLabelpos, yLabelpos - Search.ARRAY_ELEM_HEIGHT); this.cmd("CreateLabel",this.arrayLabelID[i], i, xLabelpos, yLabelpos); this.cmd("SetForegroundColor", this.arrayLabelID[i], "#0000FF"); @@ -266,21 +266,21 @@ Search.prototype.setup = function() this.movingLabelID = this.nextIndex++; this.cmd("CreateLabel",this.movingLabelID, "", 0, 0); - // this.cmd("CreateLabel", this.leftoverLabelID, "", PUSH_LABEL_X, PUSH_LABEL_Y); + // this.cmd("CreateLabel", this.leftoverLabelID, "", Search.PUSH_LABEL_X, Search.PUSH_LABEL_Y); this.searchForBoxID = this.nextIndex++; this.searchForBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.searchForBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,SEARCH_FOR_X, SEARCH_FOR_Y); - this.cmd("CreateLabel", this.searchForBoxLabel, "Seaching For ", SEARCH_FOR_X, SEARCH_FOR_Y); + this.cmd("CreateRectangle", this.searchForBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.SEARCH_FOR_X, Search.SEARCH_FOR_Y); + this.cmd("CreateLabel", this.searchForBoxLabel, "Seaching For ", Search.SEARCH_FOR_X, Search.SEARCH_FOR_Y); this.cmd("AlignLeft", this.searchForBoxLabel, this.searchForBoxID); this.resultBoxID = this.nextIndex++; this.resultBoxLabel = this.nextIndex++; this.resultString = this.nextIndex++; - this.cmd("CreateRectangle", this.resultBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,RESULT_X, RESULT_Y); - this.cmd("CreateLabel", this.resultBoxLabel, "Result ", RESULT_X, RESULT_Y); - this.cmd("CreateLabel", this.resultString, "", RESULT_X, RESULT_Y); + this.cmd("CreateRectangle", this.resultBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.RESULT_X, Search.RESULT_Y); + this.cmd("CreateLabel", this.resultBoxLabel, "Result ", Search.RESULT_X, Search.RESULT_Y); + this.cmd("CreateLabel", this.resultString, "", Search.RESULT_X, Search.RESULT_Y); this.cmd("AlignLeft", this.resultBoxLabel, this.resultBoxID); this.cmd("AlignRight", this.resultString, this.resultBoxID); this.cmd("SetTextColor", this.resultString, "#FF0000"); @@ -289,51 +289,51 @@ Search.prototype.setup = function() this.indexBoxID = this.nextIndex++; this.indexBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.indexBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,INDEX_X, INDEX_Y); - this.cmd("CreateLabel", this.indexBoxLabel, "index ", INDEX_X, INDEX_Y); + this.cmd("CreateRectangle", this.indexBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.INDEX_X, Search.INDEX_Y); + this.cmd("CreateLabel", this.indexBoxLabel, "index ", Search.INDEX_X, Search.INDEX_Y); this.cmd("AlignLeft", this.indexBoxLabel, this.indexBoxID); this.midBoxID = this.nextIndex++; this.midBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.midBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,MID_POS_X, MID_POS_Y); - this.cmd("CreateLabel", this.midBoxLabel, "mid ", MID_POS_X, MID_POS_Y); + this.cmd("CreateRectangle", this.midBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.MID_POS_X, Search.MID_POS_Y); + this.cmd("CreateLabel", this.midBoxLabel, "mid ", Search.MID_POS_X, Search.MID_POS_Y); this.cmd("AlignLeft", this.midBoxLabel, this.midBoxID); - this.cmd("SetForegroundColor", this.midBoxID, MID_CIRCLE_COLOR); - this.cmd("SetTextColor", this.midBoxID, MID_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.midBoxID, MID_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.midBoxID, Search.MID_CIRCLE_COLOR); + this.cmd("SetTextColor", this.midBoxID, Search.MID_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.midBoxID, Search.MID_BACKGROUND_COLOR); this.midCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.midCircleID, MID_CIRCLE_COLOR, 0, 0, HIGHLIGHT_CIRCLE_SIZE); + this.cmd("CreateHighlightCircle", this.midCircleID, Search.MID_CIRCLE_COLOR, 0, 0, Search.HIGHLIGHT_CIRCLE_SIZE); this.lowBoxID = this.nextIndex++; this.lowBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.lowBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,LOW_POS_X, LOW_POS_Y); - this.cmd("CreateLabel", this.lowBoxLabel, "low ", LOW_POS_X, LOW_POS_Y); + this.cmd("CreateRectangle", this.lowBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.LOW_POS_X, Search.LOW_POS_Y); + this.cmd("CreateLabel", this.lowBoxLabel, "low ", Search.LOW_POS_X, Search.LOW_POS_Y); this.cmd("AlignLeft", this.lowBoxLabel, this.lowBoxID); - this.cmd("SetForegroundColor", this.lowBoxID, LOW_CIRCLE_COLOR); - this.cmd("SetTextColor", this.lowBoxID, LOW_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.lowBoxID, LOW_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.lowBoxID, Search.LOW_CIRCLE_COLOR); + this.cmd("SetTextColor", this.lowBoxID, Search.LOW_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.lowBoxID, Search.LOW_BACKGROUND_COLOR); this.lowCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.lowCircleID, LOW_CIRCLE_COLOR, 0,0,HIGHLIGHT_CIRCLE_SIZE); + this.cmd("CreateHighlightCircle", this.lowCircleID, Search.LOW_CIRCLE_COLOR, 0,0,Search.HIGHLIGHT_CIRCLE_SIZE); this.highBoxID = this.nextIndex++; this.highBoxLabel = this.nextIndex++; - this.cmd("CreateRectangle", this.highBoxID, "", EXTRA_FIELD_WIDTH, EXTRA_FIELD_HEIGHT,HIGH_POS_X, HIGH_POS_Y); - this.cmd("CreateLabel", this.highBoxLabel, "high ", HIGH_POS_X, HIGH_POS_Y); + this.cmd("CreateRectangle", this.highBoxID, "", Search.EXTRA_FIELD_WIDTH, Search.EXTRA_FIELD_HEIGHT,Search.HIGH_POS_X, Search.HIGH_POS_Y); + this.cmd("CreateLabel", this.highBoxLabel, "high ", Search.HIGH_POS_X, Search.HIGH_POS_Y); this.cmd("AlignLeft", this.highBoxLabel, this.highBoxID); - this.cmd("SetForegroundColor", this.highBoxID, HIGH_CIRCLE_COLOR); - this.cmd("SetTextColor", this.highBoxID, HIGH_CIRCLE_COLOR); - this.cmd("SetBackgroundColor", this.highBoxID, HIGH_BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.highBoxID, Search.HIGH_CIRCLE_COLOR); + this.cmd("SetTextColor", this.highBoxID, Search.HIGH_CIRCLE_COLOR); + this.cmd("SetBackgroundColor", this.highBoxID, Search.HIGH_BACKGROUND_COLOR); this.highCircleID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.highCircleID, HIGH_CIRCLE_COLOR, 0 , 0, HIGHLIGHT_CIRCLE_SIZE); + this.cmd("CreateHighlightCircle", this.highCircleID, Search.HIGH_CIRCLE_COLOR, 0 , 0, Search.HIGHLIGHT_CIRCLE_SIZE); this.cmd("SetALpha", this.lowBoxID, 0); @@ -367,15 +367,15 @@ Search.prototype.setup = function() Search.prototype.setup_small = function() { - HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_SMALL; - ARRAY_START_X = ARRAY_START_X_SMALL; - ARRAY_START_Y = ARRAY_START_Y_SMALL; - ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_SMALL; - ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_SMALL; - ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_SMALL; - ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_SMALL; - SIZE = SIZE_SMALL; - this.size = SMALL_SIZE; + Search.HIGHLIGHT_CIRCLE_SIZE = Search.HIGHLIGHT_CIRCLE_SIZE_SMALL; + Search.ARRAY_START_X = Search.ARRAY_START_X_SMALL; + Search.ARRAY_START_Y = Search.ARRAY_START_Y_SMALL; + Search.ARRAY_ELEM_WIDTH = Search.ARRAY_ELEM_WIDTH_SMALL; + Search.ARRAY_ELEM_HEIGHT = Search.ARRAY_ELEM_HEIGHT_SMALL; + Search.ARRAY_ELEMS_PER_LINE = Search.ARRAY_ELEMS_PER_LINE_SMALL; + Search.ARRAY_LINE_SPACING = Search.ARRAY_LINE_SPACING_SMALL; + SIZE = Search.SIZE_SMALL; + this.size = Search.SMALL_SIZE; this.setup(); } @@ -383,15 +383,15 @@ Search.prototype.setup_small = function() { Search.prototype.setup_large = function() { - HIGHLIGHT_CIRCLE_SIZE = HIGHLIGHT_CIRCLE_SIZE_LARGE; - ARRAY_START_X = ARRAY_START_X_LARGE; - ARRAY_START_Y = ARRAY_START_Y_LARGE; - ARRAY_ELEM_WIDTH = ARRAY_ELEM_WIDTH_LARGE; - ARRAY_ELEM_HEIGHT = ARRAY_ELEM_HEIGHT_LARGE; - ARRAY_ELEMS_PER_LINE = ARRAY_ELEMS_PER_LINE_LARGE; - ARRAY_LINE_SPACING = ARRAY_LINE_SPACING_LARGE; - SIZE = SIZE_LARGE; - this.size = LARGE_SIZE; + Search.HIGHLIGHT_CIRCLE_SIZE = Search.HIGHLIGHT_CIRCLE_SIZE_LARGE; + Search.ARRAY_START_X = Search.ARRAY_START_X_LARGE; + Search.ARRAY_START_Y = Search.ARRAY_START_Y_LARGE; + Search.ARRAY_ELEM_WIDTH = Search.ARRAY_ELEM_WIDTH_LARGE; + Search.ARRAY_ELEM_HEIGHT = Search.ARRAY_ELEM_HEIGHT_LARGE; + Search.ARRAY_ELEMS_PER_LINE = Search.ARRAY_ELEMS_PER_LINE_LARGE; + Search.ARRAY_LINE_SPACING = Search.ARRAY_LINE_SPACING_LARGE; + SIZE = Search.SIZE_LARGE; + this.size = Search.LARGE_SIZE; this.setup() } @@ -432,9 +432,9 @@ Search.prototype.binarySearch = function(searchVal) this.cmd("SetAlpha", this.lowCircleID, 1); this.cmd("SetAlpha", this.midCircleID, 1); this.cmd("SetAlpha", this.highCircleID, 1); - this.cmd("SetPosition", this.lowCircleID, LOW_POS_X, LOW_POS_Y); - this.cmd("SetPosition", this.midCircleID, MID_POS_X, MID_POS_Y); - this.cmd("SetPosition", this.highCircleID, HIGH_POS_X, HIGH_POS_Y); + this.cmd("SetPosition", this.lowCircleID, Search.LOW_POS_X, Search.LOW_POS_Y); + this.cmd("SetPosition", this.midCircleID, Search.MID_POS_X, Search.MID_POS_Y); + this.cmd("SetPosition", this.highCircleID, Search.HIGH_POS_X, Search.HIGH_POS_Y); this.cmd("SetAlpha", this.indexBoxID, 0); this.cmd("SetAlpha", this.indexBoxLabel, 0); @@ -556,7 +556,7 @@ Search.prototype.binarySearch = function(searchVal) this.cmd("SetText", this.movingLabelID, mid); this.cmd("SetPosition", this.movingLabelID, this.getIndexX(mid), this.getIndexY(mid)); - this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); + this.cmd("Move", this.movingLabelID, Search.RESULT_X, Search.RESULT_Y); this.cmd("AlignRight", this.resultString, this.resultBoxID); this.cmd("SetForegroundColor", this.binaryCodeID[6][0], Search.CODE_HIGHLIGHT_COLOR); @@ -594,7 +594,7 @@ Search.prototype.linearSearch = function(searchVal) this.cmd("SetAlpha", this.midCircleID, 0); this.cmd("SetAlpha", this.highCircleID, 0); - this.cmd("SetPosition", this.lowCircleID, INDEX_X, INDEX_Y); + this.cmd("SetPosition", this.lowCircleID, Search.INDEX_X, Search.INDEX_Y); this.cmd("SetALpha", this.indexBoxID, 1); this.cmd("SetALpha", this.indexBoxLabel, 1); @@ -684,7 +684,7 @@ Search.prototype.linearSearch = function(searchVal) this.cmd("SetText", this.movingLabelID, foundIndex); this.cmd("SetPosition", this.movingLabelID, this.getIndexX(foundIndex), this.getIndexY(foundIndex)); - this.cmd("Move", this.movingLabelID, RESULT_X, RESULT_Y); + this.cmd("Move", this.movingLabelID, Search.RESULT_X, Search.RESULT_Y); this.cmd("AlignRight", this.resultString, this.resultBoxID); this.cmd("Step"); diff --git a/AlgorithmLibrary/TopoSortIndegree.js b/AlgorithmLibrary/TopoSortIndegree.js index e42c474..d1272d4 100644 --- a/AlgorithmLibrary/TopoSortIndegree.js +++ b/AlgorithmLibrary/TopoSortIndegree.js @@ -102,7 +102,7 @@ TopoSortIndegree.prototype.setup = function() this.cmd("CreateLabel", this.orderID[i], "", 0, 0); // HACK!! this.cmd("CreateRectangle", this.indegreeID[i], " ", TopoSortIndegree.INDEGREE_ARRAY_ELEM_WIDTH, TopoSortIndegree.INDEGREE_ARRAY_ELEM_HEIGHT, TopoSortIndegree.INDEGREE_ARRAY_START_X, TopoSortIndegree.INDEGREE_ARRAY_START_Y + i*TopoSortIndegree.INDEGREE_ARRAY_ELEM_HEIGHT); this.cmd("CreateLabel", this.setIndexID[i], i, TopoSortIndegree.INDEGREE_ARRAY_START_X - TopoSortIndegree.INDEGREE_ARRAY_ELEM_WIDTH ,TopoSortIndegree.INDEGREE_ARRAY_START_Y + i*TopoSortIndegree.INDEGREE_ARRAY_ELEM_HEIGHT); - this.cmd("SetForegroundColor", this.setIndexID[i], VERTEX_INDEX_COLOR); + this.cmd("SetForegroundColor", this.setIndexID[i], Graph.VERTEX_INDEX_COLOR); } this.cmd("CreateLabel", this.nextIndex++, "Indegree", TopoSortIndegree.INDEGREE_ARRAY_START_X - 1 * TopoSortIndegree.INDEGREE_ARRAY_ELEM_WIDTH, TopoSortIndegree.INDEGREE_ARRAY_START_Y - TopoSortIndegree.INDEGREE_ARRAY_ELEM_HEIGHT * 1.5, 0); @@ -188,7 +188,7 @@ TopoSortIndegree.prototype.doTopoSort = function(ignored) this.cmd("Delete", this.highlightCircleL); this.cmd("Delete", this.highlightCircleAL); this.cmd("Delete", this.highlightCircleAM); - this.cmd("SetTextColor", this.indegreeID[neighbor], EDGE_COLOR); + this.cmd("SetTextColor", this.indegreeID[neighbor], Graph.EDGE_COLOR); this.highlightEdge(vertex, neighbor, 0); } @@ -268,7 +268,7 @@ TopoSortIndegree.prototype.doTopoSort = function(ignored) this.cmd("Delete", this.highlightCircleL); this.cmd("Delete", this.highlightCircleAL); this.cmd("Delete", this.highlightCircleAM); - this.cmd("SetTextColor", this.indegreeID[vertex], EDGE_COLOR); + this.cmd("SetTextColor", this.indegreeID[vertex], Graph.EDGE_COLOR); this.highlightEdge(nextElem, vertex, 0); } From cbc654dee733a8376af785fff18e65f8d5381165 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 19:28:50 +0200 Subject: [PATCH 17/25] SPLAYTREE -> SplayTree --- AlgorithmLibrary/SplayTree.js | 202 +++++++++++++++++----------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/AlgorithmLibrary/SplayTree.js b/AlgorithmLibrary/SplayTree.js index c2462a4..709733c 100644 --- a/AlgorithmLibrary/SplayTree.js +++ b/AlgorithmLibrary/SplayTree.js @@ -27,34 +27,34 @@ // Constants. -SPLAYTREE.LINK_COLOR = "#007700"; -SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR = "#007700"; -SPLAYTREE.FOREGROUND_COLOR = "#007700"; -SPLAYTREE.BACKGROUND_COLOR = "#EEFFEE"; -SPLAYTREE.PRINT_COLOR = SPLAYTREE.FOREGROUND_COLOR; +SplayTree.LINK_COLOR = "#007700"; +SplayTree.HIGHLIGHT_CIRCLE_COLOR = "#007700"; +SplayTree.FOREGROUND_COLOR = "#007700"; +SplayTree.BACKGROUND_COLOR = "#EEFFEE"; +SplayTree.PRINT_COLOR = SplayTree.FOREGROUND_COLOR; -SPLAYTREE.WIDTH_DELTA = 50; -SPLAYTREE.HEIGHT_DELTA = 50; -SPLAYTREE.STARTING_Y = 50; +SplayTree.WIDTH_DELTA = 50; +SplayTree.HEIGHT_DELTA = 50; +SplayTree.STARTING_Y = 50; -SPLAYTREE.FIRST_PRINT_POS_X = 50; -SPLAYTREE.PRINT_VERTICAL_GAP = 20; -SPLAYTREE.PRINT_HORIZONTAL_GAP = 50; +SplayTree.FIRST_PRINT_POS_X = 50; +SplayTree.PRINT_VERTICAL_GAP = 20; +SplayTree.PRINT_HORIZONTAL_GAP = 50; -function SPLAYTREE(am, w, h) +function SplayTree(am, w, h) { this.init(am, w, h); } -SPLAYTREE.inheritFrom(Algorithm); +SplayTree.inheritFrom(Algorithm); -SPLAYTREE.prototype.init = function(am, w, h) +SplayTree.prototype.init = function(am, w, h) { - var sc = SPLAYTREE.superclass; + var sc = SplayTree.superclass; this.startingX = w / 2; - this.first_print_pos_y = h - 2 * SPLAYTREE.PRINT_VERTICAL_GAP; + this.first_print_pos_y = h - 2 * SplayTree.PRINT_VERTICAL_GAP; this.print_max = w - 10; var fn = sc.init; @@ -70,7 +70,7 @@ SPLAYTREE.prototype.init = function(am, w, h) } -SPLAYTREE.prototype.addControls = function() +SplayTree.prototype.addControls = function() { this.insertField = this.addControlToAlgorithmBar("Text", ""); this.insertField.onkeydown = this.returnSubmit(this.insertField, this.insertCallback.bind(this), 4); @@ -88,13 +88,13 @@ SPLAYTREE.prototype.addControls = function() this.printButton.onclick = this.printCallback.bind(this); } -SPLAYTREE.prototype.reset = function() +SplayTree.prototype.reset = function() { this.nextIndex = 1; this.treeRoot = null; } -SPLAYTREE.prototype.insertCallback = function(event) +SplayTree.prototype.insertCallback = function(event) { var insertedValue = this.insertField.value; // Get text value @@ -107,7 +107,7 @@ SPLAYTREE.prototype.insertCallback = function(event) } } -SPLAYTREE.prototype.deleteCallback = function(event) +SplayTree.prototype.deleteCallback = function(event) { var deletedValue = this.deleteField.value; if (deletedValue != "") @@ -122,7 +122,7 @@ SPLAYTREE.prototype.deleteCallback = function(event) // TODO: This top-down version is broken. Don't use -SPLAYTREE.prototype.splay = function(value) +SplayTree.prototype.splay = function(value) { if (this.treeRoot == null) { @@ -217,12 +217,12 @@ SPLAYTREE.prototype.splay = function(value) -SPLAYTREE.prototype.printCallback = function(event) +SplayTree.prototype.printCallback = function(event) { this.implementAction(this.printTree.bind(this),""); } -SPLAYTREE.prototype.printTree = function(unused) +SplayTree.prototype.printTree = function(unused) { this.commands = []; @@ -230,8 +230,8 @@ SPLAYTREE.prototype.printTree = function(unused) { this.highlightID = this.nextIndex++; var firstLabel = this.nextIndex; - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); - this.xPosOfNextLabel = SPLAYTREE.FIRST_PRINT_POS_X; + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, this.treeRoot.x, this.treeRoot.y); + this.xPosOfNextLabel = SplayTree.FIRST_PRINT_POS_X; this.yPosOfNextLabel = this.first_print_pos_y; this.printTreeRec(this.treeRoot); this.cmd("Delete", this.highlightID); @@ -246,7 +246,7 @@ SPLAYTREE.prototype.printTree = function(unused) return this.commands; } -SPLAYTREE.prototype.printTreeRec = function(tree) +SplayTree.prototype.printTreeRec = function(tree) { this.cmd("Step"); if (tree.left != null) @@ -258,15 +258,15 @@ SPLAYTREE.prototype.printTreeRec = function(tree) } var nextLabelID = this.nextIndex++; this.cmd("CreateLabel", nextLabelID, tree.data, tree.x, tree.y); - this.cmd("SetForegroundColor", nextLabelID, SPLAYTREE.PRINT_COLOR); + this.cmd("SetForegroundColor", nextLabelID, SplayTree.PRINT_COLOR); this.cmd("Move", nextLabelID, this.xPosOfNextLabel, this.yPosOfNextLabel); this.cmd("Step"); - this.xPosOfNextLabel += SPLAYTREE.PRINT_HORIZONTAL_GAP; + this.xPosOfNextLabel += SplayTree.PRINT_HORIZONTAL_GAP; if (this.xPosOfNextLabel > this.print_max) { - this.xPosOfNextLabel = SPLAYTREE.FIRST_PRINT_POS_X; - this.yPosOfNextLabel += SPLAYTREE.PRINT_VERTICAL_GAP; + this.xPosOfNextLabel = SplayTree.FIRST_PRINT_POS_X; + this.yPosOfNextLabel += SplayTree.PRINT_VERTICAL_GAP; } if (tree.right != null) @@ -279,7 +279,7 @@ SPLAYTREE.prototype.printTreeRec = function(tree) return; } -SPLAYTREE.prototype.findCallback = function(event) +SplayTree.prototype.findCallback = function(event) { var findValue; findValue = this.normalizeNumber(this.findField.value, 4); @@ -287,7 +287,7 @@ SPLAYTREE.prototype.findCallback = function(event) this.implementAction(this.findElement.bind(this),findValue); } -SPLAYTREE.prototype.findElement = function(findValue) +SplayTree.prototype.findElement = function(findValue) { this.commands = []; @@ -313,7 +313,7 @@ SPLAYTREE.prototype.findElement = function(findValue) } -SPLAYTREE.prototype.doFind = function(tree, value) +SplayTree.prototype.doFind = function(tree, value) { this.cmd("SetText", 0, "Searching for "+value); if (tree != null) @@ -338,7 +338,7 @@ SPLAYTREE.prototype.doFind = function(tree, value) this.cmd("SetHighlight", tree.graphicID, 0); if (tree.left!= null) { - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.left.x, tree.left.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -357,7 +357,7 @@ SPLAYTREE.prototype.doFind = function(tree, value) this.cmd("SetHighlight", tree.graphicID, 0); if (tree.right!= null) { - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.right.x, tree.right.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -383,7 +383,7 @@ SPLAYTREE.prototype.doFind = function(tree, value) } } -SPLAYTREE.prototype.insertElement = function(insertedValue) +SplayTree.prototype.insertElement = function(insertedValue) { this.commands = new Array(); this.cmd("SetText", 0, "Inserting "+insertedValue); @@ -391,18 +391,18 @@ SPLAYTREE.prototype.insertElement = function(insertedValue) if (this.treeRoot == null) { - this.cmd("CreateCircle", this.nextIndex, insertedValue, this.startingX, SPLAYTREE.STARTING_Y); - this.cmd("SetForegroundColor", this.nextIndex, SPLAYTREE.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.nextIndex, SPLAYTREE.BACKGROUND_COLOR); + this.cmd("CreateCircle", this.nextIndex, insertedValue, this.startingX, SplayTree.STARTING_Y); + this.cmd("SetForegroundColor", this.nextIndex, SplayTree.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.nextIndex, SplayTree.BACKGROUND_COLOR); this.cmd("Step"); - this.treeRoot = new BSTNode(insertedValue, this.nextIndex, this.startingX, SPLAYTREE.STARTING_Y) + this.treeRoot = new BSTNode(insertedValue, this.nextIndex, this.startingX, SplayTree.STARTING_Y) this.nextIndex += 1; } else { this.cmd("CreateCircle", this.nextIndex, insertedValue, 100, 100); - this.cmd("SetForegroundColor", this.nextIndex, SPLAYTREE.FOREGROUND_COLOR); - this.cmd("SetBackgroundColor", this.nextIndex, SPLAYTREE.BACKGROUND_COLOR); + this.cmd("SetForegroundColor", this.nextIndex, SplayTree.FOREGROUND_COLOR); + this.cmd("SetBackgroundColor", this.nextIndex, SplayTree.BACKGROUND_COLOR); this.cmd("Step"); var insertElem = new BSTNode(insertedValue, this.nextIndex, 100, 100) @@ -421,7 +421,7 @@ SPLAYTREE.prototype.insertElement = function(insertedValue) } -SPLAYTREE.prototype.insert = function(elem, tree) +SplayTree.prototype.insert = function(elem, tree) { this.cmd("SetHighlight", tree.graphicID , 1); this.cmd("SetHighlight", elem.graphicID , 1); @@ -447,11 +447,11 @@ SPLAYTREE.prototype.insert = function(elem, tree) this.cmd("SetHighlight", elem.graphicID, 0); tree.left=elem; elem.parent = tree; - this.cmd("Connect", tree.graphicID, elem.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", tree.graphicID, elem.graphicID, SplayTree.LINK_COLOR); } else { - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.left.x, tree.left.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -466,14 +466,14 @@ SPLAYTREE.prototype.insert = function(elem, tree) this.cmd("SetHighlight", elem.graphicID, 0); tree.right=elem; elem.parent = tree; - this.cmd("Connect", tree.graphicID, elem.graphicID, SPLAYTREE.LINK_COLOR); - elem.x = tree.x + SPLAYTREE.WIDTH_DELTA/2; - elem.y = tree.y + SPLAYTREE.HEIGHT_DELTA + this.cmd("Connect", tree.graphicID, elem.graphicID, SplayTree.LINK_COLOR); + elem.x = tree.x + SplayTree.WIDTH_DELTA/2; + elem.y = tree.y + SplayTree.HEIGHT_DELTA this.cmd("Move", elem.graphicID, elem.x, elem.y); } else { - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); this.cmd("Move", this.highlightID, tree.right.x, tree.right.y); this.cmd("Step"); this.cmd("Delete", this.highlightID); @@ -484,7 +484,7 @@ SPLAYTREE.prototype.insert = function(elem, tree) } -SPLAYTREE.prototype.deleteElement = function(deletedValue) +SplayTree.prototype.deleteElement = function(deletedValue) { this.commands = []; this.cmd("SetText", 0, "Deleting "+deletedValue); @@ -497,7 +497,7 @@ SPLAYTREE.prototype.deleteElement = function(deletedValue) return this.commands; } -SPLAYTREE.prototype.treeDelete = function(tree, valueToDelete) +SplayTree.prototype.treeDelete = function(tree, valueToDelete) { this.cmd("SetText", 0, "Finding "+valueToDelete + " and splaying to rooot"); this.cmd("Step"); @@ -541,7 +541,7 @@ SPLAYTREE.prototype.treeDelete = function(tree, valueToDelete) this.splayUp(largestLeft); this.cmd("SetText", 0, "Left tree now has no right subtree, connect left and right trees"); this.cmd("Step"); - this.cmd("Connect", largestLeft.graphicID, right.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", largestLeft.graphicID, right.graphicID, SplayTree.LINK_COLOR); largestLeft.parent = null; largestLeft.right = right; right.parent = largestLeft; @@ -556,7 +556,7 @@ SPLAYTREE.prototype.treeDelete = function(tree, valueToDelete) -SPLAYTREE.prototype.singleRotateRight = function(tree) +SplayTree.prototype.singleRotateRight = function(tree) { var B = tree; var t3 = B.right; @@ -572,11 +572,11 @@ SPLAYTREE.prototype.singleRotateRight = function(tree) if (t2 != null) { this.cmd("Disconnect", A.graphicID, t2.graphicID); - this.cmd("Connect", B.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, t2.graphicID, SplayTree.LINK_COLOR); t2.parent = B; } this.cmd("Disconnect", B.graphicID, A.graphicID); - this.cmd("Connect", A.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, B.graphicID, SplayTree.LINK_COLOR); A.parent = B.parent; if (B.parent == null) { @@ -584,8 +584,8 @@ SPLAYTREE.prototype.singleRotateRight = function(tree) } else { - this.cmd("Disconnect", B.parent.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); - this.cmd("Connect", B.parent.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR) + this.cmd("Disconnect", B.parent.graphicID, B.graphicID, SplayTree.LINK_COLOR); + this.cmd("Connect", B.parent.graphicID, A.graphicID, SplayTree.LINK_COLOR) if (B.isLeftChild()) { B.parent.left = A; @@ -602,7 +602,7 @@ SPLAYTREE.prototype.singleRotateRight = function(tree) } -SPLAYTREE.prototype.zigZigRight = function(tree) +SplayTree.prototype.zigZigRight = function(tree) { var C = tree; var B = tree.left; @@ -623,7 +623,7 @@ SPLAYTREE.prototype.zigZigRight = function(tree) if (C.parent != null) { this.cmd("Disconnect", C.parent.graphicID, C.graphicID); - this.cmd("Connect", C.parent.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", C.parent.graphicID, A.graphicID, SplayTree.LINK_COLOR); if (C.isLeftChild()) { C.parent.left = A; @@ -641,19 +641,19 @@ SPLAYTREE.prototype.zigZigRight = function(tree) if (t2 != null) { this.cmd("Disconnect", A.graphicID, t2.graphicID); - this.cmd("Connect", B.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, t2.graphicID, SplayTree.LINK_COLOR); t2.parent = B; } if (t3 != null) { this.cmd("Disconnect", B.graphicID, t3.graphicID); - this.cmd("Connect", C.graphicID, t3.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", C.graphicID, t3.graphicID, SplayTree.LINK_COLOR); t3.parent = C; } this.cmd("Disconnect", B.graphicID, A.graphicID); - this.cmd("Connect", A.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, B.graphicID, SplayTree.LINK_COLOR); this.cmd("Disconnect", C.graphicID, B.graphicID); - this.cmd("Connect", B.graphicID, C.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, C.graphicID, SplayTree.LINK_COLOR); A.right = B; A.parent = C.parent; @@ -666,7 +666,7 @@ SPLAYTREE.prototype.zigZigRight = function(tree) } -SPLAYTREE.prototype.zigZigLeft = function(tree) +SplayTree.prototype.zigZigLeft = function(tree) { var A = tree; var B = tree.right; @@ -688,7 +688,7 @@ SPLAYTREE.prototype.zigZigLeft = function(tree) if (A.parent != null) { this.cmd("Disconnect", A.parent.graphicID, A.graphicID); - this.cmd("Connect", A.parent.graphicID, C.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.parent.graphicID, C.graphicID, SplayTree.LINK_COLOR); if (A.isLeftChild()) { A.parent.left = C; @@ -706,19 +706,19 @@ SPLAYTREE.prototype.zigZigLeft = function(tree) if (t2 != null) { this.cmd("Disconnect", B.graphicID, t2.graphicID); - this.cmd("Connect", A.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, t2.graphicID, SplayTree.LINK_COLOR); t2.parent = A; } if (t3 != null) { this.cmd("Disconnect", C.graphicID, t3.graphicID); - this.cmd("Connect", B.graphicID, t3.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, t3.graphicID, SplayTree.LINK_COLOR); t3.parent = B; } this.cmd("Disconnect", A.graphicID, B.graphicID); this.cmd("Disconnect", B.graphicID, C.graphicID); - this.cmd("Connect", C.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); - this.cmd("Connect", B.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", C.graphicID, B.graphicID, SplayTree.LINK_COLOR); + this.cmd("Connect", B.graphicID, A.graphicID, SplayTree.LINK_COLOR); C.parent = A.parent; A.right = t2; B.left = A; @@ -731,7 +731,7 @@ SPLAYTREE.prototype.zigZigLeft = function(tree) } -SPLAYTREE.prototype.singleRotateLeft = function(tree) +SplayTree.prototype.singleRotateLeft = function(tree) { var A = tree; var B = tree.right; @@ -746,11 +746,11 @@ SPLAYTREE.prototype.singleRotateLeft = function(tree) if (t2 != null) { this.cmd("Disconnect", B.graphicID, t2.graphicID); - this.cmd("Connect", A.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, t2.graphicID, SplayTree.LINK_COLOR); t2.parent = A; } this.cmd("Disconnect", A.graphicID, B.graphicID); - this.cmd("Connect", B.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, A.graphicID, SplayTree.LINK_COLOR); B.parent = A.parent; if (A.parent == null) { @@ -758,8 +758,8 @@ SPLAYTREE.prototype.singleRotateLeft = function(tree) } else { - this.cmd("Disconnect", A.parent.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); - this.cmd("Connect", A.parent.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR) + this.cmd("Disconnect", A.parent.graphicID, A.graphicID, SplayTree.LINK_COLOR); + this.cmd("Connect", A.parent.graphicID, B.graphicID, SplayTree.LINK_COLOR) if (A.isLeftChild()) { @@ -779,7 +779,7 @@ SPLAYTREE.prototype.singleRotateLeft = function(tree) -SPLAYTREE.prototype.splayUp = function(tree) +SplayTree.prototype.splayUp = function(tree) { if (tree.parent == null) { @@ -821,12 +821,12 @@ SPLAYTREE.prototype.splayUp = function(tree) } -SPLAYTREE.prototype.findMax = function(tree) +SplayTree.prototype.findMax = function(tree) { if (tree.right != null) { this.highlightID = this.nextIndex++; - this.cmd("CreateHighlightCircle", this.highlightID, SPLAYTREE.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); + this.cmd("CreateHighlightCircle", this.highlightID, SplayTree.HIGHLIGHT_CIRCLE_COLOR, tree.x, tree.y); this.cmd("Step"); while(tree.right != null) { @@ -844,7 +844,7 @@ SPLAYTREE.prototype.findMax = function(tree) } -SPLAYTREE.prototype.doubleRotateRight = function(tree) +SplayTree.prototype.doubleRotateRight = function(tree) { this.cmd("SetText", 0, "Zig-Zag Right"); var A = tree.left; @@ -865,14 +865,14 @@ SPLAYTREE.prototype.doubleRotateRight = function(tree) this.cmd("Disconnect",B.graphicID, t2.graphicID); t2.parent = A; A.right = t2; - this.cmd("Connect", A.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, t2.graphicID, SplayTree.LINK_COLOR); } if (t3 != null) { this.cmd("Disconnect",B.graphicID, t3.graphicID); t3.parent = C; C.left = t2; - this.cmd("Connect", C.graphicID, t3.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", C.graphicID, t3.graphicID, SplayTree.LINK_COLOR); } if (C.parent == null) { @@ -882,7 +882,7 @@ SPLAYTREE.prototype.doubleRotateRight = function(tree) else { this.cmd("Disconnect",C.parent.graphicID, C.graphicID); - this.cmd("Connect",C.parent.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect",C.parent.graphicID, B.graphicID, SplayTree.LINK_COLOR); if (C.isLeftChild()) { C.parent.left = B @@ -896,8 +896,8 @@ SPLAYTREE.prototype.doubleRotateRight = function(tree) } this.cmd("Disconnect", C.graphicID, A.graphicID); this.cmd("Disconnect", A.graphicID, B.graphicID); - this.cmd("Connect", B.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); - this.cmd("Connect", B.graphicID, C.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, A.graphicID, SplayTree.LINK_COLOR); + this.cmd("Connect", B.graphicID, C.graphicID, SplayTree.LINK_COLOR); B.left = A; A.parent = B; B.right=C; @@ -910,7 +910,7 @@ SPLAYTREE.prototype.doubleRotateRight = function(tree) } -SPLAYTREE.prototype.doubleRotateLeft = function(tree) +SplayTree.prototype.doubleRotateLeft = function(tree) { this.cmd("SetText", 0, "Zig-Zag Left"); var A = tree; @@ -931,14 +931,14 @@ SPLAYTREE.prototype.doubleRotateLeft = function(tree) this.cmd("Disconnect",B.graphicID, t2.graphicID); t2.parent = A; A.right = t2; - this.cmd("Connect", A.graphicID, t2.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", A.graphicID, t2.graphicID, SplayTree.LINK_COLOR); } if (t3 != null) { this.cmd("Disconnect",B.graphicID, t3.graphicID); t3.parent = C; C.left = t2; - this.cmd("Connect", C.graphicID, t3.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", C.graphicID, t3.graphicID, SplayTree.LINK_COLOR); } @@ -950,7 +950,7 @@ SPLAYTREE.prototype.doubleRotateLeft = function(tree) else { this.cmd("Disconnect",A.parent.graphicID, A.graphicID); - this.cmd("Connect",A.parent.graphicID, B.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect",A.parent.graphicID, B.graphicID, SplayTree.LINK_COLOR); if (A.isLeftChild()) { A.parent.left = B @@ -965,8 +965,8 @@ SPLAYTREE.prototype.doubleRotateLeft = function(tree) } this.cmd("Disconnect", A.graphicID, C.graphicID); this.cmd("Disconnect", C.graphicID, B.graphicID); - this.cmd("Connect", B.graphicID, A.graphicID, SPLAYTREE.LINK_COLOR); - this.cmd("Connect", B.graphicID, C.graphicID, SPLAYTREE.LINK_COLOR); + this.cmd("Connect", B.graphicID, A.graphicID, SplayTree.LINK_COLOR); + this.cmd("Connect", B.graphicID, C.graphicID, SplayTree.LINK_COLOR); B.left = A; A.parent = B; B.right=C; @@ -981,7 +981,7 @@ SPLAYTREE.prototype.doubleRotateLeft = function(tree) -SPLAYTREE.prototype.resizeTree = function() +SplayTree.prototype.resizeTree = function() { var startingPoint = this.startingX; this.resizeWidths(this.treeRoot); @@ -995,14 +995,14 @@ SPLAYTREE.prototype.resizeTree = function() { startingPoint = Math.max(this.treeRoot.leftWidth, 2 * startingPoint - this.treeRoot.rightWidth); } - this.setNewPositions(this.treeRoot, startingPoint, SPLAYTREE.STARTING_Y, 0); + this.setNewPositions(this.treeRoot, startingPoint, SplayTree.STARTING_Y, 0); this.animateNewPositions(this.treeRoot); this.cmd("Step"); } } -SPLAYTREE.prototype.setNewPositions = function(tree, xPosition, yPosition, side) +SplayTree.prototype.setNewPositions = function(tree, xPosition, yPosition, side) { if (tree != null) { @@ -1016,12 +1016,12 @@ SPLAYTREE.prototype.setNewPositions = function(tree, xPosition, yPosition, side) xPosition = xPosition + tree.leftWidth; } tree.x = xPosition; - this.setNewPositions(tree.left, xPosition, yPosition + SPLAYTREE.HEIGHT_DELTA, -1) - this.setNewPositions(tree.right, xPosition, yPosition + SPLAYTREE.HEIGHT_DELTA, 1) + this.setNewPositions(tree.left, xPosition, yPosition + SplayTree.HEIGHT_DELTA, -1) + this.setNewPositions(tree.right, xPosition, yPosition + SplayTree.HEIGHT_DELTA, 1) } } -SPLAYTREE.prototype.animateNewPositions = function(tree) +SplayTree.prototype.animateNewPositions = function(tree) { if (tree != null) { @@ -1031,14 +1031,14 @@ SPLAYTREE.prototype.animateNewPositions = function(tree) } } -SPLAYTREE.prototype.resizeWidths = function(tree) +SplayTree.prototype.resizeWidths = function(tree) { if (tree == null) { return 0; } - tree.leftWidth = Math.max(this.resizeWidths(tree.left), SPLAYTREE.WIDTH_DELTA / 2); - tree.rightWidth = Math.max(this.resizeWidths(tree.right), SPLAYTREE.WIDTH_DELTA / 2); + tree.leftWidth = Math.max(this.resizeWidths(tree.left), SplayTree.WIDTH_DELTA / 2); + tree.rightWidth = Math.max(this.resizeWidths(tree.right), SplayTree.WIDTH_DELTA / 2); return tree.leftWidth + tree.rightWidth; } @@ -1066,7 +1066,7 @@ BSTNode.prototype.isLeftChild = function() } -SPLAYTREE.prototype.disableUI = function(event) +SplayTree.prototype.disableUI = function(event) { this.insertField.disabled = true; this.insertButton.disabled = true; @@ -1077,7 +1077,7 @@ SPLAYTREE.prototype.disableUI = function(event) this.printButton.disabled = true; } -SPLAYTREE.prototype.enableUI = function(event) +SplayTree.prototype.enableUI = function(event) { this.insertField.disabled = false; this.insertButton.disabled = false; @@ -1094,6 +1094,6 @@ var currentAlg; function init() { var animManag = initCanvas(); - currentAlg = new SPLAYTREE(animManag, canvas.width, canvas.height); + currentAlg = new SplayTree(animManag, canvas.width, canvas.height); } \ No newline at end of file From 834779cf2137d49372a642116960daa5d8b130f8 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Fri, 17 Jan 2020 20:25:03 +0200 Subject: [PATCH 18/25] fix typo --- Algorithms.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Algorithms.html b/Algorithms.html index 77e3eef..71f4f38 100644 --- a/Algorithms.html +++ b/Algorithms.html @@ -81,7 +81,7 @@
  • Insertion Sort
  • Shell Sort
  • Merge Sort
  • -
  • Quck Sort
  • +
  • Quick Sort
  • Bucket Sort
  • From 188ad3b7058afc50f2e55def644940bc4dc0d238 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sat, 18 Jan 2020 21:23:21 +0200 Subject: [PATCH 19/25] Create Function.prototype.bind only if not exists --- AnimationLibrary/CustomEvents.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/AnimationLibrary/CustomEvents.js b/AnimationLibrary/CustomEvents.js index 5aa0bf5..de65395 100644 --- a/AnimationLibrary/CustomEvents.js +++ b/AnimationLibrary/CustomEvents.js @@ -31,17 +31,19 @@ Function.prototype.inheritFrom = function(superConstructor) { this.prototype.constructor = this; // for instanceof } -Function.prototype.bind = function() { - var _function = this; - - var args = Array.prototype.slice.call(arguments); - var scope = args.shift() - return function() { - for (var i = 0; i < arguments.length; i++) - { - args.push(arguments[i]); +if(!Function.prototype.bind) { // ECMAScript 5 is supported everywhere by now + Function.prototype.bind = function() { + var _function = this; + + var args = Array.prototype.slice.call(arguments); + var scope = args.shift() + return function() { + for (var i = 0; i < arguments.length; i++) + { + args.push(arguments[i]); + } + return _function.apply(scope, args); } - return _function.apply(scope, args); } } From 0288ef8a5b8ee37955db6849799186b3167aebb8 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sat, 18 Jan 2020 21:25:57 +0200 Subject: [PATCH 20/25] BFS/DFS bugfix: empty messageID on reset --- AlgorithmLibrary/BFS.js | 2 ++ AlgorithmLibrary/DFS.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/AlgorithmLibrary/BFS.js b/AlgorithmLibrary/BFS.js index 44e8ed0..7e338fa 100644 --- a/AlgorithmLibrary/BFS.js +++ b/AlgorithmLibrary/BFS.js @@ -224,6 +224,8 @@ BFS.prototype.doBFS = function(startVetex) BFS.prototype.reset = function() { // Throw an error? + + this.messageID = new Array(); } diff --git a/AlgorithmLibrary/DFS.js b/AlgorithmLibrary/DFS.js index 605cf4a..3f7d094 100644 --- a/AlgorithmLibrary/DFS.js +++ b/AlgorithmLibrary/DFS.js @@ -225,6 +225,8 @@ DFS.prototype.dfsVisit = function(startVertex, messageX) DFS.prototype.reset = function() { // Throw an error? + + this.messageID = new Array(); } From f2ff45bb77156d9656c08ac511ed442fef689bd7 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sat, 18 Jan 2020 22:50:21 +0200 Subject: [PATCH 21/25] Graph: set directed param in subclasses --- AlgorithmLibrary/BFS.js | 8 ++++---- AlgorithmLibrary/DFS.js | 8 ++++---- AlgorithmLibrary/DijkstraPrim.js | 10 +++++----- AlgorithmLibrary/Floyd.js | 8 ++++---- AlgorithmLibrary/Graph.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/AlgorithmLibrary/BFS.js b/AlgorithmLibrary/BFS.js index 7e338fa..a2aebe7 100644 --- a/AlgorithmLibrary/BFS.js +++ b/AlgorithmLibrary/BFS.js @@ -25,10 +25,10 @@ // or implied, of the University of San Francisco -function BFS(am, w, h) +function BFS(am, w, h, dir) { // call superclass' constructor, which calls init - BFS.superclass.constructor.call(this, am, w, h); + BFS.superclass.constructor.call(this, am, w, h, dir); } BFS.inheritFrom(Graph); @@ -62,10 +62,10 @@ BFS.prototype.addControls = function() } -BFS.prototype.init = function(am, w, h) +BFS.prototype.init = function(am, w, h, dir) { showEdgeCosts = false; - BFS.superclass.init.call(this, am, w, h); // TODO: add no edge label flag to this? + BFS.superclass.init.call(this, am, w, h, dir); // TODO: add no edge label flag to this? // Setup called in base class constructor } diff --git a/AlgorithmLibrary/DFS.js b/AlgorithmLibrary/DFS.js index 3f7d094..18b310d 100644 --- a/AlgorithmLibrary/DFS.js +++ b/AlgorithmLibrary/DFS.js @@ -42,10 +42,10 @@ DFS.QUEUE_START_Y = 50; DFS.QUEUE_SPACING = 30; -function DFS(am, w, h) +function DFS(am, w, h, dir) { // call superclass' constructor, which calls init - DFS.superclass.constructor.call(this, am, w, h); + DFS.superclass.constructor.call(this, am, w, h, dir); } DFS.inheritFrom(Graph); @@ -61,10 +61,10 @@ DFS.prototype.addControls = function() } -DFS.prototype.init = function(am, w, h) +DFS.prototype.init = function(am, w, h, dir) { showEdgeCosts = false; - DFS.superclass.init.call(this, am, w, h); // TODO: add no edge label flag to this? + DFS.superclass.init.call(this, am, w, h, dir); // TODO: add no edge label flag to this? // Setup called in base class constructor } diff --git a/AlgorithmLibrary/DijkstraPrim.js b/AlgorithmLibrary/DijkstraPrim.js index b476cb6..ecb9600 100644 --- a/AlgorithmLibrary/DijkstraPrim.js +++ b/AlgorithmLibrary/DijkstraPrim.js @@ -39,12 +39,12 @@ DijkstraPrim.HIGHLIGHT_CIRCLE_COLOR = "#000000"; -function DijkstraPrim(am, runningDijkstra, w, h) +function DijkstraPrim(am, w, h, runningDijkstra, dir) { this.runningDijkstra = runningDijkstra; // call superclass' constructor, which calls init - DijkstraPrim.superclass.constructor.call(this, am, w, h); + DijkstraPrim.superclass.constructor.call(this, am, w, h, dir, false); } DijkstraPrim.inheritFrom(Graph); @@ -70,10 +70,10 @@ DijkstraPrim.prototype.addControls = function() } -DijkstraPrim.prototype.init = function(am, runningDijkstra, w, h) +DijkstraPrim.prototype.init = function(am, w, h, dir) { this.showEdgeCosts = true; - DijkstraPrim.superclass.init.call(this, am, w, h, false, false); // TODO: add no edge label flag to this? + DijkstraPrim.superclass.init.call(this, am, w, h, dir, false); // TODO: add no edge label flag to this? // Setup called in base class init function } @@ -428,5 +428,5 @@ var currentAlg; function init(runDijkstra) { var animManag = initCanvas(); - currentAlg = new DijkstraPrim(animManag, runDijkstra, canvas.width, canvas.height); + currentAlg = new DijkstraPrim(animManag, canvas.width, canvas.height, runDijkstra); } diff --git a/AlgorithmLibrary/Floyd.js b/AlgorithmLibrary/Floyd.js index df66de3..73b0c97 100644 --- a/AlgorithmLibrary/Floyd.js +++ b/AlgorithmLibrary/Floyd.js @@ -26,10 +26,10 @@ -function Floyd(am, w, h) +function Floyd(am, w, h, dir) { // call superclass' constructor, which calls init - Floyd.superclass.constructor.call(this, am, w, h); + Floyd.superclass.constructor.call(this, am, w, h, dir); } Floyd.inheritFrom(Graph); @@ -88,10 +88,10 @@ Floyd.prototype.addControls = function() } -Floyd.prototype.init = function(am, w, h) +Floyd.prototype.init = function(am, w, h, dir) { this.showEdgeCosts = true; - Floyd.superclass.init.call(this, am, w, h, true, false); // TODO: add no edge label flag to this? + Floyd.superclass.init.call(this, am, w, h, dir, false); // TODO: add no edge label flag to this? // Setup called in base class init function } diff --git a/AlgorithmLibrary/Graph.js b/AlgorithmLibrary/Graph.js index e5237f8..27c7c86 100644 --- a/AlgorithmLibrary/Graph.js +++ b/AlgorithmLibrary/Graph.js @@ -33,7 +33,7 @@ function Graph(am, w, h, dir, dag) if (!am) throw "this shouldn't happen"; - this.init(am, w, h, dir,dag); + this.init(am, w, h, dir, dag); } Graph.inheritFrom(Algorithm); From a7cc3d9449623981e20e438a1334d34a0ec4cbd8 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 19 Jan 2020 11:56:10 +0200 Subject: [PATCH 22/25] BTree: allow passing max_degree in the constructor --- AlgorithmLibrary/BTree.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/AlgorithmLibrary/BTree.js b/AlgorithmLibrary/BTree.js index 8292de9..182f205 100644 --- a/AlgorithmLibrary/BTree.js +++ b/AlgorithmLibrary/BTree.js @@ -51,8 +51,10 @@ BTree.PRINT_COLOR = BTree.FOREGROUND_COLOR; -function BTree(am, w, h) +function BTree(am, w, h, max_degree) { + this.initial_max_degree = this.max_degree = max_degree || 3; + this.init(am, w, h); } @@ -76,13 +78,9 @@ BTree.prototype.init = function(am, w, h) this.addControls(); - this.max_keys = 2; - this.min_keys = 1; - this.split_index = 1; - - this.max_degree = 3; - - + this.max_keys = this.max_degree - 1; + this.min_keys = Math.floor((this.max_degree + 1) / 2) - 1; + this.split_index = Math.floor((this.max_degree - 1) / 2); this.messageID = this.nextIndex++; @@ -169,10 +167,13 @@ BTree.prototype.addControls = function() BTree.prototype.reset = function() { this.nextIndex = 3; - this.max_degree = 3; - this.max_keys = 2; - this.min_keys = 1; - this.split_index = 1; + + this.max_degree = this.initial_max_degree; + + this.max_keys = this.max_degree - 1; + this.min_keys = Math.floor((this.max_degree + 1) / 2) - 1; + this.split_index = Math.floor((this.max_degree - 1) / 2); + // NOTE: The order of these last two this.commands matters! this.treeRoot = null; this.ignoreInputs = true; From c3e948bde45888022250c1601504e92313a5fc85 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Sun, 19 Jan 2020 14:34:04 +0200 Subject: [PATCH 23/25] fix typo --- AlgorithmLibrary/BPlusTree.js | 2 +- AlgorithmLibrary/BTree.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AlgorithmLibrary/BPlusTree.js b/AlgorithmLibrary/BPlusTree.js index 45d7b6d..0295127 100644 --- a/AlgorithmLibrary/BPlusTree.js +++ b/AlgorithmLibrary/BPlusTree.js @@ -592,7 +592,7 @@ BPlusTree.prototype.insertRepair = function(tree) BPlusTree.prototype.split = function(tree) { - this.cmd("SetText", this.messageID, "Node now contains too many keys. Splittig ..."); + this.cmd("SetText", this.messageID, "Node now contains too many keys. Splitting ..."); this.cmd("SetHighlight", tree.graphicID, 1); this.cmd("Step"); this.cmd("SetHighlight", tree.graphicID, 0); diff --git a/AlgorithmLibrary/BTree.js b/AlgorithmLibrary/BTree.js index 182f205..32a209a 100644 --- a/AlgorithmLibrary/BTree.js +++ b/AlgorithmLibrary/BTree.js @@ -674,7 +674,7 @@ BTree.prototype.insertRepair = function(tree) BTree.prototype.split = function(tree) { - this.cmd("SetText", this.messageID, "Node now contains too many keys. Splittig ..."); + this.cmd("SetText", this.messageID, "Node now contains too many keys. Splitting ..."); this.cmd("SetHighlight", tree.graphicID, 1); this.cmd("Step"); this.cmd("SetHighlight", tree.graphicID, 0); From 07c4773ef1e0f262bac8f07532e2af3e3f96d196 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Tue, 31 Mar 2020 16:58:04 +0300 Subject: [PATCH 24/25] Heap: allow passing a compare function --- AlgorithmLibrary/Heap.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/AlgorithmLibrary/Heap.js b/AlgorithmLibrary/Heap.js index d14f967..80b150e 100644 --- a/AlgorithmLibrary/Heap.js +++ b/AlgorithmLibrary/Heap.js @@ -25,9 +25,11 @@ // or implied, of the University of San Francisco -function Heap(am) +function Heap(am, w, h, compare) { - this.init(am); + this.compare = compare ? window[compare] : function(a, b) { return a < b ? -1 : a > b ? 1 : 0; }; + + this.init(am, w, h); } Heap.inheritFrom(Algorithm); @@ -220,7 +222,7 @@ Heap.prototype.pushDown = function(index) this.cmd("Step"); this.setIndexHighlight(2*index, 0); this.setIndexHighlight(2*index + 1, 0); - if (this.arrayData[2*index + 1] < this.arrayData[2*index]) + if (this.compare(this.arrayData[2*index + 1], this.arrayData[2*index]) < 0) { smallestIndex = 2*index + 1; } @@ -231,7 +233,7 @@ Heap.prototype.pushDown = function(index) this.setIndexHighlight(index, 0); this.setIndexHighlight(smallestIndex, 0); - if (this.arrayData[smallestIndex] < this.arrayData[index]) + if (this.compare(this.arrayData[smallestIndex], this.arrayData[index]) < 0) { this.swap(smallestIndex, index); index = smallestIndex; @@ -354,7 +356,7 @@ Heap.prototype.insertElement = function(insertedValue) this.setIndexHighlight(parentIndex, 0); } - while (currentIndex > 1 && this.arrayData[currentIndex] < this.arrayData[parentIndex]) + while (currentIndex > 1 && this.compare(this.arrayData[currentIndex], this.arrayData[parentIndex]) < 0) { this.swap(currentIndex, parentIndex); currentIndex = parentIndex; From 159b7da08b403ced890ea46f9b7869791c23e739 Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Tue, 31 Mar 2020 17:42:28 +0300 Subject: [PATCH 25/25] buildHeap: allow passing initial data --- AlgorithmLibrary/Heap.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/AlgorithmLibrary/Heap.js b/AlgorithmLibrary/Heap.js index 80b150e..34049cf 100644 --- a/AlgorithmLibrary/Heap.js +++ b/AlgorithmLibrary/Heap.js @@ -290,13 +290,26 @@ Heap.prototype.buildHeapCallback = function(event) this.implementAction(this.buildHeap.bind(this),""); } -Heap.prototype.buildHeap = function(ignored) +Heap.prototype.buildHeap = function(data) { this.commands = []; this.clear(); - for (var i = 1; i 1) @@ -306,7 +319,6 @@ Heap.prototype.buildHeap = function(ignored) } this.cmd("Step"); - this.currentHeapSize = Heap.ARRAY_SIZE - 1; var nextElem = this.currentHeapSize; while(nextElem > 0) {