WhoScored Player Grabber
/*
####################
### INSTRUCTIONS ###
####################
1) Copy all of this code
2) Go to "https://www.whoscored.com/"
3) Open the developer console
4) Paste the code in and run it (with ENTER)
Tips : 
- You can amend players returned by changing value of 'numberOfPlayers' below (if you have too many the CSV download will fail for some reason)
*/
var numberOfPlayers = 7500;
console.log("LOG | number of players per call=" + numberOfPlayers);
whoScoredData = {};
whoScoredData.players = {};
whoScoredData.functions = {};
whoScoredData.apiQueue = [];
whoScoredData.csv = {};
whoScoredData.csv.full = [];
whoScoredData.csv.headers = [];
whoScoredData.csv.full.export = [];
whoScoredData.functions.csvPrepper = function (){
	console.log("LOG | CSV prepper beginning");
	//whoScoredData.csv = {};
	//whoScoredData.csv.full = [];
	//whoScoredData.csv.headers = [];
	//whoScoredData.csv.full.export = [];
	for (attribute in whoScoredData.players[Object.keys(whoScoredData.players)[0]]){
		whoScoredData.csv.headers.push(attribute);
	}
	whoScoredData.csv.full.push(whoScoredData.csv.headers);
	console.log("LOG | CSV headers defined");
	for (playerId in whoScoredData.players){
		var playerArray = [];
		for (attribute in whoScoredData.players[playerId]){
			playerArray.push(whoScoredData.players[playerId][attribute]);
		}
		whoScoredData.csv.full.push(playerArray);
	}
	whoScoredData.functions.csvExporter(whoScoredData.csv.full);
}
whoScoredData.functions.apiQueuer = function (endpoint){
	whoScoredData.apiQueue.push(endpoint);
	console.log("LOG | API call queued : endpoint=" + endpoint);
}
whoScoredData.functions.apiQueueDispatcher = function (){
	if(whoScoredData.apiQueue.length > 0){
		console.log("LOG | API queue has " + whoScoredData.apiQueue.length + " calls remaining");
		var apiCall = whoScoredData.apiQueue.pop();
		whoScoredData.functions.apiCaller(apiCall);
	} else {
		console.log("LOG | API queue completed");
		whoScoredData.functions.csvPrepper();
	}
	
}
whoScoredData.functions.apiCaller = function(endpoint) {
	console.log("LOG | API call being made : endpoint=" + endpoint);
	// send data to API
	jQuery.ajax({
		type: "GET", // GET/POST/PUT ETC
		url: endpoint, // change to your URL endpoint
		//data: data, 
		dataType: "json",
		//success: success() // build throttling
		contentType: "application/json"
	}).success(function(playerData) {
		// Success
		console.log("LOG | SUCCESS");
		
		// 1) Prep 
		for (var i = 0; i < playerData.playerTableStats.length; i++) {
			
			whoScoredData.players[playerData.playerTableStats[i].playerId] = whoScoredData.players[playerData.playerTableStats[i].playerId] || {};			
			for (attribute in playerData.playerTableStats[i]){
				whoScoredData.players[playerData.playerTableStats[i].playerId][attribute] = playerData.playerTableStats[i][attribute];
			}			
		}
		// Dispatch more calls
		whoScoredData.functions.apiQueueDispatcher();
	}).fail(function(err) {
		// Fail
		// ADD ERROR DETAILS		
		console.log("LOG | FAIL | " + err);
	});
}
// FUNCTION : CSV EXPORTER
whoScoredData.functions.csvExporter = function(data) {
	console.log("LOG | CSV Exporter called : Creating CSV");
	// data must be formatted in arrays of arrays of data (one big array with an array per line, e.g. [[line1data1,line1data2],[line2data1,line2data2]])
	var csvContent = "data:text/csv;charset=utf-8,";
	csvContent += "NOTE : All commas have been replaced by '-' to ensure CSV could be generated correctly" + "\n" + "\n";	
	// Loop through and build rows
	for (var i = 0; i < data.length; i++) {
		// Loop through and remove ','s
		for (var j = 0; j < data[i].length; j++) {
			if (data[i][j]) {
				data[i][j] = data[i][j].toString().replace(/,/g, "-");
			}
		}
		var dataString = data[i].join(",");
		csvContent += dataString + "\n";
	}
	// Get date
	var d = new Date();
	var year = d.getFullYear();
	var month = d.getMonth() + 1;
	var day = d.getDate();
	var hour = d.getHours() + 1;
	var minute = d.getMinutes() + 1;
	var seconds = d.getSeconds() + 1;
	// Fix dates
	var dateFixer = function(date) {
		if (date.toString().length === 1) {
			date = "0" + date.toString();
		}
		return date;
	}
	// Fix dates
	var month = dateFixer(month);
	var day = dateFixer(day);
	var hour = dateFixer(hour);
	var minute = dateFixer(minute);
	var seconds = dateFixer(seconds);
	// Set Date 
	var timestamp = year + "-" + month + "-" + day + "_" + hour + "-" + minute + "-" + seconds;
	var encodedUri = encodeURI(csvContent);
	var link = document.createElement("a");
	link.setAttribute("href", encodedUri);
	link.setAttribute("download", "Top_" + numberOfPlayers + "players_" + timestamp + ".csv");
	document.body.appendChild(link); // Required for FF
	link.click(); // This will download the data file named "my_data.csv".
	console.log("LOG | CSV created");
}
// Queue API Calls
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=summary&subcategory=all&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=&appearances=&appearancesComparisonType=&field=Overall&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=&isMinApp=false&page=&includeZeroValues=true&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=summary&subcategory=defensive&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=&appearances=&appearancesComparisonType=&field=Overall&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=&isMinApp=true&page=&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=summary&subcategory=offensive&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=&appearances=&appearancesComparisonType=&field=Overall&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=&isMinApp=true&page=&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=summary&subcategory=passing&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=&appearances=&appearancesComparisonType=&field=Overall&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=&isMinApp=true&page=&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=shots&subcategory=zones&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=0&appearances=&appearancesComparisonType=0&field=&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=0&isMinApp=&page=1&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=dribbles&subcategory=success&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=0&appearances=&appearancesComparisonType=0&field=&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=0&isMinApp=&page=1&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
whoScoredData.functions.apiQueuer("https://www.whoscored.com/StatisticsFeed/1/GetPlayerStatistics?category=shots&subcategory=accuracy&statsAccumulationType=0&isCurrent=true&playerId=&teamIds=&matchId=&stageId=&tournamentOptions=2,3,4,5,22&sortBy=Rating&sortAscending=&age=&ageComparisonType=0&appearances=&appearancesComparisonType=0&field=&nationality=&positionOptions=&timeOfTheGameEnd=&timeOfTheGameStart=0&isMinApp=&page=1&includeZeroValues=&numberOfPlayersToPick=" + numberOfPlayers);
// Dispatch Queue
whoScoredData.functions.apiQueueDispatcher();