// ==UserScript==
// @name Imperia Online Auto Merchant
// @namespace imperia_merchant
// @version 1.4
// @description Purchases resource from the market.
// @author ChoMPi
// @match http://*.imperiaonline.org/imperia/game_v6/game/village.php*
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
/* jshint -W097 */
'use strict';
var interval;
var lang = "en";
var currentLowset = 0;
$.fn.serializeObject = function() {
var form = {};
$.each($(this).serializeArray(), function (i, field) {
form[field.name] = field.value || "";
});
return form;
};
String.prototype.replaceAll = function (find, replace) {
var str = this;
return str.replace(new RegExp(find, 'g'), replace);
};
function nFormatter(num)
{
if (num >= 1000000) {
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
}
if (num >= 1000) {
return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
}
return num;
}
function GetSettings()
{
var settings = GM_getValue('automerchantsettings' + uid + REALM, null);
if (settings == null) {
return { resType: "1", highestPrice: "0.8", goal: "0", interval: "4000" };
}
return JSON.parse(settings);
}
function SaveSettings(obj)
{
GM_setValue('automerchantsettings' + uid + REALM, JSON.stringify(obj));
}
function GetAutoMerchantState()
{
var state = GM_getValue('automerchantstate' + uid + REALM, '0');
return (state == '1');
}
function SetAutoMerchantState(state)
{
GM_setValue('automerchantstate' + uid + REALM, (state ? '1' : '0'));
}
function GetSession()
{
var session = GM_getValue('automerchantsession' + uid + REALM, null);
if (session == null) {
return { purchased: 0, spent: 0 };
}
return JSON.parse(session);
}
function SetSession(obj)
{
GM_setValue('automerchantsession' + uid + REALM, JSON.stringify(obj));
}
function ResetSession()
{
SetSession({ purchased: 0, spent: 0 });
}
function UpdateSessionInfo()
{
if (container.isOpen({saveName:"auto-merchant"})) {
var cont = $('#auto-merchant .window-content');
$('#session-status', cont).html((GetAutoMerchantState() ? 'Running' : 'Stopped'));
$('#session-purchased', cont).html(GetSession().purchased);
$('#session-spent', cont).html(GetSession().spent);
$('#session-current-lowset', cont).html(currentLowset);
}
}
function UpdateButtons()
{
var cont = $('#auto-merchant .window-content');
if (typeof cont == 'undefined' || cont.length == 0) {
return;
}
if (GetAutoMerchantState()) {
$('button#auto-merchant-start', cont).hide();
$('button#auto-merchant-stop', cont).show();
} else {
$('button#auto-merchant-start', cont).show();
$('button#auto-merchant-stop', cont).hide();
}
}
function OpenWindow()
{
container.open({saveName:'auto-merchant', title:'Auto Merchant'});
var html =
'<span class="window-decor-left"></span>' +
'<span class="window-decor-right"></span>' +
'<div class="window-tight auto-merchant-main">' +
'<div class="content">' +
'<div id="auto-merchant-id" class="auto-merchant">' +
'<div class="centered">' +
'<form onsubmit="return false" id="auto-merchant-form"><table align="center" style="width: 60%;">' +
'<tr>' +
'<td style="width:156px;">Resource to purchase</td>' +
'<td><select class="dropdown" name="resType" id="resTypeId">' +
'<option value="1"' + (GetSettings().resType == "1" ? ' selected="selected"' : '') + '>Wood</option>' +
'<option value="2"' + (GetSettings().resType == "2" ? ' selected="selected"' : '') + '>Iron</option>' +
'<option value="3"' + (GetSettings().resType == "3" ? ' selected="selected"' : '') + '>Stone</option>' +
'</select></td>' +
'</tr>' +
'<tr>' +
'<td style="width:156px;">Resource goal</td>' +
'<td><div style="position:relative;">' +
'<input class="text" name="goal" id="goalId" size="10" value="' + GetSettings().goal + '" onkeyup="this.value=IsNumeric(this.value);" onblur="if(this.value.length==0)this.value=0;" />' +
'<span id="goalN" style="position:absolute;width:100px;top:4px;right:-100px;">' + (parseInt(GetSettings().goal) > 0 ? nFormatter(GetSettings().goal) : '') + '</span>' +
'</div></td>' +
'</tr>' +
'<tr><td style="width:156px;">Highest price</td><td><input class="text" name="highestPrice" id="highestPriceId" size="5" value="' + GetSettings().highestPrice + '" onkeyup="this.value=IsNumeric2(this.value);" /></td></tr>' +
'<tr><td style="width:156px;">Interval</td><td><input class="text" name="interval" id="intervalId" size="5" value="' + GetSettings().interval + '" onkeyup="this.value=IsNumeric(this.value);" onblur="if(parseInt(this.value)<1000)this.value=1000;" /> ms</td></tr>' +
'</table></form>' +
'<hr class="divider" />' +
'<table align="center" style="width: 60%;">' +
'<tr>' +
'<td style="width:156px;">Status</td>' +
'<td id="session-status">' + (GetAutoMerchantState() ? 'Running' : 'Stopped') + '</td>' +
'</tr>' +
'<tr>' +
'<td style="width:156px;">Amount purchased</td>' +
'<td id="session-purchased">' + GetSession().purchased + '</td>' +
'</tr>' +
'<tr>' +
'<td style="width:156px;">Gold spent</td>' +
'<td id="session-spent">' + GetSession().spent + '</td>' +
'</tr>' +
'<tr>' +
'<td style="width:156px;">Current price</td>' +
'<td id="session-current-lowset">' + currentLowset + '</td>' +
'</tr>' +
'</table>' +
'<hr class="divider" />' +
'<div class="centered-block visual-loading fnone" style="">' +
'<button class="button" type="button" id="auto-merchant-start" value="Start" onclick="return false" style="' + (GetAutoMerchantState() ? 'display:none' : '') + '">Start</button>' +
'<button class="button" type="button" id="auto-merchant-stop" value="Stop" onclick="return false" style="' + (!GetAutoMerchantState() ? 'display:none' : '') + '">Stop</button>' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</div>';
var cont = $('#auto-merchant .window-content');
cont.html(html);
$('#resTypeId', cont).on('change', function() {
SaveSettings($('#auto-merchant-form', cont).serializeObject());
});
$('#highestPriceId', cont).on('keyup', function() {
SaveSettings($('#auto-merchant-form', cont).serializeObject());
});
$('#goalId', cont).on('keyup', function() {
SaveSettings($('#auto-merchant-form', cont).serializeObject());
var val = $(this).val();
if (val.length > 0 && parseInt(val) > 0) {
$('#goalN').html(nFormatter(parseInt(val)));
} else {
$('#goalN').html('');
}
});
$('#intervalId', cont).on('blur', function() {
SaveSettings($('#auto-merchant-form', cont).serializeObject());
});
$('button#auto-merchant-start', cont).click(function(){
SetAutoMerchantState(true);
ResetSession();
OpenWindow();
});
$('button#auto-merchant-stop', cont).click(function(){
SetAutoMerchantState(false);
OpenWindow();
});
container.position();
ui.constructor();
}
function GetRowValues(element)
{
var e1 = $('td:eq(1)', element);
if (e1.find('a').length > 0) {
e1 = $(e1.find('a').get(0));
}
var html = e1.html().replaceAll(' ', '').replaceAll(' ', '');
var amount = parseInt(html);
var price = parseFloat($('td:eq(2)', element).text());
return { amount: amount, price: price };
}
function GetMaxAmount(content)
{
var as = content.find('div a.clickLabel');
if (as.length == 0) {
return 0;
}
var a = $(as.get(0));
var hrefSearch = /calculate\((\d+)\)\;/;
var results = a.attr('href').match(hrefSearch);
if (typeof results != 'undefined' && results.length > 0 && typeof results[1] != 'undefined') {
return parseInt(results[1]);
}
return 0;
}
function GetMarketData(callback)
{
var resType = GetSettings().resType.toString();
$.post(location.protocol + "//" + location.host + "/imperia/game_v6/game/xajax_loader.php", {
xjxfun: "viewTradeScreen",
xjxr: Date.now(),
xjxargs: ["Smarket", "<xjxobj><e><k>tab</k><v>N2</v></e><e><k>resType</k><v>N" + resType + "</v></e><e><k>vexok</k><v>Btrue</v></e></xjxobj>"],
},
function(data) {
var e2 = $(data).find("#messageboxTradeContent").get(0);
var html = $(e2).html();
var content = $('<div></div>').html(html);
var as = content.find('td > a.clickLabel');
if (as.length == 0) {
return;
}
var maxAmount = GetMaxAmount(content);
if (maxAmount < 100) {
return;
}
var tr = $(as.get(0)).parent().parent();
var values = GetRowValues(tr);
if (values.amount < 100) {
values = GetRowValues(tr.next());
}
if (values.amount > maxAmount) {
values.amount = maxAmount;
}
callback({ price: values.price, amount: values.amount, resType: resType });
}, "xml");
}
function GetResID(resType)
{
if (resType == "1") {
return "wood";
} else if (resType == "2") {
return "iron";
} else if (resType == "3") {
return "stone";
}
}
function BuyResource(data)
{
var goal = parseInt(GetSettings().goal);
if (goal > 0 && goal == GetSession().purchased) {
SetAutoMerchantState(false);
if (!container.isOpen({saveName:"auto-merchant"})) {
OpenWindow();
}
$('#auto-merchant .content').prepend('<div class="notice-wrapper"><div class="notice positive"><span></span>Your resource goal has been reached.<br></div></div>');
UpdateButtons();
return;
}
if (goal > 0 && (GetSession().purchased + data.amount) > goal) {
data.amount = goal - GetSession().purchased;
}
var onclickprice = Math.floor(data.amount * data.price);
$.post(location.protocol + "//" + location.host + "/imperia/game_v6/game/xajax_loader.php", {
xjxfun: "doBuyResource",
xjxr: Date.now(),
xjxargs: ["Smarket", "<xjxobj><e><k>onClickPrice</k><v>S" + onclickprice.toString() + "</v></e><e><k>resId</k><v>S" + GetResID(data.resType) + "</v></e><e><k>resType</k><v>S" + data.resType + "</v></e><e><k>amountToBuy</k><v>S" + data.amount.toString() + "</v></e><e><k>buttonBuy</k><v>SBuy</v></e><e><k>vexok</k><v>Btrue</v></e></xjxobj>"],
},
function(response) {
var e2 = $(response).find("#messageboxTradeContent").get(0);
var html = $(e2).html();
var content = $('<div></div>').html(html);
if (content.find('.notice-wrapper div.notice.positive').length > 0) {
// Success
var session = GetSession();
session.purchased += data.amount;
session.spent += onclickprice;
SetSession(session);
}
else
{
var notice = content.find('.notice-wrapper div.notice');
if (notice.length > 0) {
if (!container.isOpen({saveName:"auto-merchant"})) {
OpenWindow();
}
$('#auto-merchant .content').prepend(notice.parent());
}
}
}, "xml");
}
function Update()
{
clearTimeout(interval);
interval = setTimeout(Update, GetSettings().interval);
if (!GetAutoMerchantState()) {
return;
}
GetMarketData(function(data)
{
if (data.price <= parseFloat(GetSettings().highestPrice))
{
BuyResource(data);
}
currentLowset = data.price;
UpdateSessionInfo();
});
}
function Init()
{
var cont = $('<div id="widget-automerchant"><div class="ui-bg ui-buttons"></div></div>');
var btn = $('<a href="javascript:void(0);" style="padding: 5px 3px;box-sizing:border-box;">AM</a>');
btn.click(function() {
OpenWindow();
});
$('.ui-buttons', cont).append(btn);
$('.ui-bottom-right').append(cont);
interval = setTimeout(Update, GetSettings().interval);
}
function hookFunction(object, functionName, callback) {
(function(originalFunction) {
object[functionName] = function () {
var returnValue = originalFunction.apply(this, arguments);
callback.apply(this, arguments);
return returnValue;
};
}(object[functionName]));
}
$(document).ready(function()
{
function InitCheck()
{
if (typeof io.showUI != 'undefined')
{
hookFunction(io, 'showUI', function() {
Init();
});
}
else
{
setTimeout(InitCheck, 500);
}
}
InitCheck();
});