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);