dirtrally stage stats

leaderboard stage times and rankings for weekly/monthly events

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        dirtrally stage stats
// @namespace   http://sportscores.de/dirt
// @description leaderboard stage times and rankings for weekly/monthly events
// @include     https://www.dirtgame.com/uk/events
// @version     1.01
// @require  https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js?version=6349
// @grant         GM_xmlhttpRequest
// @grant    GM_addStyle
// ==/UserScript==


var eventMode = {
	daily : 0,
	weekly : 1,
	monthly : 2,
	daily2 : 3,
	weekly2 : 4
};
var currentEventMode = eventMode.daily;
var eventModeInd = "";
var currentPlayer = null;
var currentPlayerName = "";
var playerList = [];

function initPlayerDataForRow(tableRow, isAdded) {
	var playerNode = tableRow.find(".player_name");
	var player = new Object();
	player.name = playerNode.html();
	if (player.name != "") {
		player.pos = playerNode.prev().prev().find(".ng-binding").html();
		player.car = playerNode.next().html();
		var timeTd = playerNode.next().next();
		player.time = timeTd.html();

		playerList.push(player);

		if (tableRow.hasClass("player_entry")) {
			player.isPlayer = true;
			currentPlayer = player;
			currentPlayerName = player.name;
		}
		
		if (currentEventMode != eventMode.daily && currentEventMode != eventMode.daily2) {
			if (isAdded) {				
				$(".event." + eventModeInd + " .ownplayer").remove();				
				
				timeTd.next().after("<td class='ownplayer'><span id='idDiff_" + eventModeInd + "_own' /></td>")
				.after("<td class='ownplayer'><span id='id_" + eventModeInd + "_own' /><span class='stagerank' id='id_" + eventModeInd + "_own_rank' /></td>");
			} else if ($("#id_" + eventModeInd + "_" + player.pos).length <= 0) {

				timeTd.next().after("<td><span id='idDiff_" + eventModeInd + "_" + player.pos + "' /></td>")
				.after("<td><span id='id_" + eventModeInd + "_" + player.pos + "' /><span class='stagerank' id='id_" + eventModeInd + "_" + player.pos + "_rank' /></td>");
			}
		}
	}
}

function handleAsyncData(jNode) {

	eventModeInd = getEventModePrefix();
	
	var selector = $("#" + eventModeInd + "_prevEvents");
	if (selector.length > 0 && selector[0].selectedIndex != 0)
		return;

	if (jNode.next().length > 0)
		initPlayerDataForRow(jNode);

	if (jNode.next().next().length == 0)
	{
		processData();
		currentPlayer = null;
		playerList = [];
	}
}

function postData(postDataObj) {
	var dataJson = JSON.stringify({
			dirtObj : postDataObj
		});

	GM_xmlhttpRequest({
		method : "POST",
		  url: "http://sportscores.de/dirt/Default.aspx/DirtCall",
		data : dataJson,
		headers : {
			'Content-Type' : 'application/json; charset=UTF-8'
		},
		onload : function (response) {
			postDataResponse(response.responseText);
		}
	});
}


function postDataResponse(response) {
	var json = jQuery.parseJSON(response);

	if (json.d) {
		var stageId = json.d.stageid;
		var indicateMode = json.d.eventmode;		

		// add header columns once
		if ($("#th_" + indicateMode).length <= 0 && $(".event." + indicateMode + " table").length > 0 && stageId > 1) {
			$(".event." + indicateMode + " table thead tr").append("<th style='width:150px; display:none;' id='th_" + indicateMode + "'><div class='" + indicateMode +
				" stageOverlay' style='position:relative'><div class='divStage' style='overflow:hidden'><span id='idStageTime_" + indicateMode +
				"' class='stageHead'></span><span id='idStageTime_" + indicateMode + "_rank' class='stagerank'></span></div></div></th>").append("<th style='width:150px; display:none;' id='thdiff_" +
				indicateMode + "'><span id='idStageTimeDiff_" + indicateMode + "'></span></th>");

			if (((indicateMode == "weekly" || indicateMode == "weekly2") && $("#" + indicateMode + "_stageid")[0].selectedIndex != 0) || indicateMode == "monthly") {
				$("#th_" + indicateMode).show();
				$("#thdiff_" + indicateMode).show();
				$("#idStageTime_" + indicateMode).html("<u>S." + stageId + " Time</u>");
				$("#idStageTimeDiff_" + indicateMode).html("S." + stageId + " Diff");
			}
		}

		var entriesStored = json.d.entries;
		var totalEntries = $(".event." + indicateMode + " .total > span")[0].textContent;

		$("#idStageTime_" + indicateMode + "_rank").html(entriesStored);
		if ($("#" + indicateMode + "_stageid")[0].selectedIndex > 0) {
			$.each(json.d.list, function (index, value) {				
				if (currentPlayerName === value.name && !$(".event." + indicateMode + " .player_entry").hasClass("ng-scope")) {
					
					$("#id_" + indicateMode + "_own").html(value.time);
					if (value.stagerank > 0)
						$("#id_" + indicateMode + "_own_rank").html(value.stagerank);
					$("#idDiff_" + indicateMode + "_own").html(value.diffTime);
				} else {
					$("#id_" + indicateMode + "_" + value.pos).html(value.time);
					if (value.stagerank > 0)
						$("#id_" + indicateMode + "_" + value.pos + "_rank").html(value.stagerank);
					$("#idDiff_" + indicateMode + "_" + value.pos).html(value.diffTime);

				}
			});
		}
		// build overlay table
		var rows = "";
		$.each(json.d.stagelist, function (index, value) {
			rows += "<tr class='" + (value.name == currentPlayerName ? "player" : "") + "'><td style='font-weight:bold;'>" + value.pos + "</td><td class='format'>" + value.name + "</td><td class='format'>" +
			value.car + "</td><td class='format2'>" + value.time + "</td><td class='format2'>" + value.diffTime + "</td></tr>";
		});
		var div = "<div class='topBetsLayer'><table class='overlayTable'><tr style='background-color:#F2F2F2;'><th colspan='3'>Stage " + stageId +
			" - Top 20</th><th colspan='2' style='text-align:right;font-weight:normal;'>Saved: " + entriesStored + " / " + totalEntries + "</th></tr>" + rows + "</table></div>";

		
		var elem = $("." + indicateMode + ".stageOverlay .divStage");		
		if(elem){
			$("." + indicateMode + ".stageOverlay .divStage .topBetsLayer").remove();
			elem.append(div);
		}		
		
		$("." + indicateMode + ".stageOverlay").on("mouseenter", function (event) {
			$(".topBetsLayer").show();
		});

		$("." + indicateMode + ".stageOverlay").on("mouseleave", function () {
			$(".topBetsLayer").hide();
		});
		
	}
}

