Fix bugs with new crafting algo
This commit is contained in:
@@ -95,8 +95,8 @@ GitHub.file.itemDescription.fileName = _.template "item.cg"
|
|||||||
GitHub.file.itemDescription.path = _.template "/data/<%= modSlug %>/items/<%= itemSlug %>"
|
GitHub.file.itemDescription.path = _.template "/data/<%= modSlug %>/items/<%= itemSlug %>"
|
||||||
|
|
||||||
exports.Limits = Limits = {}
|
exports.Limits = Limits = {}
|
||||||
Limits.maximumGraphSize = 10000
|
Limits.maximumGraphSize = 5000
|
||||||
Limits.maximumPlanCount = 10000
|
Limits.maximumPlanCount = 5000
|
||||||
|
|
||||||
exports.Login = Login = {}
|
exports.Login = Login = {}
|
||||||
Login.authorizeUrl = _.template "https://github.com/login/oauth/authorize" +
|
Login.authorizeUrl = _.template "https://github.com/login/oauth/authorize" +
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ Copyright (c) 2014-2015 by Redwood Labs
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
###
|
###
|
||||||
|
|
||||||
|
_ = require 'underscore'
|
||||||
AdsenseController = require './adsense_controller'
|
AdsenseController = require './adsense_controller'
|
||||||
CraftPage = require '../models/craft_page'
|
CraftPage = require '../models/craft_page'
|
||||||
|
CraftsmanWorkingController = require './craftsman_working_controller'
|
||||||
|
{Event} = require '../constants'
|
||||||
InventoryController = require './inventory_controller'
|
InventoryController = require './inventory_controller'
|
||||||
PageController = require './page_controller'
|
PageController = require './page_controller'
|
||||||
StepController = require './step_controller'
|
StepController = require './step_controller'
|
||||||
_ = require 'underscore'
|
|
||||||
{Event} = require '../constants'
|
|
||||||
{Text} = require '../constants'
|
{Text} = require '../constants'
|
||||||
{Url} = require '../constants'
|
{Url} = require '../constants'
|
||||||
|
|
||||||
@@ -32,15 +33,13 @@ module.exports = class CraftPageController extends PageController
|
|||||||
@modPack = options.modPack
|
@modPack = options.modPack
|
||||||
@storage = options.storage
|
@storage = options.storage
|
||||||
|
|
||||||
@model.craftsman.on Event.change, => @tryRefresh()
|
|
||||||
|
|
||||||
# Event Methods ################################################################################
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
onHaveInventoryChanged: ->
|
onHaveInventoryChanged: ->
|
||||||
@storage.store 'crafting-plan:have', @model.craftsman.have.unparse()
|
@storage.store 'crafting-plan:have', @model.craftsman.have.unparse()
|
||||||
|
|
||||||
onMoveNeedToHave: (itemSlug)->
|
onMoveNeedToHave: (itemSlug)->
|
||||||
quantity = @model.craftsman.need.quantityOf itemSlug
|
quantity = @needInventoryController.model.quantityOf itemSlug
|
||||||
@model.craftsman.have.add itemSlug, quantity
|
@model.craftsman.have.add itemSlug, quantity
|
||||||
@onHaveInventoryChanged()
|
@onHaveInventoryChanged()
|
||||||
|
|
||||||
@@ -106,12 +105,16 @@ module.exports = class CraftPageController extends PageController
|
|||||||
firstButtonType: 'up'
|
firstButtonType: 'up'
|
||||||
@needInventoryController.on Event.button.first, (c, s)=> @onMoveNeedToHave(s)
|
@needInventoryController.on Event.button.first, (c, s)=> @onMoveNeedToHave(s)
|
||||||
|
|
||||||
|
@workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working',
|
||||||
|
model: @model.craftsman
|
||||||
|
|
||||||
@$instructionsSection = @$('.instructions.section')
|
@$instructionsSection = @$('.instructions.section')
|
||||||
@$makeSection = @$('.make.section')
|
@$makeSection = @$('.make.section')
|
||||||
@$toolsSection = @$('.tools.section')
|
@$toolsSection = @$('.tools.section')
|
||||||
@$ingredientsSection = @$('.ingredients.section')
|
@$ingredientsSection = @$('.ingredients.section')
|
||||||
@$stepsSection = @$('.steps.section')
|
@$stepsSection = @$('.steps.section')
|
||||||
@$stepsContainer = @$('.steps.section .panel')
|
@$stepsContainer = @$('.steps.section .panel')
|
||||||
|
@$workingSection = @$('.view__craftsman_working')
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
@@ -139,14 +142,23 @@ module.exports = class CraftPageController extends PageController
|
|||||||
return not @model.craftsman.want.hasAtLeast controller.model.outputItemSlug
|
return not @model.craftsman.want.hasAtLeast controller.model.outputItemSlug
|
||||||
|
|
||||||
_refreshSectionVisibility: ->
|
_refreshSectionVisibility: ->
|
||||||
|
return unless @_rendered
|
||||||
|
|
||||||
if @model.craftsman.want.isEmpty
|
if @model.craftsman.want.isEmpty
|
||||||
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
||||||
@hide $el
|
@hide $el
|
||||||
@show @$instructionsSection
|
@show @$instructionsSection
|
||||||
|
@hide @$workingSection
|
||||||
|
else if not @model.craftsman.complete
|
||||||
|
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
||||||
|
@hide $el
|
||||||
|
@hide @$instructionsSection
|
||||||
|
@show @$workingSection
|
||||||
else
|
else
|
||||||
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
||||||
@show $el
|
@show $el
|
||||||
@hide @$instructionsSection
|
@hide @$instructionsSection
|
||||||
|
@hide @$workingSection
|
||||||
|
|
||||||
_refreshSteps: ->
|
_refreshSteps: ->
|
||||||
steps = @model.craftsman.plan?.steps or []
|
steps = @model.craftsman.plan?.steps or []
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
###
|
||||||
|
Crafting Guide - crafting_grid_controller.coffee
|
||||||
|
|
||||||
|
Copyright (c) 2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
BaseController = require './base_controller'
|
||||||
|
Craftsman = require '../models/crafting/craftsman'
|
||||||
|
{Event} = require '../constants'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class CraftsmanWorkingController extends BaseController
|
||||||
|
|
||||||
|
constructor: (options={})->
|
||||||
|
if not options.model then throw new Error 'options.model is required'
|
||||||
|
options.templateName = 'craftsman_working'
|
||||||
|
super options
|
||||||
|
|
||||||
|
@model.on Event.change, => @_refreshStatusText()
|
||||||
|
|
||||||
|
# BaseController Methods #######################################################################
|
||||||
|
|
||||||
|
onDidRender: ->
|
||||||
|
@$message = @$('.message p')
|
||||||
|
@$count = @$('.count p')
|
||||||
|
super
|
||||||
|
|
||||||
|
refresh: ->
|
||||||
|
@_refreshStatusText()
|
||||||
|
super
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_refreshStatusText: ->
|
||||||
|
return unless @$message? and @$count?
|
||||||
|
|
||||||
|
switch @model.stage
|
||||||
|
when Craftsman::STAGE.WAITING
|
||||||
|
@$message.html 'Preparing crafting calculation...'
|
||||||
|
@$count.html ''
|
||||||
|
when Craftsman::STAGE.GRAPHING
|
||||||
|
@$message.html 'Researching recipes...'
|
||||||
|
@$count.html "Found #{@model.stageCount} recipes so far..."
|
||||||
|
when Craftsman::STAGE.PLANNING
|
||||||
|
@$message.html 'Figuring out possible crafting plans...'
|
||||||
|
@$count.html "Found #{@model.stageCount} possibilities so far..."
|
||||||
|
when Craftsman::STAGE.ANALYZING
|
||||||
|
@$message.html 'Looking for the best plan...'
|
||||||
|
@$count.html "Finished checking #{@model.stageCount} so far..."
|
||||||
|
when Craftsman::STAGE.COMPLETE
|
||||||
|
@$message.html 'All done!'
|
||||||
|
@$count.html ''
|
||||||
@@ -72,7 +72,7 @@ module.exports = class FullRecipeController extends BaseController
|
|||||||
|
|
||||||
if @model?
|
if @model?
|
||||||
for stack in @model.input
|
for stack in @model.input
|
||||||
inputs.add stack.itemSlug, stack.quantity
|
inputs.add stack.itemSlug, @model.getQuantityRequired stack.itemSlug
|
||||||
|
|
||||||
|
|
||||||
_refreshOutputs: ->
|
_refreshOutputs: ->
|
||||||
@@ -81,7 +81,7 @@ module.exports = class FullRecipeController extends BaseController
|
|||||||
|
|
||||||
if @model?
|
if @model?
|
||||||
for stack in @model.output
|
for stack in @model.output
|
||||||
outputs.add stack.itemSlug, stack.quantity
|
outputs.add stack.itemSlug, @model.getQuantityProduced stack.itemSlug
|
||||||
|
|
||||||
_refreshTools: ->
|
_refreshTools: ->
|
||||||
@$toolContainer.empty()
|
@$toolContainer.empty()
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ module.exports = class CraftPage extends BaseModel
|
|||||||
|
|
||||||
@modPack.on Event.change, => @_consumeParams()
|
@modPack.on Event.change, => @_consumeParams()
|
||||||
@on Event.change + ':params', => @_consumeParams()
|
@on Event.change + ':params', => @_consumeParams()
|
||||||
@craftsman.on Event.change, => @trigger Event.change, this
|
@craftsman.on Event.change + ':stage', => @trigger Event.change, this
|
||||||
|
@craftsman.on Event.change + ':complete', => @trigger Event.change, this
|
||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ SimpleInventory = require '../simple_inventory'
|
|||||||
|
|
||||||
module.exports = class CraftingPlan
|
module.exports = class CraftingPlan
|
||||||
|
|
||||||
constructor: (steps, want, modPack)->
|
constructor: (modPack, want, have, steps)->
|
||||||
if not modPack? then throw new Error 'modPack is required'
|
if not modPack? then throw new Error 'modPack is required'
|
||||||
if not steps? then throw new Error 'steps is required'
|
|
||||||
if not want? then throw new Error 'want is required'
|
if not want? then throw new Error 'want is required'
|
||||||
|
if not have? then throw new Error 'have is required'
|
||||||
|
if not steps? then throw new Error 'steps is required'
|
||||||
|
|
||||||
|
@_have = have
|
||||||
@_made = null
|
@_made = null
|
||||||
@_modPack = modPack
|
@_modPack = modPack
|
||||||
@_need = null
|
@_need = null
|
||||||
@@ -31,9 +33,11 @@ module.exports = class CraftingPlan
|
|||||||
|
|
||||||
computeRequired: ->
|
computeRequired: ->
|
||||||
@_need = new SimpleInventory modPack:@_modPack
|
@_need = new SimpleInventory modPack:@_modPack
|
||||||
@_made = new SimpleInventory modPack:@_modPack
|
|
||||||
@_need.addInventory @_want
|
@_need.addInventory @_want
|
||||||
|
|
||||||
|
@_made = new SimpleInventory modPack:@_modPack
|
||||||
|
@_made.addInventory @_have
|
||||||
|
|
||||||
for i in [@_steps.length-1..0] by -1
|
for i in [@_steps.length-1..0] by -1
|
||||||
step = @_steps[i]
|
step = @_steps[i]
|
||||||
step.multiplier = 0
|
step.multiplier = 0
|
||||||
@@ -47,6 +51,8 @@ module.exports = class CraftingPlan
|
|||||||
@_executeStep step
|
@_executeStep step
|
||||||
|
|
||||||
@_made.addInventory @_want
|
@_made.addInventory @_want
|
||||||
|
@_pruneEmptySteps()
|
||||||
|
@_numberSteps()
|
||||||
|
|
||||||
hasRawScore: (name)->
|
hasRawScore: (name)->
|
||||||
return @_rawScores[name]?
|
return @_rawScores[name]?
|
||||||
@@ -69,6 +75,8 @@ module.exports = class CraftingPlan
|
|||||||
# Property Methods #############################################################################
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
Object.defineProperties @prototype,
|
Object.defineProperties @prototype,
|
||||||
|
have:
|
||||||
|
get: -> @_have
|
||||||
length:
|
length:
|
||||||
get: -> @steps.length
|
get: -> @steps.length
|
||||||
made:
|
made:
|
||||||
@@ -87,6 +95,10 @@ module.exports = class CraftingPlan
|
|||||||
@_want.each (stack)->
|
@_want.each (stack)->
|
||||||
result.push " #{stack}"
|
result.push " #{stack}"
|
||||||
|
|
||||||
|
result.push "When you already have:"
|
||||||
|
@_have.each (stack)->
|
||||||
|
result.push " #{stack}"
|
||||||
|
|
||||||
result.push "Start with:"
|
result.push "Start with:"
|
||||||
@_need.each (stack)->
|
@_need.each (stack)->
|
||||||
result.push " #{stack}"
|
result.push " #{stack}"
|
||||||
@@ -140,3 +152,12 @@ module.exports = class CraftingPlan
|
|||||||
_numberSteps: ->
|
_numberSteps: ->
|
||||||
for step, i in @_steps
|
for step, i in @_steps
|
||||||
step.number = i + 1
|
step.number = i + 1
|
||||||
|
|
||||||
|
_pruneEmptySteps: ->
|
||||||
|
index = 0
|
||||||
|
while index < @_steps.length
|
||||||
|
step = @_steps[index]
|
||||||
|
if step.multiplier is 0
|
||||||
|
@_steps.splice index, 1
|
||||||
|
else
|
||||||
|
index++
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ w = require 'when'
|
|||||||
|
|
||||||
module.exports = class Craftsman extends BaseModel
|
module.exports = class Craftsman extends BaseModel
|
||||||
|
|
||||||
@::ANALYZE_STEP_INCREMENT = 100
|
@::ANALYZE_STEP_INCREMENT = 29
|
||||||
|
|
||||||
@::GRAPH_STEP_INCREMENT = 10
|
@::GRAPH_STEP_INCREMENT = 59
|
||||||
|
|
||||||
@::PLAN_STEP_INCREMENT = 50
|
@::PLAN_STEP_INCREMENT = 39
|
||||||
|
|
||||||
@::STAGE =
|
@::STAGE =
|
||||||
WAITING: 'waiting'
|
WAITING: 'waiting'
|
||||||
@@ -43,32 +43,29 @@ module.exports = class Craftsman extends BaseModel
|
|||||||
|
|
||||||
reset = _.throttle (=> @reset()), 100
|
reset = _.throttle (=> @reset()), 100
|
||||||
|
|
||||||
@_have = new Inventory
|
@_have = new Inventory modPack:@_modPack
|
||||||
@_have.on Event.change, reset
|
@_have.on Event.change, reset
|
||||||
|
|
||||||
@_want = new Inventory
|
@_want = new Inventory modPack:@_modPack
|
||||||
@_want.on Event.change, reset
|
@_want.on Event.change, reset
|
||||||
|
|
||||||
@on Event.change + ':paused', reset
|
@on Event.change + ':paused', reset
|
||||||
@on Event.change + ':stage', => logger.info "Craftsman has started #{@stage}..."
|
@on Event.change + ':stage', => logger.info "Craftsman has started #{@stage}..."
|
||||||
|
@on 'scheduleNextWork', => @_scheduleNextWork()
|
||||||
@reset()
|
@reset()
|
||||||
|
|
||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
work: ->
|
work: ->
|
||||||
return if @_want.isEmpty
|
return if @_want.isEmpty
|
||||||
logger.verbose => "stage: #{@stage}(#{@stageCount}) working..."
|
|
||||||
|
|
||||||
if not @_graphBuilder?
|
if not @_graphBuilder?
|
||||||
want = new Inventory {modPack:@_modPack}, clone:@_want
|
@_want.localize()
|
||||||
want.localize()
|
@_have.localize()
|
||||||
|
|
||||||
have = new Inventory {modPack:@_modPack}, clone:@_have
|
logger.info -> "Craftsman starting to build #{@_want} from #{@_have}"
|
||||||
have.localize()
|
|
||||||
|
|
||||||
logger.info -> "Craftsman starting to build #{want} from #{have}"
|
@_graphBuilder = new GraphBuilder modPack:@_modPack, want:@_want, have:@_have
|
||||||
|
|
||||||
@_graphBuilder = new GraphBuilder modPack:@_modPack, want:want, have:have
|
|
||||||
@stage = @STAGE.GRAPHING
|
@stage = @STAGE.GRAPHING
|
||||||
@stageCount = 0
|
@stageCount = 0
|
||||||
else if not @_graphBuilder.complete
|
else if not @_graphBuilder.complete
|
||||||
@@ -77,7 +74,7 @@ module.exports = class Craftsman extends BaseModel
|
|||||||
else if not @_planBuilder?
|
else if not @_planBuilder?
|
||||||
logger.debug => "Craftsman finished computing graph:\n#{@_graphBuilder.rootNode}"
|
logger.debug => "Craftsman finished computing graph:\n#{@_graphBuilder.rootNode}"
|
||||||
|
|
||||||
@_planBuilder = new PlanBuilder @_graphBuilder.rootNode, @_modPack, want:@_graphBuilder.want
|
@_planBuilder = new PlanBuilder @_graphBuilder.rootNode, @_modPack, have:@_have, want:@_want
|
||||||
@stage = @STAGE.PLANNING
|
@stage = @STAGE.PLANNING
|
||||||
@stageCount = 0
|
@stageCount = 0
|
||||||
else if not @_planBuilder.complete
|
else if not @_planBuilder.complete
|
||||||
@@ -96,11 +93,13 @@ module.exports = class Craftsman extends BaseModel
|
|||||||
@_planEvaluator.findBestPlan PlanEvaluator::CRITERIA.LEAST_MATERIALS
|
@_planEvaluator.findBestPlan PlanEvaluator::CRITERIA.LEAST_MATERIALS
|
||||||
]
|
]
|
||||||
@_plans[0].computeRequired()
|
@_plans[0].computeRequired()
|
||||||
logger.info => "Craftsman has finished with plans: #{(p.toString() for p in @_plans).join('\n')}"
|
@stage = @STAGE.COMPLETE
|
||||||
@trigger Event.change + ':complete', this
|
@stageCount = 0
|
||||||
@trigger Event.change, this
|
|
||||||
|
|
||||||
@_scheduleNextWork()
|
logger.info => "Craftsman has finished with plans: #{(p.toString() for p in @_plans).join('\n')}"
|
||||||
|
|
||||||
|
@trigger Event.change, this
|
||||||
|
@trigger 'scheduleNextWork'
|
||||||
return @complete
|
return @complete
|
||||||
|
|
||||||
reset: ->
|
reset: ->
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ module.exports = class InventoryNode extends CraftingNode
|
|||||||
@inventory.each (stack)=>
|
@inventory.each (stack)=>
|
||||||
item = @modPack.findItem stack.itemSlug
|
item = @modPack.findItem stack.itemSlug
|
||||||
if not item? then throw new Error "Could not find an item for slug: #{stack.itemSlug}"
|
if not item? then throw new Error "Could not find an item for slug: #{stack.itemSlug}"
|
||||||
result.push new ItemNode modPack:@modPack, item:item
|
result.push new ItemNode modPack:@modPack, item:item, ignoreGatherable:true
|
||||||
return result
|
return result
|
||||||
|
|
||||||
_checkCompleteness: ->
|
_checkCompleteness: ->
|
||||||
|
|||||||
@@ -17,21 +17,25 @@ module.exports = class ItemNode extends CraftingNode
|
|||||||
@::TYPE = CraftingNode::TYPES.ITEM
|
@::TYPE = CraftingNode::TYPES.ITEM
|
||||||
|
|
||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
if not options.item?
|
if not options.item? then throw new Error 'options.item is required'
|
||||||
throw new Error 'options.item is required'
|
|
||||||
super options
|
super options
|
||||||
|
|
||||||
@item = options.item
|
@item = options.item
|
||||||
|
@_ignoreGatherable = options.ignoreGatherable ?= false
|
||||||
@_recipes = null
|
@_recipes = null
|
||||||
|
|
||||||
# Property Methods #############################################################################
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
getRecipes: ->
|
getRecipes: ->
|
||||||
if not @_recipes?
|
if not @_recipes?
|
||||||
@_recipes = @modPack.findRecipes @item.slug
|
@_recipes = @modPack.findRecipes @item.slug, forCrafting:true, onlyPrimary:true
|
||||||
|
if not @_recipes
|
||||||
|
@_recipes = @modPack.findRecipes @item.slug, forCrafting:true
|
||||||
|
|
||||||
return @_recipes or []
|
return @_recipes or []
|
||||||
|
|
||||||
isGatherable: ->
|
isGatherable: ->
|
||||||
|
if not @_ignoreGatherable
|
||||||
return true if @item.isGatherable
|
return true if @item.isGatherable
|
||||||
return true if @getRecipes().length is 0
|
return true if @getRecipes().length is 0
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -17,8 +17,10 @@ module.exports = class PlanBuilder
|
|||||||
|
|
||||||
constructor: (rootNode, modPack, options={})->
|
constructor: (rootNode, modPack, options={})->
|
||||||
if not rootNode? then throw new Error 'rootNode is required'
|
if not rootNode? then throw new Error 'rootNode is required'
|
||||||
|
if not modPack? then throw new Error 'modPack is required'
|
||||||
|
|
||||||
@want = options.want
|
@want = options.want
|
||||||
|
@have = options.have
|
||||||
|
|
||||||
@_choiceNodes = []
|
@_choiceNodes = []
|
||||||
@_complete = false
|
@_complete = false
|
||||||
@@ -53,6 +55,10 @@ module.exports = class PlanBuilder
|
|||||||
complete:
|
complete:
|
||||||
get: -> @_complete
|
get: -> @_complete
|
||||||
|
|
||||||
|
have:
|
||||||
|
get: -> @_have
|
||||||
|
set: (have)-> @_have = have or new Inventory
|
||||||
|
|
||||||
maxPlanCount:
|
maxPlanCount:
|
||||||
get: -> @_maxPlanCount
|
get: -> @_maxPlanCount
|
||||||
set: (value)-> @_maxPlanCount = value
|
set: (value)-> @_maxPlanCount = value
|
||||||
@@ -95,7 +101,7 @@ module.exports = class PlanBuilder
|
|||||||
seenRecipes[recipeSlug] = true
|
seenRecipes[recipeSlug] = true
|
||||||
steps.push new CraftingStep node.recipe, @_modPack
|
steps.push new CraftingStep node.recipe, @_modPack
|
||||||
|
|
||||||
plan = new CraftingPlan steps, @_want, @_modPack
|
plan = new CraftingPlan @_modPack, @_want, @_have, steps
|
||||||
return plan
|
return plan
|
||||||
|
|
||||||
_incrementChoiceNodes: ->
|
_incrementChoiceNodes: ->
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ All rights reserved.
|
|||||||
###
|
###
|
||||||
|
|
||||||
CraftingNode = require './crafting_node'
|
CraftingNode = require './crafting_node'
|
||||||
|
Item = require '../item'
|
||||||
# ItemNode = require './item_node' # don't include here, causes a cycle
|
# ItemNode = require './item_node' # don't include here, causes a cycle
|
||||||
|
ItemSlug = require '../item_slug'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
@@ -29,6 +31,9 @@ module.exports = class RecipeNode extends CraftingNode
|
|||||||
|
|
||||||
for stack in @recipe.input
|
for stack in @recipe.input
|
||||||
item = @modPack.findItem stack.itemSlug
|
item = @modPack.findItem stack.itemSlug
|
||||||
|
if not item?
|
||||||
|
name = @modPack.findName stack.itemSlug
|
||||||
|
item = new Item name:name, slug:stack.itemSlug, gatherable:true
|
||||||
result.push new ItemNode modPack:@modPack, item:item
|
result.push new ItemNode modPack:@modPack, item:item
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -39,6 +44,7 @@ module.exports = class RecipeNode extends CraftingNode
|
|||||||
|
|
||||||
_checkValidity: ->
|
_checkValidity: ->
|
||||||
return false if @_isRepeatedRecipe()
|
return false if @_isRepeatedRecipe()
|
||||||
|
return false if @_requiresToolBeingMade()
|
||||||
|
|
||||||
for child in @children
|
for child in @children
|
||||||
return false unless child.valid
|
return false unless child.valid
|
||||||
@@ -55,6 +61,18 @@ module.exports = class RecipeNode extends CraftingNode
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
_requiresToolBeingMade: ->
|
||||||
|
for toolStack in @recipe.tools
|
||||||
|
toolSlug = toolStack.itemSlug
|
||||||
|
|
||||||
|
nextParent = @parent
|
||||||
|
while nextParent?
|
||||||
|
if ItemSlug.equal toolSlug, nextParent.item?.slug
|
||||||
|
return true
|
||||||
|
nextParent = nextParent.parent
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
# Object Overrides ############################################################################
|
# Object Overrides ############################################################################
|
||||||
|
|
||||||
toString: (options={})->
|
toString: (options={})->
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ module.exports = class ItemSlug
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
@equal: (a, b)->
|
@equal: (a, b)->
|
||||||
|
return true if not a? and not b?
|
||||||
|
return false unless a? and b?
|
||||||
return false unless a.mod is b.mod
|
return false unless a.mod is b.mod
|
||||||
return false unless a.item is b.item
|
return false unless a.item is b.item
|
||||||
return true
|
return true
|
||||||
@@ -56,6 +58,7 @@ module.exports = class ItemSlug
|
|||||||
return ItemSlug.compare this, that
|
return ItemSlug.compare this, that
|
||||||
|
|
||||||
matches: (slug, options={exact:false})->
|
matches: (slug, options={exact:false})->
|
||||||
|
return false unless slug?
|
||||||
return false unless typeof(slug.matches) is 'function'
|
return false unless typeof(slug.matches) is 'function'
|
||||||
|
|
||||||
if slug.isQualified and this.isQualified
|
if slug.isQualified and this.isQualified
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ module.exports = class ModVersion extends BaseModel
|
|||||||
|
|
||||||
findRecipes: (itemSlug, result=[], options={})->
|
findRecipes: (itemSlug, result=[], options={})->
|
||||||
options.onlyPrimary ?= false
|
options.onlyPrimary ?= false
|
||||||
|
options.forCrafting ?= false
|
||||||
|
|
||||||
primaryRecipes = []
|
primaryRecipes = []
|
||||||
otherRecipes = []
|
otherRecipes = []
|
||||||
@@ -146,6 +147,7 @@ module.exports = class ModVersion extends BaseModel
|
|||||||
for recipe in _.values @_recipes
|
for recipe in _.values @_recipes
|
||||||
continue unless recipe.isConditionSatisfied()
|
continue unless recipe.isConditionSatisfied()
|
||||||
continue unless recipe.hasAllTools()
|
continue unless recipe.hasAllTools()
|
||||||
|
continue if options.forCrafting and recipe.ignoreDuringCrafting
|
||||||
|
|
||||||
if recipe.itemSlug.matches itemSlug
|
if recipe.itemSlug.matches itemSlug
|
||||||
primaryRecipes.push recipe
|
primaryRecipes.push recipe
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
|||||||
@_recipeData = null
|
@_recipeData = null
|
||||||
|
|
||||||
_command_ignoreDuringCrafting: (value)->
|
_command_ignoreDuringCrafting: (value)->
|
||||||
if not @_itemData? then throw new Error 'cannot declare "ignoreDuringCraft" before "item"'
|
if not @_recipeData? then throw new Error 'cannot declare "ignoreDuringCrafting" before "recipe"'
|
||||||
if @_itemData.ignoreDuringCrafting? then throw new Error 'duplicate declaration of "ignoreDuringCraft"'
|
if @_recipeData.ignoreDuringCrafting? then throw new Error 'duplicate declaration of "ignoreDuringCrafting"'
|
||||||
if not (value in ['yes', 'no']) then throw new Error 'ignoreDuringCraft must be either "yes" or "no"'
|
if not (value in ['yes', 'no']) then throw new Error 'ignoreDuringCrafting must be either "yes" or "no"'
|
||||||
|
|
||||||
@_itemData.ignoreDuringCrafting = (value is 'yes')
|
@_recipeData.ignoreDuringCrafting = (value is 'yes')
|
||||||
|
|
||||||
_command_input: (inputNames...)->
|
_command_input: (inputNames...)->
|
||||||
if not @_recipeData? then throw new Error 'cannot declare "input" before "recipe"'
|
if not @_recipeData? then throw new Error 'cannot declare "input" before "recipe"'
|
||||||
@@ -183,6 +183,7 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
|||||||
|
|
||||||
recipe = new Recipe
|
recipe = new Recipe
|
||||||
condition: recipeData.condition
|
condition: recipeData.condition
|
||||||
|
ignoreDuringCrafting: recipeData.ignoreDuringCrafting
|
||||||
input: @_buildStackList modVersion, recipeData.input, recipeData.pattern
|
input: @_buildStackList modVersion, recipeData.input, recipeData.pattern
|
||||||
output: @_buildStackList modVersion, recipeData.output
|
output: @_buildStackList modVersion, recipeData.output
|
||||||
pattern: recipeData.pattern
|
pattern: recipeData.pattern
|
||||||
@@ -311,6 +312,7 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
|||||||
.push 'extras: '
|
.push 'extras: '
|
||||||
.call => @_unparseStackList builder, extraOutputs
|
.call => @_unparseStackList builder, extraOutputs
|
||||||
.line()
|
.line()
|
||||||
|
.onlyIf recipe.ignoreDuringCrafting, => builder.line 'ignoreDuringCrafting: yes'
|
||||||
.push 'input: '
|
.push 'input: '
|
||||||
.loop inputNames
|
.loop inputNames
|
||||||
.line()
|
.line()
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ module.exports = class Recipe extends BaseModel
|
|||||||
attributes.pattern = @_parsePattern attributes.pattern
|
attributes.pattern = @_parsePattern attributes.pattern
|
||||||
|
|
||||||
attributes.condition ?= null
|
attributes.condition ?= null
|
||||||
|
attributes.ignoreDuringCrafting ?= false
|
||||||
attributes.modVersion ?= null
|
attributes.modVersion ?= null
|
||||||
attributes.tools ?= []
|
attributes.tools ?= []
|
||||||
options.logEvents ?= false
|
options.logEvents ?= false
|
||||||
|
|||||||
@@ -108,8 +108,10 @@ module.exports = class SimpleInventory
|
|||||||
|
|
||||||
stack.quantity -= quantity
|
stack.quantity -= quantity
|
||||||
if stack.quantity is 0
|
if stack.quantity is 0
|
||||||
delete @_stacks[itemSlug]
|
for currentItemSlug, index in @_itemSlugs
|
||||||
@_itemSlugs = (s for s in @_itemSlugs when not ItemSlug.equal(s, itemSlug))
|
if ItemSlug.equal itemSlug, currentItemSlug
|
||||||
|
@_itemSlugs.splice index, 1
|
||||||
|
break
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,7 @@
|
|||||||
.panel
|
.panel
|
||||||
.view__inventory.large.editable
|
.view__inventory.large.editable
|
||||||
|
|
||||||
//- .tools.section.hideable.hidden
|
.view__craftsman_working.section
|
||||||
//- h2 Tools
|
|
||||||
//- .panel
|
|
||||||
//- .inUse
|
|
||||||
//- h3 In Use
|
|
||||||
//- .view__inventory.large
|
|
||||||
//-
|
|
||||||
//- .options
|
|
||||||
//- h3 More Options
|
|
||||||
//- .view__inventory.large
|
|
||||||
|
|
||||||
.ingredients.section.hideable.hidden
|
.ingredients.section.hideable.hidden
|
||||||
h2 Ingredients
|
h2 Ingredients
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//-
|
||||||
|
//- Crafting Guide - item_group.jade
|
||||||
|
//-
|
||||||
|
//- Copyright (c) 2015 by Redwood Labs
|
||||||
|
//- All rights reserved.
|
||||||
|
//-
|
||||||
|
|
||||||
|
.view__item_group.section.hideable.hidden
|
||||||
|
.content
|
||||||
|
.waiting
|
||||||
|
img(src='/images/wait.gif')
|
||||||
|
.message
|
||||||
|
p
|
||||||
|
.count
|
||||||
|
p
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Crafting Table - crafting_table.scss
|
||||||
|
|
||||||
|
Copyright (c) 2014-2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.view__craftsman_working .content {
|
||||||
|
align-items: center;
|
||||||
|
background: $color-white;
|
||||||
|
box-shadow: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 3em;
|
||||||
|
|
||||||
|
.waiting {
|
||||||
|
margin-bottom: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.count {
|
||||||
|
p {
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,9 @@ All rights reserved.
|
|||||||
@import 'adsense';
|
@import 'adsense';
|
||||||
@import 'browse_page';
|
@import 'browse_page';
|
||||||
@import 'crafting_grid';
|
@import 'crafting_grid';
|
||||||
@import 'craft_page';
|
|
||||||
@import 'crafting_table';
|
@import 'crafting_table';
|
||||||
|
@import 'craft_page';
|
||||||
|
@import 'craftsman_working';
|
||||||
@import 'feedback';
|
@import 'feedback';
|
||||||
@import 'full_recipe';
|
@import 'full_recipe';
|
||||||
@import 'home_page';
|
@import 'home_page';
|
||||||
@@ -27,8 +28,8 @@ All rights reserved.
|
|||||||
@import 'mod_pack';
|
@import 'mod_pack';
|
||||||
@import 'mod_page';
|
@import 'mod_page';
|
||||||
@import 'mod_selector';
|
@import 'mod_selector';
|
||||||
@import 'stack';
|
|
||||||
@import 'slot';
|
@import 'slot';
|
||||||
|
@import 'stack';
|
||||||
@import 'step';
|
@import 'step';
|
||||||
@import 'tutorial';
|
@import 'tutorial';
|
||||||
@import 'video';
|
@import 'video';
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ MOD_VERSION_FILE =
|
|||||||
"""
|
"""
|
||||||
schema: 1
|
schema: 1
|
||||||
|
|
||||||
|
item: Bed
|
||||||
|
recipe:
|
||||||
|
input: Oak Planks, Wool
|
||||||
|
pattern: ... 000 111
|
||||||
|
|
||||||
item: Charcoal
|
item: Charcoal
|
||||||
recipe:
|
recipe:
|
||||||
input: 8 Oak Wood, Coal
|
input: 8 Oak Wood, Coal
|
||||||
@@ -140,14 +145,15 @@ module.exports = fixtures =
|
|||||||
makePlans: (stacks...)->
|
makePlans: (stacks...)->
|
||||||
modPack = fixtures.makeModPack()
|
modPack = fixtures.makeModPack()
|
||||||
|
|
||||||
|
have = new Inventory
|
||||||
want = new Inventory
|
want = new Inventory
|
||||||
for stack in stacks
|
for stack in stacks
|
||||||
want.add ItemSlug.slugify(stack[1]), stack[0]
|
want.add ItemSlug.slugify(stack[1]), stack[0]
|
||||||
|
|
||||||
graphBuilder = new GraphBuilder modPack:fixtures.makeModPack(), want:want
|
graphBuilder = new GraphBuilder modPack:modPack, want:want
|
||||||
graphBuilder.expandGraph()
|
graphBuilder.expandGraph()
|
||||||
|
|
||||||
planBuilder = new PlanBuilder graphBuilder.rootNode, modPack, want:graphBuilder.want
|
planBuilder = new PlanBuilder graphBuilder.rootNode, modPack, want:want, have:have
|
||||||
return planBuilder.producePlans()
|
return planBuilder.producePlans()
|
||||||
|
|
||||||
makeTree: (itemSlug, quantity=1)->
|
makeTree: (itemSlug, quantity=1)->
|
||||||
|
|||||||
@@ -71,4 +71,7 @@ describe 'GraphBuilder.coffee', ->
|
|||||||
runSingleItemTreeBuildingTest 'test__copper_ingot', 6, 15
|
runSingleItemTreeBuildingTest 'test__copper_ingot', 6, 15
|
||||||
|
|
||||||
it 'an item which gatherable and craftable', ->
|
it 'an item which gatherable and craftable', ->
|
||||||
runSingleItemTreeBuildingTest 'test__wool', 2, 2
|
runSingleItemTreeBuildingTest 'test__wool', 4, 4
|
||||||
|
|
||||||
|
it 'an item which requires a gatherable and craftable item', ->
|
||||||
|
runSingleItemTreeBuildingTest 'test__bed', 6, 7
|
||||||
|
|||||||
@@ -52,9 +52,10 @@ describe 'plan_evaluator.coffee', ->
|
|||||||
beforeEach ->
|
beforeEach ->
|
||||||
modPack = fixtures.makeModPack()
|
modPack = fixtures.makeModPack()
|
||||||
wanted = new Inventory modPack:modPack
|
wanted = new Inventory modPack:modPack
|
||||||
planA = new CraftingPlan [], wanted, modPack
|
have = new Inventory modPack:modPack
|
||||||
planB = new CraftingPlan [], wanted, modPack
|
planA = new CraftingPlan modPack, wanted, have, []
|
||||||
planC = new CraftingPlan [], wanted, modPack
|
planB = new CraftingPlan modPack, wanted, have, []
|
||||||
|
planC = new CraftingPlan modPack, wanted, have, []
|
||||||
plans = [planA, planB, planC]
|
plans = [planA, planB, planC]
|
||||||
evaluator = new PlanEvaluator plans
|
evaluator = new PlanEvaluator plans
|
||||||
criteria = PlanEvaluator::CRITERIA.FEWEST_STEPS
|
criteria = PlanEvaluator::CRITERIA.FEWEST_STEPS
|
||||||
|
|||||||
Reference in New Issue
Block a user