NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name ArkhamDB Utils
// @namespace http://franco.nom.es
// @version 0.2
// @description Utilidades para ArkhamDB
// @updateURL https://openuserjs.org/meta/fafranco82/ArkhamDB_Utils.meta.js
// @author fafranco82
// @match http://*.arkhamdb.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery.rest/1.0.2/jquery.rest.min.js
// @require https://cdn.rawgit.com/caolan/async/master/dist/async.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js
// @require https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js
// @require https://cdn.rawgit.com/padolsey-archive/jquery.fn/master/sortElements/jquery.sortElements.js
// @grant none
// ==/UserScript==
(function($) {
'use strict';
var lo = _.noConflict();
var nest = function(seq, keys) {
if(!keys.length) {
return seq;
} else {
var first = keys[0];
var rest = keys.slice(1);
return lo.mapValues(lo.groupBy(seq, first), function(value) {
return nest(value, rest);
});
}
};
lo.mixin({nest: nest});
window.lo = lo;
$(document).ready(function($) {
$('nav.navbar').removeClass('navbar-static-top').addClass('navbar-fixed-top');
$('body').css('margin-top', '90px');
var options = {
links: {
'position': {
text: 'Posicionar',
click: function(callback) {
var $d = loading('Calculando posiciones...');
var deck_cards = lo(app.data.cards.find({
type_code: {$in: ['asset', 'event', 'skill']},
restrictions: {$exists: false}
})).reduce(function(acc, card) {
var number = card.quantity / 2;
if(card.pack_code=='core')
number = number * 2;
for(var i=0;i < number; i++) {
acc.push(card);
}
return acc;
}, []);
deck_cards = lo(deck_cards).orderBy(['faction_code', 'type_code', 'code']).nest(['faction_code', 'type_code']).value();
var investigator_cards = lo(app.data.cards.find({
type_code: 'investigator'
})).orderBy(['faction_code', 'code']).nest(['faction_code']).mapValues(function(cards, faction_code) {
return lo.reduce(cards, function(acc, i) {
acc.push(i);
app.data.cards.find({code: {$in: lo.keys(i.deck_requirements.card)}}).forEach(function(r) {
acc.push(r);
});
return acc;
}, []);
}).value();
async.each($('[data-code]:visible'), function(elem, done) {
var card = app.data.cards.findById($(elem).data('code'));
var idx = lo.findIndex(deck_cards[card.faction_code][card.type_code], {code: card.code});
if(idx < 0 && lo.has(card, 'restrictions.investigator')) {
var ref = app.data.cards.findById(card.restrictions.investigator[0]);
idx = lo.findIndex(investigator_cards[ref.faction_code], {code: card.code});
}
if(idx >= 0) {
var sheet = parseInt(idx / 18) + 1;
var sheet_idx = idx % 18;
var side = parseInt(sheet_idx / 9);
var pocket = (sheet_idx % 9) + 1;
var text = '[' + sheet+'-'+(side ? 'B' : 'A')+'-'+pocket + ']';
$(elem).find('span.position').remove();
$('<span>').addClass('position').css('margin-right','0.1em').text(text).prependTo(elem);
}
done();
}, function(err) {
$d.close();
if(callback && typeof callback==='function')
callback();
});
}
},
'order': {
text: 'Ordenar',
click: function(callback) {
var tw = {'investigator': 0, 'asset': 1, 'event': 2, 'skill': 3};
var fw = ['neutral', 'guardian', 'seeker', 'rogue', 'mystic', 'survivor'];
var $d = loading('Ordenando...');
async.each($('div > [data-code]').closest('div').parent().closest('div'), function(root, done) {
$('div > [data-code]', root).sortElements(function(a, b) {
var ca = app.data.cards.findById($(a).data('code'));
var cb = app.data.cards.findById($(b).data('code'));
if(ca.faction_code==cb.faction_code) {
if(ca.type_code==cb.type_code) {
return ca.code < cb.code ? -1 : (ca.code > cb.code ? 1 : 0);
} else {
return tw[ca.type_code] < tw[cb.type_code] ? -1 : 1;
}
} else {
return fw.indexOf(ca.faction_code) < fw.indexOf(cb.faction_code) ? -1 : 1;
}
}, function() {
return $(this).closest('div').get(0);
});
done();
}, function(err) {
$d.close();
if(callback && typeof callback==='function')
callback();
});
}
},
'order_position': {
text: 'Ordenar y posicionar',
click: function() {
async.series([
options.links.order.click,
options.links.position.click
], function(err) {
});
}
}
}
};
var dropdown = Handlebars.compile(
'<li> ' +
' <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> ' +
' <span class="fa fa-cog"></span> ' +
' <span class="caret"></span> ' +
' </a> ' +
' <ul class="dropdown-menu"> ' +
' {{#each links}} ' +
' <li> ' +
' <a class="util" href="#" data-link="{{@key}}">{{this.text}}</a> ' +
' </li> ' +
' {{/each}} ' +
' </ul> ' +
'</li> ');
$(dropdown(options)).appendTo('ul.navbar-right').on('click', 'a.util', function(e) {
options.links[$(e.target).data('link')].click();
});
});
var loadingHtml = Handlebars.compile(
'<div class="modal" data-backdrop="static"> ' +
' <div class="modal-dialog"> ' +
' <div class="modal-content"> ' +
' <div class="modal-body"> ' +
' <div class="row"> ' +
' <div class="col-xs-12 text-center"> ' +
' <span class="fa fa-spinner fa-spin fa-5x"></span> ' +
' </div> ' +
' </div> ' +
' <div class="row"> ' +
' <div class="col-xs-12 text-center"> ' +
' <h4>{{texto}}</h4> ' +
' </div> ' +
' </div> ' +
' </div> ' +
' </div> ' +
' </div> ' +
'</div> ');
function loading(text) {
var $d = $(loadingHtml({texto:text})).appendTo('body').modal();
return {
"close": function() {
$d.modal('hide').remove();
}
};
}
})(jQuery);