// ==UserScript==
// @name IMDbTvShowStatistics
// @namespace notableTieView
// @author notableTieView
// @description Shows season statistics for TV Shows on IMDB
// @include http://www.imdb.com/title/*
// @include http://www.imdb.com/title/*/eprate*
// @version 1.2
// @grant none
// @license Creative Commons Attribution-NonCommercial 3.0 http://creativecommons.org/licenses/by-nc/3.0/
//
// This script uses the following external libraries which are available under different licenses:
// jQuery (https://jquery.com/) is provided under the MIT License https://tldrlegal.com/license/mit-license
// d3 (http://d3js.org/) is provided under the BSD 3-Clause License https://github.com/mbostock/d3/blob/master/LICENSE
// Chart.js (http://www.chartjs.org/) is provided under the MIT License http://opensource.org/licenses/MIT
// Highcharts (http://shop.highsoft.com/highcharts.html) is provided by Highsoft (http://shop.highsoft.com/) for non-commercial use under the Creative Commons Attribution-NonCommercial 3.0 license: http://creativecommons.org/licenses/by-nc/3.0/
//
// @require https://code.jquery.com/jquery-2.1.4.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js
// @require http://code.highcharts.com/highcharts.js
// @require http://code.highcharts.com/highcharts-more.js
// @require http://code.highcharts.com/modules/exporting.js
//
// @downloadURL none
// ==/UserScript==
// compatibility
this.$ = this.jQuery = jQuery.noConflict(true);
var processedRows=0;
/*
Plot a box plot for every season (min, q1, median, q3, max)
divId - the div to add the plot to
plotData - the data
*/
function plotBoxPlot(divId, plotData, width) {
$(divId).highcharts({
chart: {
type: 'boxplot',
width: width,
height: 200
},
title: {
text: ''
},
legend: {
enabled: false
},
xAxis: {
categories: plotData.labels,
title: {
text: '' //Seasons'
}
},
yAxis: {
title: {
text: ''
},
plotLines: [
{
value: plotData.median,
color: 'red',
width: 2,
label: {
align: 'left',
style: {
color: 'gray'
}
}
}
]
},
series: [
{
name: 'Stats',
data: plotData.quartiles,
tooltip: {
headerFormat: 'Season {point.key}
'
}
}
]
});
}
/*
Compute the average over an array
ar - the array (numeric)
*/
function getAverage(ar) {
var count = 0;
for (var i = 0, n = ar.length; i < n; i++) {
count += ar[i];
}
return count / ar.length;
}
/*
Get a quartile of an array
ar - array, sorted (highest first)
q - the quartile we want: e.g. 0.25, 0.5 (median), 0.75
*/
function getQuartile(q, ar) {
var realQ = (1 - q) * ar.length;
var floorQ = Math.ceil(realQ);
if (realQ === floorQ) {
if (floorQ === 0) {
return ar[0];
} else if (floorQ === ar.length) {
return ar[ar.length - 1];
} else {
return getAverage([ar[floorQ - 1], ar[floorQ]]);
}
}
return ar[floorQ];
}
/*
Transform seasonData into data structure thats easy to use for plotting
seasonData - a hash with an array of ratings for each season
the index in the hash is the seaons, season 0 is for specials
*/
function getPlotData(seasonData) {
seasons = Object.keys(seasonData);
n = seasons.length;
seasonLabels = [
];
seasonAverages = [
];
seasonQuartiles = [
[]
];
allRatings = [
];
specials = false;
seasons.forEach(function (season) {
index = season - 1;
if (season == 0) {
index = n - 1;
seasonLabels[index] = 'S'; //specials';
specials = true;
} else {
seasonLabels[index] = season.toString();
}
seasonAverages[index] = getAverage(seasonData[season]);
seasonQuartiles[index] = [
Math.min.apply(null, seasonData[season]),
getQuartile(0.25, seasonData[season]),
getQuartile(0.5, seasonData[season]),
getQuartile(0.75, seasonData[season]),
Math.max.apply(null, seasonData[season])
];
allRatings = allRatings.concat(seasonData[season]);
});
allRatings.sort(function (a, b) {
return b - a
}); //sort in reverse order
averageData = {
averages: seasonAverages,
labels: seasonLabels,
quartiles: seasonQuartiles,
minimumFloor: Math.max(Math.floor(Math.min.apply(null, seasonAverages)) - 1, 0),
median: getQuartile(0.5, allRatings),
num: n,
specials: specials
};
return averageData;
}
/*
Plot a simple chart with season averages as bars
divId - the id to add the plot to
plotData - the datastructure
*/
function plotChart(divId, plotData) {
var data = {
labels: plotData.labels,
datasets: [
{
label: 'Average Season Ratings',
fillColor: 'rgba(19,108,178,0.5)',
strokeColor: 'rgba(220,220,220,0.8)',
highlightFill: 'rgba(19,108,178,0.9)',
highlightStroke: 'rgba(220,220,220,1)',
data: plotData.averages
}
]
};
var options = {
scaleOverride: true,
scaleStepWidth: 1,
scaleSteps: (10 - averageData.minimumFloor),
scaleStartValue: averageData.minimumFloor,
}
var ctx = $(divId).get(0).getContext('2d');
new Chart(ctx).Bar(data, options);
}
/*
Extract the data from one table row of the ratings table
row - the row (jquery object)
scoresBySeason - the hash of arrays to append the extracted rating to
*/
function workOnTableRow(row, scoresBySeason) {
seasonEpisodeField = $(row).children().eq(0);
if (seasonEpisodeField.is('th')) {
$(row).children().eq(3).before('