MediaWiki:XPtable.js

From Blue Archive Wiki
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* XP tables generic - start */
var xptable_data = {};
var xpTableCounter = 0;

	
$( document ).ready(function() {
	initXPTable();
	$(".xpcalc .controls > .levels input").on("change mouseup keyup click", function(){updateXPTable($(this).closest("table"));});
	$(".xpcalc .controls > .items input").on("change mouseup keyup click", function(){updateXPTable($(this).closest("table"), false);});
	$(".xpcalc .controls > .items img").on("click", function(e){addItemCount($(this).closest("table"), $(this).closest("div.item").attr('data-itemnumber'),e);});
	$(".xpcalc .xptable > div.content").children("div").on("click", function(){changeTargetLevel($(this).closest("table"),$(this).find('span.level').html());});
});
	

function initXPTable(){
	$(".xpcalc").each(function(){
		var id = 'xpcalc-'+(++xpTableCounter);
		$(this).attr('id',id);
		
		var data = {};
		data.settings = {
			'type': $(this).attr('data-type'), 
			'level_cap': parseInt($(this).attr('data-levelcap')),
			'max_level': parseInt($(this).attr('data-levelcap')),
			'default_level': parseInt($(this).attr('data-defaultlevel')) || parseInt($(this).attr('data-levelcap')), 
			'credit_price': parseInt($(this).attr('data-creditprice')) || 0, 
			'level_from': 0, 
			'level_to': 0, 
			'target_xp':0,
			'planned_xp':0,
			'xp_overshoot': 0,
			'total_credits': 0,
		};

		data.items = {};
		$(this).find(".controls > .items div.item").each(function(){
			var item_number = $(this).attr('data-itemnumber');
			var value = $(this).attr('data-value');
			data.items[item_number] = parseInt(value);
		});


		$(this).find(".xptable .content > div").each(function(){
			var level = $(this).find('span.level').html();
			data[level] = {};
			var xp = $(this).find('span.xp').html();
			var total_xp = $(this).find('span.total_xp').html();
			data[level] = {'xp':parseInt(xp), 'total_xp':parseInt(total_xp)};

			if (level >  data.settings.level_cap) {
				$(this).addClass('tbd').attr('title', "Currently not attainable in the game");
				data.settings.max_level = level;
				//console.log(`Level ${level} is outside of expected cap`);
			}
		});

		$(this).find(".controls > .levels .level-from").append('<input type="number" value="1" step="1" min="1" max="'+data.settings.max_level+'">');
		$(this).find(".controls > .levels .level-to").append('<input type="number" value="'+data.settings.default_level+'" step="1" min="1" max="'+data.settings.max_level+'">');
		$(this).find(".controls > .items .item").append('<input type="number" value="0" step="1" min="0" max="999"></span>');

		xptable_data[id] = data;

		updateXPTable($(this));
	});
}


function changeTargetLevel (xpcalc, target_level) {
	xpcalc.find('.controls > .levels > .level-to > input').val(target_level);
	updateXPTable(xpcalc);
}

function addItemCount (xpcalc, item_id, event) {
	var count = 1;
	if (event.shiftKey) count *= 10; 
	if (event.ctrlKey) count *= -1;

	var input = xpcalc.find('.controls > .items .item-'+item_id+' > input');
	input.val( parseInt(input.val())+count );
	updateXPTable(xpcalc, false);
}


function planXPItems (id) {
	//var data = xptable_data[id]
	var settings = xptable_data[id].settings;
	var items = xptable_data[id].items;
	var itemplan = new Array(Object.keys(items).length); for (let i=1; i<Object.keys(items).length+1; ++i) itemplan[i] = 0;
	var planned_xp = 0; //actual XP of planned items, should be >= target with minimal overshot
	var target_xp = 0; //the minimum XP amount needed to reach target level
	var hysteresis = items[1];
	

	for (var index = settings.level_from; index < settings.level_to; index++) {
		target_xp += xptable_data[id][index].xp;
	}
	settings.target_xp = target_xp;

	for (index = Object.keys(items).length; index > 0; index--) {
		itemplan[index] = Math.floor((target_xp + hysteresis)/items[index]);
		if ( itemplan[index] > 999 ) itemplan[index] = 999;
		planned_xp += items[index] * itemplan[index];
		target_xp -= items[index] * itemplan[index];

		//console.log(`Added item ${index} x ${itemplan[index]}, remaining target xp is ${target_xp} `);
	}
	settings.planned_xp = planned_xp;
	if (target_xp<0) settings.xp_overshoot = -target_xp;
	settings.total_credits = planned_xp*settings.credit_price;
	settings.itemplan = itemplan;
}
	

function getXPItems (xpcalc, id) {
	var data = xptable_data[id];
	var settings = xptable_data[id].settings;
	var items = xptable_data[id].items;
	var itemplan = new Array(Object.keys(items).length); 
	var planned_xp = 0; //actual XP of planned items, should be >= target with minimal overshot
	var target_xp = 0; //the minimum XP amount needed to reach target level
	//var hysteresis = items[1];
	//var level_to = 0;
	
	for (let index=1; index<Object.keys(items).length+1; ++index) {
		itemplan[index] = parseInt(xpcalc.find('.controls > .items .item-'+index+' > input').val());
		if (itemplan[index] < 0) itemplan[index] = 0; 
		planned_xp += items[index] * itemplan[index];
	}
	settings.itemplan = itemplan;
	settings.planned_xp = planned_xp;
	settings.total_credits = planned_xp*settings.credit_price;

	//console.log(`Starting with planned xp ${planned_xp}`)
	for (var index = settings.level_from; index < settings.max_level; index++) {
		if (planned_xp < data[index].xp) break;	 
		planned_xp -= data[index].xp;
		target_xp += data[index].xp;
		settings.level_to = index+1;
	}

	//console.log(`Upgraded to level ${settings.level_to } with remaining planned xp ${planned_xp}`);
	settings.target_xp = target_xp;
	settings.xp_overshoot = planned_xp;
	
	xpcalc.find('.controls > .levels > .level-to > input').val(settings.level_to);

}


function updateXPTable (xpcalc, optimize_items){
	optimize_items = (typeof optimize_items !== 'undefined') ? optimize_items : true; //default true, ES5 does not support function defaults

	var id = xpcalc.attr('id');
	var settings = xptable_data[id].settings;
	//console.log(settings);

	var level_from = parseInt(xpcalc.find('.controls > .levels > .level-from > input').val());
	var level_to = parseInt(xpcalc.find('.controls > .levels > .level-to > input').val());
	
	level_from = (typeof level_from !== 'undefined' && !isNaN(level_from)) ? level_from : 1;
	level_to = (typeof level_to !== 'undefined' && !isNaN(level_to)) ? level_to : settings.level_cap;
	
	if (level_from < 1) 	 				{ xpcalc.find('.controls > .levels > .level-from > input').val(1);	level_from = 1; }
	if (level_from >= settings.max_level) 	{ xpcalc.find('.controls > .levels > .level-from > input').val(settings.max_level-1); level_from = settings.max_level-1; }

	if (level_to <= level_from) 			{ xpcalc.find('.controls > .levels > .level-to > input').val(level_from+1);	level_to = level_from+1; }
	if (level_to > settings.max_level) 		{ xpcalc.find('.controls > .levels > .level-to > input').val(settings.max_level); level_to = settings.max_level; }

	settings.level_from = level_from;
	settings.level_to = level_to;

	//console.log (`Calculating Exp from level ${level_from} to ${level_to}`)
	if (optimize_items) planXPItems(id);
	else getXPItems(xpcalc, id);
	//console.log('Itemplan after is '+settings.itemplan);
	
	//console.log (`Exp ${settings.planned_xp}/${settings.target_xp}; total price ${settings.total_credits}`)

	
	for (var index = Object.keys(xptable_data[id].items).length; index > 0; index--) {
		xpcalc.find('.controls > .items .item-'+index+' > input').val(settings.itemplan[index]);
	}	
	
	xpcalc.find('.controls > .output > .total-xp > span:last-of-type').html(settings.planned_xp.toLocaleString());
	xpcalc.find('.controls > .output').attr('title','XP: '+settings.planned_xp+'/'+settings.target_xp+'\nOvershoot: '+settings.xp_overshoot);
	if (settings.target_xp>0 && settings.xp_overshoot > xptable_data[id].items[1])  xpcalc.find('.controls > .output').addClass('warn'); 
	else xpcalc.find('.controls > .output').removeClass('warn');
	
	if (settings.credit_price) xpcalc.find('.controls > .output > .total-credits > span:last-of-type').html(settings.total_credits.toLocaleString());
	
}
/* XP tables generic - end */