Wanikani Reorder Ultimate 2 Embe Mod

Learn in the order you want to.

// ==UserScript==
// @name          Wanikani Reorder Ultimate 2 Embe Mod
// @namespace     https://www.wanikani.com
// @description   Learn in the order you want to.
// @version       2.1
// @include       *://www.wanikani.com/lesson/session*
// @include       *://www.wanikani.com/review/session*
// @grant         none
// ==/UserScript==

// Original source:  https://gist.github.com/xMunch/6beafa1a79a77386cd92/raw/WKU.user.js
// Wanikani thread:  https://www.wanikani.com/chat/api-and-third-party-apps/8471/page/31#post332221
// Author: xMunch

(function ($) {$.each(['hide', 'addClass'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); })(jQuery);/*
 * HTML5 Sortable jQuery Plugin
 * http://farhadi.ir/projects/html5sortable
 *
 * Copyright 2012, Ali Farhadi
 * Released under the MIT license.
 */
(function(e){var t,n=e();e.fn.sortable=function(r){var i=String(r);r=e.extend({connectWith:false},r);return this.each(function(){if(/^enable|disable|destroy$/.test(i)){var s=e(this).children(e(this).data("items")).attr("draggable",i=="enable");if(i=="destroy"){s.add(this).removeData("connectWith items").off("dragstart.h5s dragend.h5s selectstart.h5s dragover.h5s dragenter.h5s drop.h5s")}return}var o,u,s=e(this).children(r.items);var a=e("<"+(/^ul|ol$/i.test(this.tagName)?"li":"div")+' class="sortable-placeholder">');s.find(r.handle).mousedown(function(){o=true}).mouseup(function(){o=false});e(this).data("items",r.items);n=n.add(a);if(r.connectWith){e(r.connectWith).add(this).data("connectWith",r.connectWith)}s.attr("draggable","true").on("dragstart.h5s",function(n){if(r.handle&&!o){return false}o=false;var i=n.originalEvent.dataTransfer;i.effectAllowed="move";i.setData("Text","dummy");u=(t=e(this)).addClass("sortable-dragging").index()}).on("dragend.h5s",function(){if(!t){return}t.removeClass("sortable-dragging").show();n.detach();if(u!=t.index()){t.parent().trigger("sortupdate",{item:t})}t=null}).not("a[href], img").on("selectstart.h5s",function(){this.dragDrop&&this.dragDrop();return false}).end().add([this,a]).on("dragover.h5s dragenter.h5s drop.h5s",function(i){if(!s.is(t)&&r.connectWith!==e(t).parent().data("connectWith")){return true}if(i.type=="drop"){i.stopPropagation();n.filter(":visible").after(t);t.trigger("dragend.h5s");return false}i.preventDefault();i.originalEvent.dataTransfer.dropEffect="move";if(s.is(this)){if(r.forcePlaceholderSize){a.height(t.outerHeight())}t.hide();e(this)[a.index()<e(this).index()?"after":"before"](a);n.not(a).detach()}else if(!n.is(this)&&!e(this).children(r.items).length){n.detach();e(this).append(a)}return false})})}})(jQuery);

var ui_css =
    '.ui, .ui-small {'+
    '	list-style: none;'+
    '	color: #000000;'+
    '	margin: 5px;'+
    '	padding: 5px;'+
    '	min-height: 30px;'+
    '	background: #eeeeee;'+
    '}'+
    '.ui-small {margin: 5px;padding: 5px;text-align: right;margin-bottom: 5px;}'+
    '.center {margin: 0 auto;}'+
    '#left {min-width: 150px; min-height: 150px;}'+
    '#mid {padding-top: 20px; text-align: center;}'+
    '#right {min-width: 150px; min-height: 150px; text-align: right;}'+
	'.fob item {'+
    '    cursor: pointer;'+
    '    display: inline-block;'+
    '    font-size: 16px;'+
    '    margin-left: -43px;'+
    '    horizontal-align: center;'+
    '    padding: 0.4em 0.4em 0.3em;'+
    '    color: #fff;'+
    '    line-height: 1em;'+
    '    border-radius: 2px;'+
    '    background-color: #c8c8c8;'+
    '    -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);'+
    '    -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);'+
    '    box-shadow: inset 0 0 10px rgba(0,0,0,0.1);'+
    '    -webkit-box-sizing: border-box;'+
    '    -moz-box-sizing: border-box;'+
    '    box-sizing: border-box;'+
	'}'+
    '.unsorted, .hidden {display: none !important; visibility: none !important}'+
    'item[id^=level-] {background-color: #5571E2}'+
    '.sortable {padding: 0}'+
    '.sortable item {'+
    '    cursor: pointer;'+
    '    display: inline-block;'+
    '    font-size: 16px;'+
    '    list-style: none;'+
    '    margin-top: 0.28em;'+
    '    margin-right: 0.25em;'+
    '    padding: 0.4em 0.4em 0.3em;'+
    '    color: #fff;'+
    '    line-height: 1em;'+
    '    text-shadow: 1px 1px 0 rgba(0,0,0,0.1);'+
    '    -webkit-border-radius: 2px;'+
    '    -moz-border-radius: 2px;'+
    '    border-radius: 2px;'+
    '    -webkit-box-shadow: 2px 2px 0 #d5d5d5;'+
    '    -moz-box-shadow: 2px 2px 0 #d5d5d5;'+
    '    box-shadow: 2px 2px 0 #d5d5d5;'+
    '    -webkit-box-sizing: border-box;'+
    '    -moz-box-sizing: border-box;'+
    '    box-sizing: border-box;'+
    '}'+
    '.sortable-placeholder {'+
    '    display: inline !important;'+
    '    border: 0px dashed #CCC !important;'+
    '    background: none;'+
    '    padding: 0.4em 0.4em 0.3em; !important;'+
    '}'+
    '#priority, #priority2 {'+
    '    background: url(http://i.imgur.com/VbrYlGF.png);'+
    '    background-repeat: no-repeat;'+
    '    width: 150px;'+
    '    height: 150px;'+
    '    display: block'+
    '}'+
    '#priority {float: right;}'+
    '.balance {background-position: -1px -1px !important}'+
    '.balance2 {background-position: -153px -1px !important}'+
    '.level-heavy {background-position: -1px -153px !important}'+
    '.meaning-heavy {background-position: -153px -153px !important}'+
    '.reading-heavy {background-position: -305px -1px !important}'+
    '.type-heavy {background-position: -305px -153px !important}'+
    '#overlay {'+
    '    background-image: url(http://i.imgur.com/7drJZs4.png);'+
    '    background-repeat: no-repeat;'+
    '	 display: block;'+
    '}'+
    '.top {width: 150px; height: 150px; background-position: -1px -1px;}'+
    '.bottom {width: 150px; height: 150px; background-position: -153px -1px;}'+
    '.middle {width: 150px; height: 150px; background-position: -1px -153px;}'+
    '#reverse {margin-left:20px; cursor:pointer;}'+
    '#quick-next {cursor: pointer; display: inline-block; color: #888; font-size: 16px;}'+
    '#quick-next.active {color: orange;}'+
    '#version {float: right;}';

var ui_html =
    '<div class="ui-small hidden pure-g-r">'+
 	'   <div id="icon-plus" class="icon-plus" style="margin-right: 5px"></div>'+
    '</div>'+
    '<div class="ui pure-g-r">'+
    '<div class="pure-u-1-4" id="left">'+
    '<div id="r-only">'+
    '        <div style="padding: 10px;"><input type="checkbox" id="mode"> Single Mode&nbsp;&nbsp;|&nbsp;&nbsp;<div id="quick-next" class="icon-bolt"></div></div>'+
    '	    <div class="balance2" id="priority2"><div id="overlay" class=""></div></div>'+
    '    </div>'+
    '</div>'+
    '<div class="pure-u-1-2" id="mid">'+
    '	<div>'+
    '       <ul class="sortable" id="types">'+
    '           <div>'+
    '                <input type="checkbox" id="sort-types" value="checked" checked=""> Sort Types'+
	'				<span id="reverse" class="icon-refresh"><span style="font-family:Source Sans Pro;"> Reverse</span></span>'+
	'			</div>'+
    '           <item class="radical" style="background-color:#0af;" draggable="true">Radicals</item>'+
    '            <item class="kanji" style="background-color:#f0a;" draggable="true">Kanji</item>'+
    '            <item class="vocabulary" style="background-color:#AA38C6;" draggable="true">Vocabulary</item>'+
    '        </ul>'+
    '    </div>'+
    '    <div>'+
    '       <ul class="sortable" id="levels" style="margin-top: -12px">'+
    '           <div>'+
    '                <input type="checkbox" id="sort-levels" checked=""> Sort Levels'+
	'				<span id="reverse" class="icon-refresh"><span style="font-family:Source Sans Pro;"> Reverse</span></span>'+
	'			</div>'+
    '        </ul>'+
    '    </div>'+
    '    <div>'+
    '            <ul class="fob">'+
    '                    <item id="reorder" onclick="this.blur();" tabindex="-1">Force Reorder</item>'+
    '            </ul>'+
    '    </div>'+
    '</div>'+
    '<div class="pure-u-1-4"  id="right">'+
    '    <div><div id="icon-minus" class="icon-minus" style="color:black; margin-bottom: 17px;"></div></div>'+
    ' 	<div class="balance" id="priority" style="margin-top: 20px"><div id="overlay" class=""></div></div>'+
    ' </div>'+
    '</div>';

var activeLevels = [];
var dataset = {};
var lastUpdate = new Date().getTime();
var lessonset = {
	quick: 'l',
	queue: 'l/lessonQueue',
	active: 'l/activeQueue',
	updateVisual: function() {
		$('li[data-index="0"]').click();
		var items = $.jStorage.get(dataset.queue).concat($.jStorage.get(dataset.active));
		$.jStorage.set('l/count/rad', sorter.filterType("rad", items).length);
		$.jStorage.set('l/count/kan', sorter.filterType("kan", items).length);
		$.jStorage.set('l/count/voc', sorter.filterType("voc", items).length);
	}
};

var showerr = function(err) {
    $('#supplement-info, #information').first().after('<div id="error" style="text-align:center;">An error has occurred within WaniKani Reorder Ultimate.  Please post the error below on the forum thread.<br><a href="https://www.wanikani.com/chat/api-and-third-party-apps/8471" target="_blank">https://www.wanikani.com/chat/api-and-third-party-apps/8471</a><br><br>' + err + '<br>' + err.stack + '<br><br>Logs:<br>' + console.dlog.join('<br>') + '</div>');
};

var reviewset = {
	quick: 'r',
	queue: 'reviewQueue',
	active: 'activeQueue',
	updateVisual: function() {
		var item = $.jStorage.get(dataset.active)[Math.floor(window.Math.random(true))];
		if (item.rad) {
			$.jStorage.set('questionType', 'meaning');
		}
		if (item) {
			$.jStorage.set('currentItem', item);
		}
		var count = $.jStorage.get(dataset.queue).length + $.jStorage.get(dataset.active).length;
		$("#available-count").html(count); // to stop the double-up bug.
	}
};
var ordered = false;
var settings = {
	data: {
		sorttypes: !0,
		sortlevels: !0,
		onebyone: !1,
		quickNext: !1,
		priority: {
			'rad': 1,
			'kan': 2,
			'voc': 3,
		},
		questionTypeMode: "0",
		typePriorityMode: "0"
	},
	load: function() {
		var a = $.jStorage.get('WKU/' + dataset.quick + '/settings');
		if (a === null) {
			settings.save();
			return settings.load();
		}
		utilities.log("Loading settings...");
		for (var s in settings.data) {
			if (a[s] !== null) settings.data[s] = a[s];
		}
		$('#types item').sort(function(a, b) {
			return sorter.getHTMLElementPriority(a) - sorter.getHTMLElementPriority(b);
		}).appendTo('#types');
		$('#sort-types').prop('checked', settings.data.sorttypes).change();
		$('#sort-levels').prop('checked', settings.data.sortlevels).change();
		$('#priority').removeClass().addClass(utilities.settingsValueToClass('priority', settings.data.typePriorityMode));
		$('#quick-next').toggleClass('active', settings.data.quickNext);
		if (dataset.quick === 'r') {
			$('#mode').prop('checked', settings.data.onebyone).change();
			$('#priority2').removeClass().addClass(utilities.settingsValueToClass('priority2', settings.data.questionTypeMode));
		}
		utilities.log(settings.data);
	},
	save: function() {
		$.jStorage.set('WKU/' + dataset.quick + '/settings', settings.data);
	}
};
var setup = {
	init: function() {
		try {
			$('div[id*="loading"]').off('hide');
			console.dlog = [];
			utilities.log("WKU Init()");
			if (!setup.update.check()) {
				setup.update.patch();
			} else {
				setup.ui.create();
			}
		} catch (err) {
			showerr(err);
		}
	},
	update: {
		apply: function() {
			try {
				utilities.log("Applying UID levels");
				var queue = $.jStorage.get(dataset.active).concat($.jStorage.get(dataset.queue));
				var current = $.jStorage.get('currentItem');
				var list = $.jStorage.get('uids') || [];
				$.each(queue, function() {
					this.level = list[utilities.toUID(this)] || 0;
					if (current && utilities.toUID(this) === utilities.toUID(current)) {
						$.jStorage.set('currentItem', this);
					}
					if (activeLevels.indexOf(this.level) == -1) {
						activeLevels.push(this.level);
					}
				});
				activeLevels.sort(function(a, b) {
					return a - b;
				});
				var review = queue.splice((dataset.quick === 'r' ? 10 : $.jStorage.get('l/batchSize')));
				$.jStorage.set(dataset.active, queue);
				$.jStorage.set(dataset.queue, review);
				dataset.updateVisual();
			} catch (err) {
				showerr(err);
			}
		},
		check: function() {
			try {
				utilities.log("Checking for UID updates");
				var all = $.jStorage.get(dataset.queue).concat($.jStorage.get(dataset.active));
				var list = $.jStorage.get('uids') || [];
				return list && all.every(function(ele) {
					return ele && list[utilities.toUID(ele)];
				});
			} catch (err) {
				showerr(err);
			}
		},
		patch: function() {
			try {
				utilities.log("Gathering data for patch");
				var count = 0;
				var all = {};
				$('#information, #supplement-info').first().after('<div id="updateUID" style="text-align:center;">WKU::Please Wait::Currently updating UID list... <span id="id-percent">0%</span></div>');
				["radicals", "kanji", "vocabulary"].forEach(function(ele1, ind1, arr1) {
					["PLEASANT", "PAINFUL", "DEATH", "HELL", "PARADISE", "REALITY"].forEach(function(ele2, ind2, arr2) {
						$.get('https://www.wanikani.com/' + ele1 + '?difficulty=' + ele2, function(resp) {
							$('#id-percent').text(Math.round((++count / (arr1.length * arr2.length)) * 100) + "%");
							$(resp).find('section[id^=level-]').each(function() {
								var level = $(this).attr('id').replace(/[^\d]/g, "");
								$(this).find('.character-item').each(function() {
									var a = $(this).attr('id');
									a = a.substr(0, 1) + a.replace(/[^\d]/g, "");
									all[a] = level;
								});
							});
							if (count >= (arr1.length * arr2.length)) {
								$.jStorage.set('uids', all);
								utilities.log("DONE!");
								$('#updateUID').remove();
								setup.ui.create();
							}
						}).fail(function() {
							$('#supplement-info, #information').first().after('<div id="error" style="text-align:center;">WaniKani Reorder Ultimate has failed to load [' + ele2 + ' level ' + ele1 + ']<br>Please reload the page.</div>');
						});
					});
				});
			} catch (err) {
				showerr(err);
			}
		}
	},
	ui: {
		create: function() {
			setup.update.apply();
			$('head').append('<style>'+ui_css+'</style>');
            utilities.log("Creating UI...");
            var info = $('#supplement-info, #information').first();
            info.after(ui_html);
            $('#version').text("v" + GM_info.script.version);
            if (dataset.quick === 'l') {
                $('.ui').find('#r-only').remove();
            }
            if (!setup.update.check()) {
                $('.ui-small').first().before('<div id="updateUID-failed" style="text-align:center; display:none;">Failed to update UIDs.<br>Complain here <a href="https://www.wanikani.com/chat/api-and-third-party-apps/8471" target="_blank">https://www.wanikani.com/chat/api-and-third-party-apps/8471</a><div>');
                $('#updateUID-failed').fadeIn(500).delay(7500).fadeOut(500);
            }
            $('fieldset').on('addClass', function(evt) {
                if (settings.data.quickNext) {
                    setTimeout(function() {
                        if ($('fieldset').hasClass('correct')) {
                            $('fieldset button').click();
                        }
                    }, 25);
                }
            });
            $('#quick-next').click(function() {
                $(this).toggleClass('active');
                settings.data.quickNext = $(this).hasClass('active');
                settings.save();
            });
$('#priority, #priority2').click(function(e) {
					var offset = $(this).offset();
					var x = (e.pageX - offset.middle);
					var y = (e.pageY - offset.top);
					var id = $(this).attr('id');
					if (y < 50) {
							if (id === "priority") {
								$(this).removeClass().addClass("level-heavy");
								settings.data.typePriorityMode = "1";
								sorter.reorder();
							} else {
								$(this).removeClass().addClass("reading-heavy");
								settings.data.questionTypeMode = "1";
								utilities.forceQuestionTypeUpdate();
							} 
						} else { if (y > 100) {
							if (id === "priority") {
								$(this).removeClass().addClass("type-heavy");
								settings.data.typePriorityMode = "2";
								sorter.reorder();
							} else {
								$(this).removeClass().addClass("meaning-heavy");
								settings.data.questionTypeMode = "2";
								utilities.forceQuestionTypeUpdate();
							}
						}
					 else {
						if (id === "priority") {
							$(this).removeClass().addClass("balance");
							settings.data.typePriorityMode = "0";
							sorter.reorder();
						} else {
							$(this).removeClass().addClass("balance2");
							settings.data.questionTypeMode = "0";
							utilities.forceQuestionTypeUpdate();
						}
					}}
					settings.save();
				}).mousemove(function(e) {
					var offset = $(this).offset();
					var x = (e.pageX - offset.middle);
					var y = (e.pageY - offset.top);
					var ele = $(this).find('#overlay');
					if (y < 50) {
							ele.removeClass().addClass('top');
						} else { if (y > 100) {
							ele.removeClass().addClass('bottom');
						}
					 else {
						ele.removeClass().addClass('middle');
					}}
				}).mouseleave(function(e) {
					$(this).find('#overlay').removeClass();
				});
				activeLevels.forEach(function(ele) {
					$('.ui #levels').append('<item id="level-' + ele + '">' + ele + '</item>');
				});
				$('span#reverse').click(function() {
					var parent = $(this).parents('.sortable');
					var items = parent.children('item');
					parent.append(items.get().reverse());
					sorter.reorder();
					settings.save();
				});
            $('.icon-minus, .icon-plus').click(function() {
                $('.ui, .ui-small').toggleClass('hidden');
            });
            $('#sort-types, #sort-levels').change(function() {
                $(this).parents('.sortable').find('item').toggleClass('unsorted', !this.checked);
                settings.data[$(this).attr('id').replace("-", "")] = this.checked;
                settings.save();
            });
            if (dataset.quick === 'r') {
                $('#mode').on('change', function() {
                    settings.data.onebyone = this.checked;
                    if (settings.data.questionTypeMode > 0) {
                        utilities.forceQuestionTypeUpdate();
                    }
                    settings.save();
                });
                $('#option-wrap-up').click(function() {
                    if ($(this).attr('class') === 'wrap-up-selected') {
                        var fullQueue = $.jStorage.get(dataset.active).concat($.jStorage.get(dataset.queue));
                        $.jStorage.set(dataset.active, fullQueue.splice(0, 10));
                        $.jStorage.set(dataset.queue, fullQueue);
                    } else {
                        if (ordered) {
                            sorter.reorder();
                        }
                    }
                });
            }
            settings.load();
            setup.ui.toggler();
            $('#reorder').click(function() {
                sorter.reorder();
            });
            $('body').on('contextmenu', '.ui', function(e) {
                e.preventDefault();
            });
            $('item').mousedown(function(event) {
                if (event.which === 3) {
                    var ele = $(this).addClass('hidden');
                    if (ele.attr('id')) {
                        sorter.removeLevel(parseInt(ele.text()));
                    } else {
                        sorter.removeType(ele.attr('class'));
                    }
                }
            });
            $('.sortable').sortable({
                items: ':not(div, button)'
            }).bind('sortupdate', function() {
                sorter.reorder();
                settings.save();
            });
		},
		toggler: function() {
			if ($('.sortable').length) {
				var fq = $.jStorage.get(dataset.queue).concat($.jStorage.get(dataset.active));
				if (!fq.length) {
					utilities.log("There are no options available... Removing UI.");
					$('.ui').remove();
				} else {
					$('#types .radical').toggleClass('hidden', !sorter.filterType("rad", fq).length).prop('title', function() {
						var filtered = sorter.filterType("rad", fq);
						var text = "Total: " + filtered.length;
						$.each(activeLevels, function() {
							var amount = sorter.filterLevel(this, filtered).length;
							if (amount) {
								text += "\nLevel " + this + ": " + amount + "";
							}
						});
						return text;
					});
					$('#types .kanji').toggleClass('hidden', !sorter.filterType("kan", fq).length).prop('title', function() {
						var filtered = sorter.filterType("kan", fq);
						var text = "Total: " + filtered.length;
						$.each(activeLevels, function() {
							var amount = sorter.filterLevel(this, filtered).length;
							if (amount) {
								text += "\nLevel " + this + ": " + amount + "";
							}
						});
						return text;
					});
					$('#types .vocabulary').toggleClass('hidden', !sorter.filterType("voc", fq).length).prop('title', function() {
						var filtered = sorter.filterType("voc", fq);
						var text = "Total: " + filtered.length;
						$.each(activeLevels, function() {
							var amount = sorter.filterLevel(this, filtered).length;
							if (amount) {
								text += "\nLevel " + this + ": " + amount + "";
							}
						});
						return text;
					});
					activeLevels.forEach(function(level) {
						$('#level-' + level).toggleClass('hidden', !sorter.filterLevel(level, fq).length).prop('title', function() {
							var filtered = sorter.filterLevel(level, fq);
							var rad = sorter.filterType("rad", filtered).length;
							var kan = sorter.filterType("kan", filtered).length;
							var voc = sorter.filterType("voc", filtered).length;
							var text = "Total: " + filtered.length;
							if (rad) {
								text += "\nRadicals: " + rad;
							}
							if (kan) {
								text += "\nKanji: " + kan;
							}
							if (voc) {
								text += "\nVocabulary: " + voc;
							}
							return text;
						});
					});
					$('input[type="checkbox"]:disabled').removeAttr('disabled');
				}
			}
		}
	},
	listeners: function() {
		var lastCount = $.jStorage.get(dataset.active).length + $.jStorage.get(dataset.queue).length;
		$.jStorage.listenKeyChange('currentItem', function() {
			if (lastCount < ($.jStorage.get(dataset.active).length + $.jStorage.get(dataset.queue).length)) {
				lastCount = $.jStorage.get(dataset.active).length + $.jStorage.get(dataset.queue).length; // will infinitely trigger if not here.
				setup.init();
			}
			lastCount = $.jStorage.get(dataset.active).length + $.jStorage.get(dataset.queue).length;
		});
		$.jStorage.listenKeyChange('currentItem', utilities.forceQuestionTypeUpdate);
		$.jStorage.listenKeyChange(dataset.active, setup.ui.toggler);
	}
};
var sorter = {
	filterLevel: function(level, list) {
		if (!list) {
			return [];
		}
		return list.filter(function(ele, ind) {
			return ele.level == level;
		});
	},
	filterType: function(type, list) {
		if (!list) {
			return [];
		}
		return list.filter(function(ele, ind) {
			return ele[type.substr(0, 3)];
		});
	},
	getHTMLElementPriority: function(a) {
		return a.className === 'radical' ? settings.data.priority.rad : a.className === 'kanji' ? settings.data.priority.kan : settings.data.priority.voc;
	},
	getPriority: function(a) {
		return a.rad ? settings.data.priority.rad : a.kan ? settings.data.priority.kan : settings.data.priority.voc;
	},
	randomize: function(list) {
		return list.sort(function() {
			return 0.5 - window.Math.randomB();
		});
	},
	reorder: function() {
		ordered = true;
		sorter.setPriorities();
		var fullQueue = $.jStorage.get(dataset.queue).concat($.jStorage.get(dataset.active));
		fullQueue = sorter.randomize(fullQueue);
		if (parseInt(settings.data.typePriorityMode) == 1) {
			if (settings.data.sortlevels) {
				$('#levels > item').each(function() {
					var level = parseInt(this.innerHTML);
					var sorted = sorter.filterLevel(level, fullQueue);
					if (settings.data.sorttypes) {
						sorted = sorter.sortByType(sorted);
					} else {
						sorted = sorter.randomize(sorted);
					}
					fullQueue = sorter.removeLevel(level, fullQueue);
					fullQueue = fullQueue.concat(sorted);
				});
			}
		}
		if (parseInt(settings.data.typePriorityMode) == 2) {
			if (settings.data.sorttypes) {
				$('#types > item').each(function() {
					var typeFilter = sorter.filterType(this.className, fullQueue);
					if (settings.data.sortlevels) {
						$('#levels > item').each(function() {
							var level = parseInt(this.innerHTML);
							var sorted = sorter.filterLevel(level, typeFilter);
							typeFilter = sorter.removeLevel(level, typeFilter);
							typeFilter = typeFilter.concat(sorted);
						});
					} else {
						typeFilter = sorter.randomize(typeFilter);
					}
					fullQueue = sorter.removeType(this.className, fullQueue);
					fullQueue = fullQueue.concat(typeFilter);
				});
			}
		}
		$.jStorage.set(dataset.active, (dataset.quick === 'r' ? fullQueue : fullQueue.splice(0, $.jStorage.get('l/batchSize'))));
		$.jStorage.set(dataset.queue, (dataset.quick === 'r' ? [] : fullQueue));
		dataset.updateVisual();
	},
	removeLevel: function(level, list) {
		if (!list) {
			var fullQueue = sorter.removeLevel(level, $.jStorage.get(dataset.queue));
			var activeQueue = sorter.removeLevel(level, $.jStorage.get(dataset.active));
			$.jStorage.set(dataset.queue, fullQueue);
			$.jStorage.set(dataset.active, activeQueue);
			sorter.reorder();
			return;
		}
		return list.filter(function(ele, ind) {
			return ele.level != level;
		});
	},
	removeType: function(type, list) {
		if (!list) {
			var fullQueue = sorter.removeType(type, $.jStorage.get(dataset.queue));
			var activeQueue = sorter.removeType(type, $.jStorage.get(dataset.active));
			$.jStorage.set(dataset.queue, fullQueue);
			$.jStorage.set(dataset.active, activeQueue);
			sorter.reorder();
			return;
		}
		return list.filter(function(ele, ind) {
			return !ele[type.substr(0, 3)];
		});
	},
	sortByType: function(list) {
		return list.sort(function(a, b) {
			return (sorter.getPriority(a) - sorter.getPriority(b));
		});
	},
	setPriorities: function() {
		settings.data.priority.rad = $('#types .radical').index();
		settings.data.priority.kan = $('#types .kanji').index();
		settings.data.priority.voc = $('#types .vocabulary').index();
	}
};
var utilities = {
	forceQuestionTypeUpdate: function() {
		var current = $.jStorage.get("currentItem");
		if (!current) {
			return;
		}
		var type = $.jStorage.get("questionType");
		if (current.rad) {
			if (type !== "meaning") {
				$.jStorage.set("questionType", "meaning");
				$.jStorage.set("currentItem", current);
			}
			return;
		}
		var typeMethod = parseInt(settings.data.questionTypeMode);
		var data = $.jStorage.get(utilities.toUID(current));
		if (!typeMethod && (!data || (!data.mc && !data.rc))) {
			if ((new Date().getTime() - lastUpdate) > 500) {
				lastUpdate = new Date().getTime();
				var nextRandType = ["reading", "meaning"][Math.round(window.Math.randomB())];
				console.log(type, nextRandType);
				if (type != nextRandType) {
					$.jStorage.set('questionType', nextRandType);
					$.jStorage.set("currentItem", current);
				}
			}
		}
		if (typeMethod === 1) {
			if (!data || !data.rc) {
				if (type !== "reading") {
					$.jStorage.set("questionType", "reading");
					$.jStorage.set("currentItem", current);
				}
			} else {
				if (type !== "meaning") {
					$.jStorage.set("questionType", "meaning");
					$.jStorage.set("currentItem", current);
				}
			}
		}
		if (typeMethod === 2) {
			if (!data || !data.mc) {
				if (type !== "meaning") {
					$.jStorage.set("questionType", "meaning");
					$.jStorage.set("currentItem", current);
				}
			} else {
				if (type !== "reading") {
					$.jStorage.set("questionType", "reading");
					$.jStorage.set("currentItem", current);
				}
			}
		}
	},
	highestPriorityType: function() {
		return $('#types item').not('.hidden').first().attr('class');
	},
	highestPriorityLevel: function() {
		return parseInt($('#levels item').not('.hidden').first().text());
	},
	log: function(msg) {
		console.dlog.push(msg);
		console.debug(msg);
	},
	newRandom: function(fullVal) {
		if (!settings.data.onebyone && ordered) {
			var fullQueue = $.jStorage.get(dataset.active).concat($.jStorage.get(dataset.queue));
			var fullLength = fullQueue.length;
			if (settings.data.sortlevels && parseInt(settings.data.typePriorityMode) == 1) {
				fullQueue = sorter.filterLevel(utilities.highestPriorityLevel(), fullQueue);
				if (settings.data.sorttypes) {
					fullQueue = sorter.filterType(utilities.toType(fullQueue[0]), fullQueue);
				}
			}
			if (settings.data.sorttypes && parseInt(settings.data.typePriorityMode) == 2) {
				fullQueue = sorter.filterType(utilities.highestPriorityType(), fullQueue);
				if (settings.data.sortlevels) {
					fullQueue = sorter.filterLevel(fullQueue[0].level, fullQueue);
				}
			}
			return Math.floor(window.Math.randomB() * Math.min(10, fullQueue.length)) / (fullVal ? 1 : Math.max(fullLength, 1));
		}
		return settings.data.onebyone ? 0 : window.Math.randomB();
	},
	toType: function(item) {
		return (item && item.rad) ? 'rad' : item.kan ? 'kan' : 'voc' || "-1";
	},
	toUID: function(item) {
		return ((item && item.rad) ? 'r' : item.kan ? 'k' : 'v') + item.id || "-1";
	},
	settingsValueToClass: function(id, val) {
		val = parseInt(val);
		if (id === "priority") {
			switch (val) {
				case 0:
					return "balance";
				case 1:
					return "level-heavy";
				case 2:
					return "type-heavy";
			}
		} else {
			switch (val) {
				case 0:
					return "balance2";
				case 1:
					return "reading-heavy";
				case 2:
					return "meaning-heavy";
			}
		}
	}
};
$('div[id*="loading"]:visible').on('hide', function() {
	dataset = (location.pathname.match('review') ? reviewset : lessonset);
	window.Math.randomB = window.Math.random;
	if (dataset.quick === 'r') {
		window.Math.random = utilities.newRandom;
	}
	setup.listeners();
	setup.init();
});

// Hook into App Store
try { $('.app-store-menu-item').remove(); $('<li class="app-store-menu-item"><a href="https://community.wanikani.com/t/there-are-so-many-user-scripts-now-that-discovering-them-is-hard/20709">App Store</a></li>').insertBefore($('.navbar .dropdown-menu .nav-header:contains("Account")')); window.appStoreRegistry = window.appStoreRegistry || {}; window.appStoreRegistry[GM_info.script.uuid] = GM_info; localStorage.appStoreRegistry = JSON.stringify(appStoreRegistry); } catch (e) {}