Ikariam Military

By Toranaga Last update Sep 1, 2009 — Installed 78,576 times.

There are 12 previous versions of this script.

// ==UserScript==
// @name          Ikariam Military
// @version       1.3
// @copyright     2009, Yoshi Toranaga
// @license       GPL v3 (http://www.gnu.org/copyleft/gpl.html)
// @namespace     http://www.home.org/ikariam/military
// @description   Calculates the strength of your troops/ships
// @include       http://s*.ikariam.*/*
// @exclude       http://board.ikariam.*/*
// @require       http://www.JSON.org/json2.js
// @require       http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js
// ==/UserScript==

// globals
var SCORES = {};

// constants
var CACHE_KEY = "Cache";
var UNITS = "un";
var UPGRADES = "up";
var DEBUG = true;
var ATT = 'att';
var DEF = 'def';
var STA = 'sta';
var QTY = 'qty';
var BONUS = 'bns';
var UNIT_TYPE = 'tip';
var SHIP = 'shp';
var TROOP = 'trp';
var NONE = 'no bonus';
var ASSAULT = 'assault bonus';
var RESISTANCE = 'resistance bonus';
var RAM = 'ram bonus';
var HEALER = 'healer bonus';
var REGENERATION = 'regeneration bonus';

//----------- CACHE FUNCTIONS -------------------
function makeCacheKey(server, town) {
	if (town === undefined) {
		return CACHE_KEY + "." + server + "." + UPGRADES;
	}
	return CACHE_KEY + "." + server + "." + town;	
}

function readCache(server, town) {
	var json = GM_getValue(makeCacheKey(server, town));
	var result = {};
	if (json) {
		log("Reading[" + makeCacheKey(server, town) + "] = " + json);
		result = JSON.parse(json);
	}
	return result;
}

function writeCache(cache, server, town) {
	var json = JSON.stringify(cache);
	log("Writing[" + makeCacheKey(server, town) + "] = " + json);
	GM_setValue(makeCacheKey(server, town), json);
}

function updateUnitsCache(serverName, townName, unitType, units) {
	log("Updating units of type " + unitType + " for town " + townName + "@" + serverName);
	var cache = readCache(serverName, townName);
	cache[unitType] = units;
	writeCache(cache, serverName, townName);	
}

function updateUpgradesCache(serverName, unitType, upgrades) {
	log("Updating upgrades for type " + unitType + " for server " + serverName);
	var cache = readCache(serverName);
	cache[unitType] = upgrades;
	writeCache(cache, serverName);	
}

function updateUnitsAndUpgradesCache(serverName, townName, unitType, unitsAndUpgrades) {
	updateUnitsCache(serverName, townName, unitType, unitsAndUpgrades[UNITS]);
	updateUpgradesCache(serverName, unitType, unitsAndUpgrades[UPGRADES]);
}

//----------- UNIT DATA -------------------
function initializeData() {
	//      UNIT NAME             TYPE    --------ATT-------    --------DEF-------   STA   BONUS
	addUnit('slinger',            TROOP,    7,   8,   9,  10,     6,   7,   8,   9,   7,   NONE);
	addUnit('swordsman',          TROOP,   18,  20,  23,  27,    11,  12,  13,  15,   4,   ASSAULT);
	addUnit('phalanx',            TROOP,   14,  16,  18,  20,    30,  34,  39,  45,   8,   RESISTANCE);
	addUnit('archer',             TROOP,   26,  29,  34,  41,    23,  24,  25,  26,   4,   RESISTANCE);
	addUnit('marksman',           TROOP,   42,  47,  55,  66,    21,  23,  25,  27,   5,   ASSAULT);
	addUnit('gyrocopter',         TROOP,   35,  39,  44,  50,    30,  33,  37,  42,   3,   NONE);
	addUnit('steamgiant',         TROOP,   67,  75,  85,  97,    50,  58,  68,  80,   4,   NONE);
	addUnit('bombardier',         TROOP,  184, 206, 234, 268,    54,  60,  68,  78,   3,   ASSAULT);
	addUnit('ram',                TROOP,    6,   8,  10,  12,    50,  58,  68,  80,   5,   RAM);
	addUnit('catapult',           TROOP,   34,  42,  52,  64,    33,  37,  43,  51,   5,   RAM);
	addUnit('mortar',             TROOP,  142, 157, 175, 196,    92, 102, 114, 128,   5,   RAM);
	addUnit('medic',              TROOP,    8,   8,   8,   8,    22,  22,  22,  22,  10,   HEALER);
	addUnit('cook',               TROOP,   12,  12,  12,  12,    18,  18,  18,  18,  10,   REGENERATION);	
	
	addUnit('ship_ram',           SHIP,    16,  18,  21,  24,    13,  14,  15,  17,   5,   ASSAULT);
	addUnit('ship_ballista',      SHIP,    15,  16,  18,  20,    17,  20,  23,  27,   6,   RESISTANCE);
	addUnit('ship_flamethrower',  SHIP,    39,  44,  50,  57,    17,  19,  22,  26,   5,   ASSAULT);
	addUnit('ship_catapult',      SHIP,    26,  29,  33,  38,    38,  43,  49,  56,   6,   RESISTANCE);
	addUnit('ship_steamboat',     SHIP,    84,  94, 107, 123,    25,  27,  31,  37,   5,   ASSAULT);
	addUnit('ship_mortar',        SHIP,    54,  60,  68,  78,   108, 120, 136, 156,   6,   RESISTANCE);
	addUnit('ship_submarine',     SHIP,   142, 160, 181, 205,    56,  62,  70,  80,   3,   NONE);
}

