// Constants ////////////////////////////////////////////////////////////////////////////////////////////////////////// var ERROR_DISPLAY_DURATION = 10000; // ms var FADE_DURATION = 250; // ms var SLIDE_DURATION = 600; // ms // Global Variables /////////////////////////////////////////////////////////////////////////////////////////////////// var __inventory = createManifest(); var __loadingCount = 0; var __recipebooks = []; var __toolsIncluded = false; // UI Functions /////////////////////////////////////////////////////////////////////////////////////////////////////// $(function() { $("#recipebook_load_button").click(onRecipeLoadButtonClicked); $("#crafting_count").change(onCraftingSelectorChanged); $("#tools_included").change(onIncludeToolsChanged); $("#crafting_selector").focus(onCraftingSelectorFocused); $("#inventory").keyup(onInventoryChanged); loadRecipebook("data/vanilla.json"); loadRecipebook("data/buildcraft.json"); loadRecipebook("data/industrial_craft.json"); }); function onCraftingSelectorChanged() { var recipeName = $("#crafting_selector").val(); var count = parseInt($("#crafting_count option:selected").val()); if (count === undefined) return; var recipe = findRecipe(recipeName); if (recipe === undefined) { $("#crafting_output").slideUp(SLIDE_DURATION); } else { var inventory = __inventory.copy(); var craftedItems = createManifest(); var missingMaterials = createManifest(); for (var i = 0; i < count; i++) { recipe.craft(inventory, craftedItems, missingMaterials); if (inventory.contains(count, recipeName)) break; } $("#missing_materials").html(missingMaterials.toHtml()); $("#crafted_items").html(craftedItems.toHtml()); $("#leftover_materials").html(inventory.toHtml()); $("#crafting_output").slideDown(SLIDE_DURATION); } updatePageState(count, recipeName); } function onCraftingSelectorFocused() { $("#crafting_selector").autocomplete("search"); } function onIncludeToolsChanged() { __toolsIncluded = $("#tools_included").is(":checked"); onCraftingSelectorChanged() } function onInventoryChanged() { __inventory.removeAll(); var inventoryText = $("#inventory").val(); if (inventoryText) { var inventoryLines = inventoryText.split("\n"); for (var i = 0; i < inventoryLines.length; i++) { var line = inventoryLines[i].trim(); var match = /^([0-9]+)(.*)$/.exec(line); var count = (match) ? parseInt(match[1]) : 1; var itemName = (match) ? match[2].trim() : line; if (itemName.length > 0) { __inventory.add(count, itemName); } } } onCraftingSelectorChanged(); } function onRecipeBookLoaded() { if (__loadingCount > 0 || __recipebooks.length === 0) { $("#crafting").fadeOut(FADE_DURATION); } else if (__loadingCount === 0 && __recipebooks.length > 0) { updateCraftingSelector(); parseUrlParameters(); $("#crafting").fadeIn(FADE_DURATION); } } function onRecipeLoadButtonClicked() { $("#reipebook_load_button").attr("disabled", true); loadRecipebook($("#recipebook_url").val(), function() { $("#recipebook_url").val(""); $("#reipebook_load_button").removeAttr("disabled"); }); } // UI Helper Functions //////////////////////////////////////////////////////////////////////////////////////////////// function loadRecipebook(recipebookUrl) { __loadingCount++; $.ajax({ url: recipebookUrl, dataType: "text", success: function(text) { try { var recipebook = createRecipebook(recipebookUrl, $.parseJSON(text)); __recipebooks.push(recipebook); recipebook.asTableRow().insertBefore($("#recipebook_table tr").last()); } catch (e) { $("#load_error").html(e); $("#load_error").slideDown(FADE_DURATION).delay(ERROR_DISPLAY_DURATION).slideUp(FADE_DURATION); } }, error: function(response, status, error) { $("#load_error").html(status + ": " + error); $("#load_error").slideDown(FADE_DURATION).delay(ERROR_DISPLAY_DURATION).slideUp(FADE_DURATION); }, complete: function() { __loadingCount--; onRecipeBookLoaded(); } }); } function parseUrlParameters() { var quantity = $.url().param('quantity'); if (quantity !== undefined) { $("#crafting_count").val(quantity); if ($("#crafting_count option:selected").val() === undefined) { $("#crafting_count").val(1); $("#crafting_error").html("Unsupported quantity: " + quantity); $("#crafting_error").fadeIn(FADE_DURATION).delay(ERROR_DISPLAY_DURATION).fadeOut(FADE_DURATION); } } var recipeName = $.url().param('recipeName'); if (recipeName !== undefined) { $("#crafting_selector").val(recipeName); if (findRecipe(recipeName) !== undefined) { onCraftingSelectorChanged(); } else if (recipeName.length > 0) { $("#crafting_error").html("Cannot find recipe for " + recipeName); $("#crafting_error").fadeIn(FADE_DURATION).delay(ERROR_DISPLAY_DURATION).fadeOut(FADE_DURATION); } } } function updateCraftingSelector() { var $selector = $("crafting_selector"); var names = []; $(__recipebooks).each(function(i, recipebook) { for (var name in recipebook.recipes) { names.push(name); } }); names.sort(); $("#crafting_selector").autocomplete({ source: names, delay: 0, minLength: 0, change: onCraftingSelectorChanged, close: onCraftingSelectorChanged, select: onCraftingSelectorChanged, }); } function updatePageState(count, recipeName) { var newTitle = "Crafting Guide"; var newLink = window.location.pathname; var state = {} if (recipeName !== undefined && recipeName.length > 0) { newTitle = "Crafting Guide: " + count + " " + recipeName; newLink = "?count=" + count + "&recipeName=" + encodeURIComponent(recipeName); newLink = newLink.replace(/%20/g, "+"); state = {count: count, name: recipeName}; } document.title = newTitle; history.pushState(state, newTitle, newLink); ga('send', 'pageview'); } // Manifest Object //////////////////////////////////////////////////////////////////////////////////////////////////// function createManifest() { var object = {materials: {}}; object.add = function(count, name) { if (object.materials[name] === undefined) { object.materials[name] = count; } else { object.materials[name] = object.materials[name] + count; } }; object.contains = function(count, name) { if (object.materials[name] === undefined) return false; return (object.materials[name] >= count); }; object.copy = function(count, name) { var result = createManifest(); for (var name in object.materials) { result.add(object.materials[name], name); } return result; } object.remove = function(count, name) { if (object.materials[name] !== undefined) { if (object.materials[name] <= count) { delete object.materials[name] } else { object.materials[name] -= count; } } }; object.removeAll = function() { object.materials = {}; } object.toHtml = function() { var result = ""; var count = 0; for (var name in object.materials) { result += "