diff --git a/css/style.css b/css/style.css
index eb7e513..3113ff5 100644
--- a/css/style.css
+++ b/css/style.css
@@ -25,7 +25,7 @@ html, body {
.sorter {
background:#f4f4f4;
border:1px solid #bbb;
- height:270px;
+ height:260px;
margin:20px auto;
padding:10px;
position:relative;
@@ -33,7 +33,7 @@ html, body {
}
.sorter-sidebar {
- height:230px;
+ height:220px;
position:absolute;
right:10px;
top:10px;
@@ -43,7 +43,7 @@ html, body {
.sorter-svg {
background:#fff;
border:1px solid #ccc;
- height:200px;
+ height:190px;
left:10px;
position:absolute;
top:10px;
@@ -63,7 +63,7 @@ html, body {
height:40px;
left:10px;
position:absolute;
- top:220px;
+ top:210px;
width:770px;
}
diff --git a/index.html b/index.html
index f320a13..ef5e39e 100644
--- a/index.html
+++ b/index.html
@@ -81,8 +81,8 @@
-
-
+
+
diff --git a/js/itemgroup.js b/js/itemgroup.js
new file mode 100644
index 0000000..b030141
--- /dev/null
+++ b/js/itemgroup.js
@@ -0,0 +1,146 @@
+/**
+ *
+ */
+var Itemgroup = {
+ /**
+ *
+ */
+ items: function items(group, delay, n) {
+ var g;
+ var all = [];
+
+ // Items start with no background by default.
+ for (var i = 0; i < n; i++) {
+ g = group.append('g')
+ .attr('class', `i${i}`)
+ .attr('transform', function transform(d) {
+ return `translate(${i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding}, ${Visualizer.padding})`;
+ });;
+
+ g.append('rect')
+ .attr('class', 'item')
+ .attr('height', Visualizer.itemH)
+ .attr('width', Visualizer.itemW)
+ .attr('fill', 'transparent');
+
+ // Item labels
+ g.append('text')
+ .attr('fill', '#aaa')
+ .attr('font-size', 10)
+ .attr('font-family', 'sans-serif')
+ .attr('transform', function transform(d) {
+ return `rotate(90 0,0), translate(5, -3)`;
+ });
+
+ all.push(g);
+ };
+
+ return all;
+ },
+
+ /**
+ *
+ */
+ swap: function swap(group, delay, indexA, indexB) {
+ var x, a, b;
+ var len = group.selectAll('g')[0].length;
+
+ // NOTE pitfalls in the swapping problem.
+ // NOTE Two way binding here between dataset and function parameter?
+ // NOTE swapping will not reorder index and i parameter will be off
+ // NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
+
+ // Animate a node swap which will be quietly undone after completion.
+ group.selectAll('g').transition().duration(delay - 100)
+ .attr('transform', function transform(d, i) {
+ x = i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
+
+ if (i === indexA) {
+ x = indexB * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
+ a = d3.select(this).select('text').text();
+ }
+ else if (i === indexB) {
+ x = indexA * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
+ b = d3.select(this).select('text').text();
+
+ }
+
+ return `translate(${x}, ${Visualizer.padding})`;
+ })
+ .each('end', function(d, i) {
+ if (i !== len - 1) {
+ return;
+ }
+
+ console.log(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`);
+
+ // Undo the animation by restoring the original positions and swapping the values.
+ group.selectAll('g')
+ .attr('transform', function transform(d, i) {
+ x = i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
+ return `translate(${x}, ${Visualizer.padding})`;
+ })
+ .each(function(d, i) {
+ if (i === indexA) {
+ d3.select(this).select('text').text(b);
+ }
+ else if (i === indexB) {
+ d3.select(this).select('text').text(a);
+ }
+ });
+
+ console.warn(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`);
+ });
+ },
+
+ /**
+ *
+ */
+ background: function background(group, delay, start, end, color) {
+ group.selectAll('g').each(function(d, i) {
+ if (i >= start && i <= end) {
+ d3.select(this).select('rect').attr('fill', color);
+ }
+ });
+ },
+
+ /**
+ *
+ */
+ foreground: function foreground(group, delay, start, end, color) {
+ group.selectAll('g').each(function(d, i) {
+ if (i >= start && i <= end) {
+ d3.select(this).select('text').attr('fill', color);
+ }
+ });
+ },
+
+ /**
+ *
+ */
+ text: function text(group, delay, which, text) {
+ // NOTE http://stackoverflow.com/questions/28390754/get-one-element-from-d3js-selection-by-index
+ group.selectAll('g')
+ .filter(function filter(d, i) { return i === which; })
+ .select('text').text(text);
+ },
+
+ /**
+ *
+ */
+ opacity: function opacity(group, delay, start, end, opacity) {
+ group.selectAll('g').each(function(d, i) {
+ if (i >= start && i <= end) {
+ d3.select(this).attr('opacity', opacity);
+ }
+ });
+ },
+
+ /**
+ * Message updates.
+ */
+ message: function message(group, delay, which, msg) {
+ var msg = msg || ' ';
+ this.parent.querySelector(`.message:nth-child(${which})`).innerHTML = msg;
+ },
+};
diff --git a/js/mergesort.js b/js/mergesort.js
index 952b140..14258f2 100644
--- a/js/mergesort.js
+++ b/js/mergesort.js
@@ -1,96 +1,120 @@
/**
*
*/
-var MergeSort = function(VisualizerInstance) {
+var MergeSort = function() {
//===== Inits.
- this.V = VisualizerInstance;
+ this.actions = [];
this.comparisons = 0;
//===== Action management.
//
- this.initSort = function(arr, start, end) {
- this.V
- .instruct(this.V.unhighlight, 0)
- .instruct(this.V.unfade, 0)
- .instruct(this.V.fade, 0, -1, start - 1)
- .instruct(this.V.fade, 0, end + 1, arr.length)
- .instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`)
- .instruct(this.V.message, 0, 2, '')
- .instruct(this.V.message, 0, 3, '')
- .instruct(this.V.message, 0, 4, '')
- .instruct(this.V.message, 0, 5, '');
+ this.reset = function(arr, start, end) {
+ var len = arr.length;
+
+ this
+ .instruct(Itemgroup.background, 0, 0, '#f00', 0, len)
+
+ .instruct(Itemgroup.opacity, 0, 0, 0, len, 1)
+ .instruct(Itemgroup.opacity, 0, 0, -1, start - 1, 0.2)
+ .instruct(Itemgroup.opacity, 0, 0, end + 1, len, 0.2)
+
+ .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`)
+ .instruct(Itemgroup.message, 0, 0, 2, '')
+ .instruct(Itemgroup.message, 0, 0, 3, '')
+ .instruct(Itemgroup.message, 0, 0, 4, '')
+ .instruct(Itemgroup.message, 0, 0, 5, '');
};
//
this.splitSingle = function(index) {
- this.V.instruct(this.V.message, 100, 2, `Single element [${index}]`);
+ this
+ .instruct(Itemgroup.message, 0, 100, 2, `Single element [${index}]`);
};
//
this.preSort = function(start, mid, end) {
- this.V
- .instruct(this.V.message, 0, 2, `Sorting [${start}] - [${end}]`)
- .instruct(this.V.message, 0, 3, 'Slicing and recursing:')
- .instruct(this.V.message, 100, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`);
+ this
+ .instruct(Itemgroup.message, 0, 0, 2, `Sorting [${start}] - [${end}]`)
+ .instruct(Itemgroup.message, 0, 0, 3, 'Slicing and recursing:')
+ .instruct(Itemgroup.message, 0, 100, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`);
};
//
- this.preMerge = function(arr1, arr2, start, mid, end) {
- var i, j, x, y, v;
- var len1 = arr1.length;
- var len2 = arr2.length;
-
- for (var i = 0; i < len1; i++) {
- x = Visualizer.padding + (i + start) * (Visualizer.itemW + Visualizer.spacerW);
- y = Visualizer.padding * 2 + Visualizer.itemH;
- v = arr1[i].value;
- this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#05350D')
- }
-
- for (var j = 0; j < len2; j++) {
- x = Visualizer.padding + (j + len1 + start) * (Visualizer.itemW + Visualizer.spacerW);
- y = Visualizer.padding * 2 + Visualizer.itemH;
- v = arr2[j].value;
- this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#028E2D')
- }
-
- this.V
- // .instruct(this.V.fade, 0, 0, arr.length)
- .instruct(this.V.message, 0, 2, ``)
- .instruct(this.V.message, 0, 3, 'Merging slices:')
- .instruct(this.V.message, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`)
- .instruct(this.V.removeTertiary, 0);
+ this.preMerge = function(start, mid, end, len) {
+ this
+ .instruct(Itemgroup.message, 0, 0, 2, ``)
+ .instruct(Itemgroup.message, 0, 0, 3, 'Merging slices:')
+ .instruct(Itemgroup.message, 0, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`)
+
+ .instruct(Itemgroup.opacity, 1, 0, 0, len, 0)
+ .instruct(Itemgroup.opacity, 1, 0, start, end, 1)
+ .instruct(Itemgroup.opacity, 2, 0, 0, len, 0)
};
//
- this.postMerge = function() {
- this.V.instruct(this.V.removeSecondary, 0);
+ this.postMerge = function(len) {
+ this
+ .instruct(Itemgroup.opacity, 1, 0, 0, len, 0)
};
//
this.midMerge = function(index, value, message) {
- var x = Visualizer.padding + index * (Visualizer.itemW + Visualizer.spacerW);
- var y = Visualizer.padding * 3 + Visualizer.itemH * 2
-
- this.V
- .instruct(this.V.item, 0, 'tertiary', x, y, value, '#8E5500')
- .instruct(this.V.message, 0, 4, message)
- .instruct(this.V.message, 100, 5, `Pushing ${value} to sub-result.`);
+ this
+ .instruct(Itemgroup.opacity, 1, 0, index, index, 1)
+ .instruct(Itemgroup.text, 1, 0, index, value)
+ .instruct(Itemgroup.message, 0, 100, 5, `Pushing ${value} to sub-result.`);
};
//
this.updateComparisons = function() {
- this.V.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`);
+ this.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`);
};
};
MergeSort.prototype = Object.create(Sorter.prototype);
+/**
+ *
+ */
+MergeSort.prototype.init = function() {
+ var len = this.shuffled.length;
+
+ this
+ .instruct(Itemgroup.items, 0, 0, len)
+ .instruct(Itemgroup.items, 1, 0, len)
+ .instruct(Itemgroup.items, 2, 0, len)
+
+ for (var i = 0; i < len; i++) {
+ this.instruct(Itemgroup.text, 0, 0, i, this.shuffled[i]);
+ }
+
+ this
+ .instruct(Itemgroup.foreground, 0, 0, 0, len, Visualizer.fg0)
+ .instruct(Itemgroup.background, 0, 0, 0, len, Visualizer.bg0)
+
+ .instruct(Itemgroup.opacity, 1, 0, 0, 0, len)
+ .instruct(Itemgroup.foreground, 1, 0, 0, len, Visualizer.fg1)
+ .instruct(Itemgroup.background, 1, 0, 0, len, Visualizer.bg1)
+
+ .instruct(Itemgroup.opacity, 2, 0, 0, 0, len)
+ .instruct(Itemgroup.foreground, 2, 0, 0, len, Visualizer.fg2)
+ .instruct(Itemgroup.background, 2, 100, 0, len, Visualizer.bg2)
+
+
+ this
+ .instruct(Itemgroup.swap, 0, 1000, 0, 1)
+ .instruct(Itemgroup.swap, 0, 1000, 1, 2)
+ .instruct(Itemgroup.swap, 0, 1000, 2, 3)
+ .instruct(Itemgroup.swap, 0, 1000, 3, 2)
+ .instruct(Itemgroup.swap, 0, 1000, 2, 1)
+ .instruct(Itemgroup.swap, 0, 1000, 1, 0)
+};
+
/**
*
*/
MergeSort.prototype.sort = function(arr, start, end) {
- this.initSort(arr, start, end);
+ this.reset(arr, start, end);
if (arr.length === 0) {
return arr;
@@ -98,7 +122,7 @@ MergeSort.prototype.sort = function(arr, start, end) {
if (start === end) {
this.splitSingle(start);
- return new Array(arr[start]);
+ return [arr[start]];
}
@@ -108,10 +132,10 @@ MergeSort.prototype.sort = function(arr, start, end) {
var arr1 = this.sort(arr, start, mid);
var arr2 = this.sort(arr, mid + 1, end);
- this.preMerge(arr1, arr2, start, mid, end);
+ this.preMerge(start, mid, end, arr.length);
var result = this.merge(arr1, arr2);
+ this.postMerge(arr.length);
- this.postMerge();
return result;
};
@@ -120,28 +144,28 @@ MergeSort.prototype.sort = function(arr, start, end) {
*/
MergeSort.prototype.merge = function(arr1, arr2) {
var result = [];
- var e;
+ var n;
while (arr1.length > 0 || arr2.length > 0) {
if (arr1.length === 0) {
- e = arr2.shift();
- result.push(e);
- this.midMerge(result.length, e.value, 'One element left to merge.');
+ n = arr2.shift();
+ result.push(n);
+ this.midMerge(result.length, n, 'One element left to merge.');
}
else if (arr2.length === 0) {
- e = arr1.shift();
- result.push(e);
- this.midMerge(result.length, e.value, 'One element left to merge.');
+ n = arr1.shift();
+ result.push(n);
+ this.midMerge(result.length, n, 'One element left to merge.');
}
- else if (arr1[0].value <= arr2[0].value) {
- e = arr1.shift()
- result.push(e);
- this.midMerge(result.length, e.value, `${e.value} <= ${arr2[0].value}`);
+ else if (arr1[0] <= arr2[0]) {
+ n = arr1.shift()
+ result.push(n);
+ this.midMerge(result.length, n, `${n} <= ${arr2[0]}`);
}
else {
- e = arr2.shift();
- result.push(e);
- this.midMerge(result.length, e.value, `${arr1[0].value} > ${e.value}`);
+ n = arr2.shift();
+ result.push(n);
+ this.midMerge(result.length, n, `${arr1[0]} > ${n}`);
}
this.comparisons++;
diff --git a/js/sorter.js b/js/sorter.js
index 03b3c9c..292173c 100644
--- a/js/sorter.js
+++ b/js/sorter.js
@@ -1,7 +1,14 @@
/**
*
*/
-var Sorter = function() {};
+var Sorter = function() {
+ this.data = [];
+ this.shuffled = [];
+ this.ordered = [];
+
+ this.actions = [];
+ this.comparisons = [];
+};
// NOTE fisher-yates, http://bost.ocks.org/mike/algorithms/
/**
@@ -22,40 +29,49 @@ Sorter.prototype.shuffle = function(arr) {
/**
*
*/
-Sorter.prototype.generate = function(n) {
- var arr = [];
- var v;
- for (var i = 0; i < n; i++) {
- v = Math.floor(i * 255 / n);
- arr.push({
- value: v,
- fill: `rgb(0, 0, ${v})`
- });
- };
+Sorter.prototype.swap = function(arr, i, j) {
+ var tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+};
- return arr;
+/**
+ *
+ */
+Sorter.prototype.sort = function() {
+ throw new Error('Sorter.sort() method override required.');
};
/**
*
*/
-Sorter.prototype.swap = function(arr, i, j) {
- // console.info(`swapping ${arr[i].value} and ${arr[j].value}`)
- var tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
+Sorter.prototype.init = function() {
+ throw new Error('Sorter.init() method override required.');
};
/**
*
*/
-Sorter.prototype.sort = function(instruction) {
- throw new Error('Sorter.sort() method override required.');
+Sorter.prototype.instruct = function() {
+ this.actions.push(arguments);
+ return this;
};
/**
*
*/
-Sorter.prototype.addInstruction = function(instruction) {
- throw new Error('Sorter.addInstruction() method override required.');
+Sorter.prototype.generate = function(n) {
+ this.data = [];
+
+ var upper = Math.floor(Math.random() * 300 + n);
+ for (var i = 0; i < n; i++) {
+ this.data.push(Math.floor(i * upper / n));
+ };
+
+ this.shuffled = this.shuffle(this.data);
+ this.ordered = this.shuffled.slice();
+ this.init();
+ // this.sort(this.ordered, 0, this.ordered.length - 1);
+
+ return this.actions;
};
diff --git a/js/visualizer-actions.js b/js/visualizer-actions.js
deleted file mode 100644
index 06b9287..0000000
--- a/js/visualizer-actions.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- *
- */
-Visualizer.prototype.swap = function(delay, indexA, indexB) {
- // NOTE Two way binding here between dataset and function parameter?
- // NOTE swapping will not reorder index and i parameter will be off
- // NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
- this.groups
- .transition().duration(delay)
- .attr('transform', function doTransform(d) {
- if (d.index === indexA) {
- d.index = indexB;
- }
- else if (d.index === indexB) {
- d.index = indexA;
- }
-
- return `translate(${Visualizer.calculateX(d.index)}, ${Visualizer.itemY})`;
- });
-};
-
-/**
- * Highlights a range of indices with a color. End index and color optional.
- */
-Visualizer.prototype.highlight = function(delay, startIndex, endIndex, color) {
- if (endIndex === undefined) {
- endIndex = startIndex;
- }
-
- if (color === undefined) {
- color = 'orangered';
- }
-
- this.groups.each(function(d, i) {
- if (d.index >= startIndex && d.index <= endIndex) {
- d3.select(this).select('rect').attr('fill', color);
- }
- });
-};
-
-/**
- * Un-highlights an index.
- */
-Visualizer.prototype.unhighlight = function() {
- // this.svg.selectAll('.item').attr('fill', function(d) { return d.fill; });
- this.svg.selectAll('.item').attr('fill', '#1A45AC');
-};
-
-/**
- * Greys out an item.
- */
-Visualizer.prototype.fade = function(delay, startIndex, endIndex) {
- this.groups.each(function(d) {
- if (d.index >= startIndex && d.index <= endIndex) {
- d3.select(this).style('opacity', '0.2');
- }
- });
-};
-
-/**
- * Restores all items to un-greyed state.
- */
-Visualizer.prototype.unfade = function() {
- this.groups.each(function(d) {
- d3.select(this).style('opacity', 1);
- });
-};
-
-/**
- * Message updates.
- */
-Visualizer.prototype.message = function(delay, which, msg) {
- var msg = msg || ' ';
- this.parent.querySelector(`.message:nth-child(${which})`).innerHTML = msg;
-};
-
-/**
- *
- */
-Visualizer.prototype.item = function(delay, classname, x, y, text, color) {
- var g = this.svg.append('g')
- .attr('class', classname)
- .attr('transform', `translate(${x}, ${y})`);
-
- g.append('rect').attr('width', Visualizer.itemW)
- .attr('height', Visualizer.itemH)
- .attr('fill', color);
-
- g.append('text').text(text)
- .attr('fill', '#aaa')
- .attr('font-size', 10)
- .attr('font-family', 'sans-serif')
- .attr('transform', function doTransform(d) {
- return `rotate(90 0,0), translate(5, -3)`;
- });
-};
-
-/**
- *
- */
-Visualizer.prototype.removeSecondary = function() {
- this.svg.selectAll('.secondary').remove();
-};
-
-/**
- *
- */
-Visualizer.prototype.removeTertiary = function() {
- this.svg.selectAll('.tertiary').remove();
-};
-
-/**
- *
- */
-Visualizer.prototype.remove = function(delay, id) {
- this.svg.select(`#${id}`).remove();
-};
-
-/**
- *
- */
-// Visualizer.prototype.move = function()
diff --git a/js/visualizer-inits.js b/js/visualizer-dom.js
similarity index 80%
rename from js/visualizer-inits.js
rename to js/visualizer-dom.js
index d7dce74..a327dc0 100644
--- a/js/visualizer-inits.js
+++ b/js/visualizer-dom.js
@@ -3,51 +3,23 @@
/**
*
*/
-Visualizer.prototype.initItems = function(n) {
- var data = this.sorter.generate(n);
- var shuffled = this.sorter.shuffle(data);
- var ordered = Object.create(shuffled);
- ordered = this.sorter.sort(ordered, 0, ordered.length - 1);
-
- // A swap on the dataset will not take effect until after transition is complete, so custom index is required.
- var n = 0;
- for (var i in shuffled) {
- shuffled[i].index = n++;
- }
-
- if (this.svg !== undefined) {
- this.svg.remove();
- }
-
- this.actionIndex = 0;
- this.svg = d3.select(this.parent).append('svg')
- .attr('class', 'sorter-svg');
-
- // Items
- this.groups = this.svg.selectAll('g').data(shuffled).enter().insert('g')
- .attr('transform', `translate(0, ${Visualizer.padding})`);
-
- this.groups.append('rect')
- .attr('class', 'item')
- .attr('height', Visualizer.itemH)
- .attr('width', Visualizer.itemW)
- // .attr('fill', function doFill(d) { return d.fill; });
- .attr('fill', '#1A45AC');
-
- this.groups.transition(500)
- .attr('transform', function doTransform(d, i) {
- return `translate(${i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding}, ${Visualizer.padding})`;
- });
-
- // Item labels
- this.groups.append('text')
- .text(function t(d) { return d.value; })
- .attr('fill', '#aaa')
- .attr('font-size', 10)
- .attr('font-family', 'sans-serif')
- .attr('transform', function doTransform(d) {
- return `rotate(90 0,0), translate(5, -3)`;
- });
+Visualizer.prototype.initSvg = function() {
+ var svg = d3.select(this.parent).append('svg').attr('class', 'sorter-svg');
+ var groups = [];
+
+ groups.push(svg.append('g')
+ .attr('transform', `translate(0, 0)`)
+ );
+
+ groups.push(svg.append('g')
+ .attr('transform', `translate(0, ${Visualizer.padding + Visualizer.itemH})`)
+ );
+
+ groups.push(svg.append('g')
+ .attr('transform', `translate(0, ${Visualizer.padding * 2 + Visualizer.itemH * 2})`)
+ );
+
+ return groups;
};
/**
diff --git a/js/visualizer.js b/js/visualizer.js
index 420aa7f..0ecda9f 100644
--- a/js/visualizer.js
+++ b/js/visualizer.js
@@ -3,9 +3,11 @@
*/
function Visualizer(parent) {
this.actions = [];
+ this.actionIndex = 0;
this.parent = parent;
this.sorter = null;
this.paused = true;
+ this.groups = this.initSvg();
var sorterSidebarContainer = document.createElement('div');
sorterSidebarContainer.className = 'sorter-sidebar';
@@ -25,60 +27,51 @@ function Visualizer(parent) {
switch(parent.attributes['data-algorithm'].value) {
case 'quick':
- this.sorter = new QuickSort(this);
+ this.sorter = new QuickSort();
break;
case 'merge':
- this.sorter = new MergeSort(this);
+ this.sorter = new MergeSort();
break;
case 'selection':
- this.sorter = new SelectionSort(this);
+ this.sorter = new SelectionSort();
break;
case 'bubble':
- this.sorter = new BubbleSort(this);
+ this.sorter = new BubbleSort();
break;
case 'insertion':
- this.sorter = new InsertionSort(this);
+ this.sorter = new InsertionSort();
break;
case 'shell':
- this.sorter = new ShellSort(this);
+ this.sorter = new ShellSort();
break;
case 'radix':
- this.sorter = new RadixSort(this);
+ this.sorter = new RadixSort();
break;
default:
throw new Error('Unrecognized sort type.');
}
- this.initItems(10);
+ this.actions = this.sorter.generate(10);
};
-// Static properties (mutable)
+// Static properties (global, mutable)
Visualizer.spacerW = 5;
Visualizer.itemW = 14;
Visualizer.itemH = 50;
Visualizer.padding = 10;
-
-/**
- * Static.
- */
-Visualizer.calculateX = function(index) {
- return Visualizer.spacerW + index * (Visualizer.itemW + Visualizer.spacerW)
-};
-
-/**
- *
- */
-Visualizer.prototype.instruct = function() {
- this.actions.push(arguments);
- return this;
-};
+Visualizer.bg0 = '#284A8F';
+Visualizer.bg1 = '#C25C49';
+Visualizer.bg2 = '#CCCC53';
+Visualizer.fg0 = '#e7e7e7';
+Visualizer.fg1 = '#e7e7e7';
+Visualizer.fg2 = '#000000';
/**
* Instructions contain a string with the name of a function in this object which is called to perform an action.
@@ -89,30 +82,33 @@ Visualizer.prototype.go = function() {
}
var obj = this.actions[this.actionIndex];
- var instruction = new Array();
+ var action = new Array();
for (var key in obj) {
if (obj[key].hasOwnProperty) {
- instruction.push(obj[key]);
+ action.push(obj[key]);
}
}
- var delay = instruction[1];
- var args = instruction.slice(1);
+ action[1] = this.groups[action[1]];
+ var delay = action[2];
+ var args = action.slice(1);
+
+ action[0].apply(this, args);
// TODO add tabs for best/worst cases
// TODO add links to stats
// TODO fix init slider
// TODO heap sort
// TODO extra memory
- // TODO width and height updates
+ // TODO width update
+ // TODO disable next button if no further actions and during action
+ // NOTE functional programming discussion
// NOTE interesting (anti?)pattern here.
// NOTE use of call() vs apply() (apply only delivered first array item as string)
// if (typeof operation === 'function') {
- // operation.call(this, instruction);
-
- instruction[0].apply(this, args);
+ // operation.call(this, action);
if (delay === 0) {
this.actionIndex++;