diff --git a/src/client/models/site/craft_page.coffee b/src/client/models/site/craft_page.coffee
index 4f2325d41..087b98f0d 100644
--- a/src/client/models/site/craft_page.coffee
+++ b/src/client/models/site/craft_page.coffee
@@ -5,45 +5,89 @@
# All rights reserved.
#
-CraftingGuideCommon = require "crafting-guide-common"
-
-{BaseModel} = CraftingGuideCommon.deprecated
-{Craftsman} = CraftingGuideCommon.deprecated.crafting
-{Inventory} = CraftingGuideCommon.deprecated.game
-{ModPack} = CraftingGuideCommon.deprecated.game
+{Inventory} = require("crafting-guide-common").models
+{Observable} = require("crafting-guide-common").util
+{PlanBuilder} = require("crafting-guide-common").crafting
+{ResourcesEvaluator} = require("crafting-guide-common").crafting
+{StepsEvaluator} = require("crafting-guide-common").crafting
########################################################################################################################
-module.exports = class CraftPage extends BaseModel
+module.exports = class CraftPage extends Observable
- constructor: (attributes={}, options={})->
- if not attributes.modPack then throw new Error 'attributes.modPack is required'
- attributes.params ?= null
- attributes.craftsman ?= new Craftsman attributes.modPack
- super attributes, options
+ constructor: (attributes={})->
+ super
- @modPack.on c.event.change, => @_consumeParams()
- @on c.event.change + ':params', => @_consumeParams()
- @craftsman.on c.event.change + ':stage', => @trigger c.event.change, this
- @craftsman.on c.event.change + ':complete', => @trigger c.event.change, this
+ @muted -> @modPack = attributes.modPack
+
+ @_currentPlan = null
+ @_have = new Inventory
+ @_planBuilder = new PlanBuilder new StepsEvaluator
+ @_want = new Inventory
+
+ @_consumeParams attributes.params
+
+ @_have.on Observable::ANY, this, "_onHaveChanged"
+ @_want.on Observable::ANY, this, "_onWantChanged"
+
+ # Properties ###################################################################################
+
+ Object.defineProperties @prototype,
+
+ currentPlan:
+ get: -> return @_currentPlan
+ set: -> throw new Error "currentPlan cannot be assigned"
+
+ have:
+ get: -> return @_have
+ set: -> throw new "have cannot be assigned"
+
+ isDirty:
+ get: -> return @_isDirty
+ set: -> throw new Error "isDirty cannot be assigned"
+
+ isOutdated:
+ get: -> return @currentPlan? and @isDirty
+ set: -> throw new Error "isOutdated cannot be assigned"
+
+ modPack:
+ get: -> return @_modPack
+ set: (modPack)->
+ if @_modPack? then throw new Error "modPack cannot be reassigned"
+ if not modPack? then throw new Error "modPack is required"
+ @_modPack = modPack
+
+ planBuilder:
+ get: -> return @_planBuilder
+ set: -> throw new Error "planBuilder cannot be assigned"
+
+ want:
+ get: -> return @_want
+ set: -> throw new Error "want cannot be assigned"
+
+ # Public Methods ###############################################################################
+
+ createPlan: ->
+ newPlan = @_planBuilder.createPlan @_want, @_have
+ @triggerPropertyChange "currentPlan", @_currentPlan, newPlan, ->
+ @_currentPlan = newPlan
+ @triggerPropertyChange "isDirty", @_isDirty, false
# Private Methods ##############################################################################
- _consumeParams: ->
- return unless @params?
+ _consumeParams: (params)->
+ return unless params?.inventoryText?
- @craftsman.want.clear()
- if not @params.inventoryText?
- @params = null
- else
- inventory = new Inventory
- inventory.parse @params.inventoryText
+ newWant = Inventory.fromUrlString params.inventoryText, @modPack
+ @_want.clear()
- inventory.each (stack)=>
- item = @modPack.findItem stack.itemSlug, enableAsNeeded:true
- return unless item? and item.isCraftable
+ for itemId, stack of newWant.stacks
+ continue unless stack.item.isCraftable
+ @_want.add stack.item, stack.quantity
- @craftsman.want.add stack.itemSlug, stack.quantity
- inventory.remove stack.itemSlug
+ _onHaveChanged: ->
+ @triggerPropertyChange "isDirty", @_isDirty, true
- if inventory.isEmpty then @params = null
+ _onWantChanged: ->
+ @triggerPropertyChange "isDirty", @_isDirty, true, ->
+ if @want.isEmpty then @triggerPropertyChange "currentPlan", @_currentPlan, null
diff --git a/src/client/models/site/item_display.coffee b/src/client/models/site/item_display.coffee
index a42b12cb6..ac789c463 100644
--- a/src/client/models/site/item_display.coffee
+++ b/src/client/models/site/item_display.coffee
@@ -37,6 +37,10 @@ module.exports = class ItemDisplay
if not item? then throw new Error "item is required"
@_item = item
+ mod:
+ get: -> return @_item.mod
+ set: -> throw new Error "mod cannot be assigned"
+
modUrl:
get: -> return c.url.mod modId:@item.mod.id
set: -> throw new Error "modUrl cannot be assigned"
diff --git a/src/client/models/site/item_page.coffee b/src/client/models/site/item_page.coffee
index 92b1388cf..f7caffe7e 100644
--- a/src/client/models/site/item_page.coffee
+++ b/src/client/models/site/item_page.coffee
@@ -6,7 +6,7 @@
#
{Item} = require("crafting-guide-common").models
-ItemDisplay = require "../item_display"
+ItemDisplay = require "./item_display"
{Observable} = require("crafting-guide-common").util
########################################################################################################################
diff --git a/src/client/models/site/item_selector.coffee b/src/client/models/site/item_selector.coffee
index 2c4f8beb9..00c07a1a2 100644
--- a/src/client/models/site/item_selector.coffee
+++ b/src/client/models/site/item_selector.coffee
@@ -5,52 +5,49 @@
# All rights reserved.
#
-{BaseModel} = require('crafting-guide-common').deprecated
-{ItemSlug} = require('crafting-guide-common').deprecated.game
+{Observable} = require("crafting-guide-common").util
########################################################################################################################
-module.exports = class ItemSelector extends BaseModel
+module.exports = class ItemSelector extends Observable
- constructor: (attributes={}, options={})->
- if not options.modPack? then throw new Error 'options.modPack is required'
- options.isAcceptable ?= (item)-> return true # accept everything by default
- super attributes, options
+ constructor: (modPack, options={})->
+ super
- @_isAcceptable = options.isAcceptable
+ @_isAcceptable = options.isAcceptable or (item)-> return true # accept everything by default
@_maxResults = 100
@_minHintLength = 3
- @_modPack = options.modPack
@_results = []
+ @modPack = modPack
+
# Property Methods #############################################################################
Object.defineProperties @prototype,
hint:
- get: ->
- return @_hint
+ get: -> return @_hint
+ set: (hint)->
+ @triggerPropertyChange "hint", @_hint, hint, ->
+ @_hint = hint?.toLowerCase()
+ @_refreshResults()
- set: (newHint)->
- oldHint = @_hint
- return if newHint is oldHint
-
- @_hint = newHint.toLowerCase()
-
- @trigger c.event.change + ':hint', this, oldHint, newHint
- @_refreshResults()
- @trigger c.event.change, this
+ modPack:
+ get: -> return @_modPack
+ set: (modPack)->
+ if not modPack? then throw new Error "modPack is required"
+ if @_modPack? then throw new Error "modPack cannot be reassigned"
+ @_modPack = modPack
results:
- get: ->
- return @_results
+ get: -> return @_results
# Private Methods ##############################################################################
- _computeScore: (name, itemSlug)->
+ _computeScore: (item)->
hintIndex = 0
hintLetter = @_hint[hintIndex]
- name = name.toLowerCase()
+ name = item.displayName.toLowerCase()
nextScore = 1
totalScore = 0
@@ -60,8 +57,6 @@ module.exports = class ItemSelector extends BaseModel
nextScore += 1
hintIndex += 1
if hintIndex is @_hint.length
- item = @_modPack.findItem itemSlug
- return 0 unless item?
return 0 unless @_isAcceptable item
break
@@ -75,29 +70,34 @@ module.exports = class ItemSelector extends BaseModel
return totalScore
_refreshResults: ->
- oldResults = @_results
scoredItems = []
count = 0
- logger.verbose => "Looking for items which match: #{@_hint}"
if @_hint.length >= @_minHintLength
- @_modPack.eachMod (mod)=>
+ for modId, mod of @_modPack.mods
return if count >= @_maxResults
- return unless mod.enabled
+ return unless mod.isEnabled
- mod.eachName (name, itemSlug)=>
+ for itemId, item of mod.items
return if scoredItems.length >= @_maxResults
- return unless itemSlug.isQualified
- score = @_computeScore name, itemSlug
+ score = @_computeScore item
if score >= @_hint.length
- scoredItems.push score:score, itemSlug:itemSlug
+ scoredItems.push score:score, item:item
scoredItems.sort (a, b)->
if a.score isnt b.score
return if a.score > b.score then -1 else +1
- return ItemSlug.compare a.itemSlug, b.itemSlug
- newResults = (e.itemSlug for e in scoredItems)
- @_results = newResults
- @trigger c.event.change + ':results', this, oldResults, newResults
+ nameA = a.item.displayName
+ nameB = b.item.displayName
+ if nameA.length isnt nameB.length
+ return if nameA.length < nameB.length then -1 else +1
+
+ if nameA isnt nameB
+ return if nameA < nameB then -1 else +1
+
+ return 0
+
+ @_results = (e.item for e in scoredItems)
+ @trigger c.event.change + ':results', this
diff --git a/src/client/site/base_controller.coffee b/src/client/site/base_controller.coffee
index c4fcff5ed..31b43ac61 100644
--- a/src/client/site/base_controller.coffee
+++ b/src/client/site/base_controller.coffee
@@ -112,7 +112,7 @@ module.exports = class BaseController extends Backbone.View
newModel = @onWillChangeModel @_model, newModel
@_model = newModel
- @tryRefresh()
+ @onDidModelChange()
rendered:
get: -> @_rendered
@@ -149,6 +149,7 @@ module.exports = class BaseController extends Backbone.View
@$el.data $renderedEl.data()
@delegateEvents()
+ @$el.controller = this
@_rendered = true
@onDidRender()
diff --git a/src/client/site/common/crafting_grid/crafting_grid_controller.coffee b/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
index ab87389b9..53a22709c 100644
--- a/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
+++ b/src/client/site/common/crafting_grid/crafting_grid_controller.coffee
@@ -5,39 +5,47 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-SlotController = require '../slot/slot_controller'
+BaseController = require "../../base_controller"
+{Recipe} = require("crafting-guide-common").models
+SlotController = require "../slot/slot_controller"
########################################################################################################################
module.exports = class CraftingGridController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- # options.model should be a recipe
- options.templateName = 'common/crafting_grid'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/crafting_grid"
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@_router = options.router
- @_modPack.on c.event.change, => @tryRefresh()
-
# BaseController Methods #######################################################################
+ onWillChangeModel: (oldModel, newModel)->
+ if newModel? and (newModel.constructor isnt Recipe) then throw new Error "options.model must be a Recipe"
+ super
+
onDidRender: ->
@_slotControllers = []
- for el in @$('.view__slot')
+ for el in @$(".view__slot")
controller = new SlotController el:el, imageLoader:@_imageLoader, modPack:@_modPack, router:@_router
controller.render()
@_slotControllers.push controller
super
refresh: ->
- for controller, index in @_slotControllers
- controller.model = @model?.getStackAtSlot(index)
+ index = 0
+ for y in [0..2]
+ for x in [0..2]
+ controller = @_slotControllers[index++]
+ if @model?
+ controller.model = @model.getInputAt x, y
+ else
+ controller.model = null
super
diff --git a/src/client/site/common/inventory/inventory_controller.coffee b/src/client/site/common/inventory/inventory_controller.coffee
index 9e2e4fe11..315e87d43 100644
--- a/src/client/site/common/inventory/inventory_controller.coffee
+++ b/src/client/site/common/inventory/inventory_controller.coffee
@@ -47,8 +47,6 @@ module.exports = class InventoryController extends BaseController
@_stackControllers = []
- @listenTo @_modPack, c.event.change, => @tryRefresh()
-
# Event Methods ################################################################################
onClearButtonClicked: ->
@@ -61,31 +59,33 @@ module.exports = class InventoryController extends BaseController
@trigger c.event.change, this
onFirstButtonClicked: (stackController)->
- tracker.trackEvent @_trackingContext, 'remove-from', "#{stackController?.model?.itemSlug}"
- @trigger c.event.button.first, this, stackController?.model?.itemSlug
+ itemId = stackController.model?.item.id
+ tracker.trackEvent @_trackingContext, 'remove-from', itemId
+ @trigger c.event.button.first, this, itemId
onItemSelectorButtonClicked: ->
return unless @model?
tracker.trackEvent @_trackingContext, 'launch-add-to'
@_selector.launch()
- .then (itemSlug)=>
- if not itemSlug?
+ .then (item)=>
+ if not item?
tracker.trackEvent @_trackingContext, 'cancel-add-to'
return
- tracker.trackEvent @_trackingContext, 'complete-add-to', "#{itemSlug}"
- @model.add itemSlug, 1
- @trigger c.event.add, this, itemSlug
+ tracker.trackEvent @_trackingContext, 'complete-add-to', "#{item.id}"
+ @model.add item, 1
+ @trigger c.event.add, this, item.id
@trigger c.event.change, this
onSecondButtonClicked: (stackController)->
+ itemId = stackController.model?.item.id
@trigger c.event.button.second, this, stackController?.model?.itemSlug
# BaseController Overrides #####################################################################
onDidRender: ->
- @_selector = @addChild ItemSelectorController, null, isAcceptable: @_isAcceptable, modPack: @_modPack
+ @_selector = @addChild ItemSelectorController, null, isAcceptable:@_isAcceptable, modPack:@_modPack
@$clearButton = @$('.button.clear')
@$emptyPlaceholder = @$('.empty_placeholder')
@@ -131,7 +131,7 @@ module.exports = class InventoryController extends BaseController
index = 0
if @model?
- @model.each (stack)=>
+ for itemId, stack of @model.stacks
controller = @_stackControllers[index]
if not controller?
controller = new StackController
@@ -153,6 +153,7 @@ module.exports = class InventoryController extends BaseController
@$itemContainer.append controller.$el
else
controller.model = stack
+
index += 1
while @_stackControllers.length > index
diff --git a/src/client/site/common/item_selector/element/element_controller.coffee b/src/client/site/common/item_selector/element/element_controller.coffee
index c1ccbe108..38dd56d6c 100644
--- a/src/client/site/common/item_selector/element/element_controller.coffee
+++ b/src/client/site/common/item_selector/element/element_controller.coffee
@@ -5,58 +5,63 @@
# All rights reserved.
#
-BaseController = require '../../../base_controller'
+BaseController = require "../../../base_controller"
+ItemDisplay = require "../../../../models/site/item_display"
########################################################################################################################
module.exports = class ElementController extends BaseController
constructor: (options={})->
- if not options.model? then throw new Error 'options.model is required'
- options.onClicked ?= (controller)-> # do nothing
- options.onSelected ?= (controller)-> # do nothing
- options.templateName = 'common/item_selector/element'
+ if not options.model? then throw new Error "options.model is required"
+ options.templateName = "common/item_selector/element"
options.useAnimations = false
super options
- @onClicked = options.onClicked
- @onSelected = options.onSelected
+ @onClicked = options.onClicked or (controller)-> # do nothing
+ @onSelected = options.onSelected or (controller)-> # do nothing
# Property Methods #############################################################################
- isSelected: ->
- return @_selected
-
- setSelected: (newSelected)->
- oldSelected = @_selected
- return if newSelected is oldSelected
-
- @_selected = newSelected
- @tryRefresh()
-
- @trigger c.event.change + ':selected', this, oldSelected, newSelected
- @trigger c.event.change, this
-
Object.defineProperties @prototype,
- selected: {get:@prototype.isSelected, set:@prototype.setSelected}
+
+ display:
+ get: -> return @_display ?= new ItemDisplay @model
+ set: -> throw new Error "display cannot be assigned"
+
+ isSelected:
+ get: -> return @_selected
+ set: (newSelected)->
+ oldSelected = @_selected
+ return if newSelected is oldSelected
+
+ @_selected = newSelected
+ @tryRefresh()
+
+ @trigger c.event.change + ":selected", this, oldSelected, newSelected
+ @trigger c.event.change, this
# BaseController Overrides #####################################################################
+ onDidModelChange: ->
+ @_display = null
+ super
+
onDidRender: ->
- @$icon = @$('img')
- @$name = @$('.name')
- @$modName = @$('.modName')
+ @$icon = @$("img")
+ @$name = @$(".name")
+ @$modName = @$(".modName")
super
refresh: ->
- @$icon.attr 'src', @model.iconUrl
- @$name.html @model.itemName
- @$modName.html @model.modName
+ @$icon.attr "src", @display.iconUrl
+ @$name.html @model.displayName
+ @$modName.html @model.mod.displayName
if @_selected
- @$el.addClass 'selected'
+ @$el.addClass "selected"
else
- @$el.removeClass 'selected'
+ @$el.removeClass "selected"
super
@@ -64,15 +69,15 @@ module.exports = class ElementController extends BaseController
events: ->
return _.extend super,
- 'click': '_onClick'
- 'mouseenter': '_onMouseEnter'
+ "click": "_onClick"
+ "mouseenter": "_onMouseEnter"
# Private Methods ##############################################################################
_onClick: (event)->
- event.preventDefault()
@onClicked this
+ return false
_onMouseEnter: (event)->
- event.preventDefault()
@onSelected this
+ return false
diff --git a/src/client/site/common/item_selector/item_selector_controller.coffee b/src/client/site/common/item_selector/item_selector_controller.coffee
index 33c634a7a..25f70433d 100644
--- a/src/client/site/common/item_selector/item_selector_controller.coffee
+++ b/src/client/site/common/item_selector/item_selector_controller.coffee
@@ -5,21 +5,22 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-ItemSelector = require '../../../models/site/item_selector'
-ElementController = require './element/element_controller'
+BaseController = require "../../base_controller"
+ItemDisplay = require "../../../models/site/item_display"
+ItemSelector = require "../../../models/site/item_selector"
+ElementController = require "./element/element_controller"
w = require "when"
########################################################################################################################
module.exports = class ItemSelectorController extends BaseController
- constructor: (options)->
- if not options.modPack? then throw new Error 'options.modPack is required'
+ constructor: (options={})->
+ if not options.modPack? then throw new Error "options.modPack is required"
options.isAcceptable ?= null
- options.model ?= new ItemSelector {}, modPack:options.modPack, isAcceptable:options.isAcceptable
+ options.model ?= new ItemSelector options.modPack, isAcceptable:options.isAcceptable
options.onChoseItem ?= (item)-> # do nothing
- options.templateName = 'common/item_selector'
+ options.templateName = "common/item_selector"
super options
@_modPack = options.modPack
@@ -29,25 +30,25 @@ module.exports = class ItemSelectorController extends BaseController
# Public Methods ###############################################################################
- launch: (hint='')->
+ launch: (hint="")->
@model.hint = hint
if @rendered then @refresh()
@_disableWindowScrolling()
- @$page.addClass 'blur'
+ @$page.addClass "blur"
@$screen.append @$popup
- @$screen.css 'display', ''
+ @$screen.css "display", ""
@$popup.off c.event.click
@$popup.on c.event.click, (event)=> @onPopupClicked(event)
- @$hintField.off 'keyup input'
- @$hintField.on 'keyup', (event)=> @onHintKeyPress(event)
- @$hintField.on 'input', (event)=> @onHintChanged(event)
+ @$hintField.off "keyup input"
+ @$hintField.on "keyup", (event)=> @onHintKeyPress(event)
+ @$hintField.on "input", (event)=> @onHintChanged(event)
@$hintField.focus()
- @$closeButton.one 'click', (event)=> @_close()
+ @$closeButton.one "click", (event)=> @_close()
@$screen.one c.event.click, (event)=> @onScreenClicked(event)
@@ -85,17 +86,17 @@ module.exports = class ItemSelectorController extends BaseController
return false
onResultClicked: (controller)->
- @_session.resolve controller.model.slug
+ @_session.resolve controller.model
@_session = null
@_close()
return false
onResultSelected: (controller)->
for c in @_elementControllers
- c.selected = false
+ c.isSelected = false
if controller?
- controller.selected = true
+ controller.isSelected = true
return false
@@ -106,14 +107,14 @@ module.exports = class ItemSelectorController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @$page = $('.page') # find the shared, global page
- @$screen = $('.view__screen') # find the shared, global screen
+ @$page = $(".page") # find the shared, global page
+ @$screen = $(".view__screen") # find the shared, global screen
- @$closeButton = @$('img.close')
- @$popup = @$('.view__item_selector_popup')
- @$hintField = @$('.view__item_selector_popup input')
- @$searchInput = @$('.search input')
- @$resultsContainer = @$('.results')
+ @$closeButton = @$("img.close")
+ @$popup = @$(".view__item_selector_popup")
+ @$hintField = @$(".view__item_selector_popup input")
+ @$searchInput = @$(".search input")
+ @$resultsContainer = @$(".results")
@$popup.detach()
super
@@ -127,16 +128,16 @@ module.exports = class ItemSelectorController extends BaseController
_chooseSelected: ->
for controller in @_elementControllers
- if controller.selected
+ if controller.isSelected
@onResultClicked controller
return
_close: ->
@_enableWindowScrolling()
- @$page.removeClass 'blur'
- @$screen.css 'display', 'none'
+ @$page.removeClass "blur"
+ @$screen.css "display", "none"
@$popup.detach()
- @model.hint = ''
+ @model.hint = ""
if @_session
@_session.resolve null
@@ -144,28 +145,27 @@ module.exports = class ItemSelectorController extends BaseController
_disableWindowScrolling: ->
@_windowScrollPosition = $(window).scrollTop()
- $('body').addClass('scrollDisabled').css('margin-top', -@_windowScrollPosition)
+ $("body").addClass("scrollDisabled").css("margin-top", -@_windowScrollPosition)
_enableWindowScrolling: ->
- $('body').removeClass('scrollDisabled').css('margin-top', 0)
+ $("body").removeClass("scrollDisabled").css("margin-top", 0)
$(window).scrollTop @_windowScrollPosition
_refreshResults: ->
index = 0
- for itemSlug in @model.results
- displayModel = @_modPack.findItemDisplay itemSlug
+ for item in @model.results
controller = @_elementControllers[index]
if not controller?
controller = new ElementController
- model: displayModel
+ model: item
onClicked: (c)=> @onResultClicked(c)
onSelected: (c)=> @onResultSelected(c)
controller.render show:false
@_elementControllers[index] = controller
@$resultsContainer.append controller.$el
else
- controller.model = displayModel
+ controller.model = item
controller.show()
index += 1
@@ -180,14 +180,17 @@ module.exports = class ItemSelectorController extends BaseController
controller = @_elementControllers[i]
nextController = @_elementControllers[i + 1]
- if controller.selected
- controller.selected = false
- nextController.selected = true
+ if controller.isSelected
+ controller.isSelected = false
+ nextController.isSelected = true
@_showElement nextController.$el
return
+ [..., controller] = @_elementControllers
+ controller.isSelected = false
+
controller = @_elementControllers[0]
- controller.selected = true
+ controller.isSelected = true
@_showElement controller.$el
_selectPrevious: ->
@@ -197,14 +200,17 @@ module.exports = class ItemSelectorController extends BaseController
previousController = @_elementControllers[i - 1]
controller = @_elementControllers[i]
- if controller.selected
- previousController.selected = true
- controller.selected = false
+ if controller.isSelected
+ previousController.isSelected = true
+ controller.isSelected = false
@_showElement previousController.$el
return
- controller = @_elementControllers[@_elementControllers.length - 1]
- controller.selected = true
+ controller = @_elementControllers[0]
+ controller.isSelected = false
+
+ [..., controller] = @_elementControllers
+ controller.isSelected = true
@_showElement controller.$el
_showElement: ($el)->
diff --git a/src/client/site/common/recipe/recipe_controller.coffee b/src/client/site/common/recipe/recipe_controller.coffee
index 9089af172..0d851b546 100644
--- a/src/client/site/common/recipe/recipe_controller.coffee
+++ b/src/client/site/common/recipe/recipe_controller.coffee
@@ -5,20 +5,21 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
-CraftingGridController = require '../crafting_grid/crafting_grid_controller'
-SlotController = require '../slot/slot_controller'
-{StringBuilder} = require('crafting-guide-common').util
+BaseController = require "../../base_controller"
+CraftingGridController = require "../crafting_grid/crafting_grid_controller"
+ItemDisplay = require "../../../models/site/item_display"
+SlotController = require "../slot/slot_controller"
+{StringBuilder} = require("crafting-guide-common").util
########################################################################################################################
module.exports = class RecipeController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- options.templateName = 'common/recipe'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/recipe"
super options
@_imageLoader = options.imageLoader
@@ -29,26 +30,26 @@ module.exports = class RecipeController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @_gridController = @addChild CraftingGridController, '.view__crafting_grid',
+ @_gridController = @addChild CraftingGridController, ".view__crafting_grid",
modPack: @_modPack
imageLoader: @_imageLoader
router: @_router
- @_outputSlotController = @addChild SlotController, '.output .view__slot',
+ @_outputSlotController = @addChild SlotController, ".output .view__slot",
imageLoader: @_imageLoader
modPack: @_modPack
router: @_router
- @$multiplier = @$('.multiplier')
- @$outputImg = @$('.output img')
- @$outputLink = @$('.output a')
- @$outputQuantity = @$('.quantity')
- @$toolContainer = @$('.tool')
+ @$multiplier = @$(".multiplier")
+ @$outputImg = @$(".output img")
+ @$outputLink = @$(".output a")
+ @$outputQuantity = @$(".quantity")
+ @$toolContainer = @$(".tool")
super
refresh: ->
@_gridController.model = @model
- @_outputSlotController.model = @model?.output?[0]
+ @_outputSlotController.model = @model?.output
@_refreshMultiplier()
@_refreshTools()
@@ -69,14 +70,14 @@ module.exports = class RecipeController extends BaseController
@_multiplier = newMultiplier
@_refreshMultiplier()
- @trigger Event.change + ':multiplier', this, oldMultiplier, newMultiplier
+ @trigger Event.change + ":multiplier", this, oldMultiplier, newMultiplier
@trigger Event.change, this
# Backbone.View Methods ########################################################################
events: ->
return _.extend super,
- 'click a': 'routeLinkClick'
+ "click a": "routeLinkClick"
# Private Methods ##############################################################################
@@ -84,14 +85,15 @@ module.exports = class RecipeController extends BaseController
if @multiplier > 1
@$multiplier.html "x#{@multiplier}"
else
- @$multiplier.html ''
+ @$multiplier.html ""
_refreshTools: ->
@$toolContainer.empty()
return unless @model?
- builder = new StringBuilder
- builder.loop @model.tools, delimiter:', ', onEach:(b, stack)=>
- display = @_modPack.findItemDisplay stack.itemSlug
- b.push "#{display.itemName}"
- @$toolContainer.html builder.toString()
+ toolLinks = []
+ for itemId, item of @model.tools
+ display = new ItemDisplay item
+ toolLinks.push "#{display.name}"
+
+ @$toolContainer.html toolLinks.join ", "
diff --git a/src/client/site/common/slot/slot_controller.coffee b/src/client/site/common/slot/slot_controller.coffee
index ecde0b23d..a5f710f25 100644
--- a/src/client/site/common/slot/slot_controller.coffee
+++ b/src/client/site/common/slot/slot_controller.coffee
@@ -5,18 +5,19 @@
# All rights reserved.
#
-BaseController = require '../../base_controller'
+BaseController = require "../../base_controller"
+ItemDisplay = require "../../../models/site/item_display"
+{Stack} = require("crafting-guide-common").models
########################################################################################################################
module.exports = class SlotController extends BaseController
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- # options.model should be a Stack
- options.templateName = 'common/slot'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ options.templateName = "common/slot"
options.useAnimations = false
super options
@@ -27,27 +28,31 @@ module.exports = class SlotController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
- @$link = @$('a')
- @$image = @$('img')
- @$quantity = @$('.quantity')
+ @$link = @$("a")
+ @$image = @$("img")
+ @$quantity = @$(".quantity")
+ super
+
+ onWillChangeModel: (oldModel, newModel)->
+ if newModel? and (newModel.constructor isnt Stack) then throw new Error "newModel must be a Stack"
super
refresh: ->
if @model?
- display = @_modPack.findItemDisplay @model.itemSlug
- @$link.attr 'href', display.itemUrl
+ display = new ItemDisplay @model.item
+ @$link.attr "href", display.url
@_imageLoader.load display.iconUrl, @$image
if @model.quantity > 1
@$quantity.html @model.quantity
else
- @$quantity.html ''
+ @$quantity.html ""
else
- @$link.removeAttr 'href'
- @$quantity.html ''
+ @$link.removeAttr "href"
+ @$quantity.html ""
- @$image.attr 'src', '/images/empty.png'
+ @$image.attr "src", "/images/empty.png"
super
@@ -55,4 +60,4 @@ module.exports = class SlotController extends BaseController
events: ->
return _.extend super,
- 'click a': 'routeLinkClick'
+ "click a": "routeLinkClick"
diff --git a/src/client/site/common/stack/stack_controller.coffee b/src/client/site/common/stack/stack_controller.coffee
index 4e939ec36..7c8825877 100644
--- a/src/client/site/common/stack/stack_controller.coffee
+++ b/src/client/site/common/stack/stack_controller.coffee
@@ -6,6 +6,7 @@
#
BaseController = require '../../base_controller'
+ItemDisplay = require "../../../models/site/item_display"
########################################################################################################################
@@ -38,8 +39,6 @@ module.exports = class StackController extends BaseController
@_shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
@_trackingContext = options.trackingContext ?= null
- @_modPack.on c.event.change, => @tryRefresh()
-
# Event Methods ################################################################################
onFirstButtonClicked: (event)->
@@ -71,7 +70,7 @@ module.exports = class StackController extends BaseController
@trigger c.event.change + ':quantity', this, oldQuantity, newQuantity
@trigger c.event.change, this
- tracker.trackEvent @_trackingContext, 'update-quantity', @model.itemSlug, @model.quantity
+ tracker.trackEvent @_trackingContext, 'update-quantity', @model.item.id, @model.quantity
onQuantityFieldChanged: ->
return unless @_editable
@@ -119,10 +118,10 @@ module.exports = class StackController extends BaseController
refresh: ->
if not @model? then throw new Error "must have a model to render"
- display = @_modPack.findItemDisplay @model.itemSlug
+ display = new ItemDisplay @model.item
@_imageLoader.load display.iconUrl, @$image
- @$nameLink.html display.itemName
+ @$nameLink.html display.name
@$nameLink.attr 'href', display.itemUrl
quantityText = if @model.quantity > 10000 then "#{@model.quantity / 1000}k" else "#{@model.quantity}"
diff --git a/src/client/site/craft_page/craft_page.jade b/src/client/site/craft_page/craft_page.jade
index bcafb4bcf..32d51aec6 100644
--- a/src/client/site/craft_page/craft_page.jade
+++ b/src/client/site/craft_page/craft_page.jade
@@ -53,4 +53,4 @@
h2 Steps
.panel
- section.view__craftsman_working
+ section.view__working_panel
diff --git a/src/client/site/craft_page/craft_page_controller.coffee b/src/client/site/craft_page/craft_page_controller.coffee
index 48467c18c..1abc722c0 100644
--- a/src/client/site/craft_page/craft_page_controller.coffee
+++ b/src/client/site/craft_page/craft_page_controller.coffee
@@ -5,14 +5,13 @@
# All rights reserved.
#
-BaseController = require '../base_controller'
-CraftPage = require '../../models/site/craft_page'
-{Craftsman} = require('crafting-guide-common').deprecated.crafting
-CraftsmanWorkingController = require './craftsman_working/craftsman_working_controller'
-InventoryController = require '../common/inventory/inventory_controller'
-PageController = require '../page_controller'
-{SimpleInventory} = require('crafting-guide-common').deprecated.crafting
-StepController = require './step/step_controller'
+CraftPage = require "../../models/site/craft_page"
+WorkingPanelController = require "./working_panel/working_panel_controller"
+{Inventory} = require("crafting-guide-common").models
+InventoryController = require "../common/inventory/inventory_controller"
+{Observable} = require("crafting-guide-common").util
+PageController = require "../page_controller"
+StepController = require "./step/step_controller"
########################################################################################################################
@@ -21,12 +20,12 @@ module.exports = class CraftPageController extends PageController
@::SCROLL_BUFFER = 8 # px
constructor: (options={})->
- if not options.imageLoader? then throw new Error 'options.imageLoader is required'
- if not options.modPack? then throw new Error 'options.modPack is required'
- if not options.router? then throw new Error 'options.router is required'
- if not options.storage? then throw new Error 'options.storage is required'
+ if not options.imageLoader? then throw new Error "options.imageLoader is required"
+ if not options.modPack? then throw new Error "options.modPack is required"
+ if not options.router? then throw new Error "options.router is required"
+ if not options.storage? then throw new Error "options.storage is required"
- options.model ?= new CraftPage modPack:options.modPack
+ options.model ?= new CraftPage modPack:options.modPack, params:options.params
options.templateName = 'craft_page'
super options
@@ -35,41 +34,46 @@ module.exports = class CraftPageController extends PageController
@_router = options.router
@_storage = options.storage
+ @model.have.on Observable::ANY, this, "onHaveInventoryChanged"
+ @model.want.on Observable::ANY, this, "onWantInventoryChanged"
+
# Event Methods ################################################################################
onHaveInventoryChanged: ->
- @_storage.store 'crafting-plan:have', @model.craftsman.have.unparse()
+ @_storage.store 'crafting-plan:have', @model.have.toUrlString()
- onMoveNeedToHave: (itemSlug)->
- quantity = @_needInventoryController.model.quantityOf itemSlug
- @model.craftsman.have.add itemSlug, quantity
+ onMoveNeedToHave: (itemId)->
+ quantity = @_needInventoryController.model.getQuantity itemId
+ item = @_modPack.findItem itemId
+ @model.have.add item, quantity
- onRemoveFromHaveInventory: (itemSlug)->
- @model.craftsman.have.remove itemSlug
+ onRemoveFromHave: (itemId)->
+ @model.have.remove itemId
- onRemoveFromWant: (itemSlug)->
- @model.craftsman.want.remove itemSlug
+ onRemoveFromWant: (itemId)->
+ @model.want.remove itemId
@onWantInventoryChanged()
onSampleClicked: (event)->
$el = $(event.target)
while $el.length > 0
- inventoryText = $el.attr 'data-slug'
+ inventoryText = $el.attr "data-slug"
break if inventoryText
$el = $el.parent()
if inventoryText?
- tracker.trackEvent c.tracking.category.craft, 'add-sample', inventoryText
- sampleInventory = new SimpleInventory
- sampleInventory.parse inventoryText
- @model.craftsman.want.addInventory sampleInventory
- @_scrollTo @$workingSection
- @onWantInventoryChanged()
+ try
+ tracker.trackEvent c.tracking.category.craft, "add-sample", inventoryText
+ sampleInventory = Inventory.fromUrlString inventoryText, @_modPack
+ @model.want.merge sampleInventory
+ @_scrollTo @$workingSection
+ catch e
+ logger.error e
return false
onWantInventoryChanged: ->
- text = @model.craftsman.want.unparse()
+ text = @model.want.toUrlString()
url = c.url.crafting inventoryText:text
@router.navigate url
@@ -79,7 +83,7 @@ module.exports = class CraftPageController extends PageController
return c.text.craftDescription()
getTitle: ->
- description = @model.craftsman.want.toDescription()
+ description = @model.want.toDescription()
return null unless description?
return "Crafting Plan for #{description}"
@@ -91,21 +95,19 @@ module.exports = class CraftPageController extends PageController
imageLoader: @_imageLoader
isAcceptable: (item)=> item.isCraftable
modPack: @_modPack
- model: @model.craftsman.want
+ model: @model.want
router: @_router
trackingContext: c.tracking.category.craftWant
- @_wantInventoryController.on c.event.button.first, (c, s)=> @onRemoveFromWant(s)
- @_wantInventoryController.on c.event.change, (c)=> @onWantInventoryChanged()
+ @_wantInventoryController.on c.event.button.first, (controller, itemId)=> @onRemoveFromWant itemId
@_haveInventoryController = @addChild InventoryController, '.have .view__inventory',
firstButtonType: 'down'
imageLoader: @_imageLoader
modPack: @_modPack
- model: @model.craftsman.have
+ model: @model.have
router: @_router
trackingContext: c.tracking.category.craftHave
- @_haveInventoryController.on c.event.button.first, (controller, itemSlug)=>
- @onRemoveFromHaveInventory itemSlug
+ @_haveInventoryController.on c.event.button.first, (controller, itemId)=> @onRemoveFromHave itemId
@_needInventoryController = @addChild InventoryController, '.need .view__inventory',
editable: false
@@ -115,11 +117,9 @@ module.exports = class CraftPageController extends PageController
model: null
router: @_router
trackingContext: c.tracking.category.craftNeed
- @_needInventoryController.on c.event.button.first, (c, s)=> @onMoveNeedToHave(s)
+ @_needInventoryController.on c.event.button.first, (controller, itemId)=> @onMoveNeedToHave itemId
- @_workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working',
- model: @model.craftsman
- @_workingSectionController.on c.event.click, => @_scrollTo @$workingSection
+ @_workingPanelController = @addChild WorkingPanelController, '.view__working_panel', model:@model
@$haveSection = @$('section.have')
@$instructionsSection = @$('section.instructions')
@@ -128,7 +128,7 @@ module.exports = class CraftPageController extends PageController
@$stepsContainer = @$('section.steps .panel')
@$stepsSection = @$('section.steps')
@$toolsSection = @$('section.tools')
- @$workingSection = @$('.view__craftsman_working')
+ @$workingSection = @$('.view__working_panel')
if c.screen.type.compute() is c.screen.type.mobile
@$('.view__inventory.large').removeClass 'large'
@@ -136,20 +136,15 @@ module.exports = class CraftPageController extends PageController
super
onWillRender: ->
- @model.craftsman.have.clear()
- @model.craftsman.have.parse @_storage.load('crafting-plan:have')
- @model.craftsman.have.on c.event.change, => @onHaveInventoryChanged()
-
- @model.craftsman.want.on c.event.change, => @refresh()
-
- @model.craftsman.on c.event.change + ":stage", =>
- return unless @model.craftsman.stage is Craftsman::STAGE.COMPLETE
- @_scrollTo @$needSection
+ @model.have.clear()
+ @model.have.merge Inventory.fromUrlString @_storage.load('crafting-plan:have')
+ @model.have.on Observable::ANY, this, "onHaveInventoryChanged"
+ @model.want.on Observable::ANY, this, "tryRefresh"
super
refresh: ->
- @_needInventoryController.model = @model.craftsman.plan?.need
+ @_needInventoryController.model = @model.currentPlan?.need
@_refreshOutdated()
@_refreshSectionVisibility()
@_refreshSteps()
@@ -165,33 +160,30 @@ module.exports = class CraftPageController extends PageController
# Private Methods ################################################################################
_addTools: (controller)->
- controller.model.addToolsTo @model.craftsman.want
+ controller.model.addToolsTo @model.want
_completeStep: (controller)->
- controller.markComplete @model.craftsman.have
+ controller.markComplete @model.have
_isAddingToolsPossible: (controller)->
tools = controller.model.recipe.tools
return false unless tools.length > 0
- have = @model.craftsman.have
- want = @model.craftsman.want
+ have = @model.have
+ want = @model.want
for stack in tools
- return false if have.hasAtLeast stack.itemSlug
- return false if want.hasAtLeast stack.itemSlug
+ return false if @model.have.contains stack.item.id
+ return false if @model.want.contains stack.item.id
return true
_isStepCompletable: (controller)->
- recipe = controller.model.recipe
- for stack in recipe.output
- return false if @model.craftsman.want.hasAtLeast stack.itemSlug
-
- return true
+ wantsOutput = @model.want.contains controller.model.recipe.output.item.id
+ return wantsOutput
_refreshOutdated: ->
- if @model.craftsman.stage is Craftsman::STAGE.OUTDATED
+ if @model.isOutdated
@$el.addClass 'outdated'
else
@$el.removeClass 'outdated'
@@ -205,22 +197,25 @@ module.exports = class CraftPageController extends PageController
visibleSections = []
- if @model.craftsman.want.isEmpty
+ # TODO: Figure out what to do if the planner can't make a valid plan
+ # else if @model.craftsman.stage is Craftsman::STAGE.INVALID
+ # visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
+ # TODO: Play around and see if the algo ever takes too long
+ # else if not @model.craftsman.complete
+ # visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
+
+ if @model.want.isEmpty
visibleSections.push el for el in [@$instructionsSection, @$wantSection]
- else if @model.craftsman.stage is Craftsman::STAGE.INVALID
- visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
- else if not @model.craftsman.complete
- visibleSections.push el for el in [@$wantSection, @$haveSection, @$workingSection]
else
visibleSections.push el for el in [@$haveSection, @$wantSection, @$workingSection]
- if @model.craftsman.plan?
+ if @model.currentPlan?
visibleSections.push el for el in [@$needSection, @$stepsSection]
@hide $el for $el in allSections
@show $el for $el in visibleSections
_refreshSteps: ->
- steps = @model.craftsman.plan?.steps or []
+ steps = @model.currentPlan?.steps or []
@_stepControllers ?= []
index = 0
diff --git a/src/client/site/craft_page/craftsman_working/craftsman_working_controller.coffee b/src/client/site/craft_page/craftsman_working/craftsman_working_controller.coffee
deleted file mode 100644
index f2e214538..000000000
--- a/src/client/site/craft_page/craftsman_working/craftsman_working_controller.coffee
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# Crafting Guide - craftsman_working_controller.coffee
-#
-# Copyright © 2014-2017 by Redwood Labs
-# All rights reserved.
-#
-
-BaseController = require '../../base_controller'
-{Craftsman} = require('crafting-guide-common').deprecated.crafting
-
-########################################################################################################################
-
-module.exports = class CraftsmanWorkingController extends BaseController
-
- @::HIDE_TIMER_DURATION = 2000
-
- constructor: (options={})->
- if not options.model then throw new Error 'options.model is required'
- options.templateName = 'craft_page/craftsman_working'
- super options
-
- @_hideTimer = null
-
- # Event Methods ################################################################################
-
- onButtonClicked: ->
- tracker.trackEvent c.tracking.category.craft, 'start'
- @trigger c.event.click
- @model.reset()
- @model.work()
- return false
-
- # BaseController Methods #######################################################################
-
- onDidModelChange: ->
- @refresh()
-
- onDidRender: ->
- @$button = @$('.button')
- @$count = @$('.count p')
- @$message = @$('.message p')
- @$outdated = @$('.outdated')
- @$waiting = @$('.waiting')
-
- @_controls = [@$button, @$count, @$message, @$outdated, @$waiting]
- super
-
- refresh: ->
- return unless @$message? and @$count?
-
- button = count = message = outdated = waiting = null
-
- switch @model.stage
- when Craftsman::STAGE.READY
- message = 'Ready to compute crafting plan!'
- count = 'Click "Calculate" to continue.'
- button = true
- when Craftsman::STAGE.GRAPHING
- message = 'Researching recipes...'
- count = "Found #{@model.stageCount} recipes so far..."
- watiing = true
- when Craftsman::STAGE.PLANNING
- message = 'Figuring out possible crafting plans...'
- count = "Found #{@model.stageCount} possibilities so far..."
- watiing = true
- when Craftsman::STAGE.ANALYZING
- message = 'Looking for the best plan...'
- count = "Finished checking #{@model.stageCount} so far..."
- watiing = true
- when Craftsman::STAGE.COMPLETE
- message = 'Crafting plan is complete.'
- when Craftsman::STAGE.INVALID
- message = 'Couldn\'t make a crafting plan!'
- count = 'Please report this problem using the Feedback box.'
- when Craftsman::STAGE.OUTDATED
- message = 'Your crafting plan is out of date!'
- count = 'Click "Calculate" to re-compute.'
- button = true
- outdated = true
-
- @hide(control) for control in @_controls
-
- if button?
- @show @$button
-
- if count?
- @show @$count
- @$count.html count
-
- if message?
- @show @$message
- @$message.html message
-
- if outdated?
- @show @$outdated
-
- if waiting?
- @show @$waiting
-
- super
-
- # Backbone.View Overrides ######################################################################
-
- events: ->
- return _.extend super,
- 'click .button': 'onButtonClicked'
diff --git a/src/client/site/craft_page/step/step_controller.coffee b/src/client/site/craft_page/step/step_controller.coffee
index eef7e330e..f5d364860 100644
--- a/src/client/site/craft_page/step/step_controller.coffee
+++ b/src/client/site/craft_page/step/step_controller.coffee
@@ -6,16 +6,19 @@
#
BaseController = require '../../base_controller'
+{Inventory} = require("crafting-guide-common").models
+{CraftingPlanStep} = require("crafting-guide-common").crafting
InventoryController = require '../../common/inventory/inventory_controller'
RecipeController = require '../../common/recipe/recipe_controller'
-{SimpleInventory} = require('crafting-guide-common').deprecated.crafting
+
########################################################################################################################
module.exports = class StepController extends BaseController
constructor: (options={})->
- if not options.model? then throw new Error 'options.model is required'
+ if options.model?.constructor isnt CraftingPlanStep
+ throw new Error "options.model must be a CraftingPlanStep"
if not options.modPack? then throw new Error 'options.modPack is required'
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
options.templateName = 'craft_page/step'
@@ -41,7 +44,7 @@ module.exports = class StepController extends BaseController
onCompleteButtonClicked: (event)->
return if @$completeButton.hasClass 'disabled'
- tracker.trackEvent c.tracking.category.craft, 'mark-complete', null, @model.number
+ tracker.trackEvent c.tracking.category.craft, 'mark-complete', null, @model.count
@onComplete this
onShowToolPlan: (event)->
@@ -54,7 +57,7 @@ module.exports = class StepController extends BaseController
@inventoryController = @addChild InventoryController, '.view__inventory',
editable: false
imageLoader: @_imageLoader
- model: @model.inventory
+ model: @model.inputInventory
modPack: @_modPack
router: @_router
@@ -78,12 +81,11 @@ module.exports = class StepController extends BaseController
return super
refresh: ->
- itemDisplay = @_modPack.findItemDisplay @model.recipe.output[0].itemSlug
- @$header.html "#{@model.number}. #{itemDisplay.itemName}"
+ @$header.html "#{@model.number}. #{@model.recipe.output.item.displayName}"
- @inventoryController.model = @model.inventory
+ @inventoryController.model = @model.inputInventory
@recipeController.model = @model.recipe
- @recipeController.multiplier = @model.multiplier
+ @recipeController.multiplier = @model.count
@_refreshCompleteButton()
@_refreshToolButton()
@@ -100,12 +102,11 @@ module.exports = class StepController extends BaseController
# Private Methods ##############################################################################
_refreshToolButton: ->
- inventory = new SimpleInventory {}, modPack:@_modPack
- for toolStack in @model.recipe.tools
- inventory.add toolStack.itemSlug, toolStack.quantity
- inventory.localize()
+ inventory = new Inventory
+ for itemId, item in @model.recipe.tools
+ inventory.add item
- inventoryText = inventory.unparse()
+ inventoryText = inventory.toUrlString()
@$toolButton.attr 'href', "/craft/#{inventoryText}"
@$toolButton.attr 'target', inventoryText
diff --git a/src/client/site/craft_page/craftsman_working/craftsman_working.jade b/src/client/site/craft_page/working_panel/working_panel.jade
similarity index 100%
rename from src/client/site/craft_page/craftsman_working/craftsman_working.jade
rename to src/client/site/craft_page/working_panel/working_panel.jade
diff --git a/src/client/site/craft_page/craftsman_working/craftsman_working.scss b/src/client/site/craft_page/working_panel/working_panel.scss
similarity index 100%
rename from src/client/site/craft_page/craftsman_working/craftsman_working.scss
rename to src/client/site/craft_page/working_panel/working_panel.scss
diff --git a/src/client/site/craft_page/working_panel/working_panel_controller.coffee b/src/client/site/craft_page/working_panel/working_panel_controller.coffee
new file mode 100644
index 000000000..06da9fa4a
--- /dev/null
+++ b/src/client/site/craft_page/working_panel/working_panel_controller.coffee
@@ -0,0 +1,89 @@
+#
+# Crafting Guide - working_panel_controller.coffee
+#
+# Copyright © 2014-2017 by Redwood Labs
+# All rights reserved.
+#
+
+BaseController = require '../../base_controller'
+CraftPage = require "../../../models/site/craft_page"
+
+########################################################################################################################
+
+module.exports = class WorkingPanelController extends BaseController
+
+ @::HIDE_TIMER_DURATION = 2000
+
+ constructor: (options={})->
+ if not options.model?.constructor is CraftPage then throw new Error "options.model must be a CraftPage"
+ options.templateName = "craft_page/working_panel"
+ super options
+
+ @_hideTimer = null
+
+ # Event Methods ################################################################################
+
+ onButtonClicked: ->
+ tracker.trackEvent c.tracking.category.craft, "start"
+ @trigger c.event.click
+ @model.createPlan()
+ return false
+
+ # BaseController Methods #######################################################################
+
+ onDidModelChange: ->
+ @refresh()
+
+ onDidRender: ->
+ @$button = @$('.button')
+ @$count = @$('.count p')
+ @$message = @$('.message p')
+ @$outdated = @$('.outdated')
+ @$waiting = @$('.waiting')
+
+ @_controls = [@$button, @$count, @$message, @$outdated, @$waiting]
+ super
+
+ refresh: ->
+ return unless @$message? and @$count?
+
+ button = count = message = outdated = null
+
+ if @model.isOutdated
+ message = "Your crafting plan is out of date!"
+ count = 'Click "Calculate" to re-compute.'
+ button = true
+ outdated = true
+ else if @model.currentPlan?
+ message = "Crafting plan is complete."
+ else
+ message = "Ready to compute crafting plan!"
+ count = 'Click "Calculate" to continue.'
+ button = true
+
+ @hide(control) for control in @_controls
+
+ if button?
+ @show @$button
+
+ if count?
+ @show @$count
+ @$count.html count
+
+ if message?
+ @show @$message
+ @$message.html message
+
+ if outdated?
+ @show @$outdated
+
+ if waiting?
+ @show @$waiting
+
+ super
+
+ # Backbone.View Overrides ######################################################################
+
+ events: ->
+ return _.extend super,
+ 'click .button': 'onButtonClicked'
diff --git a/src/client/site/router.coffee b/src/client/site/router.coffee
index b7624a57a..39783e41f 100644
--- a/src/client/site/router.coffee
+++ b/src/client/site/router.coffee
@@ -117,8 +117,7 @@ module.exports = class Router extends Backbone.Router
@route__craft()
route__craft: (text)->
- controller = new CraftPageController @_makeOptions {}
- controller.model.params = inventoryText:text
+ controller = new CraftPageController @_makeOptions params:inventoryText:text
@_siteController.setPage 'craft', controller
route__login: ->