//----------- HELPERS -------------------
function log(msg) {
	if (DEBUG) {
		GM_log(msg);
	}
}

function makeMilitaryScore(att, def, sta) {
	var result = { };
	result[ATT] = att;
	result[DEF] = def;
	result[STA] = sta;
	return result;
}
	
function addUnit(unitName, unitType, att0, att1, att2, att3, def0, def1, def2, def3, sta, bonus) {
	var attack = [ att0, att1, att2, att3 ];
	var defense = [ def0, def1, def2, def3 ];
	var stamina = [ sta ];
	var score = {};
	score[ATT] = attack;
	score[DEF] = defense;
	score[STA] = stamina;
	score[BONUS] = bonus;
	score[UNIT_TYPE] = unitType;
	SCORES[unitName] = score;
}

//----------- COMPUTATION FUNCTIONS -------------------
function getScore(unitType, qty, upgrades, scoreType, wallLevel) {
	
	log("Looking for the " + scoreType + " score of " + qty + " units of type " + unitType + " with " + upgrades + " upgrades");
	var unitData = SCORES[unitType];
	if (!unitData) {
		log("Unknown unit type " + unitType);
		return 0;
	}
	var typeScores = unitData[scoreType];
	var scorePerUnit = typeScores[upgrades];
	
	// apply wall for troops
	if (scoreType == DEF && unitData[UNIT_TYPE] == TROOP) {
		scorePerUnit *= (1 + wallLevel/10);
	}
	
	// apply bonus
	if (scoreType == ATT && unitData[BONUS] == ASSAULT ||
		scoreType == DEF && unitData[BONUS] == RESISTANCE) {
		scorePerUnit *= 1.3;
	}
	
	return Math.round(qty * scorePerUnit);
}

function calculateScore(units, upgrades, wallLevel) {
	var score = makeMilitaryScore(0, 0, 0);
	for (var i=0; i<units.length; i++) {
		var unit = units[i];
		var unitType = unit[UNIT_TYPE];
		var upgrade = upgrades[unitType];
		if (!upgrade) {
			upgrade = makeMilitaryScore(0,0,0);
		}
		score[ATT] += getScore(unitType, unit[QTY], upgrade[ATT], ATT, wallLevel);
		score[DEF] += getScore(unitType, unit[QTY], upgrade[DEF], DEF, wallLevel);
		score[STA] += getScore(unitType, unit[QTY], 0, STA, wallLevel);
	}
	log("Computed ATT: " + score[ATT] + ", DEF: " + score[DEF] + ", STA: " + score[STA]);
	return score;
}

//----------- EXTRACTION FUNCTIONS -------------------
function extractNumber(phrase) {
	if (!phrase) {
		return 0;
	}
	
	var words = phrase.split(" ");
	for (var i = 0; i < words.length; i++) {
		var num = parseInt(words[i], 10);
		if (num) {
			return num;
		}
	}
	return 0;
}

function extractUpgrade(imgSrc) {
	return imgSrc ? 4 - parseInt(imgSrc.replace(/.*icon(.*)\.gif.*/, "$1")) : 0;
}

function extractUpgrades(node) {
	var result = makeMilitaryScore(0, 0, 0);
	result[ATT] = extractUpgrade($("img[class*=att]", node).attr('src'));
	result[DEF] = extractUpgrade($("img[class*=def]", node).attr('src'));
	return result;
}

function makeUnitsAndUpgrades(units, upgrades) {
	var result = {};
	result[UNITS] = units;
	result[UPGRADES] = upgrades;
	return result;
}

function extractUnitsAndUpgrades() {	
	var units = [];
	var upgrades = {};

	$('ul#units > li').each(
		function () {
			var unitType = $(this).attr('class').split(' ')[1];
			var quantity = parseInt($.trim( $('.unitcount', $(this)).html().replace(/<span.*?\/span>/, "") ));
			var unitUpgrades = extractUpgrades($(this));

			var unit = {};
			unit[UNIT_TYPE] = unitType;
			unit[QTY] = quantity;
			units.push(unit);
			
			var upgrade = {};
			upgrade[ATT] = unitUpgrades[ATT];
			upgrade[DEF] = unitUpgrades[DEF];			
			upgrades[unitType] = upgrade;
		}
	);

	return makeUnitsAndUpgrades(units, upgrades);
}

