Created
August 18, 2014 23:40
-
-
Save Zemnmez/d2e004991b59a0870b51 to your computer and use it in GitHub Desktop.
Puts a coloured div in the top left hand corner that is random and seeded from the hash of the hostname.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function hash(s) { | |
var hash = 0, i, chr, len; | |
if (s.length == 0) return hash; | |
for (i = 0, len = s.length; i < len; i++) { | |
chr = s.charCodeAt(i); | |
hash = ((hash << 5) - hash) + chr; | |
hash |= 0; // Convert to 32bit integer | |
} | |
return hash; | |
} | |
/** | |
* @preserve | |
* LICENSE (MIT) | |
* ------------- | |
* Copyright (c)2014 David Bau. | |
* Permission is hereby granted, free of charge, to any person obtaining | |
* a copy of this software and associated documentation files (the | |
* "Software"), to deal in the Software without restriction, including | |
* without limitation the rights to use, copy, modify, merge, publish, | |
* distribute, sublicense, and/or sell copies of the Software, and to | |
* permit persons to whom the Software is furnished to do so, subject to | |
* the following conditions: | |
* The above copyright notice and this permission notice shall be | |
* included in all copies or substantial portions of the Software. | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
/** | |
* All code is in an anonymous closure to keep the global namespace clean. | |
*/ | |
(function ( | |
global, pool, math, width, chunks, digits, module, define, rngname) { | |
// | |
// The following constants are related to IEEE 754 limits. | |
// | |
var startdenom = math.pow(width, chunks), | |
significance = math.pow(2, digits), | |
overflow = significance * 2, | |
mask = width - 1, | |
// | |
// seedrandom() | |
// This is the seedrandom function described above. | |
// | |
impl = math['seed' + rngname] = function(seed, options, callback) { | |
var key = []; | |
options = (options == true) ? { entropy: true } : (options || {}); | |
// Flatten the seed string or build one from local entropy if needed. | |
var shortseed = mixkey(flatten( | |
options.entropy ? [seed, tostring(pool)] : | |
(seed == null) ? autoseed() : seed, 3), key); | |
// Use the seed to initialize an ARC4 generator. | |
var arc4 = new ARC4(key); | |
// Mix the randomness into accumulated entropy. | |
mixkey(tostring(arc4.S), pool); | |
// Calling convention: what to return as a function of prng, seed, is_math. | |
return (options.pass || callback || | |
// If called as a method of Math (Math.seedrandom()), mutate Math.random | |
// because that is how seedrandom.js has worked since v1.0. Otherwise, | |
// it is a newer calling convention, so return the prng directly. | |
function(prng, seed, is_math_call) { | |
if (is_math_call) { math[rngname] = prng; return seed; } | |
else return prng; | |
})( | |
// This function returns a random double in [0, 1) that contains | |
// randomness in every bit of the mantissa of the IEEE 754 value. | |
function() { | |
var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48 | |
d = startdenom, // and denominator d = 2 ^ 48. | |
x = 0; // and no 'extra last byte'. | |
while (n < significance) { // Fill up all significant digits by | |
n = (n + x) * width; // shifting numerator and | |
d *= width; // denominator and generating a | |
x = arc4.g(1); // new least-significant-byte. | |
} | |
while (n >= overflow) { // To avoid rounding up, before adding | |
n /= 2; // last byte, shift everything | |
d /= 2; // right using integer math until | |
x >>>= 1; // we have exactly the desired bits. | |
} | |
return (n + x) / d; // Form the number within [0, 1). | |
}, shortseed, 'global' in options ? options.global : (this == math)); | |
}; | |
// | |
// ARC4 | |
// | |
// An ARC4 implementation. The constructor takes a key in the form of | |
// an array of at most (width) integers that should be 0 <= x < (width). | |
// | |
// The g(count) method returns a pseudorandom integer that concatenates | |
// the next (count) outputs from ARC4. Its return value is a number x | |
// that is in the range 0 <= x < (width ^ count). | |
// | |
/** @constructor */ | |
function ARC4(key) { | |
var t, keylen = key.length, | |
me = this, i = 0, j = me.i = me.j = 0, s = me.S = []; | |
// The empty key [] is treated as [0]. | |
if (!keylen) { key = [keylen++]; } | |
// Set up S using the standard key scheduling algorithm. | |
while (i < width) { | |
s[i] = i++; | |
} | |
for (i = 0; i < width; i++) { | |
s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))]; | |
s[j] = t; | |
} | |
// The "g" method returns the next (count) outputs as one number. | |
(me.g = function(count) { | |
// Using instance members instead of closure state nearly doubles speed. | |
var t, r = 0, | |
i = me.i, j = me.j, s = me.S; | |
while (count--) { | |
t = s[i = mask & (i + 1)]; | |
r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))]; | |
} | |
me.i = i; me.j = j; | |
return r; | |
// For robust unpredictability discard an initial batch of values. | |
// See http://www.rsa.com/rsalabs/node.asp?id=2009 | |
})(width); | |
} | |
// | |
// flatten() | |
// Converts an object tree to nested arrays of strings. | |
// | |
function flatten(obj, depth) { | |
var result = [], typ = (typeof obj), prop; | |
if (depth && typ == 'object') { | |
for (prop in obj) { | |
try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {} | |
} | |
} | |
return (result.length ? result : typ == 'string' ? obj : obj + '\0'); | |
} | |
// | |
// mixkey() | |
// Mixes a string seed into a key that is an array of integers, and | |
// returns a shortened string seed that is equivalent to the result key. | |
// | |
function mixkey(seed, key) { | |
var stringseed = seed + '', smear, j = 0; | |
while (j < stringseed.length) { | |
key[mask & j] = | |
mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++)); | |
} | |
return tostring(key); | |
} | |
// | |
// autoseed() | |
// Returns an object for autoseeding, using window.crypto if available. | |
// | |
/** @param {Uint8Array|Navigator=} seed */ | |
function autoseed(seed) { | |
try { | |
global.crypto.getRandomValues(seed = new Uint8Array(width)); | |
return tostring(seed); | |
} catch (e) { | |
return [+new Date, global, (seed = global.navigator) && seed.plugins, | |
global.screen, tostring(pool)]; | |
} | |
} | |
// | |
// tostring() | |
// Converts an array of charcodes to a string | |
// | |
function tostring(a) { | |
return String.fromCharCode.apply(0, a); | |
} | |
// | |
// When seedrandom.js is loaded, we immediately mix a few bits | |
// from the built-in RNG into the entropy pool. Because we do | |
// not want to intefere with determinstic PRNG state later, | |
// seedrandom will not call math.random on its own again after | |
// initialization. | |
// | |
mixkey(math[rngname](), pool); | |
// | |
// Nodejs and AMD support: export the implemenation as a module using | |
// either convention. | |
// | |
if (module && module.exports) { | |
module.exports = impl; | |
} else if (define && define.amd) { | |
define(function() { return impl; }); | |
} | |
// End anonymous scope, and pass initial values. | |
})( | |
this, // global window object | |
[], // pool: entropy pool starts empty | |
Math, // math: package containing random, pow, and seedrandom | |
256, // width: each RC4 output is 0 <= x < 256 | |
6, // chunks: at least six RC4 outputs for each double | |
52, // digits: there are 52 significant digits in a double | |
(typeof module) == 'object' && module, // present in node.js | |
(typeof define) == 'function' && define, // present with an AMD loader | |
'random'// rngname: name for Math.random and Math.seedrandom | |
); | |
//generate a colour using the hash as a seed | |
function pageColour() { | |
Math.seedrandom(hash(document.location.host)) | |
return "rgb("+[0,0,0].map(rndUint8)+")" | |
} | |
function rndUint8() { | |
return Math.ceil(Math.random()*255) | |
} | |
document.body.appendChild(document.createElement("div")).setAttribute( | |
"style", | |
"background-color:"+pageColour()+";width:15rem;height:10rem;position:fixed;top:0;left:0;z-index:100" | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment