Skip to content

Instantly share code, notes, and snippets.

@xtrntr
Created August 11, 2016 00:27
Show Gist options
  • Save xtrntr/a789b7a8a2632d4e51038db0c53b48eb to your computer and use it in GitHub Desktop.
Save xtrntr/a789b7a8a2632d4e51038db0c53b48eb to your computer and use it in GitHub Desktop.
<html>
<head>
<script src="https://d3js.org/d3.v4.0.0-alpha.22.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
</head>
<body>
<script>
var ASCII = "01010100 01101000 01100101 00100000 01110001 01110101 01101001 01100011 01101011 00100000 01100010 01110010 01101111 01110111 01101110 00100000 01100110 01101111 01111000 00100000 01101010 01110101 01101101 01110000 01110011 00100000 01101111 01110110 01100101 01110010 00100000 01110100 01101000 01100101 00100000 01101100 01100001 01111010 01111001 00100000 01100100 01101111 01100111"
var huffman_encoded = "01110 10110 1010 110 01100 0100 00001 01010 111101 110 111110 1001 001 111111 00000 110 00011 001 111100 110 111010 0100 101111 01111 111000 110 001 111011 1010 1001 110 01011 10110 1010 110 10001 111001 00010 101110 110 10000 001 01101"
var current_block = 0
var uncompressed_data = objectify(ASCII, "ascii")
var compressed_data = objectify(huffman_encoded, "huffman")
var ASCII_len = ASCII.length, //
huffman_len = huffman_encoded.length,
destination_index = 0;
// 960/500 gives a 1.92 ratio
square_width = 10,
cell_size = 20,
body_width = square_width * cell_size
var indexToPixel = function(index) {
row = Math.floor(index / square_width);
col = index % square_width;
return { x: col * cell_size, y: row * cell_size };
};
var svgContainer, rectangle;
svgContainer = d3.select("body").append("svg")
.attr("width", 800)
.attr("height", 800);
// artificial compress is basically the function that takes in both the uncompressed and the compressed data, and at each timestep, substitutes a block of compressed data for a block of uncompressed data. it calls the update function every 5 seconds.
function update(data) {
rectangles = svgContainer.selectAll("rect")
.data(data);
rectangles.enter()
.append("rect")
.attr("width", cell_size)
.attr("height", cell_size)
.style("stroke", function(d) { return "#999999" })
.style("opacity", 1)
.style("stroke-width", function(d) { return "1px" })
rectangles
.style("fill", function(d) {
return (d.value == "0") ? "white" : "black" })
.attr("id", function(d) {
return "square-"+String(d.index); } )
.style("transform", function(d) {
return "translate(" + indexToPixel(d.index).x + "px, " + indexToPixel(d.index).y + "px)"; });
uncompressed_bits = _.filter(uncompressed_data, function(bits) { return bits.block_idx > current_block })
compressed_bits = _.filter(compressed_data, function(bits) { return bits.block_idx <= current_block })
uncompressed_block = _.filter(uncompressed_data, function(bits) { return bits.block_idx == current_block })
compressed_block = _.filter(compressed_data, function(bits) { return bits.block_idx == current_block })
compressed_values = compressed_block.map(function(d) {
return d.value })
compressed_length = compressed_block.length
d3.selectAll("rect")
.filter(function(d) { return d.block_idx == current_block && d.label == "ascii" })
.each(function (d,i) {
d3.select(this)
.transition()
.duration(200)
.style("transform",
function(d) { return "translate(" + (300 + (d.bit_idx % 8) * 40) + "px,300px) scale(2)" })
.transition()
.duration(100)
.style("transform",
function(d) {
if (compressed_length > d.bit_idx)
{
return "translate(" + (300 + (d.bit_idx % 8) * 40) + "px,300px) scale(2)"
} else {
return "translate(" + (300 + compressed_values.indexOf("1") * 40) + "px,300px) scale(2)"}
})
.style("fill", function(d) {
if (compressed_length > d.bit_idx)
{
return (compressed_block[d.bit_idx].value == "0") ? "white" : "black" };
})
.transition()
.duration(200)
.style("transform",
function(d) {
if (compressed_length > d.bit_idx) {
return "translate(" + indexToPixel(compressed_bits.length + d.bit_idx - compressed_length).x + "px, " + indexToPixel(compressed_bits.length + d.bit_idx - compressed_length).y + "px)";
} else {
return "translate(" + indexToPixel(compressed_bits.length + compressed_values.indexOf("1") - compressed_length).x + "px, " + indexToPixel(compressed_bits.length + compressed_values.indexOf("1") - compressed_length).y + "px)";
}})
.transition()
});
console.log(compressed_block.map(function(d) {
return d.value }))
var new_data = compressed_bits.concat(uncompressed_bits);
current_block++;
if (huffman_encoded.replace(/\s+/g, '').length != new_data.length) {
setTimeout(function(d){
update(d);
}, 500, new_data);
}
}
function objectify(data, label) {
var objs = [], index = 0;
var blocks = data.split(" "); // split into blocks
blocks.forEach(function(block, block_idx) {
var bits = block.split("");
bits.forEach(function(bit, bit_idx) {
obj = {
block_idx: block_idx, // this is which block it's a part of
bit_idx: bit_idx, // this is the index of the bit inside the block.
value: bit, // this is the value
index: index++, // this is the index in the whole text. this is the original index. i guess not the "global index" . i really have a difficult time tracking down the bugs... i can't tell if they're mine or they're just me not knowing how to use d3
label: label // ascii or huffman. because i only want to highlight the ascii.
};
objs.push(obj)
});
})
return objs;
}
update(uncompressed_data);
</script>
<style>
body {
margin: 0;
}
.bit {
position: absolute;
width: 20px;
height: 20px;
border: solid 1px #666;
}
</style>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment