127 lines
4.0 KiB
CoffeeScript
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)
|