141 lines
4.4 KiB
CoffeeScript
141 lines
4.4 KiB
CoffeeScript
###
|
|
Crafting Guide - craftsman.coffee
|
|
|
|
Copyright (c) 2015 by Redwood Labs
|
|
All rights reserved.
|
|
###
|
|
|
|
_ = require 'underscore'
|
|
BaseModel = require '../base_model'
|
|
{Event} = require '../../constants'
|
|
GraphBuilder = require './graph_builder'
|
|
Inventory = require '../inventory'
|
|
PlanBuilder = require './plan_builder'
|
|
PlanEvaluator = require './plan_evaluator'
|
|
w = require 'when'
|
|
|
|
########################################################################################################################
|
|
|
|
module.exports = class Craftsman extends BaseModel
|
|
|
|
@::ANALYZE_STEP_INCREMENT = 100
|
|
|
|
@::GRAPH_STEP_INCREMENT = 10
|
|
|
|
@::PLAN_STEP_INCREMENT = 50
|
|
|
|
@::STAGE =
|
|
WAITING: 'waiting'
|
|
GRAPHING: 'examining recipes'
|
|
PLANNING: 'computing plans'
|
|
ANALYZING: 'analyzing plans'
|
|
COMPLETE: 'complete'
|
|
|
|
constructor: (modPack)->
|
|
if not modPack? then throw new Error 'modPack is required'
|
|
attributes =
|
|
paused: false
|
|
stage: @STAGE.WAITING
|
|
stageCount: 0
|
|
super attributes, {}
|
|
|
|
@_modPack = modPack
|
|
|
|
reset = _.throttle (=> @reset()), 100
|
|
|
|
@_have = new Inventory
|
|
@_have.on Event.change, reset
|
|
|
|
@_want = new Inventory
|
|
@_want.on Event.change, reset
|
|
|
|
@on Event.change + ':paused', reset
|
|
@on Event.change + ':stage', => logger.info "Craftsman has started #{@stage}..."
|
|
@reset()
|
|
|
|
# Public Methods ###############################################################################
|
|
|
|
work: ->
|
|
return if @_want.isEmpty
|
|
logger.verbose => "stage: #{@stage}(#{@stageCount}) working..."
|
|
|
|
if not @_graphBuilder?
|
|
want = new Inventory {modPack:@_modPack}, clone:@_want
|
|
want.localize()
|
|
|
|
have = new Inventory {modPack:@_modPack}, clone:@_have
|
|
have.localize()
|
|
|
|
logger.info -> "Craftsman starting to build #{want} from #{have}"
|
|
|
|
@_graphBuilder = new GraphBuilder modPack:@_modPack, want:want, have:have
|
|
@stage = @STAGE.GRAPHING
|
|
@stageCount = 0
|
|
else if not @_graphBuilder.complete
|
|
@_graphBuilder.expandGraph @GRAPH_STEP_INCREMENT
|
|
@stageCount = @_graphBuilder.stepCount
|
|
else if not @_planBuilder?
|
|
logger.debug => "Craftsman finished computing graph:\n#{@_graphBuilder.rootNode}"
|
|
|
|
@_planBuilder = new PlanBuilder @_graphBuilder.rootNode, @_modPack, want:@_graphBuilder.want
|
|
@stage = @STAGE.PLANNING
|
|
@stageCount = 0
|
|
else if not @_planBuilder.complete
|
|
@_planBuilder.producePlans @PLAN_STEP_INCREMENT
|
|
@stageCount = @_planBuilder.plans.length
|
|
else if not @_planEvaluator?
|
|
@_planEvaluator = new PlanEvaluator @_planBuilder.plans
|
|
@stage = @STAGE.ANALYZING
|
|
@stageCount = 0
|
|
else if not @_planEvaluator.complete
|
|
@_planEvaluator.scorePlans @ANALYZE_STEP_INCREMENT
|
|
@stageCount = @_planEvaluator.lastScored
|
|
else
|
|
@_plans = [
|
|
@_planEvaluator.findBestPlan PlanEvaluator::CRITERIA.FEWEST_STEPS
|
|
@_planEvaluator.findBestPlan PlanEvaluator::CRITERIA.LEAST_MATERIALS
|
|
]
|
|
@_plans[0].computeRequired()
|
|
logger.info => "Craftsman has finished with plans: #{(p.toString() for p in @_plans).join('\n')}"
|
|
@trigger Event.change + ':complete', this
|
|
@trigger Event.change, this
|
|
|
|
@_scheduleNextWork()
|
|
return @complete
|
|
|
|
reset: ->
|
|
@_graphBuilder = null
|
|
@_planBuilder = null
|
|
@_planEvaluator = null
|
|
@_plans = null
|
|
|
|
@stage = @STAGE.WAITING
|
|
@stageCount = 0
|
|
|
|
@_scheduleNextWork()
|
|
|
|
# Property Methods #############################################################################
|
|
|
|
Object.defineProperties @prototype,
|
|
|
|
complete:
|
|
get: -> @_plans?
|
|
|
|
have:
|
|
get: -> @_have
|
|
|
|
plan:
|
|
get: -> @_plans?[0]
|
|
|
|
want:
|
|
get: -> @_want
|
|
|
|
# Private Methods ##############################################################################
|
|
|
|
_scheduleNextWork: ->
|
|
return if @paused
|
|
return if @want.isEmpty
|
|
return if @complete
|
|
|
|
_.defer => @work()
|