Add new CraftingPlan class

This commit is contained in:
Andrew Miner
2015-09-22 19:54:31 -07:00
parent 6ea97ac3aa
commit de04c79d17
9 changed files with 187 additions and 109 deletions
@@ -5,8 +5,82 @@ Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
Inventory = require '../inventory'
########################################################################################################################
module.exports = class CraftingPlan
constructor: ->
constructor: (steps, wanted)->
if not steps? then throw new Error 'steps is required'
if not wanted? then throw new Error 'wanted is required'
@_produced = new Inventory
@_required = new Inventory
@_steps = steps
@_wanted = wanted
@_computeRequired()
# Property Methods #############################################################################
Object.defineProperties @prototype,
length:
get: -> @steps.length
produced:
get: -> @_produced
required:
get: -> @_required
steps:
get: -> @_steps
wanted:
get: -> @_wanted
# Object Overrides #############################################################################
toString: ->
return "#{@constructor.name}{
wanted:#{@wanted},
required:#{@required},
steps:[#{(step.toString() for step in @steps).join(',')}],
produced:#{@produced}
}"
# Private Methods ##############################################################################
_computeRequired: ->
@_required.addInventory @_wanted
for i in [@_steps.length-1..0] by -1
recipe = @_steps[i]
for stack in recipe.output
while @_required.quantityOf(stack.itemSlug) > 0
@_executeRecipe recipe
@_produced.addInventory @_wanted
_executeRecipe: (recipe)->
#console.log "executing: #{recipe}"
for stack in recipe.input
@_use stack
for stack in recipe.output
@_produce stack
_produce: (stack)->
deficit = @_required.quantityOf stack.itemSlug
replenished = Math.min deficit, stack.quantity
surplus = stack.quantity - replenished
#console.log "producing #{stack.itemSlug}, surplus: #{surplus}, replenished:#{replenished}"
@_produced.add stack.itemSlug, surplus
@_required.remove stack.itemSlug, replenished
_use: (stack)->
available = @_produced.quantityOf stack.itemSlug
consumed = Math.min stack.quantity, available
deficit = stack.quantity - consumed
#console.log "using #{stack.itemSlug}, consumed: #{consumed}, deficit:#{deficit}"
@_produced.remove stack.itemSlug, consumed
@_required.add stack.itemSlug, deficit
@@ -19,7 +19,6 @@ module.exports = class GraphBuilder
@_wanted = options.wanted ?= new Inventory
@_wanted.on 'change', => @reset()
@reset()
# Public Methods ###############################################################################
+20 -7
View File
@@ -6,14 +6,18 @@ All rights reserved.
###
CraftingNode = require './crafting_node'
CraftingPlan = require './crafting_plan'
Inventory = require '../inventory'
########################################################################################################################
module.exports = class PlanBuilder
constructor: (rootNode)->
constructor: (rootNode, options={})->
if not rootNode? then throw new Error 'rootNode is required'
@wanted = options.wanted
@_choiceNodes = []
@_complete = false
@_plans = []
@@ -26,9 +30,9 @@ module.exports = class PlanBuilder
producePlans: (maxPlans=null)->
maxPlans = if maxPlans then @plans.length + maxPlans else Number.MAX_VALUE
while @plans.length < maxPlans and not @complete
while @plans.length is 0 or (@plans.length < maxPlans and not @complete)
plan = @_captureCurrentPlan()
@plans.push plan if plan.length > 0
@plans.push plan
@_incrementChoiceNodes()
return @_plans
@@ -41,15 +45,22 @@ module.exports = class PlanBuilder
getPlans: ->
return @_plans
getWanted: ->
return @_wanted
setWanted: (wanted)->
@_wanted = wanted or new Inventory
Object.defineProperties @prototype,
complete: { get:@prototype.isComplete }
plans: { get:@prototype.getPlans }
plans: { get:@prototype.getPlans }
wanted: { get:@prototype.getWanted, set:@prototype.setWanted }
# Private Methods ##############################################################################
_captureCurrentPlan: ->
toVisit = [@_rootNode]
plan = []
steps = []
while toVisit.length > 0
node = toVisit.shift()
@@ -59,10 +70,12 @@ module.exports = class PlanBuilder
else if node.TYPE is CraftingNode::TYPES.ITEM
toVisit.push node.children[0] if node.children.length > 0
else if node.TYPE is CraftingNode::TYPES.RECIPE
plan.push node.recipe
steps.push node.recipe
toVisit.push(c) for c in node.children
return plan.reverse()
steps.reverse()
plan = new CraftingPlan steps, @_wanted
return plan
_incrementChoiceNodes: ->
index = @_choiceNodes.length - 1
+16 -6
View File
@@ -30,6 +30,8 @@ module.exports = class Inventory extends BaseModel
# Public Methods ###############################################################################
add: (itemSlug, quantity=1)->
return this unless quantity > 0
@_add itemSlug, quantity
@trigger Event.add, this, itemSlug, quantity
@trigger Event.change, this
@@ -102,12 +104,12 @@ module.exports = class Inventory extends BaseModel
return stack.quantity
remove: (itemSlug, quantity=null)->
return if quantity is 0
stack = @_stacks[itemSlug]
if not stack? then throw new Error "cannot remove #{itemSlug} since it is not in this inventory"
return this unless stack?
quantity ?= stack.quantity
return this unless quantity > 0
if stack.quantity < quantity
throw new Error "cannot remove #{quantity}: only #{stack.quantity} #{itemSlug} in this inventory"
@@ -115,7 +117,7 @@ module.exports = class Inventory extends BaseModel
if stack.quantity is 0
@stopListening stack
delete @_stacks[itemSlug]
@_itemSlugs = _(@_itemSlugs).without itemSlug
@_itemSlugs = (s for s in @_itemSlugs when not ItemSlug.equal(s, itemSlug))
@trigger Event.remove, this, itemSlug, quantity
@trigger Event.change, this
@@ -164,8 +166,16 @@ module.exports = class Inventory extends BaseModel
getIsEmpty: ->
return @_itemSlugs.length is 0
getTotalQuantity: ->
total = 0
@each (stack)->
total += stack.quantity
return total
Object.defineProperties @prototype,
isEmpty: { get:@prototype.getIsEmpty }
isEmpty: { get:@prototype.getIsEmpty }
totalQuantity: { get:@prototype.getTotalQuantity }
# Object Overrides #############################################################################
@@ -186,7 +196,7 @@ module.exports = class Inventory extends BaseModel
_add: (itemSlug, quantity=1)->
return unless itemSlug?
return if quantity is 0
return unless quantity > 0
stack = @_stacks[itemSlug]
if not stack?