Television Simulator/Quine: A quine is a program that prints its own source code. However, that does *not* mean it is easy to read its printed output.
eval(I="S='eval(I='+JSON.stringify(I)+')';M=Math;X=M.random;B=document.body;B.bgColor='gray';with(B.children.c)width=D=448,height=500,B.style.paddingLeft=(innerWidth-D)/2+'px',C=getContext('2d');with(C){strokeStyle='#999';lineWidth=5;moveTo(Q=96,9);lineTo(224,K=166);stroke(lineTo(352,9));C[L='fillStyle']='#333';fillRect(F=Y=0,142,D,358);C[L]='#000';for(J=422;J>24;J-=2)fillRect(J,476,J<175|J>283,18);C[L]=E='#fff';font='bold 18px serif';translate(J,K);scale(2,1);fillText('JS1K',80,324);scale(.5,1);font='bold 64px monospace'}setInterval('for(i=7;i--;)C[L]=\"#\"+\"ccccc00cc0c0c0cc0000c\".substr(3*i,3),C.fillRect(57*i,0,57,H);C[L]=E;C.fillText(S.substr(F>8&&F-9&~1,9),30,(150+Y*99)%H);Q+=64*X()-32|0;if(Q<0|F>1047)Q=0;if(Q>255)Q=255;if(Q<16)Y=5;q=M.pow(Q/255,.25);d=C.getImageData(J,K,400,H);p=d.data;for(j=0;j<48E4;j+=4){p[j]*=q;p[b=j+1]*=q;p[c=j+2]*=q;r=X()*256|0;if(r>M.max(Q,p[j],p[b],p[c]))p[j]=p[b]=p[c]=r;if(Q<64)p[j]=p[b]=p[c]=(p[j]+p[b]+p[c])/3}C.putImageData(d,J,K);F++;Y&&Y--',H=300)")
ZXZhbChJPSJTPSdldmFsKEk9JytKU09OLnN0cmluZ2lmeShJKSsnKSc7TT1NYXRoO1g9TS5yYW5kb207Qj1kb2N1bWVudC5ib2R5O0IuYmdDb2xvcj0nZ3JheSc7d2l0aChCLmNoaWxkcmVuLmMpd2lkdGg9RD00NDgsaGVpZ2h0PTUwMCxCLnN0eWxlLnBhZGRpbmdMZWZ0PShpbm5lcldpZHRoLUQpLzIrJ3B4JyxDPWdldENvbnRleHQoJzJkJyk7d2l0aChDKXtzdHJva2VTdHlsZT0nIzk5OSc7bGluZVdpZHRoPTU7bW92ZVRvKFE9OTYsOSk7bGluZVRvKDIyNCxLPTE2Nik7c3Ryb2tlKGxpbmVUbygzNTIsOSkpO0NbTD0nZmlsbFN0eWxlJ109JyMzMzMnO2ZpbGxSZWN0KEY9WT0wLDE0MixELDM1OCk7Q1tMXT0nIzAwMCc7Zm9yKEo9NDIyO0o+MjQ7Si09MilmaWxsUmVjdChKLDQ3NixKPDE3NXxKPjI4MywxOCk7Q1tMXT1FPScjZmZmJztmb250PSdib2xkIDE4cHggc2VyaWYnO3RyYW5zbGF0ZShKLEspO3NjYWxlKDIsMSk7ZmlsbFRleHQoJ0pTMUsnLDgwLDMyNCk7c2NhbGUoLjUsMSk7Zm9udD0nYm9sZCA2NHB4IG1vbm9zcGFjZSd9c2V0SW50ZXJ2YWwoJ2ZvcihpPTc7aS0tOylDW0xdPVwiI1wiK1wiY2NjY2MwMGNjMGMwYzBjYzAwMDBjXCIuc3Vic3RyKDMqaSwzKSxDLmZpbGxSZWN0KDU3KmksMCw1NyxIKTtDW0xdPUU7Qy5maWxsVGV4dChTLnN1YnN0cihGPjgmJkYtOSZ+MSw5KSwzMCwoMTUwK1kqOTkpJUgpO1ErPTY0KlgoKS0zMnwwO2lmKFE8MHxGPjEwNDcpUT0wO2lmKFE+MjU1KVE9MjU1O2lmKFE8MTYpWT01O3E9TS5wb3coUS8yNTUsLjI1KTtkPUMuZ2V0SW1hZ2VEYXRhKEosSyw0MDAsSCk7cD1kLmRhdGE7Zm9yKGo9MDtqPDQ4RTQ7ais9NCl7cFtqXSo9cTtwW2I9aisxXSo9cTtwW2M9aisyXSo9cTtyPVgoKSoyNTZ8MDtpZihyPk0ubWF4KFEscFtqXSxwW2JdLHBbY10pKXBbal09cFtiXT1wW2NdPXI7aWYoUTw2NClwW2pdPXBbYl09cFtjXT0ocFtqXStwW2JdK3BbY10pLzN9Qy5wdXRJbWFnZURhdGEoZCxKLEspO0YrKztZJiZZLS0nLEg9MzAwKSIp
/*global window: false*/
"use strict";
/* This is an unoptimized version of my JS1K entry
* titled "Television Simulator/Quine." It is not
* the original code before I started optimizing;
* instead, I have maintained this code during the
* process so that it produces (nearly) identical
* output but is easy to read and passes JSLint
* using its strictest settings.
*
* Copyright © 2010 Ideal Machine. All rights reserved.
* DO NOT USE THIS CODE IN OTHER PROJECTS.
*/
var quality = 96, // Signal quality
frameNo = 0, // Frame count
resync = 0, // Resync timer (for rolling picture code)
colorBars = ["ccc", "cc0", "0cc", "0c0", "c0c", "c00", "00c"]; // Color bar colors
// Set background color, which is HTML "gray" (just a way to save bytes)
var body = window.document.body;
body.style.background = "#808080";
// Set padding
body.style.paddingLeft = (window.innerWidth - 448) / 2 + "px";
// Set canvas dimensions and get context
var B = window.document.getElementById("c");
B.width = 448;
B.height = 500;
var C = B.getContext("2d");
// Draw "TV set" background
//// Antenna
C.strokeStyle = "#999";
C.lineWidth = 5;
C.moveTo(96, 0);
C.lineTo(224, 166);
C.lineTo(352, 0);
C.stroke();
//// Cabinet
C.fillStyle = "#333";
C.fillRect(0, 142, 448, 358);
//// Speaker grille
C.fillStyle = "#000";
for (var xl = 26; xl < 175; xl += 2) {
C.fillRect(xl, 476, 1, 18);
}
for (var xr = 283; xr < 422; xr += 2) {
C.fillRect(xr, 476, 1, 18);
}
//// Brand name
C.fillStyle = "#fff";
C.font = "bold 18px serif";
C.translate(24, 166); // Also need this line for the interval code
C.save();
C.scale(2, 1);
C.fillText("JS1K", 80, 324); // Good enough; text metrics code would be too long
C.restore();
// Set font used for displaying source code
C.font = "bold 64px monospace";
// Periodically draw frames on the canvas
window.setInterval(function () {
var i, n, startChar, signalFade, imageData, data, j, noise;
// Draw color bars - the exact width is sightly greater than 57,
// so there is a small "gap" on the right-hand side.
for (i = 0, n = colorBars.length; i < n; i += 1) {
C.fillStyle = "#" + colorBars[i];
C.fillRect(57 * i, 0, 57, 300);
}
/* Write text - we "cheat" in this version to be more readable,
* but the packed version is actually a valid quine
* (e.g. it does not access the script tag or arguments.callee).
*
* The vertical position of the text is influenced by the resync timer, and
* it seems that using a clipping path is unnecessary with these parameters.
* Only the position of the text needs to vary because all the bars are vertical.
*
* The structure of the quine is basically:
* eval(I="alert('eval('+JSON.stringify(I)+')')")
* It is only 46 characters, 39 characters if you remove alert().
* Am I the first to construct a quine this way? Google didn't find anything.
*/
if (frameNo > 8) {
startChar = Math.floor((frameNo - 9) / 2) * 2;
} else {
startChar = 0;
}
C.fillStyle = "#fff";
C.fillText(window.document.querySelector("script").innerHTML.substr(startChar, 9), 30, (150 + resync * 99) % 300);
// Randomly adjust the "signal quality" a bit, and set the resync
// timer if quality is close to zero (causing a "rolling" picture).
// This part also handles the "sign-off."
quality += Math.floor(Math.random() * 64 - 32);
if (quality < 0 || frameNo > 1047) {
quality = 0;
}
else if (quality > 255) {
quality = 255;
}
if (quality < 16) {
resync = 5;
}
// Compute a signal fade multiplier based on quality
signalFade = Math.pow(quality / 255, 0.25);
// Get image data
imageData = C.getImageData(24, 166, 400, 300);
data = imageData.data;
// For each pixel...
for (j = 0; j < 480000; j += 4) {
// Multiply each component by the signal fade, causing the picture to darken.
data[j] *= signalFade;
data[j + 1] *= signalFade;
data[j + 2] *= signalFade;
// If a random number (0..255) is greater than quality and each of the components,
// then set each component's value to that number to add noise. In this
// way, the noise is always lighter than the signal it is overlaid on.
noise = Math.floor(Math.random() * 256);
if (noise > Math.max(quality, data[j], data[j + 1], data[j + 2])) {
data[j] = data[j + 1] = data[j + 2] = noise;
}
// If quality is low enough, remove color from the frame. This is not the correct
// sRGB luminance formula, but it should be good enough to satisfy the judges :)
if (quality < 64) {
data[j] = data[j + 1] = data[j + 2] = (data[j] + data[j + 1] + data[j + 2]) / 3;
}
}
// Save image data back to the canvas
C.putImageData(imageData, 24, 166);
// Increment frame count and decrement resync timer if necessary
frameNo += 1;
if (resync) {
resync -= 1;
}
}, 300); // do the above every 300 ms