diff --git a/index.html b/index.html
index 846886f..52788fc 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,21 @@
diff --git a/js/quicksort.js b/js/quicksort.js
index 88d4c46..601edf8 100644
--- a/js/quicksort.js
+++ b/js/quicksort.js
@@ -20,9 +20,9 @@ QuickSort.prototype.instruct = function() {
*/
QuickSort.prototype.sort = function(arr, start, end) {
if (end - start <= 0) {
- this.instruct('highlight', end)
- .instruct('message1', 'Start: ' + start)
- .instruct('message2', 'End: ' + end)
+ // this.instruct('highlight', true, end)
+ // .instruct('message1', true, 'Start: ' + start)
+ // .instruct('message2', true, 'End: ' + end)
return arr;
}
@@ -33,27 +33,30 @@ QuickSort.prototype.sort = function(arr, start, end) {
var pivotval = arr[pivot].value;
var tmp;
- this.instruct('initSection', left, right)
- .instruct('highlight', pivot)
- .instruct('message3', 'Pivot value: ' + pivotval);
+ this//.instruct('initSection', left, right)
+ .instruct('marker1', true, left, 'L')
+ .instruct('marker2', true, right, 'R');
+ // .instruct('unhighlight')
+ // .instruct('highlight', true, pivot)
+ // .instruct('message3', false, 'Pivot value: ' + pivotval);
while (left <= right) {
while (arr[left].value < pivotval) {
left++;
this.comparisons++;
- this.instruct('marker1', left, 'Left')
- .instruct('message1', 'Left: ' + left)
- .instruct('stats1', 'Comparisons: ' + this.comparisons)
+ this.instruct('marker1', true, left)
+ .instruct('message1', false, 'Left: ' + left)
+ .instruct('stats1', false, 'Comparisons: ' + this.comparisons)
}
while (arr[right].value > pivotval) {
right--;
this.comparisons++;
- this.instruct('marker2', right, 'Right')
- .instruct('message2', 'Right: ' + right)
- .instruct('stats1', 'Comparisons: ' + this.comparisons)
+ this.instruct('marker2', true, right)
+ .instruct('message2', false, 'Right: ' + right)
+ .instruct('stats1', false, 'Comparisons: ' + this.comparisons)
}
if (left <= right) {
@@ -65,12 +68,12 @@ QuickSort.prototype.sort = function(arr, start, end) {
right--;
this.swaps++;
- this.instruct('swap', left, right)
- .instruct('stats2', 'Swaps: ' + this.swaps)
- .instruct('message1', 'Left: ' + left)
- .instruct('message2', 'Right: ' + right)
- .instruct('marker1', left)
- .instruct('marker2', right);
+ this//.instruct('swap', left, right)
+ .instruct('stats2', false, 'Swaps: ' + this.swaps)
+ .instruct('message1', false, 'Left: ' + left)
+ .instruct('message2', false, 'Right: ' + right)
+ .instruct('marker1', true, left)
+ .instruct('marker2', true, right);
}
}
diff --git a/js/sorter.js b/js/sorter.js
index d4df3df..03b3c9c 100644
--- a/js/sorter.js
+++ b/js/sorter.js
@@ -24,9 +24,12 @@ 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: Math.floor(i * 255 / n),
+ value: v,
+ fill: `rgb(0, 0, ${v})`
});
};
diff --git a/js/visualizer-actions.js b/js/visualizer-actions.js
index 9b7eb9a..7cbc372 100644
--- a/js/visualizer-actions.js
+++ b/js/visualizer-actions.js
@@ -1,125 +1,155 @@
/**
* Instructions contain a string with the name of a function in this object which is called to perform an action.
*/
-Visualizer.prototype.actions = {
- /**
- *
- */
- initSection: function() {
- console.warn('INIT SECTION');
- },
-
- /**
- *
- */
- swap: function(indexA, indexB) {
- console.warn('SWAP');
- // Move up
- // 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(400)
- // .attr('transform', function doTransform(d) {
- // if (d.index === indexA) {
- // d.index = indexB;
- // }
- // else if (d.index === indexB) {
- // d.index = indexA;
- // }
-
- // return `translate(${d.index * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
- // })
- },
-
- /**
- * Highlights an index.
- */
- highlight: function(index) {
- console.warn('HIGHLIGHT');
- },
-
- /**
- * Un-highlights an index.
- */
- unhighlight: function(index) {
- console.warn('UNHIGHLIGHT');
- },
-
- // /**
- // * Greys out an item.
- // */
- // fade: function(startIndex, endIndex) {
- // console.log(`fading from ${startIndex} to ${endIndex}`)
-
- // this.svg.selectAll('rect')
- // // NOTE this replaces the fill function reference for each rectangle - key point!
- // .attr('fill', function fill(d) {
- // if (d.index >= startIndex && d.index <= endIndex) {
- // console.log(`${d.index} to ${d.fade}`)
- // return d.fade;
+Visualizer.prototype.initSection = function() {
+ // console.warn('INIT SECTION');
+};
+
+/**
+ *
+ */
+Visualizer.prototype.swap = function(indexA, indexB) {
+ // console.warn('SWAP');
+// Move u;
+// 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(400)
+ // .attr('transform', function doTransform(d) {
+ // if (d.index === indexA) {
+ // d.index = indexB;
// }
- // return d.fill;
- // });
- // };
-
- // /**
- // * Restores all items to un-greyed state.
- // */
- // unfade: function() {
- // this.svg.selectAll('rect')
- // .attr('fill', function fill(d) {
- // console.log(`unfade ${d.index}`)
- // return d.fill;
+ // else if (d.index === indexB) {
+ // d.index = indexA;
+ // }
+
+ // return `translate(${d.index * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
// })
- // };
-
- /**
- * Moves marker 1 to an index and sets its text label.
- */
- marker1: function(index, label) {
- console.warn('MARKER1')
- },
-
- /**
- * Moves marker 2 to an index and sets its text label.
- */
- marker2: function(index, label) {
- console.warn('MARKER2')
- },
-
- /**
- * Updates message in stats 1 div.
- */
- stats1: function(message) {
- console.warn('STATS1')
- },
-
- /**
- * Updates message in stats 2 div.
- */
- stats2: function(message) {
- console.warn('STATS2')
- },
-
- /**
- * Updates message in message 1 div.
- */
- message1: function(message) {
- console.warn('MESSAGE1')
- },
-
- /**
- * Updates message in message 2 div.
- */
- message2: function(message) {
- console.warn('MESSAGE2')
- },
-
- /**
- * Updates message in message 3 div.
- */
- message3: function(message) {
- console.warn('MESSAGE3')
- },
+};
+
+/**
+ * Highlights an index.
+ */
+Visualizer.prototype.highlight = function(args) {
+ var index = args[2];
+
+ if (index < 0) {
+ console.error('Trying to highlight index of ' + index);
+ return;
+ }
+
+ this.svg.select(`g:nth-child(${index})`).select('rect').attr('fill', 'red');
+};
+
+/**
+ * Un-highlights an index.
+ */
+Visualizer.prototype.unhighlight = function() {
+ this.svg.selectAll('.item').attr('fill', function(d) { return d.fill; });
+};
+
+// /**
+// * Greys out an item.
+// */
+// Visualizer.prototype.fade = function(startIndex, endIndex) {
+// console.log(`fading from ${startIndex} to ${endIndex}`);
+// this.svg.selectAll('rect')
+// // NOTE this replaces the fill function reference for each rectangle - key point!
+// .attr('fill', function fill(d) {
+// if (d.index >= startIndex && d.index <= endIndex) {
+// console.log(`${d.index} to ${d.fade}`)
+// return d.fade;
+// }
+// return d.fill;
+// });
+// };
+
+// /**
+// * Restores all items to un-greyed state.
+// */
+// Visualizer.prototype.unfade = function() {
+// this.svg.selectAll('rect')
+// .attr('fill', functi;n fill(d) {
+// console.log(`unfade ${d.index}`)
+// return d.fill;
+// })
+// };
+
+/**
+ * Moves marker 1 to an index and sets its text label.
+ */
+Visualizer.prototype.marker1 = function(args) {
+ var index = args[2];
+ var label = args[3];
+
+ if (label !== undefined) {
+ label = label[0].toString();
+ this.svg.select('#marker1 text').text(label)
+ }
+
+ var x = index * (Visualizer.itemW + Visualizer.spacerW);
+
+ this.svg.select('#marker1')
+ .transition().duration(300)
+ .attr('transform', `translate(${x},0)`)
+};
+
+/**
+ * Moves marker 2 to an index and sets its text label.
+ */
+Visualizer.prototype.marker2 = function(args) {
+ var index = args[2];
+ var label = args[3];
+
+ if (label !== undefined) {
+ label = label[0].toString();
+ this.svg.select('#marker2 text').text(label)
+ }
+
+ var x = index * (Visualizer.itemW + Visualizer.spacerW);
+
+ this.svg.select('#marker2')
+ .transition().duration(300)
+ .attr('transform', `translate(${x},0)`)
+};
+
+/**
+ * Updates message in stats 1 div.
+ */
+Visualizer.prototype.stats1 = function(args) {
+ var msg = args[2];
+ this.parent.querySelectorAll('.stat')[0].innerHTML = msg;
+};
+
+/**
+ * Updates message in stats 2 div.
+ */
+Visualizer.prototype.stats2 = function(args) {
+ var msg = args[2];
+ this.parent.querySelectorAll('.stat')[1].innerHTML = msg;
+};
+
+/**
+ * Updates message in message 1 div.
+ */
+Visualizer.prototype.message1 = function(args) {
+ var msg = args[2];
+ this.parent.querySelector('.message:nth-child(2)').innerHTML = msg;
+};
+
+/**
+ * Updates message in message 2 div.
+ */
+Visualizer.prototype.message2 = function(args) {
+ var msg = args[2];
+ this.parent.querySelector('.message:nth-child(2)').innerHTML = msg;
+};
+
+/**
+ * Updates message in message 3 div.
+ */
+Visualizer.prototype.message3 = function(args) {
+ var msg = args[2];
+ this.parent.querySelector('.message:nth-child(3)').innerHTML = msg;
};
diff --git a/js/visualizer-inits.js b/js/visualizer-inits.js
index 6a5abc5..9d13efb 100644
--- a/js/visualizer-inits.js
+++ b/js/visualizer-inits.js
@@ -9,23 +9,26 @@ Visualizer.prototype.initItems = function(n) {
// A swap on the dataset will not take effect until after transition is complete, so custom index is required.
var n = 0;
- for (i in shuffled) {
+ for (var i in shuffled) {
shuffled[i].index = n++;
}
+ // Items
this.groups = this.svg.selectAll('g').data(shuffled).enter().append('g')
.attr('transform', `translate(0, ${Visualizer.itemY})`);
this.groups.append('rect')
+ .attr('class', 'item')
.attr('height', Visualizer.itemH)
.attr('width', Visualizer.itemW)
- .attr('fill', function doFill(d) { return `rgb(0, 0, ${d.value})`; });
+ .attr('fill', function doFill(d) { return d.fill; });
this.groups.transition(500)
.attr('transform', function doTransform(d, i) {
return `translate(${i * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
});
+ // Item labels
this.groups.append('text')
.text(function t(d) { return d.value; })
.attr('fill', '#aaa')
@@ -35,24 +38,54 @@ Visualizer.prototype.initItems = function(n) {
return `rotate(90 0,0), translate(5, -3)`;
});
+ // Markers
+ var m1 = this.svg.append('g')
+ .attr('class', 'marker')
+ .attr('id', 'marker1');
+
+ m1.append('rect')
+ .attr('height', Visualizer.itemW)
+ .attr('width', Visualizer.itemW);
+
+ m1.append('text')
+ .attr('text-anchor', 'middle')
+ .attr('x', (Visualizer.itemW / 2))
+ .attr('y', 10);
+
+ var m2 = this.svg.append('g')
+ //temp
+ .attr('transform', 'translate(19,0)')
+ //temp
+ .attr('class', 'marker')
+ .attr('id', 'marker2');
+
+ m2.append('rect')
+ .attr('height', Visualizer.itemW)
+ .attr('width', Visualizer.itemW);
+
+ m2.append('text')
+ .attr('text-anchor', 'middle')
+ .attr('x', (Visualizer.itemW / 2))
+ .attr('y', 10);
+
setTimeout(this.followInstruction.bind(this, 0), 500);
};
/**
*
*/
-Visualizer.prototype.initComments = function() {
+Visualizer.prototype.initMessages = function() {
var container = document.createElement('div');
- container.className = 'comment-container';
+ container.className = 'message-container';
var div1 = document.createElement('div');
- div1.className = 'comment';
+ div1.className = 'message';
var div2 = document.createElement('div');
- div2.className = 'comment';
+ div2.className = 'message';
var div3 = document.createElement('div');
- div3.className = 'comment';
+ div3.className = 'message';
container.appendChild(div1);
container.appendChild(div2);
@@ -65,6 +98,15 @@ Visualizer.prototype.initComments = function() {
*
*/
Visualizer.prototype.initRange = function() {
+ var rangeInput = function(label, event) {
+ label.innerHTML = 'Number of items (n) = ' + event.target.value;
+ };
+
+ var rangeChange = function(event) {
+ this.init.items(event.target.value);
+ };
+
+
var container = document.createElement('div');
container.className = 'range-container';
@@ -77,14 +119,14 @@ Visualizer.prototype.initRange = function() {
range.setAttribute('value', 40);
range.setAttribute('min', 5);
range.setAttribute('max', 80);
- range.addEventListener('change', this.rangeChange.bind(this));
- range.addEventListener('input', this.rangeInput.bind(null, msg));
+ range.addEventListener('change', rangeChange.bind(this));
+ range.addEventListener('input', rangeInput.bind(null, msg));
container.appendChild(range);
container.appendChild(msg);
return container;
-};
+},
/**
*
@@ -110,13 +152,13 @@ Visualizer.prototype.initControls = function() {
reset.title = 'Restart'
reset.addEventListener('click', onclick);
- var msg1 = document.createElement('div');
- msg1.className = 'msg';
- msg1.innerHTML = 'Swaps: 999';
+ var stat1 = document.createElement('div');
+ stat1.className = 'stat';
+ stat1.innerHTML = 'Swaps: 999';
- var msg2 = document.createElement('div');
- msg2.className = 'msg';
- msg2.innerHTML = 'Comparisons: 999';
+ var stat2 = document.createElement('div');
+ stat2.className = 'stat';
+ stat2.innerHTML = 'Comparisons: 999';
var container = document.createElement('div');
container.className = 'controls-container';
@@ -125,8 +167,8 @@ Visualizer.prototype.initControls = function() {
container.appendChild(back);
container.appendChild(play);
container.appendChild(forward);
- container.appendChild(msg1);
- container.appendChild(msg2);
+ container.appendChild(stat1);
+ container.appendChild(stat2);
return container;
};
diff --git a/js/visualizer.js b/js/visualizer.js
index e9c45fd..2df07f6 100644
--- a/js/visualizer.js
+++ b/js/visualizer.js
@@ -13,8 +13,8 @@ function Visualizer(parent) {
var controls = this.initControls();
parent.querySelector('.bottom').appendChild(controls);
- var comments = this.initComments();
- parent.querySelector('.bottom').appendChild(comments);
+ var messages = this.initMessages();
+ parent.querySelector('.bottom').appendChild(messages);
var range = this.initRange();
parent.querySelector('.bottom').appendChild(range);
@@ -81,18 +81,18 @@ Visualizer.prototype.followInstruction = function(index) {
console.log(i);
// NOTE interesting pattern here
- if (typeof this.actions[i[0]] === 'function') {
- this.actions[i[0]](i);
+ if (typeof this[i[0]] === 'function') {
+ this[i[0]](i);
- if (this.actions[i[1]] === true) {
- setTimeout(this.followInstruction.bind(this, index + 1), 400);
+ if (i[1] === true) {
+ setTimeout(this.followInstruction.bind(this, index + 1), 400);
}
else {
this.followInstruction(index + 1);
}
}
// TODO document this
- else if (this.actions[i[0]] !== undefined) {
+ else if (this[i[0]] !== undefined) {
console.warn(this[i[0]]);
}
else {
@@ -100,17 +100,3 @@ Visualizer.prototype.followInstruction = function(index) {
throw new Error('Unidentified instruction.');
}
};
-
-/**
- *
- */
-Visualizer.prototype.rangeInput = function(label, event) {
- label.innerHTML = 'Number of items (n) = ' + event.target.value;
-};
-
-/**
- *
- */
-Visualizer.prototype.rangeChange = function(event) {
- this.init(event.target.value);
-};
diff --git a/res/distproth-webfont.eot b/res/distproth-webfont.eot
new file mode 100644
index 0000000..e2edfd0
Binary files /dev/null and b/res/distproth-webfont.eot differ
diff --git a/res/distproth-webfont.svg b/res/distproth-webfont.svg
new file mode 100644
index 0000000..3801804
--- /dev/null
+++ b/res/distproth-webfont.svg
@@ -0,0 +1,2226 @@
+
+
+
\ No newline at end of file
diff --git a/res/distproth-webfont.ttf b/res/distproth-webfont.ttf
new file mode 100644
index 0000000..8d2467b
Binary files /dev/null and b/res/distproth-webfont.ttf differ
diff --git a/res/distproth-webfont.woff b/res/distproth-webfont.woff
new file mode 100644
index 0000000..7f8586e
Binary files /dev/null and b/res/distproth-webfont.woff differ
diff --git a/res/distproth-webfont.woff2 b/res/distproth-webfont.woff2
new file mode 100644
index 0000000..f26af13
Binary files /dev/null and b/res/distproth-webfont.woff2 differ
diff --git a/res/stylesheet.css b/res/stylesheet.css
new file mode 100644
index 0000000..3631f04
--- /dev/null
+++ b/res/stylesheet.css
@@ -0,0 +1,16 @@
+/* Generated by Font Squirrel (http://www.fontsquirrel.com) on October 11, 2015 */
+
+
+
+@font-face {
+ font-family: 'district_prothin';
+ src: url('distproth-webfont.eot');
+ src: url('distproth-webfont.eot?#iefix') format('embedded-opentype'),
+ url('distproth-webfont.woff2') format('woff2'),
+ url('distproth-webfont.woff') format('woff'),
+ url('distproth-webfont.ttf') format('truetype'),
+ url('distproth-webfont.svg#district_prothin') format('svg');
+ font-weight: normal;
+ font-style: normal;
+
+}
\ No newline at end of file