This commit is contained in:
Andrew Miner
2015-10-31 13:21:14 -07:00
parent 74e95e614b
commit 4e95ab998f
28 changed files with 948 additions and 471 deletions
+45 -33
View File
@@ -18,44 +18,49 @@ describe 'crafting_plan.coffee', ->
plans.length.should.equal 1
plan = plans[0]
plan.required.unparse().should.equal 'coal'
plan.produced.unparse().should.equal 'coal'
plan.computeRequired()
plan.need.unparse().should.equal 'coal'
plan.made.unparse().should.equal 'coal'
it 'can compute a single item with one single step plan', ->
plans = fixtures.makePlans [1, 'test__charcoal']
plans.length.should.equal 1
plan = plans[0]
plan.required.unparse().should.equal 'coal:8.oak_wood'
plan.produced.unparse().should.equal '8.charcoal'
(s.toString() for s in plan.steps).should.eql ['1x 8 test__oak_wood,test__coal>>8 test__charcoal']
plan.computeRequired()
plan.need.unparse().should.equal 'coal:8.oak_wood'
plan.made.unparse().should.equal '8.charcoal'
(s.toString() for s in plan.steps).should.eql ['1x 8 test__oak_wood,test__coal>.0. ... .1.>>8 test__charcoal']
it 'can compute a large quantity of a single item with one single step plan', ->
plans = fixtures.makePlans [15, 'test__charcoal']
plans.length.should.equal 1
plan = plans[0]
plan.required.unparse().should.equal '2.coal:16.oak_wood'
plan.produced.unparse().should.equal '16.charcoal'
(s.toString() for s in plan.steps).should.eql ['2x 8 test__oak_wood,test__coal>>8 test__charcoal']
plan.computeRequired()
plan.need.unparse().should.equal '2.coal:16.oak_wood'
plan.made.unparse().should.equal '16.charcoal'
(s.toString() for s in plan.steps).should.eql ['2x 8 test__oak_wood,test__coal>.0. ... .1.>>8 test__charcoal']
it 'can compute a single item with multiple plans', ->
plans = fixtures.makePlans [1, 'test__iron_ingot']
plans.length.should.equal 2
plan = plans[0]
plan.required.unparse().should.equal 'coal:8.iron_ore:8.oak_wood'
plan.produced.unparse().should.equal '7.charcoal:8.iron_ingot'
plan.computeRequired()
plan.need.unparse().should.equal 'coal:8.iron_ore:8.oak_wood'
plan.made.unparse().should.equal '7.charcoal:8.iron_ingot'
(s.toString() for s in plan.steps).should.eql [
'1x 8 test__oak_wood,test__coal>>8 test__charcoal'
'1x 8 test__iron_ore,test__charcoal>test__furnace>8 test__iron_ingot'
'1x 8 test__oak_wood,test__coal>.0. ... .1.>>8 test__charcoal'
'1x 8 test__iron_ore,test__charcoal>.0. ... .1.>test__furnace>8 test__iron_ingot'
]
plan = plans[1]
plan.required.unparse().should.equal 'coal:8.iron_ore'
plan.produced.unparse().should.equal '8.iron_ingot'
plan.computeRequired()
plan.need.unparse().should.equal 'coal:8.iron_ore'
plan.made.unparse().should.equal '8.iron_ingot'
(s.toString() for s in plan.steps).should.eql [
'1x 8 test__iron_ore,test__coal>test__furnace>8 test__iron_ingot'
'1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot'
]
it 'can compute multiple items with multiple plans', ->
@@ -63,33 +68,40 @@ describe 'crafting_plan.coffee', ->
plans.length.should.equal 4
for plan in plans
plan.required.unparse().should.match /16.copper_ore.*8.iron_ore/
plan.produced.unparse().should.match /copper_block.*:iron_sword/
plan.computeRequired()
plan.need.unparse().should.match /16.copper_ore.*8.iron_ore/
plan.made.unparse().should.match /copper_block.*:iron_sword/
plan = plans[0]
plan.required.unparse().should.match /3.coal.*9.oak_wood/
plan.produced.unparse().should.match /7.charcoal/
"#{plan.steps[3]}".should.equal '1x 8 test__iron_ore,test__charcoal>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal '2x 8 test__copper_ore,test__coal>test__furnace>8 test__copper_ingot'
plan.need.unparse().should.match /3.coal.*9.oak_wood/
plan.made.unparse().should.match /7.charcoal/
"#{plan.steps[3]}".should.equal \
'1x 8 test__iron_ore,test__charcoal>.0. ... .1.>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal \
'2x 8 test__copper_ore,test__coal>.0. ... .1.>test__furnace>8 test__copper_ingot'
plan.steps.length.should.equal 7
plan = plans[1]
plan.required.unparse().should.match /3.coal.*:oak_wood/
plan.produced.unparse().should.not.match /charcoal/
"#{plan.steps[2]}".should.equal '1x 8 test__iron_ore,test__coal>test__furnace>8 test__iron_ingot'
"#{plan.steps[3]}".should.equal '2x 8 test__copper_ore,test__coal>test__furnace>8 test__copper_ingot'
plan.need.unparse().should.match /3.coal.*:oak_wood/
plan.made.unparse().should.not.match /charcoal/
"#{plan.steps[2]}".should.equal '1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot'
"#{plan.steps[3]}".should.equal \
'2x 8 test__copper_ore,test__coal>.0. ... .1.>test__furnace>8 test__copper_ingot'
plan.steps.length.should.equal 6
plan = plans[2]
plan.required.unparse().should.match /^coal.*9.oak_wood/
plan.produced.unparse().should.match /5.charcoal/
"#{plan.steps[3]}".should.equal '1x 8 test__iron_ore,test__charcoal>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal '2x 8 test__copper_ore,test__charcoal>test__furnace>8 test__copper_ingot'
plan.need.unparse().should.match /^coal.*9.oak_wood/
plan.made.unparse().should.match /5.charcoal/
"#{plan.steps[3]}".should.equal \
'1x 8 test__iron_ore,test__charcoal>.0. ... .1.>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal \
'2x 8 test__copper_ore,test__charcoal>.0. ... .1.>test__furnace>8 test__copper_ingot'
plan.steps.length.should.equal 7
plan = plans[3]
plan.required.unparse().should.match /2.coal.*9.oak_wood/
plan.produced.unparse().should.match /6.charcoal/
"#{plan.steps[3]}".should.equal '1x 8 test__iron_ore,test__coal>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal '2x 8 test__copper_ore,test__charcoal>test__furnace>8 test__copper_ingot'
plan.need.unparse().should.match /2.coal.*9.oak_wood/
plan.made.unparse().should.match /6.charcoal/
"#{plan.steps[3]}".should.equal '1x 8 test__iron_ore,test__coal>.0. ... .1.>test__furnace>8 test__iron_ingot'
"#{plan.steps[4]}".should.equal \
'2x 8 test__copper_ore,test__charcoal>.0. ... .1.>test__furnace>8 test__copper_ingot'
plan.steps.length.should.equal 7
+25 -6
View File
@@ -6,6 +6,7 @@ All rights reserved.
###
GraphBuilder = require '../../src/coffee/models/crafting/graph_builder'
Inventory = require '../../src/coffee/models/inventory'
ItemSlug = require '../../src/coffee/models/item_slug'
Mod = require '../../src/coffee/models/mod'
ModPack = require '../../src/coffee/models/mod_pack'
@@ -30,8 +31,10 @@ MOD_VERSION_FILE =
pattern: .00 .00 ...
item: Coal
gatherable: yes
item: Cobblestone
gatherable: yes
item: Copper Block
recipe:
@@ -56,6 +59,7 @@ MOD_VERSION_FILE =
quantity: 9
item: Copper Ore
gatherable: yes
item: Furnace
recipe:
@@ -64,6 +68,7 @@ MOD_VERSION_FILE =
tools: Crafting Table
item: Iron Ore
gatherable: yes
item: Iron Ingot
recipe:
@@ -95,12 +100,22 @@ MOD_VERSION_FILE =
quantity: 4
item: Oak Wood
gatherable: yes
item: Stick
recipe:
input: Oak Planks
pattern: .0. .0. ...
quantity: 4
item: String
gatherable: yes
item: Wool
gatherable: yes
recipe:
input: String
pattern: 00. 00. ...
"""
########################################################################################################################
@@ -108,7 +123,7 @@ MOD_VERSION_FILE =
module.exports = fixtures =
makeGraphBuilder: ->
return new GraphBuilder modPack:fixtures.makeModPack()
return new GraphBuilder modPack:fixtures.makeModPack(), want:new Inventory
makeModPack: ->
modPack = new ModPack
@@ -125,17 +140,21 @@ module.exports = fixtures =
makePlans: (stacks...)->
modPack = fixtures.makeModPack()
graphBuilder = fixtures.makeGraphBuilder()
want = new Inventory
for stack in stacks
graphBuilder.wanted.add ItemSlug.slugify(stack[1]), stack[0]
want.add ItemSlug.slugify(stack[1]), stack[0]
graphBuilder = new GraphBuilder modPack:fixtures.makeModPack(), want:want
graphBuilder.expandGraph()
planBuilder = new PlanBuilder graphBuilder.rootNode, wanted:graphBuilder.wanted
planBuilder = new PlanBuilder graphBuilder.rootNode, modPack, want:graphBuilder.want
return planBuilder.producePlans()
makeTree: (itemSlug, quantity=1)->
builder = fixtures.makeGraphBuilder()
builder.wanted.add ItemSlug.slugify itemSlug
want = new Inventory
want.add ItemSlug.slugify itemSlug
builder = new GraphBuilder modPack:fixtures.makeModPack(), want:want
builder.expandGraph()
return builder.rootNode
+6 -3
View File
@@ -22,7 +22,7 @@ describe 'GraphBuilder.coffee', ->
describe 'expand', ->
it 'can work a few steps at a time', ->
builder.wanted.add ItemSlug.slugify 'test__iron_sword'
builder.want.add ItemSlug.slugify 'test__iron_sword'
builder.expandGraph 9
builder.rootNode.depth.should.equal 6
@@ -45,7 +45,7 @@ describe 'GraphBuilder.coffee', ->
describe 'can build a tree for', ->
runSingleItemTreeBuildingTest = (slug, depth, size)->
builder.wanted.add ItemSlug.slugify slug
builder.want.add ItemSlug.slugify slug
builder.expandGraph 100
builder.rootNode.depth.should.equal depth
@@ -68,4 +68,7 @@ describe 'GraphBuilder.coffee', ->
runSingleItemTreeBuildingTest 'test__iron_sword', 8, 18
it 'an item with one recursive recipe', ->
runSingleItemTreeBuildingTest 'test__copper_ingot', 10, 24
runSingleItemTreeBuildingTest 'test__copper_ingot', 6, 15
it 'an item which gatherable and craftable', ->
runSingleItemTreeBuildingTest 'test__wool', 2, 2
+79
View File
@@ -0,0 +1,79 @@
###
Crafting Guide - plan_evaluator.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
CraftingPlan = require '../../src/coffee/models/crafting/crafting_plan'
fixtures = require './fixtures'
Inventory = require '../../src/coffee/models/inventory'
PlanEvaluator = require '../../src/coffee/models/crafting/plan_evaluator'
########################################################################################################################
criteria = evaluator = planA = planB = planC = plans = wanted = null
########################################################################################################################
describe 'plan_evaluator.coffee', ->
beforeEach ->
criteria = PlanEvaluator::CRITERIA.FEWEST_STEPS
describe 'findBestPlan', ->
it 'can find the shortest of two options', ->
evaluator = new PlanEvaluator fixtures.makePlans [1, 'test__copper_block']
evaluator.scorePlans()
bestPlan = evaluator.findBestPlan criteria
bestPlan.getScore(criteria).should.equal 1.0
it 'can find the shortest of many options', ->
evaluator = new PlanEvaluator fixtures.makePlans [1, 'test__copper_block'], [1, 'test__iron_sword']
evaluator.scorePlans()
bestPlan = evaluator.findBestPlan criteria
bestPlan.getScore(criteria).should.equal 1.0
it 'can break ties using the non-primary criteria', ->
evaluator = new PlanEvaluator fixtures.makePlans [2, 'test__iron_ingot'], [1, 'test__charcoal']
evaluator.scorePlans()
bestPlan = evaluator.findBestPlan criteria
bestPlan.getScore(criteria).should.equal 1.0
(p.getRawScore('fewest steps') for p in evaluator._plans).should.eql [2, 2]
(p.getRawScore('least materials') for p in evaluator._plans).should.eql [17, 18]
describe '_normalizeScores', ->
beforeEach ->
modPack = fixtures.makeModPack()
wanted = new Inventory modPack:modPack
planA = new CraftingPlan [], wanted, modPack
planB = new CraftingPlan [], wanted, modPack
planC = new CraftingPlan [], wanted, modPack
plans = [planA, planB, planC]
evaluator = new PlanEvaluator plans
criteria = PlanEvaluator::CRITERIA.FEWEST_STEPS
it 'does not set scores when none have been evaluated', ->
evaluator._normalizeScores()
(plan.hasRawScore(criteria) for plan in plans).should.eql [false, false, false]
it 'assigns a 1.0 when all plans equal', ->
for plan in plans
plan.setRawScore criteria, 5
evaluator._normalizeScores()
(plan.getScore(criteria) for plan in plans).should.eql [1.0, 1.0, 1.0]
it 'computes correct scores from raw scores', ->
planA.setRawScore criteria, 7
planB.setRawScore criteria, 8
planC.setRawScore criteria, 9
evaluator._normalizeScores()
(plan.getScore(criteria) for plan in plans).should.eql [1.0, 0.5, 0.0]