Last active
August 29, 2015 14:17
-
-
Save numinit/0179ca555c4ae78d4540 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// ==UserScript== | |
// @name XKCDUniqueRandom | |
// @namespace http://numin.it/ | |
// @version 0.1 | |
// @license MIT | |
// @description uniquely samples XKCDs when you press Random | |
// @author numinit | |
// @match http://xkcd.com/* | |
// @match https://xkcd.com/* | |
// @grant none | |
// ==/UserScript== | |
$(document).ready(function() { | |
var setSeed = function(seed) { | |
window.localStorage['xkcd_seed'] = seed; | |
return seed; | |
}; | |
var genSeed = function() { | |
var array = new Uint32Array(1); | |
window.crypto.getRandomValues(array); | |
return array[0]; | |
}; | |
var getSeed = function() { | |
var ret = window.parseInt(window.localStorage['xkcd_seed']); | |
return window.isNaN(ret) ? genSeed() : ret; | |
}; | |
var setMax = function(max) { | |
window.localStorage['xkcd_max'] = max; | |
return max; | |
} | |
var getMax = function() { | |
var ret = window.parseInt(window.localStorage['xkcd_max']); | |
return window.isNaN(ret) ? 0 : ret; | |
} | |
var iterate = function(seed, max) { | |
var r = function(s, m) { | |
return ((5 * s) + 1) % m; | |
}; | |
// compute the next-highest power of 2 | |
var m = (1 << (Math.ceil(Math.log2(max)) | 0)) | 0; | |
// rejection sample | |
seed = r(seed, m); | |
while (seed >= max) { | |
seed = r(seed, m); | |
} | |
return seed; | |
}; | |
if (window.location.pathname === '/') { | |
// I don't see a better way to do this... :( | |
var match = (/permanent\s+link\s+to\s+this\s+comic:\s+https?:\/\/xkcd\.com\/(\d+)\//gi).exec($('#middleContainer').text()); | |
if (match && match[1]) { | |
var seed = genSeed(), max = window.parseInt(match[1]); | |
// store the max comic | |
setMax(max); | |
setSeed(seed); | |
console.log('XKCDUniqueRandom: new session with max=' + max + ', seed=' + seed); | |
} else { | |
// We tried? | |
setMax(0); | |
console.log('XKCDUniqueRandom: couldn\'t find the max comic :('); | |
} | |
} else { | |
var max = getMax(), seed = getSeed(); | |
if (max > 0) { | |
console.log('XKCDUniqueRandom: continued session with max=' + max + ', seed=' + seed); | |
} else { | |
console.log('XKCDUniqueRandom: no max value yet; seed=' + seed); | |
} | |
} | |
// bind a random handler | |
$('a[href$="/random/comic/"]').click(function() { | |
var seed = getSeed(), max = getMax(); | |
if (!max) { | |
return true; | |
} else { | |
// find the next comic | |
console.log('XKCDUniqueRandom: previous seed ' + seed); | |
seed = iterate(seed, max); | |
if (seed == 403) { | |
// you aren't getting away that easily | |
seed = iterate(seed, max); | |
} | |
// store the seed for next time | |
setSeed(seed); | |
// go somewhere else. seeds are in 0..max-1 so add 1 to get 1..max | |
console.log('XKCDUniqueRandom: next seed ' + seed); | |
window.location.pathname = '/' + (seed + 1); | |
return false; | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment