Files
website/src/scripts/models/crafting_plan.coffee
T

127 lines
4.0 KiB
CoffeeScript

###
Crafting Guide - crafting_plan.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
BaseModel = require './base_model'
Inventory = require './inventory'
########################################################################################################################
module.exports = class CraftingPlan extends BaseModel
constructor: (attributes={}, options={})->
if not attributes.modPack then throw new Error 'modPack is required'
attributes.includingTools ?= false
super attributes, options
@have = new Inventory
@want = new Inventory
@need = new Inventory
@result = new Inventory
@have.on 'change', => @craft()
@want.on 'change', => @craft()
@modPack.on 'change', => @craft()
@clear()
# Public Methods ###############################################################################
clear: ->
@steps = []
@_expected = new Inventory
@_pending = null
@need.clear()
@result.clear()
@trigger 'change', this
return this
craft: ->
logger.trace "starting crafting plan for: #{@want} starting with #{@have}"
@clear()
return if @want.isEmpty
@want.each (stack)=>
@_expected = @want.clone()
@_pending = @want.clone()
@result.addInventory @have
@_need = new Inventory
while not @_pending.isEmpty
@_processPending()
@need.addInventory @_need
@steps.reverse()
@trigger 'change', this
# Object Overrides #############################################################################
toString: ->
return "#{@constructor.name} {
have:#{@have},
want:#{@want},
need:#{@_need},
result:#{@result},
steps:#{@steps}
}"
# Private Methods ##############################################################################
_processPending: ->
targetStack = @_pending.pop()
targetItem = @modPack.findItem targetStack.itemSlug
logger.verbose "processing item: #{targetStack}"
return unless targetItem?
return if (not targetItem.isCraftable) or targetItem.isGatherable
recipe = targetItem.recipes[0]
logger.verbose "recipe: #{recipe}"
if @includingTools
for toolStack in recipe.tools
slug = toolStack.itemSlug
totalExpected = @result.quantityOf(slug) + @_expected.quantityOf(slug)
if totalExpected < 1
@_pending.add slug
@_expected.add slug
while @_totalQuantityOf(targetItem.slug) < @_expected.quantityOf(targetItem.slug)
@steps.push recipe
for stack in recipe.input
@_processInputStack stack
for stack in recipe.output
@_processOutputStack stack
_processInputStack: (stack)->
quantityAvailable = @result.quantityOf stack.itemSlug
quantityUsed = Math.min quantityAvailable, stack.quantity
quantityNeeded = stack.quantity - quantityUsed
logger.trace "processing input:#{stack.itemSlug},
a:#{quantityAvailable}, u:#{quantityUsed}, n:#{quantityNeeded}"
@result.remove stack.itemSlug, quantityUsed
@_pending.add stack.itemSlug, quantityNeeded
@_need.add stack.itemSlug, quantityNeeded
_processOutputStack: (stack)->
quantityMissing = @_need.quantityOf stack.itemSlug
quantityUsed = Math.min quantityMissing, stack.quantity
quantityLeft = stack.quantity - quantityUsed
logger.trace "processing output:#{stack.itemSlug},
m:#{quantityMissing}, u:#{quantityUsed}, l:#{quantityLeft}"
@_need.remove stack.itemSlug, quantityUsed
@result.add stack.itemSlug, quantityLeft
_totalQuantityOf: (itemSlug)->
return @result.quantityOf(itemSlug) - @_need.quantityOf(itemSlug)