function processData() {
	var eventId = -1;
	var stageId = -1;
	var stageName = "";
	var location = "";
	var weather1 = "";
	var weather2 = "";
	
	var userEntry = $(".event." + eventModeInd + " .player_entry");
	if (userEntry && currentPlayer == null) {		
		initPlayerDataForRow(userEntry, true);
	}

	eventId = $(".event." + eventModeInd).data().ngEventId;
	var locationVisible = false;

	switch (currentEventMode) {
	case eventMode.daily:
	case eventMode.daily2:
		stageId = 0;
		locationVisible = true;
		break;
	case eventMode.weekly:
	case eventMode.weekly2:
	case eventMode.monthly:
	
		stageId = $("#" + eventModeInd + "_stageid")[0].selectedIndex;
		
		if (currentEventMode == eventMode.monthly)
			stageId = stageId + 1;
		if (stageId == 0) {
			stageId = $("#" + eventModeInd + "_stageid")[0].options.length - 1;
			$("#th_" + eventModeInd).hide();
			$("#thdiff_" + eventModeInd).hide();
		} else if (stageId <= 1) {
			$("#th_" + eventModeInd).hide();
			$("#thdiff_" + eventModeInd).hide();
			locationVisible = true;
		} else {
			$("#th_" + eventModeInd).show();
			$("#thdiff_" + eventModeInd).show();
			$("#idStageTime_" + eventModeInd).html("<u>S." + stageId + " Time</u>");
			$("#idStageTimeDiff_" + eventModeInd).html("S." + stageId + " Diff");
			locationVisible = true;
		}
		break;
	}

	if (locationVisible && $(".event." + eventModeInd + " li.ng-scope").length > 0) {
		
		location = $(".event." + eventModeInd + " li.ng-scope")[0].textContent;
		stageName = $(".event." + eventModeInd + " li.ng-scope")[1].textContent;
		weather1 = $(".event." + eventModeInd + " .name > span")[0].textContent,
		weather2 = $(".event." + eventModeInd + " .name > span")[1].textContent
	}

	var trackData = {
		location : location,
		stageName : stageName,
		stageId : stageId,
		eventid : eventId,
		eventMode : currentEventMode,
		weather1 : weather1,
		weather2 : weather2
	};

	var postDataObj = {
		trackData : trackData,
		data : playerList
	};

	postData(postDataObj);
}

waitForKeyElements(".event.daily.ng-scope .table tbody tr.ng-scope", handleAsyncDataD);
waitForKeyElements(".event.daily2.ng-scope .table tbody tr.ng-scope", handleAsyncDataD2);
waitForKeyElements(".event.weekly .table tbody tr.ng-scope", handleAsyncDataW);
waitForKeyElements(".event.weekly2 .table tbody tr.ng-scope", handleAsyncDataW2);
waitForKeyElements(".event.monthly.ng-scope .table tbody tr.ng-scope", handleAsyncDataM);

GM_addStyle("div.topBetsLayer { z-index: 2; top: -39px; left:-500px; padding-top:2px; min-height: 70px; width: 500px; background-color: #fff; position: absolute; display:none; color: #000; font-family:Tahoma; font-size:12px; font-weight: normal; };" +
	".stageBoard { font-weight:bold;font-size:12px;padding-left:10px;}" +
	".overlayTable {width:98%;margin-top:5px;border:1px solid #000;background-color:#fff;}" +
	".stagerank {font-weight:bold;position:relative;top:-6px;left:5px; font-size:11px;font-family:Arial;}" +
	".player {background-color: #E0F4F3;}" +
	".stageHead {cursor:pointer;}" +
	".overlayTable .format {overflow:hidden; white-space:nowrap; max-width:120px;}" +
	".overlayTable .format2 {text-align:right;}");

function handleAsyncDataD(jNode) {
	currentEventMode = eventMode.daily;
	handleAsyncData(jNode);
}
function handleAsyncDataD2(jNode) {
	currentEventMode = eventMode.daily2;
	handleAsyncData(jNode);
}
function handleAsyncDataW(jNode) {
	currentEventMode = eventMode.weekly;
	handleAsyncData(jNode);
}
function handleAsyncDataW2(jNode) {
	currentEventMode = eventMode.weekly2;
	handleAsyncData(jNode);
}
function handleAsyncDataM(jNode) {
	currentEventMode = eventMode.monthly;
	handleAsyncData(jNode);
}

function getEventModePrefix() {
	switch (currentEventMode) {
	case eventMode.daily:
		return "daily";
	case eventMode.daily2:
		return "daily2";
	case eventMode.weekly:
		return "weekly";
	case eventMode.weekly2:
		return "weekly2";
	case eventMode.monthly:
		return "monthly";
	}
	return "";
}