// ==UserScript== // @name IMDb Decoder Ring // @namespace http://rephrase.net/box/user-js/ // @description Show what an IMDb rating means in terms of its percentile // @include http://*.imdb.com/title/tt*/ // @include http://imdb.com/title/tt*/ // ==/UserScript== /* Using data from Tom Moertel's IMDb Decoder Ring Changelog: 2009-12-24 - Formatting tweak 2008-09-28 - Update to new IMDb HTML and April 2008 data 2007-??-?? - Initial Release */ (function(){ /* UTILITY FUNCTIONS &C */ /* Remove leading and trailing whitespace. */ String.prototype.strip = function() { return this.replace(/^\s+|\s+$/gm, ""); } /* Split by regular expression. */ String.prototype.regexsplit = function(separator, limit, separators_too) { var o = [], match, self=this.toString(); var i = 0; if (typeof limit == "undefined") limit = 1000; // sanity check while ((match = self.match(separator)) && self.length > 0 && o.length < limit) { if (RegExp.leftContext.length > 0) o.push(RegExp.leftContext); if (!!separators_too) o.push(match[0]); self = self.substr(match[0].length + RegExp.leftContext.length); } if (self.length) o.push(self); return o; } /* Get elements by CSS class. */ function getElementsByClassName(elm, classname) { var a = []; var re = new RegExp('(^| )'+classname+'( |$)'); var els = elm.getElementsByTagName("*"); for(var i=0,j=els.length; i Ignore those. */ text = elm.firstChild.nodeValue; if (!text.match(/IMDb/) && elm.href.match(/\.com\/Sections/)) genres.push(elm.firstChild.nodeValue); } return genres; } /* Extract the film's rating from the page. */ function extract_rating() { var rating_div = getElementsByClassName(document, "general rating")[0]; var meta_div = getElementsByClassName(rating_div, "meta")[0]; try { var rating = meta_div.getElementsByTagName("b")[0].firstChild.nodeValue; } catch(e) { return false; } return rating.split("/")[0]; } /* END UTILITY FUNCTIONS &C. */ var allname = "All movies"; /* This data courtesy Thomas G. Moertel April 2008 */ var data = "\ All movies 11 22 24 30 33 40 44 51 56 64 70 77 81 87 89 93 95 98\ Action 18 32 35 42 45 51 55 61 66 73 75 79 82 85 87 90 91 96\ Adventure 12 24 26 32 35 40 43 50 56 65 69 75 80 85 88 91 92 96\ Animation 5 14 16 21 25 31 34 40 44 54 60 67 75 83 89 95 97 ++\ Biography 4 10 10 13 13 15 20 25 33 42 60 68 76 89 94 97 98 99\ Comedy 11 22 26 33 38 46 52 61 67 75 79 86 90 93 94 96 97 99\ Crime 8 17 19 26 31 40 44 54 61 70 76 83 89 94 95 97 98 99\ Documentary 3 7 8 10 10 14 16 20 24 38 47 58 66 79 85 91 95 99\ Drama 5 12 15 20 24 31 36 47 54 66 73 83 89 94 96 98 98 99\ Family 15 28 34 42 47 56 61 69 74 81 84 87 92 95 97 98 99 99\ Fantasy 12 27 29 34 37 44 47 55 60 71 76 81 84 86 89 93 94 96\ History 1 2 4 6 6 13 15 25 33 46 52 63 70 85 90 95 96 97\ Horror 34 59 63 69 73 79 81 86 88 92 94 95 96 97 97 98 98 99\ Music 8 15 15 17 22 26 30 35 40 51 60 69 74 83 85 89 90 96\ Musical 15 23 30 35 40 44 47 55 65 74 79 81 92 94 95 97 97 99\ Mystery 9 20 25 32 38 49 52 60 68 77 81 85 89 92 92 94 95 96\ Reality TV 17 29 40 49 49 54 57 57 60 63 66 71 74 77 83 91 91 94\ Romance 6 14 18 25 31 39 45 56 64 74 79 86 91 94 96 98 98 ++\ Sci-Fi 26 41 43 49 50 53 56 60 64 70 75 81 84 87 90 92 92 96\ Short 3 5 7 8 10 14 15 18 21 32 36 55 66 80 87 92 96 99\ Sport 10 18 22 27 29 41 50 59 64 72 76 83 85 90 92 97 98 98\ Thriller 14 31 35 42 47 56 61 69 75 81 85 89 92 95 96 97 98 99\ War 5 9 12 16 17 22 28 36 42 53 57 63 71 82 86 91 91 96\ Western 20 30 33 37 53 57 57 57 57 67 73 80 83 97 97 97 97 ++\ "; // process the data into something useful var lines = data.regexsplit(/[A-Z][A-Z\- ]+/i, 100, true); var genre, genre_data = {}; while(lines.length) { genre = lines.shift().strip(); genre_data[genre] = lines.shift().regexsplit(/\s+/); } /* Find the (approximate) percentile of the film. */ function get_percentile(rating, genre) { if (!genre) genre = allname; rating *= 10; var data = genre_data[genre]; var o, cmp; for (var i=data.length-1, j=0; i>=0; i--, j++) { if (data[i] == "++") data[i] = "100"; cmp = !!i ? (90-(2.5*j)) : 40; // we only have data down to 4.0/10 if (rating >= cmp) { return genre + ": " + data[i]; } } return genre + ": <" + data[0]; } var rating = extract_rating(); // movie is unrated if (rating === false) return; // collect data var genre_details = [get_percentile(rating, g) for each (g in extract_genres())]; // htmlify it var div = document.createElement("div"); var h = document.createElement("h5"); h.appendChild(document.createTextNode("Rating Percentile:")); div.appendChild(h); for each (text in genre_details) { var li = document.createElement("div"); li.className = "info-content"; li.appendChild(document.createTextNode(text)); div.appendChild(li); } div.className = "info"; var ratingNode = document.getElementById("tn15rating").parentNode; ratingNode.parentNode.insertBefore(div, ratingNode.nextSibling); }());