function extractUnitType(url, type) {
	var filter = ".*60_(.*)_faceright.gif";
	if (type == SHIP) {
		filter = ".*60\/(.*)_faceright.gif";
	}
	return url.replace(new RegExp(filter), "$1");
}

function extractCount(text) {
	var txt = text.replace(/-/, "0");
	return parseInt(txt);
}

function extractUnits(tab, type) {
	var units = [];
	
	$("#" + tab + " .contentBox01h:first table tbody").each(
		function() {
			var types = $("tr[class!=count]", this);
			var index = 0;
			$("tr.count td", this).each(
				function() {
					var quantity = extractCount($(this).text());
					var unitType = extractUnitType($("th:eq(" + (index++) + ") img", types).attr("src"), type);
					
					var unit = {};
					unit[UNIT_TYPE] = unitType;
					unit[QTY] = quantity;
					
					units.push(unit);
				}
			);
		}
	);
	
	log("Extracted units: " + JSON.stringify(units));
	return units;
}

//----------- DISPLAY FUNCTIONS -------------------
function formatNumber(num) {
	var numStr = "" + num;
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(numStr)) {
		numStr = numStr.replace(rgx, '$1' + ',' + '$2');
	}
	return numStr;
}

function applyScore(prefix, score) {
	$("." + prefix + "AttScore").html(formatNumber(score[ATT]));
	$("." + prefix + "DefScore").html(formatNumber(score[DEF]));
	$("." + prefix + "StaScore").html(formatNumber(score[STA]));
}

function displayMilitary(serverName, townName) {
	// zero
	var zeroScore = makeMilitaryScore(0, 0, 0);

	var locations = $("#locations");
	var wallLevel = extractNumber($(".wall a", locations).attr("title"));
	$(".wallBonus").text((wallLevel*10) + "%");

	var units = readCache(serverName, townName);
	var upgrades = readCache(serverName);
	
	if (units && units[TROOP] && upgrades && upgrades[TROOP]) {
		applyScore(TROOP, calculateScore(units[TROOP], upgrades[TROOP], wallLevel));
	} else {
		applyScore(TROOP, zeroScore);
	}	

	if (units && units[SHIP] && upgrades && upgrades[SHIP]) {
		applyScore(SHIP, calculateScore(units[SHIP], upgrades[SHIP], wallLevel));
	} else {
		applyScore(SHIP, zeroScore);
	}	
}

function createDiv() {

	GM_addStyle("#ikariamMilitaryDiv { margin-top: 12px; } " +
				"#ikariamMilitaryDiv li { margin: 2px 10px; } " +
				"#ikariamMilitaryDiv .data .textLabel { float: left; width: 80px; } " +
				"#ikariamMilitaryDiv .militaryInfo .hdr { float: left; font-weight: bold; }");
	
	$("#information .content").append( $(
		'<div id="ikariamMilitaryDiv">' +
			'<ul>' +
				'<li class="militaryInfo"><span class="hdr">Troops:</span><br/>' +
					'<ul>' +
						'<li class="data"><span class="textLabel">Attack: </span><div class="trpAttScore">0</div></li>' +
						'<li class="data"><span class="textLabel">Defense: </span><div class="trpDefScore">0</div></li>' +
						'<li class="data"><span class="textLabel">Stamina: </span><div class="trpStaScore">0</div></li>' +
						'<li class="data"><span class="textLabel">Wall bonus: </span><div class="wallBonus">0</div></li>' +
					'</ul>' +
				'</li>' +
				'<li class="militaryInfo"><span class="hdr">Ships:</span><br/>' +
					'<ul>' +
						'<li class="data"><span class="textLabel">Attack: </span><div class="shpAttScore">0</div></li>' +
						'<li class="data"><span class="textLabel">Defense: </span><div class="shpDefScore">0</div></li>' +
						'<li class="data"><span class="textLabel">Stamina: </span><div class="shpStaScore">0</div></li>' +
					'</ul>' +
				'</li>' +
			'</ul>'
	));
}

//-------------- MAIN FUNCTION --------------------------------------
$(function () {
	try {	
		var page = $("body").attr("id");
		var serverName = top.location.host;
		var townName = $("#changeCityForm div[class*=coords]").text();

		if (page == "city") {
			if ($("#reportInboxLeft").length > 0 || $("#unitConstructionList").length > 0 ) {
				initializeData();
				createDiv();			
				displayMilitary(serverName, townName);
			}
		} else
		if (page == "barracks") {
			updateUnitsAndUpgradesCache(serverName, townName, TROOP, extractUnitsAndUpgrades());
		} else
		if (page == "shipyard") {
			updateUnitsAndUpgradesCache(serverName, townName, SHIP, extractUnitsAndUpgrades());
		} else
		if (page == "cityMilitary-army") {
			updateUnitsCache(serverName, townName, TROOP, extractUnits("tab1", TROOP));
		} else
		if (page == "cityMilitary-fleet") {
			updateUnitsCache(serverName, townName, SHIP, extractUnits("tab2", SHIP));
		}
	} catch (e) {
		log("Error: " + e);
	}
});