OGame: Search players

OGame: Displays players' info in the search page

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name OGame: Search players
// @namespace https://greasyfork.org/users/4668-black-cat
// @description OGame: Displays players' info in the search page
// @version 5.4
// @creator Black Cat
// @include http://*.ogame.gameforge.com/game/index.php?*
// @run-at document-end
// ==/UserScript==

var strFunc = (function(){
	var groupCoordsInGalaxy = true;

	var language = document.querySelector("meta[name=ogame-language]").getAttribute("content");
	var loca = {};
	switch (language) {
		case "fr":
			loca = {
				moon: {text: "L", d_unit: "km"},
				update: {before: "mis à jour il y a ", after: "", day: "j ", hour: "h ", minute: "m ", second: "s "},
				highscores: {total: "Total : ", economy: "Economie : ", research: "Recherche : ", military: "Militaire : ", defense: "Défense : ", ships: "Vaisseaux : ", nodef: "Sans défense"}
			};
			break;
		default:
			loca = {
				moon: {text: "M", d_unit: "km"},
				update: {before: "updated ", after: "ago", day: "d ", hour: "h ", minute: "m ", second: "s "},
				highscores: {total: "Total: ", economy: "Economy: ", research: "Research: ", military: "Military: ", defense: "Defense: ", ships: "Ships: ", nodef: "Without defense"}
			};
			break;
	}

	var cachedPlayers = {};

	var time = Math.round(Date.now()/1000);
	var t0 = parseInt(document.querySelector("meta[name=ogame-timestamp]").getAttribute("content"));
	var deltaT = time - t0;

	var sort_planets = function(a,b) {
		/(\d*):(\d*):(\d*)/.exec(a.coords);
		var galaxy1 = parseInt(RegExp.$1);
		var system1 = parseInt(RegExp.$2);
		var planet1 = parseInt(RegExp.$3);
		/(\d*):(\d*):(\d*)/.exec(b.coords);
		var galaxy2 = parseInt(RegExp.$1);
		var system2 = parseInt(RegExp.$2);
		var planet2 = parseInt(RegExp.$3);
		if (galaxy1 > galaxy2) return 1;
		else if (galaxy1 < galaxy2) return -1;
		if (system1 > system2) return 1;
		else if (system1 < system2) return -1;
		if (planet1 > planet2) return 1;
		else if (planet1 < planet2) return -1;
		return 0;
	}

	var doRequest = function(playerId,displayResult,param) {
		cachedPlayers[playerId] = {};
		var url = "/api/playerData.xml?id="+playerId;
		$.ajax({
			dataType:"xml",
			cache:false,
			url:url,
			success: function (xml) {
				var playerData = $(xml).find("playerData").eq(0);
				var player = {};
				player.timestamp = playerData.attr("timestamp");
				player.planets = [];
				playerData.find("planets>planet").each(function(){
					var planet = {};
					planet.name = $(this).attr("name");
					planet.coords = $(this).attr("coords");
					if (player.planets.length == 0) {
						planet.isHome = true;
					}
					var moon = $(this).find("moon").eq(0);
					if (moon.length > 0) {
						planet.moon = {};
						planet.moon.name = moon.attr("name");
						planet.moon.size = moon.attr("size");
					}
					player.planets.push(planet);
				});
				player.planets.sort(sort_planets);
				cachedPlayers[playerId] = player;
				displayResult(param,player);
			},
			error: function (xhr,status,exception) {
				delete cachedPlayers[playerId];
				throw new Error(exception + " (" + url + ")");
			}
		});
	}

	if (document.location.href.indexOf("page=galaxy") != -1) {
		var ngalaxy;
		var nsystem;

		var displayResultGalaxy = function(sel,player) {
			if (!player.planets) return;
			var tips = document.querySelectorAll(sel);
			for (var i = 0; i < tips.length; i++) {
				var list = tips[i].getElementsByClassName("ListLinks")[0];
				if (list.getElementsByClassName("coordinates").length > 0) continue;
				var prevGalaxy = 0;
				var prevSystem = 0;
				for (var j = 0; j < player.planets.length; j++) {
					/(\d*):(\d*):(\d*)/.exec(player.planets[j].coords);
					var galaxy = RegExp.$1;
					var system = RegExp.$2;
					var planet = RegExp.$3;
					if (system != prevSystem || galaxy != prevGalaxy || !groupCoordsInGalaxy) {
						var planetsList = [ planet ];
						var hasMoon = !!player.planets[j].moon;
						var item = document.createElement("li");
						item.className = "coordinates";
						var anchor = document.createElement("a");
						anchor.href = "javascript:void(0);";
						anchor.textContent = "[" + galaxy + ":" + system + ":" + planet + "]" + (hasMoon?" "+loca.moon.text:"");
						if (galaxy == ngalaxy && system == nsystem) {
							anchor.style.color = "#848484";
						} else {
							anchor.setAttribute("onclick","galaxy=" + galaxy + ";system=" + system + ";canLoadContent(" + galaxy + "," + system + ");");
						}
						item.appendChild(anchor);
						list.appendChild(item);
					} else {
						planetsList.push(planet);
						if (player.planets[j].moon) {
							hasMoon = true;
						}
						anchor.innerHTML = "[" + galaxy + ":" + system +"] <span title='" + planetsList.join(", ") + "'>(" + planetsList.length + ")</span>" + (hasMoon?" "+loca.moon.text:"");
					}
					prevGalaxy = galaxy;
					prevSystem = system;
				}
				Tipped.refresh(tips[i]);
			}
		}

		var displayResultGalaxyMobile = function(index,player) {
			var content = $(".js_detailRowPlayer" + index + " .active_row_details_content")[0];
			if (!player.planets || !content) return;
			if (content.getElementsByClassName("coordinates").length > 0) return;
			var nodes = content.childNodes;
			for (var i = nodes.length-1; i >= 0; i--) {
				if (nodes[i].nodeType == 3) {
					content.removeChild(nodes[i]);
				}
			}
			var galaxy = 0;
			var system = 0;
			for (var i = 0; i < player.planets.length; i++) {
				/(\d*):(\d*):(\d*)/.exec(player.planets[i].coords);
				var curGalaxy = RegExp.$1;
				var curSystem = RegExp.$2;
				if (i == 0 || curGalaxy > ngalaxy || (curGalaxy == ngalaxy && curSystem > nsystem)) {
					galaxy = curGalaxy;
					system = curSystem;
					if (i > 0) break;
				}
			}
			if (galaxy != ngalaxy || system != nsystem) {
				var anchor = document.createElement("a");
				anchor.className = "coordinates dark_highlight_tablet";
				anchor.href = "javascript:void(0);";
				anchor.textContent = "[" + galaxy + ":" + system + "]";
				anchor.setAttribute("onclick","galaxy=" + galaxy + ";system=" + system + ";canLoadContent(" + galaxy + "," + system + ");");
				content.appendChild(anchor);
			}
		}

		$(document).ajaxSuccess(function(e,xhr,settings){
			if (settings.url.indexOf("page=galaxyContent") == -1) return;

			ngalaxy = settings.data.replace(/^.*galaxy=(\d*).*$/,"$1");
			nsystem = settings.data.replace(/^.*system=(\d*).*$/,"$1");

			$("#galaxytable td.playername a.tooltipRel").each(function(){
				var rel = $(this).attr("rel");
				var player_id = rel.replace("player","");
				if (!isNaN(parseInt(player_id)) && parseInt(player_id) > 0) {
					if (isMobile) {
						var index = $(this).parent().attr("class").replace(/\n/g,"").replace(/^.*js_playerName(\d*).*$/,"$1");
					}
					var player = cachedPlayers[player_id];
					if (player) {
						if (isMobile) {
							displayResultGalaxyMobile(index,player);
						} else {
							displayResultGalaxy("#"+rel,player);
						}
					} else {
						if (isMobile) {
							$(this).parent().bind("click",function(){
								player = cachedPlayers[player_id];
								if (player) {
									displayResultGalaxyMobile(index,player);
								} else {
									doRequest(player_id,displayResultGalaxyMobile,index);
								}
							});
						} else {
							$(this).bind("mouseover",function(){
								player = cachedPlayers[player_id];
								if (!player) {
									doRequest(player_id,displayResultGalaxy,"#"+rel);
								}
							});
						}
					}
				}
			});
		});
	}

	var highscores = {};
	highscores["0"] = { name: loca.highscores.total };
	highscores["1"] = { name: loca.highscores.economy };
	highscores["2"] = { name: loca.highscores.research };
	highscores["3"] = { name: loca.highscores.military };
	//highscores["5"] = { name: "Military Built" };
	//highscores["6"] = { name: "Military Destroyed" };
	//highscores["4"] = { name: "Military Lost" };
	//highscores["7"] = { name: "Honor" };

	var playersXml;
	var cachedAlliances = {};

	$(document).ajaxSuccess(function(e,xhr,settings){
		if (settings.url.indexOf("page=search") == -1) return;

		var sort_players = function(a,b) {
			return a.toLowerCase().localeCompare(b.toLowerCase());
		}

		var getContentForAlly = function(allyId,doSearch) {
			var content = "";
			var names = cachedAlliances[allyId];
			if (!names && doSearch) {
				names = [];
				var players = playersXml.querySelectorAll("player[alliance='"+allyId+"']");
				for (var i = 0; i < players.length; i++) {
					var name = players[i].getAttribute("name");
					names.push(name);
				}
				names.sort(sort_players);
				cachedAlliances[allyId] = names;
			}
			if (names) {
				for (var i = 0; i < names.length; i++) {
					content += "<span style='cursor:pointer;' onclick='var el = Tipped.findElement(this);var content = $(el).parents(\".ui-dialog\").find(\".overlayDiv\");content.find(\"#searchText\").val(\"" + names[i] + "\");content.find(\"#2\").trigger(\"click\");'>" + names[i] + "</span><br />";
				}
			}
			return content;
		}

		var processAlly = function(rows) {
			for (var i = 0; i < rows.length; i++) {
				var cellPoints = rows[i].querySelector("td.allyPoints");
				if (!cellPoints) continue;
				var linkPoints = cellPoints.getElementsByTagName("a")[0];
				var ally_id = linkPoints.href.replace(/^.*searchRelId=(\d*).*$/,"$1");
				var content = getContentForAlly(ally_id,true);
				if (content.length > 0) {
					var cellMembers = rows[i].getElementsByClassName("allyMembers")[0];
					var linkAlly = document.createElement("a");
					linkAlly.href = "javascript:void(0);";
					linkAlly.className = "tooltipCustom tooltipRight js_hideTipOnMobile";
					linkAlly.title = content;
					linkAlly.innerHTML = cellMembers.innerHTML;
					cellMembers.innerHTML = "";
					cellMembers.appendChild(linkAlly);
				}
			}
		}

		if (settings.url.indexOf("ajax=1") != -1) {
			if (isMobile) return;
			$(".overlayDiv > .searchLayer").each(function(){
				var ajaxContent = this.getElementsByClassName("ajaxContent")[0];

				$(this).find("a.tab").click(function(){
					if ($(this).attr("id") == "4" && !playersXml) {
						$.get(
							"/api/players.xml",
							function (xml) {
								playersXml = xml;
								var table = ajaxContent.getElementsByClassName("searchresults")[0];
								if (table) {
									var rows = table.getElementsByTagName("tr");
									processAlly(rows);
								}
							},
							"xml"
						);
					}
					$(this).parents(".contentz").find("#searchText").focus();
				});

				if ($(this).hasClass("search-players")) return;
				$(this).addClass("search-players");

				for (var id in highscores) {
					$.get(
						"/api/highscore.xml",
						{ category:"1", type:id },
						function (xml) {
							highscores[xml.getElementsByTagName("highscore")[0].getAttribute("type")].xml = xml;
						},
						"xml"
					);
				}
			});
		} else {
			var addDots = function(nb) {
				nb = nb + "";
				while (/\d{4}/.test(nb)) {
					nb = nb.replace(/(\d+)(\d{3})/,"$1.$2");
				}
				return nb;
			}

			Array.prototype.sum = function() {
				var sum = 0;
				for (var i=0; i<this.length; i++)
					sum += this[i];
				return sum;
			}

			var displayResultSearch = function(row,player) {
				if (!player.planets) return;
				var cellHome = row.getElementsByClassName("home")[0];
				var cellPosition = row.getElementsByClassName("position")[0];
				var homeHTML = "";
				var positionHTML = "";
				for (var i = 0; i < player.planets.length; i++) {
					/(\d*):(\d*):(\d*)/.exec(player.planets[i].coords);
					var galaxy = RegExp.$1;
					var system = RegExp.$2;
					homeHTML +=
						(player.planets[i].isHome?"<span style='color:#6F9FC8;'>":"") +
						player.planets[i].name +
						(player.planets[i].isHome?"</span>":"") + "<br />";
					positionHTML +=
						"<a class='dark_highlight_tablet' href='index.php?page=galaxy&galaxy=" + galaxy + "&system=" + system + "'>" +
						"[" + player.planets[i].coords + "]" +
						(player.planets[i].moon?"&nbsp;<span title=\"" + player.planets[i].moon.name + "<br />" + player.planets[i].moon.size + " " + loca.moon.d_unit + "\" class='tooltipCustom tooltipRight js_hideTipOnMobile'>" + loca.moon.text + "</span>":"") + "</a>" + (!isMobile?"<br />":"");
				}
				if (isMobile) {
					cellHome.style.lineHeight = "44px";
				}
				cellHome.innerHTML = homeHTML;
				cellPosition.innerHTML = positionHTML;
				if (!isMobile) {
					time = Math.round(Date.now()/1000) - deltaT;
					var diff = time - player.timestamp;
					if (diff < 0) diff = 0;
					var t = {};
					t.day = Math.floor(diff/86400);
					t.hour = Math.floor(diff/3600) % 24;
					t.min = Math.floor(diff/60) % 60;
					t.sec = diff % 60;
					var up = "";
					if (t.day != 0) up += t.day + loca.update.day;
					if (t.hour != 0 || up != "") up += t.hour + loca.update.hour;
					if (t.min != 0 || up != "") up += t.min + loca.update.minute;
					up += t.sec + loca.update.second;
					up = loca.update.before + up + loca.update.after;
					cellHome.title = up;
					$(cellHome).addClass("tooltip js_hideTipOnMobile");
				}
			}

			var method = settings.data.replace(/^.*method=([\d-]*).*$/,"$1");

			$(".overlayDiv > .searchLayer .searchresults").each(function(){
				var selTab = $(this).parents(".contentz").find("li.ui-tabs-active a").attr("id");
				if (method != selTab) return;

				if ($(this).hasClass("search-players")) return;
				$(this).addClass("search-players");

				var table = this;
				var rows = table.getElementsByTagName("tr");

				if (method == "2") {
					for (var i = 0; i < rows.length; i++) {
						var cellHighscore = rows[i].querySelector("td.highscore");
						if (!cellHighscore) continue;
						var player_id = undefined;
						var linkHighscore = cellHighscore.getElementsByTagName("a")[0];
						if (linkHighscore) {
							player_id = linkHighscore.href.replace(/^.*searchRelId=(\d*).*$/,"$1");
						} else {
							var cellMessage = rows[i].getElementsByClassName("action")[0];
							var linkMessage = cellMessage.getElementsByTagName("a")[0];
							if (linkMessage) {
								player_id = linkMessage.href.replace(/^.*to=(\d*).*$/,"$1");
							}
						}
						if (!isNaN(parseInt(player_id))) {
							var player = cachedPlayers[player_id];
							if (player) {
								displayResultSearch(rows[i],player);
							} else {
								doRequest(player_id,displayResultSearch,rows[i]);
							}
							if (linkHighscore) {
								var content = "";
								var plHS = {};
								for (var id in highscores) {
									var xml = highscores[id].xml;
									if (xml) {
										var playerEl = xml.querySelector("player[id='"+player_id+"']");
										if (playerEl) {
											var position = playerEl.getAttribute("position");
											var score = parseInt(playerEl.getAttribute("score"));
											switch (id) {
												case "0":
													plHS.total = score;
													break;
												case "1":
													plHS.economy = score;
													break;
												case "2":
													plHS.research = score;
													break;
												case "3":
													plHS.military = score;
													plHS.ships = playerEl.getAttribute("ships") || "0";
													break;
												default :
													break;
											}
											content += highscores[id].name + (id == "3"?"<span title='" + loca.highscores.ships + addDots(plHS.ships) + "'>":"") + addDots(score) + (id == "3"?"</span>":"") + " #" + position + "<br />";
										}
									}
								}
								if (plHS.total != undefined && plHS.total > 0 && plHS.economy != undefined && plHS.research != undefined && plHS.military != undefined) {
									plHS.defense = Math.max(plHS.economy + plHS.research + plHS.military - plHS.total,0);
									plHS.economy = Math.max(plHS.economy - plHS.defense,0);
									plHS.military = Math.max(plHS.military - plHS.defense,0);
									var scale = 1;
									var mult = Math.pow(10,scale);
									var cal_p = [100*mult*plHS.economy/plHS.total,100*mult*plHS.research/plHS.total,100*mult*plHS.military/plHS.total,100*mult*plHS.defense/plHS.total];
									var cal_r = [];
									var cal_e = [];
									for (var k = 0; k < cal_p.length; k++) {
										cal_r[k] = Math.round(cal_p[k]);
										cal_e[k] = cal_p[k] - cal_r[k];
									}
									var total_error = Math.round(cal_e.sum()); //number of jots by which the answer is too low
									if (total_error != 0) {
										var sign = (total_error<0?-1:1);
										total_error *= sign; //absolute value
										var sorted_e = [];
										for (var k = 0; k < cal_p.length; k++) {
											sorted_e[k] = { i:k, v:cal_e[k] };
										}
										sorted_e.sort(function(a,b){var av=Math.abs(a.v);var bv=Math.abs(b.v);return bv-av});
										for (var k = 0; k < cal_p.length; k++) {
											if (cal_e[sorted_e[k].i] * sign <= 0) continue; //error goes the wrong way
											cal_r[sorted_e[k].i] += sign; //adjust value
											total_error--;
											if (total_error == 0) break;
										}
									}
									for (var k = 0; k < cal_p.length; k++) {
										cal_r[k] /= mult; 
									}
									content =
										highscores["0"].name + addDots(plHS.total) + "<br />" +
										"<span title='" + loca.highscores.nodef + "'>" + highscores["1"].name + "</span>" + addDots(plHS.economy) + " (" + cal_r[0] + "%)<br />" +
										highscores["2"].name + addDots(plHS.research) + " (" + cal_r[1] + "%)<br />" +
										"<span title='" + loca.highscores.nodef + "'>" + highscores["3"].name + "</span><span title='" + loca.highscores.ships + addDots(plHS.ships) + "'>" + addDots(plHS.military) + "</span> (" + cal_r[2] + "%)<br />" +
										loca.highscores.defense + addDots(plHS.defense) + " (" + cal_r[3] + "%)";
								}
								if (content.length > 0) {
									linkHighscore.title = content;
									$(linkHighscore).addClass("tooltipCustom tooltipRight js_hideTipOnMobile");
								}
							}
						}
						if (playersXml) {
							var cellAlly = rows[i].getElementsByClassName("allyName")[0];
							var	linkAlly = cellAlly.getElementsByTagName("a")[0];
							if (linkAlly) {
								var ally_id = linkAlly.href.replace(/^.*allianceId=(\d*).*$/,"$1");
								if (!isNaN(parseInt(ally_id))) {
									var content = getContentForAlly(ally_id,false);
									if (content.length > 0) {
										linkAlly.title = content;
										$(linkAlly).addClass("tooltipCustom tooltipRight js_hideTipOnMobile");
									}
								}
							}
						}
					}
				} else if (method == "4") {
					if (!playersXml) return;

					processAlly(rows);
				}
			});
		}
	});
}).toString();

var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.text = "(" + strFunc + ")();";
document.body.appendChild(script);