Merge branch 'andrewminer-item-detail-file'

This commit is contained in:
Andrew Miner
2015-03-10 08:47:34 -07:00
7344 changed files with 232437 additions and 196219 deletions
@@ -11,6 +11,7 @@ exports.DefaultMods = [
'applied_energistics_2',
'buildcraft',
'enderio',
'ic2_classic',
'industrial_craft_2',
'railcraft',
'thermal_expansion',
@@ -53,17 +54,17 @@ ModelState.loaded = 'loaded'
ModelState.failed = 'failed'
exports.Text = Text = {}
Text.title = 'Crafting Guide for Minecraft | The Ultimate Step-by-Step Tutorial for Making Anything in Minecraft'
Text.title = 'The Ultimate Minecraft Crafting Guide'
exports.Url = Url = {}
Url.crafting = _.template "/craft/<%= inventoryText %>"
Url.itemIcon = _.template "/data/<%= modSlug %>/<%= modVersion %>/images/<%= itemSlug %>.png"
Url.item = _.template "/browse/<%= modSlug %>/<%= itemSlug %>/"
Url.mod = _.template "/browse/<%= modSlug %>/"
Url.modData = _.template "/data/<%= modSlug %>/mod.cg"
Url.modLogo = _.template "/data/<%= modSlug %>/logo.png"
Url.modVersion = _.template "/data/<%= modSlug %>/<%= modVersion %>/mod-version.cg"
Url.modLogoImage = _.template "/data/<%= modSlug %>/logo.png"
exports.Url = Url = {}
Url.crafting = _.template "/craft/<%= inventoryText %>"
Url.item = _.template "/browse/<%= modSlug %>/<%= itemSlug %>/"
Url.itemData = _.template "/browse/<%= modSlug %>/<%= itemSlug %>/item.cg"
Url.itemIcon = _.template "/browse/<%= modSlug %>/<%= itemSlug %>/icon.png"
Url.mod = _.template "/browse/<%= modSlug %>/"
Url.modData = _.template "/data/<%= modSlug %>/mod.cg"
Url.modIcon = _.template "/browse/<%= modSlug %>/icon.png"
Url.modVersionData = _.template "/data/<%= modSlug %>/<%= modVersion %>/mod-version.cg"
exports.UrlParam = UrlParam = {}
UrlParam.quantity = 'count'
@@ -18,8 +18,8 @@ module.exports = class ItemController extends BaseController
options.templateName = 'item'
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@imageLoader = options.imageLoader
@modPack = options.modPack
# BaseController Overrides #####################################################################
@@ -30,9 +30,9 @@ module.exports = class ItemController extends BaseController
super
refresh: ->
display = @_modPack.findItemDisplay @model.slug
display = @modPack.findItemDisplay @model.slug
@_imageLoader.load display.iconUrl, @$icon
@imageLoader.load display.iconUrl, @$icon
@$name.html display.itemName
@$nameLink.attr 'href', display.itemUrl
@@ -76,7 +76,6 @@ module.exports = class ItemGroupController extends BaseController
delay += @_delayStep
else
controller.model = item
controller.refresh()
controllerIndex += 1
while @_itemControllers.length > controllerIndex
@@ -57,15 +57,17 @@ module.exports = class ItemPageController extends PageController
imageLoader: @imageLoader
modPack: @modPack
@$usedAsToolToMakeSection = @$('.usedAsToolToMake')
@$byline = @$('.byline')
@$bylineLink = @$('.byline a')
@$craftingPlanLink = @$('a.craftingPlan')
@$descriptionPanel = @$('.description .panel')
@$descriptionSection = @$('.description')
@$name = @$('h1.name')
@$recipeContainer = @$('.recipes .panel')
@$recipesSection = @$('.recipes')
@$similarSection = @$('.similar')
@$titleImage = @$('.titleImage img')
@$usedAsToolToMakeSection = @$('.usedAsToolToMake')
@$usedToMakeSection = @$('.usedToMake')
super
@@ -84,6 +86,7 @@ module.exports = class ItemPageController extends PageController
@$el.slideUp duration:Duration.normal
@_refreshByline()
@_refreshDescription()
@_refreshRecipes()
@_refreshSimilarItems()
@_refreshUsedAsToolToMake()
@@ -100,15 +103,6 @@ module.exports = class ItemPageController extends PageController
# Private Methods ##############################################################################
_refreshUsedAsToolToMake: ->
@_usedAsToolToMakeController.title = 'Used as Tool to Make'
@_usedAsToolToMakeController.model = @model.findToolForRecipes()
if @_usedAsToolToMakeController.model?
@$usedAsToolToMakeSection.slideDown duration:Duration.normal
else
@$usedAsToolToMakeSection.slideUp duration:Duration.normal
_refreshByline: ->
mod = @model.item?.modVersion?.mod
if mod?.name?.length > 0
@@ -118,14 +112,15 @@ module.exports = class ItemPageController extends PageController
else
@$byline.fadeOut duration:Duration.fast
_refreshUsedToMake: ->
@_usedToMakeController.title = 'Used to Make'
@_usedToMakeController.model = @model.findComponentInItems()
if @_usedToMakeController.model?
@$usedToMakeSection.slideDown duration:Duration.normal
_refreshDescription: ->
logger.debug "refreshing description"
logger.debug "item.description: #{@model?.item?.description}"
description = @model.compileDescription()
if description?
@$descriptionPanel.html description
@$descriptionSection.slideDown duration:Duration.normal
else
@$usedToMakeSection.slideUp duration:Duration.normal
@$descriptionSection.slideUp duration:Duration.normal
_refreshRecipes: ->
@_recipeControllers ?= []
@@ -165,10 +160,35 @@ module.exports = class ItemPageController extends PageController
else
@$similarSection.slideUp duration:Duration.normal
_resolveItemSlug: ->
item = @modPack.findItem @_itemSlug, includeDisabled:false
if item? and not ItemSlug.equal item.slug, @_itemSlug
router.navigate Url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
return
_refreshUsedAsToolToMake: ->
@_usedAsToolToMakeController.title = 'Used as Tool to Make'
@model.item = item
@_usedAsToolToMakeController.model = @model.findToolForRecipes()
if @_usedAsToolToMakeController.model?
@$usedAsToolToMakeSection.slideDown duration:Duration.normal
else
@$usedAsToolToMakeSection.slideUp duration:Duration.normal
_refreshUsedToMake: ->
@_usedToMakeController.title = 'Used to Make'
@_usedToMakeController.model = @model.findComponentInItems()
if @_usedToMakeController.model?
@$usedToMakeSection.slideDown duration:Duration.normal
else
@$usedToMakeSection.slideUp duration:Duration.normal
_resolveItemSlug: ->
return if @model.item?
item = @modPack.findItem @_itemSlug, includeDisabled:false
if item?
if not ItemSlug.equal item.slug, @_itemSlug
router.navigate Url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
return
@model.item = item
item.fetch()
item.on Event.sync, =>
logger.debug "item loaded"
@refresh()
@@ -30,7 +30,7 @@ module.exports = class ModController extends BaseController
@$el.removeClass 'empty'
@$link.attr 'href', Url.mod modSlug:@model.slug
@$logo.attr 'src', Url.modLogo modSlug:@model.slug
@$logo.attr 'src', Url.modIcon modSlug:@model.slug
@$name.html @model.name
@$description.html @model.description
else
@@ -68,7 +68,7 @@ module.exports = class ModPageController extends PageController
if @model?
@$name.html @model.name
@$byline.html "by #{@model.author}"
@$titleImage.attr 'src', Url.modLogoImage modSlug:@model.slug
@$titleImage.attr 'src', Url.modIcon modSlug:@model.slug
@$description.html @model.description
@$el.slideDown duration:Duration.normal
@@ -185,7 +185,7 @@ module.exports = class Inventory extends BaseModel
stack = @_stacks[itemSlug]
if not stack?
stack = new Stack itemSlug:itemSlug, quantity:quantity
@listenTo stack, Event.change, => @trigger Event.change
@listenTo stack, Event.change, => @trigger Event.change, stack
@_stacks[itemSlug] = stack
@_itemSlugs.push itemSlug
@_sort()
@@ -10,6 +10,7 @@ BaseModel = require './base_model'
ItemSlug = require './item_slug'
Recipe = require './recipe'
StringBuilder = require './string_builder'
{Url} = require '../constants'
########################################################################################################################
@@ -20,10 +21,13 @@ module.exports = class Item extends BaseModel
constructor: (attributes={}, options={})->
if not attributes.name? then throw new Error 'attributes.name is required'
attributes.description ?= null
attributes.group ?= Item.Group.Other
attributes.isGatherable ?= false
attributes.modVersion ?= null
attributes.officialUrl ?= null
attributes.slug ?= ItemSlug.slugify attributes.name
attributes.videos ?= []
options.logEvents ?= false
super attributes, options
@@ -54,6 +58,18 @@ module.exports = class Item extends BaseModel
Object.defineProperties @prototype,
isCraftable: {get:@prototype.getIsCraftable}
# Backbone.Model Overrides #####################################################################
parse: (text)->
ItemParser = require './item_parser' # to avoid require cycles
@_parser ?= new ItemParser model:this
@_parser.parse text
return null # prevent calling `set`
url: ->
return Url.itemData modSlug:@slug.mod, itemSlug:@slug.item
# Object Overrides #############################################################################
toString: ->
@@ -20,6 +20,10 @@ module.exports = class ItemPage extends BaseModel
# Property Methods #############################################################################
compileDescription: ->
return null unless @item?.description?
return markdown.parse @item.description
findComponentInItems: ->
return @_findRecipesMatching (recipe)=> recipe.requires @item.slug
+19
View File
@@ -0,0 +1,19 @@
###
Crafting Guide - item_parser.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
VersionedParserBase = require './versioned_parser_base'
ItemParserV1 = require './parser_versions/item_parser_v1'
########################################################################################################################
module.exports = class ItemParser extends VersionedParserBase
# VersionedParserBase Overrides ################################################################
_createParsers: (options)->
return result =
'1': new ItemParserV1 options
@@ -171,7 +171,7 @@ module.exports = class ModVersion extends BaseModel
return null # prevent calling `set`
url: ->
return Url.modVersion modSlug:@modSlug, modVersion:@version
return Url.modVersionData modSlug:@modSlug, modVersion:@version
# Object Overrides #############################################################################
@@ -39,10 +39,11 @@ module.exports = class CommandParserVersionBase
@_rawData = {}
@_lineNumber = 1
lines = text.split '\n'
for i in [0...lines.length]
@_lineNumber = i + 1
commands = @_parseLine lines[i]
@_lines = text.split '\n'
@_lineNumber = 0
while @_lineNumber < @_lines.length
@_lineNumber += 1
commands = @_parseLine @_lines[@_lineNumber - 1]
for command in commands
@_handleErrors @_execute, command
@@ -77,6 +78,8 @@ module.exports = class CommandParserVersionBase
line = line.trim()
return [] if line.length is 0
[line, hereDoc] = @_parseHereDoc line
lineParts = (part.trim() for part in line.split(';'))
commands = []
for linePart in lineParts
@@ -86,7 +89,10 @@ module.exports = class CommandParserVersionBase
if not match? then throw new Error "Expected <command>: <args>, but found: \"#{linePart}\""
args = []
args = (s.trim() for s in match[2].split(',')) if match[2]?
args = (s for s in match[2].split(',') when s.length > 0) if match[2]?
args = (s.trim() for s in args)
args = (s for s in args when s.length > 0)
args.push hereDoc if hereDoc?
commands.push name:match[1], args:args
return commands
@@ -100,3 +106,29 @@ module.exports = class CommandParserVersionBase
e.message = "line #{@_lineNumber}: #{e.message}"
if not @_showAllErrors then throw e
logger.error -> e.message
_parseHereDoc: (line)->
hereDocIndex = line.indexOf '<<-'
return [line, null] unless hereDocIndex isnt -1
hereDocStopText = line[hereDocIndex+3...line.length]
line = line[0...hereDocIndex]
hereDocLines = []
while true
@_lineNumber += 1
break if @_lineNumber >= @_lines.length
nextLine = @_lines[@_lineNumber-1]
break if nextLine.trim() is hereDocStopText
hereDocLines.push nextLine
shortestIndent = Number.MAX_VALUE
for hereDocLine in hereDocLines
shortestIndent = Math.min hereDocLine.match(/( *).*/)[1].length, shortestIndent
for i in [0...hereDocLines.length]
hereDocLines[i] = hereDocLines[i][shortestIndent..]
return [line, null] unless hereDocLines.length > 0
return [line, hereDocLines.join('\n')]
@@ -0,0 +1,46 @@
###
Crafting Guide - item_parser_v1.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
CommandParserVersionBase = require './command_parser_version_base'
########################################################################################################################
module.exports = class ItemParserV1 extends CommandParserVersionBase
# CommandParserVersionBase Overrides ###########################################################
_buildModel: (rawData, model)->
@_buildItem rawData, model
_unparseModel: (builder, model)->
@_unparseItem builder, model
# Command Methods ##############################################################################
_command_description: (textParts...)->
@_rawData.description ?= ''
@_rawData.description += textParts.join ', '
_command_officialUrl: (officialUrl)->
if @_rawData.officialUrl? then throw new Error 'duplicate declaration of "officialUrl"'
if officialUrl.length is 0 then throw new Error 'officialUrl cannot be empty'
@_rawData.officialUrl = officialUrl
_command_video: (youTubeId, nameParts...)->
if not youTubeId?.length then throw new Error 'video declaration requires a YouTubeID'
name = nameParts.join ', '
if not name?.length then throw new Error 'video declaration requires a name'
@_rawData.videos ?= []
@_rawData.videos.push youTubeId:youTubeId, name:name
# Object Building Methods ######################################################################
_buildItem: (rawData, model)->
model.description = rawData.description if rawData.description
model.officialUrl = rawData.officialUrl if rawData.officialUrl
model.videos = rawData.videos if rawData.videos
@@ -11,7 +11,7 @@ ModVersion = require '../mod_version'
########################################################################################################################
module.exports = class ModParserV2 extends CommandParserVersionBase
module.exports = class ModParserV1 extends CommandParserVersionBase
# CommandParserVersionBase Overrides ###########################################################
+84
View File
@@ -0,0 +1,84 @@
###
Crafting Guide - crafting_plan.test.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
CraftingPlan = require '../models/crafting_plan'
ItemSlug = require '../models/item_slug'
Mod = require '../models/mod'
ModPack = require '../models/mod_pack'
ModVersion = require '../models/mod_version'
########################################################################################################################
modPack = plan = null
########################################################################################################################
describe 'crafting_plan.coffee', ->
beforeEach ->
mod = new Mod name:'Minecraft', slug:'minecraft'
mod.addModVersion new ModVersion modSlug:mod.slug, version:'1.7.10'
mod.activeModVersion.parse """
schema:1
item:Oak Plank; recipe:; input:Oak Log; pattern:... .0. ...; quantity:4
item:Stick; recipe:; input:Oak Plank; pattern:... .0. .0.; quantity:4
item:Crafting Table; recipe:; input:Oak Plank; pattern:00. 00. ...
item:Furnace; recipe:; input:Cobblestone; pattern:000 0.0 000; tools:Crafting Table
item:Iron Ingot; recipe:; input:Iron Ore, furnace fuel; pattern:.0. ... .1.; tools:Furnace
item:Iron Sword; recipe:; input:Iron Ingot, Stick; pattern:.0. .0. .1.; tools:Crafting Table
"""
modPack = new ModPack
modPack.addMod mod
plan = new CraftingPlan modPack:modPack, includingTools:false
describe 'craft', ->
describe 'under the simplest conditions', ->
it 'can craft a single step recipe', ->
plan.want.add ItemSlug.slugify 'oak_plank'
plan.craft()
plan.need.unparse().should.equal 'oak_log'
plan.result.unparse().should.equal '4.oak_plank'
it 'can craft a multi-step recipe', ->
plan.want.add ItemSlug.slugify 'crafting_table'
plan.craft()
plan.need.unparse().should.equal 'oak_log'
plan.result.unparse().should.equal 'crafting_table'
it 'can craft a multi-step recipe using tools', ->
plan.want.add ItemSlug.slugify 'furnace'
plan.craft()
plan.need.unparse().should.equal '8.cobblestone'
plan.result.unparse().should.equal 'furnace'
it 'can craft a multi-step recipe re-using tools', ->
plan.want.add ItemSlug.slugify 'iron_sword'
plan.craft()
plan.need.unparse().should.equal '2.furnace_fuel:2.iron_ore:oak_log'
plan.result.unparse().should.equal 'iron_sword:2.oak_plank:3.stick'
describe 'with building tools', ->
it 'can craft a multi-step recipe using tools', ->
plan.includingTools = true
plan.want.add ItemSlug.slugify 'furnace'
plan.craft()
plan.need.unparse().should.equal '8.cobblestone:oak_log'
plan.result.unparse().should.equal 'crafting_table:furnace'
it 'can craft a multi-step recipe re-using tools', ->
plan.includingTools = true
plan.want.add ItemSlug.slugify 'iron_sword'
plan.craft()
plan.need.unparse().should.eql '8.cobblestone:2.furnace_fuel:2.iron_ore:2.oak_log'
plan.result.unparse().should.equal 'crafting_table:furnace:' +
'iron_sword:2.oak_plank:3.stick'
+28
View File
@@ -0,0 +1,28 @@
###
# Crafting Guide - event_recorder.coffee
#
# Copyright (c) 2014-2015 by Redwood Labs
# All rights reserved.
###
util = require 'util'
########################################################################################################################
module.exports = class EventRecorder
constructor: (model)->
if not model? then throw new Error 'model is required'
@model = model
@events = []
Object.defineProperty this, 'names', get:-> e.event for e in @events
@model.on 'all', (event, model, args...)=>
logger.verbose -> "#{model?.constructor?.name}(#{model?.cid}) emitted #{event}
with args: #{util.inspect(args)}"
@events.push id:model?.cid, event:event, args:args
reset: ->
@events = []
+211
View File
@@ -0,0 +1,211 @@
###
# Crafting Guide - inventory.test.coffee
#
# Copyright (c) 2014-2015 by Redwood Labs
# All rights reserved.
###
{Event} = require '../constants'
EventRecorder = require './event_recorder'
Inventory = require '../models/inventory'
Item = require '../models/item'
ItemSlug = require '../models/item_slug'
########################################################################################################################
inventory = modPack = null
########################################################################################################################
describe 'inventory.coffee', ->
beforeEach ->
inventory = new Inventory {}, silent:false
inventory.add ItemSlug.slugify('wool'), 4
inventory.add ItemSlug.slugify('string'), 20
inventory.add ItemSlug.slugify('boat')
describe 'add', ->
it 'can add to an empty inventory', ->
inventory.add ItemSlug.slugify('iron_ingot'), 4
stack = inventory._stacks['iron_ingot']
stack.constructor.name.should.equal 'Stack'
stack.itemSlug.qualified.should.equal 'iron_ingot'
stack.quantity.should.equal 4
it 'can augment quantity of existing items', ->
inventory.add ItemSlug.slugify('wool'), 2
inventory.unparse().should.equal 'boat:20.string:6.wool'
it 'can add zero quantity', ->
inventory.add ItemSlug.slugify('wool'), 0
inventory.unparse().should.equal 'boat:20.string:4.wool'
it 'emits the proper events', ->
events = new EventRecorder inventory
inventory.add ItemSlug.slugify('iron_ingot'), 10
events.names.should.eql [Event.add, Event.change]
describe 'addInventory', ->
it 'can add to an empty inventory', ->
newInventory = new Inventory
newInventory.addInventory inventory
newInventory.unparse().should.equal 'boat:20.string:4.wool'
it 'can add a mix of new and existing items', ->
newInventory = new Inventory
newInventory.add ItemSlug.slugify('string'), 2
newInventory.addInventory inventory
newInventory.unparse().should.equal 'boat:22.string:4.wool'
describe 'clone', ->
it 'creates an empty inventory from an empty inventory', ->
a = new Inventory
b = a.clone()
b._itemSlugs.should.eql []
it 'faithfully copies an existing inventory', ->
copy = inventory.clone()
copy.unparse().should.equal 'boat:20.string:4.wool'
describe 'each', ->
it 'works with an empty inventory', ->
inventory = new Inventory
result = []
inventory.each (item)-> result.push item.name
result.should.eql []
it 'works when items have only been added', ->
result = []
inventory.each (stack)-> result.push stack.itemSlug.qualified
result.should.eql ['boat', 'string', 'wool']
it 'works when items have been augmented', ->
inventory.add ItemSlug.slugify 'iron_ingot'
inventory.add ItemSlug.slugify 'boat'
inventory.add ItemSlug.slugify('wool'), 2
result = []
inventory.each (stack)-> result.push stack.itemSlug.qualified
result.should.eql ['boat', 'iron_ingot', 'string', 'wool']
describe 'hasAtLeast', ->
it 'works when the item is completely absent', ->
answer = inventory.hasAtLeast 'chicken', 1
answer.should.be.false
it 'always returns true for zero quantity', ->
inventory.hasAtLeast('chicken', 0).should.be.true
inventory.hasAtLeast('wool', 0).should.be.true
it 'works for a quantity above 1', ->
inventory.hasAtLeast('wool', 3).should.be.true
inventory.hasAtLeast('wool', 4).should.be.true
inventory.hasAtLeast('wool', 5).should.be.false
describe 'localize', ->
before ->
modPack =
modSlug:
wool: 'minecraft'
string: 'minecraft'
boat: 'minecraft'
stone_gear: 'buildcraft'
findItem: (slug)->
return slug:new ItemSlug @modSlug[slug.item], slug.item
it 'replaces item slugs with qualified slugs', ->
inventory.add ItemSlug.slugify 'stone_gear'
inventory.modPack = modPack
inventory.localize()
slugs = []
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
slugs.should.eql [
'minecraft__boat'
'minecraft__string'
'minecraft__wool'
'buildcraft__stone_gear'
]
it 'ignores qualified slugs', ->
inventory.add ItemSlug.slugify 'buildcraft__stone_gear'
inventory.modPack = modPack
inventory.localize()
slugs = []
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
slugs.should.eql [
'minecraft__boat'
'minecraft__string'
'minecraft__wool'
'buildcraft__stone_gear'
]
describe 'parse', ->
beforeEach ->
inventory = new Inventory {}, silent:false
it 'ignores an empty string', ->
result = inventory.parse ''
result.unparse().should.eql ''
it 'can parse a single item without quantity', ->
result = inventory.parse 'wool'
result.unparse().should.equal 'wool'
it 'can parse a single item with quantity', ->
result = inventory.parse '4.wool'
result.unparse().should.equal '4.wool'
it 'can parse multiple mixed-type items', ->
result = inventory.parse '4.wool:10.string:boat'
result.unparse().should.equal 'boat:10.string:4.wool'
describe 'pop', ->
it 'returns null for an empty inventory', ->
inventory = new Inventory
result = inventory.pop()
expect(result).to.be.null
it 'completely removes the last item', ->
stack = inventory.pop()
stack.itemSlug.qualified.should.equal 'wool'
stack.quantity.should.equal 4
inventory.unparse().should.equal 'boat:20.string'
it 'triggers the right events', ->
events = new EventRecorder inventory
result = inventory.pop()
events.names.should.eql [Event.remove, Event.change]
describe 'remove', ->
it 'throws when the item is absent', ->
expect(-> inventory.remove('chicken')).to.throw Error,
'cannot remove chicken since it is not in this inventory'
it 'throws when the item has insufficient quantity', ->
expect(-> inventory.remove('wool', 10)).to.throw Error,
'cannot remove 10: only 4 wool in this inventory'
it 'removes all items by default', ->
inventory.remove 'wool'
expect(inventory._stacks.wool).to.be.empty
it 'removes a quantity above 1', ->
inventory.remove 'wool', 3
inventory._stacks.wool.quantity.should.equal 1
it 'emits the proper events', ->
events = new EventRecorder inventory
inventory.remove 'wool'
events.names.should.eql [Event.change, Event.remove, Event.change]
+136
View File
@@ -0,0 +1,136 @@
###
Crafting Guide - item_slug.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
ItemSlug = require '../models/item_slug'
########################################################################################################################
describe 'item_slug.coffee', ->
describe 'constructor', ->
it 'can handle one argument', ->
slug = new ItemSlug 'alpha'
slug.item.should.equal 'alpha'
expect(slug.mod).to.be.null
slug.qualified.should.equal 'alpha'
it 'can handle two arguments', ->
slug = new ItemSlug 'alpha', 'bravo'
slug.mod.should.equal 'alpha'
slug.item.should.equal 'bravo'
slug.qualified.should.equal 'alpha__bravo'
it 'throws with zero arguments', ->
f = -> new ItemSlug
expect(f).to.throw Error, 'expected arguments to be "modSlug, itemSlug" or just "itemSlug"'
it 'throws with more arguments', ->
f = -> new ItemSlug 'alpha', 'bravo', 'charlie'
expect(f).to.throw Error, 'expected arguments to be "modSlug, itemSlug" or just "itemSlug"'
describe 'ItemSlug.compare', ->
it 'sorts qualified slugs first', ->
a = new ItemSlug 'alpha'
b = new ItemSlug 'bravo', 'charlie'
ItemSlug.compare(a, b).should.equal +1
ItemSlug.compare(b, a).should.equal -1
it 'sorts by mod when both are qualified', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'charlie', 'delta'
ItemSlug.compare(a, b).should.equal -1
ItemSlug.compare(b, a).should.equal +1
it 'sorts by item when both are qualified in the same mod', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'charlie', 'bravo'
ItemSlug.compare(a, b).should.equal -1
ItemSlug.compare(b, a).should.equal +1
it 'sorts by item when not qualified', ->
a = new ItemSlug 'alpha'
b = new ItemSlug 'bravo'
ItemSlug.compare(a, b).should.equal -1
ItemSlug.compare(b, a).should.equal +1
describe 'ItemSlug.equal', ->
it 'requires both to have the same mod', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'alpha', 'charlie'
c = new ItemSlug 'alpha', 'bravo'
ItemSlug.equal(a, b).should.be.false
ItemSlug.equal(a, c).should.be.true
it 'requires both to have the same item', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'alpha', 'charlie'
c = new ItemSlug 'alpha', 'bravo'
ItemSlug.equal(a, b).should.be.false
ItemSlug.equal(a, c).should.be.true
describe 'ItemSlug.slugify', ->
it 'can slugify a pure name', ->
slug = ItemSlug.slugify 'Alpha Bravo (Charlie)'
slug.item.should.equal 'alpha_bravo_charlie'
expect(slug.mod).to.be.null
it 'can slugify a simple item slug', ->
slug = ItemSlug.slugify 'alpha_bravo_charlie'
slug.item.should.equal 'alpha_bravo_charlie'
expect(slug.mod).to.be.null
it 'can slugify a fully-qualified slug', ->
slug = ItemSlug.slugify 'alpha_bravo__charlie_delta'
slug.mod.should.equal 'alpha_bravo'
slug.item.should.equal 'charlie_delta'
describe 'matches', ->
it 'ignores mod when either is unqualified', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'bravo'
c = new ItemSlug 'charlie'
a.matches(b).should.be.true
a.matches(c).should.be.false
it 'observes differences in mod when all are qualified', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'charlie', 'bravo'
c = new ItemSlug 'delta', 'echo'
d = new ItemSlug 'alpha', 'bravo'
a.matches(b).should.be.false
a.matches(c).should.be.false
a.matches(d).should.be.true
describe 'isQualified', ->
it 'returns true only when the mod slug is set', ->
a = new ItemSlug 'alpha', 'bravo'
b = new ItemSlug 'charlie'
a.isQualified.should.be.true
b.isQualified.should.be.false
describe '[]', ->
it 'allows slugs as a key', ->
slug = new ItemSlug 'alpha', 'bravo'
data = {}
data[slug] = 'foo'
data['alpha__bravo'].should.equal 'foo'
data[slug].should.equal 'foo'
+30
View File
@@ -0,0 +1,30 @@
###
Crafting Guide - mod.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
Mod = require '../models/mod'
########################################################################################################################
mod = null
########################################################################################################################
describe 'mod.coffee', ->
beforeEach -> mod = new Mod name:'Test', slug:'test'
describe 'compareTo', ->
it 'lists required mods first', ->
minecraft = new Mod name:'Minecraft', slug:'minecraft'
mod.compareTo(minecraft).should.equal +1
minecraft.compareTo(mod).should.equal -1
it 'sorts by name second', ->
buildcraft = new Mod name:'Buildcraft', slug:'buildcraft'
mod.compareTo(buildcraft).should.equal +1
buildcraft.compareTo(mod).should.equal -1
+103
View File
@@ -0,0 +1,103 @@
###
Crafting Guide - mod_pack.test.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
Item = require '../models/item'
ItemSlug = require '../models/item_slug'
Mod = require '../models/mod'
ModPack = require '../models/mod_pack'
ModVersion = require '../models/mod_version'
########################################################################################################################
buildcraft = industrialCraft = minecraft = modPack = null
########################################################################################################################
describe 'mod_pack.coffee', ->
beforeEach ->
minecraft = new Mod slug:'minecraft', name:'Minecraft'
minecraft.addModVersion new ModVersion modSlug:minecraft.slug, version:'1.7.10'
minecraft.activeModVersion.addItem new Item name:'Wool'
minecraft.activeModVersion.addItem new Item name:'Bed', recipes:['']
minecraft.activeModVersion.registerName ItemSlug.slugify('iron_chestplate'), 'Iron Chestplate'
buildcraft = new Mod slug:'buildcraft', name:'Buildcraft'
buildcraft.addModVersion new ModVersion modSlug:buildcraft.slug, version:'6.2.6'
buildcraft.activeModVersion.addItem new Item name:'Stone Gear', recipes:['']
buildcraft.activeModVersion.addItem new Item name:'Wrench', recipes:['']
buildcraft.activeVersion = Mod.Version.None
industrialCraft = new Mod slug:'industrial_craft', name:'Industrial Craft'
industrialCraft.addModVersion new ModVersion modSlug:industrialCraft.slug, version:'2.0'
industrialCraft.activeModVersion.addItem new Item name:'Resin'
industrialCraft.activeModVersion.addItem new Item name:'Rubber'
industrialCraft.activeModVersion.addItem new Item name:'Wrench', recipes:['']
industrialCraft.activeVersion = Mod.Version.None
modPack = new ModPack
modPack.addMod minecraft
modPack.addMod buildcraft
modPack.addMod industrialCraft
describe 'findItem', ->
it 'can find an item by partial slug', ->
item = modPack.findItem ItemSlug.slugify 'wool'
item.slug.qualified.should.equal 'minecraft__wool'
it 'can find an item by full slug', ->
item = modPack.findItem ItemSlug.slugify 'minecraft__wool'
item.name.should.equal 'Wool'
it 'can find an ambiguous item by full slug', ->
buildcraft.activeVersion = Mod.Version.Latest
industrialCraft.activeVersion = Mod.Version.Latest
item = modPack.findItem ItemSlug.slugify 'industrial_craft__wrench'
item.name.should.equal 'Wrench'
item.modVersion.mod.name.should.equal 'Industrial Craft'
it 'can find an ambiguous item by partial slug', ->
buildcraft.activeVersion = Mod.Version.Latest
industrialCraft.activeVersion = Mod.Version.Latest
item = modPack.findItem ItemSlug.slugify 'wrench'
item.name.should.equal 'Wrench'
item.modVersion.mod.name.should.equal 'Buildcraft'
describe 'findItemByName', ->
it 'finds the requested item', ->
item = modPack.findItemByName 'Bed'
item.name.should.equal 'Bed'
it 'ignores disabled mod versions', ->
item = modPack.findItemByName 'Stone Gear'
expect(item).to.be.null
describe 'findItemDisplay', ->
it 'returns all data for a regular Minecraft item', ->
display = modPack.findItemDisplay ItemSlug.slugify 'bed'
display.iconUrl.should.equal '/browse/minecraft/bed/icon.png'
display.itemUrl.should.equal '/browse/minecraft/bed/'
display.itemName.should.equal 'Bed'
display.modSlug.should.equal 'minecraft'
it 'returns all data for an item in an enabled mod', ->
buildcraft.activeVersion = '6.2.6'
display = modPack.findItemDisplay ItemSlug.slugify 'stone_gear'
display.iconUrl.should.equal '/browse/buildcraft/stone_gear/icon.png'
display.itemUrl.should.equal '/browse/buildcraft/stone_gear/'
display.itemName.should.equal 'Stone Gear'
display.modSlug.should.equal 'buildcraft'
it 'assumes an unfound item is from Minecraft', ->
display = modPack.findItemDisplay ItemSlug.slugify 'iron_chestplate'
display.iconUrl.should.equal '/browse/minecraft/iron_chestplate/icon.png'
display.itemUrl.should.equal '/browse/minecraft/iron_chestplate/'
display.itemName.should.equal 'Iron Chestplate'
display.modSlug.should.equal 'minecraft'
+96
View File
@@ -0,0 +1,96 @@
###
Crafting Guide - mod_version.test.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
Item = require '../models/item'
ItemSlug = require '../models/item_slug'
ModVersion = require '../models/mod_version'
########################################################################################################################
modVersion = null
########################################################################################################################
describe 'mod_version.coffee', ->
beforeEach ->
modVersion = new ModVersion modSlug:'test', version:'0.0'
modVersion.addItem new Item name:'underscore', group:'punctuation'
modVersion.addItem new Item name:'bravo', group:'letter'
modVersion.addItem new Item name:'alpha', group:'letter'
modVersion.addItem new Item name:'one', group:'number'
modVersion.addItem new Item name:'two', group:'number'
describe 'constructor', ->
it 'requires a mod slug', ->
expect(-> new ModVersion version:'0.0').to.throw Error, 'attributes.modSlug is required'
it 'requires a mod version', ->
expect(-> new ModVersion modSlug:'test').to.throw Error, 'attributes.version is required'
describe 'addItem', ->
it 'refuses to add duplicates', ->
modVersion.addItem new Item name:'Wool'
expect(-> modVersion.addItem new Item name:'Wool').to.throw Error, 'duplicate item for Wool'
it 'adds an item indexed by its slug', ->
modVersion.addItem new Item name:'Wool'
modVersion._items.wool.name.should.equal 'Wool'
it 'sets the modVersion', ->
modVersion.addItem new Item name:'Wool'
modVersion._items.wool.modVersion.should.equal modVersion
describe 'eachGroup', ->
it 'returns all the groups in order', ->
groupNames = []
modVersion.eachGroup (groupName)-> groupNames.push groupName
groupNames.should.eql ['letter', 'number', 'punctuation']
describe 'eachItemInGroup', ->
it 'returns immediately for unknown group', ->
slugs = []
modVersion.eachItemInGroup 'foobar', (item)-> slugs.push item.slug.qualified
slugs.should.eql []
it 'calls callback for exactly the items in a group in order', ->
slugs = []
modVersion.eachItemInGroup 'letter', (item)-> slugs.push item.slug.qualified
slugs.should.eql ['test__alpha', 'test__bravo']
slugs = []
modVersion.eachItemInGroup 'number', (item)-> slugs.push item.slug.qualified
slugs.should.eql ['test__one', 'test__two']
describe 'findItemByName', ->
it 'locates items by slugified name', ->
modVersion.addItem new Item name:'Crafting Table'
modVersion.findItemByName('Crafting Table').slug.qualified.should.equal 'test__crafting_table'
describe 'findRecipes', ->
beforeEach ->
modVersion = new ModVersion modSlug:'test', version:'1.0'
modVersion.parse """
schema:1
item: Cake
recipe:; input: Milk, Sugar, Egg, Wheat; pattern: 000 121 333; extras: 3 Bucket
recipe:; input: Milk, Cocoa Beans, Egg, Wheat; pattern: 000 121 333; extras: 3 Bucket
item: Bucket
recipe:; input: Iron Ingot; pattern: ... 0.0 .0.
"""
it 'finds all recipes which list item as output', ->
recipes = modVersion.findRecipes ItemSlug.slugify('Bucket')
(r.output[0].itemSlug.item for r in recipes).sort().should.eql ['bucket', 'cake', 'cake']
@@ -0,0 +1,48 @@
###
Crafting Guide - command_parser_version_base.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
CommandParserVersionBase = require '../../models/parser_versions/command_parser_version_base'
########################################################################################################################
parser = null
########################################################################################################################
describe 'command_parser_version_base.coffee', ->
beforeEach -> parser = new CommandParserVersionBase model:{}
describe '_parseHereDoc', ->
it 'returns null for non-heredoc lines', ->
result = parser._parseHereDoc 'foobar: baz'
expect(result[1]).to.be.null
it 'identifies the right text for a real heredoc', ->
parser._lines = ['command: <<-END', 'alpha', 'bravo', 'charlie', 'END', 'command1: arg2']
parser._lineNumber = 1
result = parser._parseHereDoc parser._lines[0]
result[0].should.equal 'command: '
result[1].should.equal 'alpha\nbravo\ncharlie'
it 'identifies an empty heredoc', ->
parser._lines = ['command: <<-END', 'END']
parser._lineNumber = 1
result = parser._parseHereDoc parser._lines[0]
result[0].should.equal 'command: '
expect(result[1]).to.be.null
it 'trims smallest leading whitespace', ->
parser._lines = ['command: <<-END', ' alpha', ' bravo', ' charlie', 'END', 'command1: arg2']
parser._lineNumber = 1
result = parser._parseHereDoc parser._lines[0]
result[0].should.equal 'command: '
result[1].should.equal 'alpha\n bravo\ncharlie'
@@ -0,0 +1,251 @@
###
Crafting Guide - mod_version_parser_v1.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
CommandParserVersionBase = require '../../models/parser_versions/command_parser_version_base'
ItemSlug = require '../../models/item_slug'
ModVersion = require '../../models/mod_version'
ModVersionParserV1 = require '../../models/parser_versions/mod_version_parser_v1'
########################################################################################################################
baseText = modVersion = parser = null
########################################################################################################################
describe 'mod_version_parser_v1.coffee', ->
beforeEach ->
modVersion = new ModVersion modSlug:'test', version:'0.0'
parser = new ModVersionParserV1 model:modVersion
describe 'Item', ->
it 'allows multiple recipes', ->
recipes = "item: Charlie;
recipe:; input:Alpha; pattern:... .0. ...;
recipe:; input:Bravo; pattern:... 0.0 ...;"
modVersion = parser.parse recipes
recipes = modVersion.findRecipes ItemSlug.slugify 'charlie'
recipes[0].input[0].itemSlug.qualified.should.equal 'alpha'
recipes[1].input[0].itemSlug.qualified.should.equal 'bravo'
describe 'name', ->
it 'adds the name when present', ->
modVersion = parser.parse 'item: Charlie'
modVersion._items.charlie.name.should.equal 'Charlie'
it 'requires a non-empty name', ->
func = -> parser.parse 'item: \n'
expect(func).to.throw Error, 'cannot be empty'
describe 'gatherable', ->
it 'adds "gatherable" when present', ->
modVersion = parser.parse 'item: Alpha Bravo; gatherable: yes'
modVersion._items.alpha_bravo.isGatherable.should.be.true
it 'does not allow a duplicate "gatherable" declaration', ->
func = -> parser.parse 'item: Alpha Bravo; gatherable: yes; gatherable: yes'
expect(func).to.throw Error, 'duplicate'
it 'requires "gatherable" to be "yes" or "no"', ->
func = -> parser.parse 'item: Alpha Bravo; gatherable: true'
expect(func).to.throw Error, 'gatherable must be'
it 'does not allow "gatherable" before "item"', ->
func = -> parser.parse 'gatherable: yes; item: Alpha Bravo; gatherable: yes'
expect(func).to.throw Error, '"gatherable" before "item"'
describe 'Recipe', ->
beforeEach -> baseText = 'item: Charlie; '
describe 'input', ->
it 'adds "input" when present', ->
modVersion = parser.parse baseText + 'recipe:; input:Alpha, Bravo, Charlie; pattern: ... 012 ...'
slugs = (s.itemSlug.item for s in modVersion.findRecipes(ItemSlug.slugify('charlie'))[0].input)
slugs.should.eql ['alpha', 'bravo', 'charlie']
it 'requires an "input" declaration', ->
func = -> parser.parse baseText + 'recipe:; pattern: ... .0. ...'
expect(func).to.throw Error, 'the "input" declaration is required'
it 'does not allow a duplicate "input" declaration', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha; pattern:....0....; input:Bravo'
expect(func).to.throw Error, 'duplicate declaration of "input"'
it 'does not allow "input" before "recipe"', ->
func = -> parser.parse baseText + 'input:Alpha, Bravo; recipe:; pattern:....0....'
expect(func).to.throw Error, 'cannot declare "input" before "recipe"'
it 'registers slugs for each input name', ->
modVersion = parser.parse baseText + 'recipe:; input:Delta, Echo, Foxtrot; pattern:...012...'
(s.item for s in modVersion._slugs).should.eql ['charlie', 'delta', 'echo', 'foxtrot']
describe 'pattern', ->
it 'adds "pattern" when present', ->
modVersion = parser.parse baseText + 'recipe:; input:Alpha, Bravo; pattern:... .0. .1.'
modVersion.findRecipes(ItemSlug.slugify('charlie'))[0].pattern.should.equal '... .0. .1.'
it 'requires a "pattern" declaration', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha, Bravo'
expect(func).to.throw Error, 'the "pattern" declaration is required'
it 'does not allow a duplicate "pattern" declaration', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha, Bravo; pattern:....0..1.; pattern:01.......'
expect(func).to.throw Error, 'duplicate declaration of "pattern"'
it 'requires pattern to be the right length', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha; pattern:000'
expect(func).to.throw Error, 'a pattern must have'
it 'requires pattern to only use proper characters', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha; pattern:abc def ghi'
expect(func).to.throw Error, 'a pattern must have'
it 'requires pattern to only refer to existing items', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha; pattern:... 010 ...'
expect(func).to.throw Error, 'there is no input 1 in this recipe'
it 'requires all items to appear in the pattern', ->
func = -> parser.parse baseText + 'recipe:; input:Alpha, Bravo; pattern: 000 0.0 000'
expect(func).to.throw Error, 'Bravo is an input'
it 'computes the input stack sizes from the pattern', ->
modVersion = parser.parse baseText + 'recipe:; input:Alpha, Bravo, Charlie; pattern:111 .0. 2.2'
recipe = modVersion.findRecipes(ItemSlug.slugify('charlie'))[0]
recipe.input[0].quantity.should.equal 1
recipe.input[1].quantity.should.equal 3
recipe.input[2].quantity.should.equal 2
it 'does not allow "pattern" before "recipe"', ->
func = -> parser.parse baseText + 'pattern:... .0. ...; recipe:; inputs:Alpha'
expect(func).to.throw Error, 'cannot declare "pattern" before "recipe"'
describe 'quantity', ->
beforeEach ->
baseText = 'item: Charlie; recipe:; input:Alpha; pattern:...0.0...; '
it 'adds "quantity" when present', ->
modVersion = parser.parse baseText + 'quantity: 2'
modVersion.findRecipes(ItemSlug.slugify('charlie'))[0].output[0].quantity.should.equal 2
it 'does not allow a duplicate "quantity" declaration', ->
func = -> parser.parse baseText + 'quantity:1; quantity:2'
expect(func).to.throw Error, 'duplicate declaration of "quantity"'
it 'requires quantity to be an integer', ->
func = -> parser.parse baseText + 'quantity:ten'
expect(func).to.throw Error, 'quantity must be an integer'
it 'assumes a quantity of 1 by default', ->
modVersion = parser.parse baseText
modVersion.findRecipes(ItemSlug.slugify('charlie'))[0].output[0].quantity.should.equal 1
it 'does not allow "quantity" before recipe', ->
func = -> parser.parse 'item:Bravo; quantity:12; recipe:;'
expect(func).to.throw Error, 'cannot declare "quantity" before "recipe"'
describe 'output', ->
beforeEach ->
baseText = 'item: Delta; item:Bravo; recipe:; input:Charlie; pattern:... .0. ...; '
it 'adds a single item as the default output', ->
modVersion = parser.parse baseText
stack = modVersion.findRecipes(ItemSlug.slugify('bravo'))[0].output[0]
stack.itemSlug.qualified.should.equal 'test__bravo'
stack.quantity.should.equal 1
it 'can add multiple extras with quantities', ->
modVersion = parser.parse baseText + 'extras:2 Delta, 4 Echo'
output = modVersion.findRecipes(ItemSlug.slugify('bravo'))[0].output
output[0].itemSlug.qualified.should.equal 'test__bravo'
output[0].quantity.should.equal 1
output[1].itemSlug.qualified.should.equal 'test__delta'
output[1].quantity.should.equal 2
output[2].itemSlug.qualified.should.equal 'echo'
output[2].quantity.should.equal 4
it 'does not allow "extras" before "recipe"', ->
func = -> parser.parse 'item:Bravo; extras:Charlie'
expect(func).to.throw Error, 'cannot declare "extras" before "recipe"'
it 'registers slugs for each output name', ->
modVersion = parser.parse baseText + 'extras:Delta, Echo'
(s.qualified for s in modVersion._slugs).should.eql [
'test__bravo', 'test__delta', 'charlie', 'echo'
]
it 'does not allow a duplicate "extras" declaration', ->
func = -> parser.parse baseText + 'extras:Echo; extras:Delta'
expect(func).to.throw Error, 'duplicate declaration of "extras"'
describe 'tools', ->
beforeEach ->
baseText = 'item:Bravo; recipe:; input:Charlie; pattern:... .0. ...; '
it 'can add a single tool', ->
modVersion = parser.parse baseText + 'tools: Furnace'
modVersion.findRecipes(ItemSlug.slugify('bravo'))[0].tools[0].itemSlug.item.should.equal 'furnace'
it 'can add multiple tools', ->
modVersion = parser.parse baseText + 'tools: Crafting Table, Furnace'
tools = modVersion.findRecipes(ItemSlug.slugify('bravo'))[0].tools
tools[0].itemSlug.item.should.equal 'crafting_table'
tools[1].itemSlug.item.should.equal 'furnace'
it 'registers slugs for each tool name', ->
modVersion = parser.parse baseText + 'tools: Crafting Table, Furnace'
(s.item for s in modVersion._slugs).should.eql ['bravo', 'charlie', 'crafting_table', 'furnace']
it 'does not allow a duplicate "tools" declaration', ->
func = -> parser.parse baseText + 'tools:Crafting Table; tools:Furnace'
expect(func).to.throw Error, 'duplicate declaration of "tools"'
describe "unparsing", ->
beforeEach ->
baseText = """
schema: 1
group: Agriculture
item: Apple
item: Baked Potato
recipe:
input: Potato, furnace fuel
pattern: .0. ... .1.
tools: Furnace
group: Functional Blocks
item: Furnace
recipe:
input: Cobblestone
pattern: 000 0.0 000
tools: Crafting Table
update: Iron Ingot
recipe:
input: Iron Dust, furnace fuel
pattern: .0. ... .1.
tools: Furnace
"""
it 'can round-trip a data file', ->
text = parser.unparse parser.parse baseText
actual = CommandParserVersionBase.simplify text
expected = CommandParserVersionBase.simplify baseText
actual.should.equal expected
+86
View File
@@ -0,0 +1,86 @@
###
Crafting Guide - recipe.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
Item = require '../models/item'
ItemSlug = require '../models/item_slug'
Recipe = require '../models/recipe'
Stack = require '../models/stack'
########################################################################################################################
input = output = pattern = recipe = null
########################################################################################################################
describe 'recipe.coffee', ->
describe 'constructor', ->
beforeEach ->
input = [
new Stack(itemSlug:new ItemSlug('iron_gear')),
new Stack(itemSlug:new ItemSlug('gold_ingot'), quantity:4)
]
pattern = '.1. 101 .1.'
it 'requires input', ->
expect(-> new Recipe slug:'gold_gear', pattern:pattern).to.throw Error, 'attributes.input is required'
it 'requires a pattern', ->
expect(-> new Recipe slug:'gold_gear', input:input).to.throw Error, 'attributes.pattern is required'
it 'requires either outputs or a slug', ->
f = -> new Recipe input:input, pattern:pattern
expect(f).to.throw 'attributes.itemSlug or attributes.output is required'
it 'creates default output', ->
recipe = new Recipe itemSlug:ItemSlug.slugify('gold_gear'), input:input, pattern:pattern
recipe.output.length.should.equal 1
recipe.output[0].itemSlug.qualified.should.equal 'gold_gear'
recipe.output[0].quantity.should.equal 1
it 'assigns a default slug', ->
recipe = new Recipe input:input, pattern:pattern, output:[new Stack itemSlug:ItemSlug.slugify('gold_gear')]
recipe.itemSlug.qualified.should.equal 'gold_gear'
describe 'getItemSlugAt', ->
beforeEach ->
input = [
new Stack itemSlug:ItemSlug.slugify('iron_gear')
new Stack itemSlug:ItemSlug.slugify('gold_ingot'), quantity:4
]
recipe = new Recipe itemSlug:'gold_gear', input:input, pattern:'.1. 101 .1.'
it 'returns the proper item for an early slot', ->
recipe.getItemSlugAt(1).qualified.should.equal 'gold_ingot'
it 'returns the proper item for a late slot', ->
recipe.getItemSlugAt(4).qualified.should.equal 'iron_gear'
it 'returns null for an invalid slot', ->
expect(recipe.getItemSlugAt(12)).to.be.null
describe '_parsePattern', ->
beforeEach ->
recipe = new Recipe
itemSlug: 'oak_wood_planks',
input: [new Stack itemSlug:new ItemSlug('oak_wood')],
pattern:'... .0. ...'
it 'normalizes invalid characters', ->
recipe._parsePattern('$$0 #() 010').should.equal '..0 ... 010'
it 'removes extra characters', ->
recipe._parsePattern('000 000 000 000').should.equal '000 000 000'
it 'fills in missing characters', ->
recipe._parsePattern('000000').should.equal '000 000 ...'
it 'fills in spaces', ->
recipe._parsePattern('000000000').should.equal '000 000 000'
@@ -0,0 +1,84 @@
###
Crafting Guide - string_builder.test.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
StringBuilder = require '../models/string_builder'
########################################################################################################################
builder = null
########################################################################################################################
describe 'string_builder.coffee', ->
beforeEach -> builder = new StringBuilder
describe 'call', ->
it 'works with no arguments', ->
builder.call (b)-> b.push 'foo'
builder.toString().should.equal 'foo'
it 'works with multiple arguments', ->
builder.call 'foo', 'bar', 'baz', (builder, a, b, c)-> builder.loop [a, b, c]
builder.toString().should.equal 'foo, bar, baz'
describe 'loop', ->
it 'can make an empty list', ->
builder.loop [], start:'[', end:']'
builder.toString().should.equal '[]'
it 'can make a list with a single element', ->
builder.loop ['foo'], start:'[', end:']'
builder.toString().should.equal '[foo]'
it 'can make a list with many elements', ->
builder.loop ['foo', 'bar', 'baz'], start:'[', end:']'
builder.toString().should.equal '[foo, bar, baz]'
it 'can make a list with a custom callback', ->
builder.loop ['foo', 'bar', 'baz'], start:'[', end:']', onEach:(b, i)-> b.push "\"#{i}\""
builder.toString().should.equal '["foo", "bar", "baz"]'
it 'can use a custom delimiter', ->
builder.loop ['foo', 'bar', 'baz'], delimiter:'|'
builder.toString().should.equal 'foo|bar|baz'
it 'can indent content', ->
builder.loop ['foo', 'bar', 'baz'], start:'[\n', end:'\n]', delimiter:',\n', indent:true
builder.toString().should.equal '[\n foo,\n bar,\n baz\n]'
describe 'onlyIf', ->
it 'calls the callback on true', ->
builder.onlyIf true, (b)-> b.push 'foo'
builder.toString().should.equal 'foo'
describe 'push', ->
it 'can build a simple string', ->
builder.push('foo').push(' bar').push(' baz')
builder.toString().should.equal 'foo bar baz'
it 'can build a multi-line string', ->
builder.push('foo').push('\nbar\n').push('baz')
builder.toString().should.equal 'foo\nbar\nbaz'
it 'can build an indented multi-line string', ->
builder
.push 'foo\n'
.indent()
.push 'bar\n'
.outdent()
.push 'baz'
builder.toString().should.equal 'foo\n bar\nbaz'
it 'can pick apart multiple newlines in a single chunk', ->
builder.indent().push('foo\nbar\nbaz').outdent().push('\nbif')
builder.toString().should.equal 'foo\n bar\n baz\nbif'
+45
View File
@@ -0,0 +1,45 @@
###
# Crafting Guide - test.coffee
#
# Copyright (c) 2014-2015 by Redwood Labs
# All rights reserved.
###
# Test Set-up ##########################################################################################################
chai.use require 'sinon-chai'
chai.config.includeStack = true
if typeof(global) is 'undefined'
window.global = window
global.assert = chai.assert
global.expect = chai.expect
global.should = chai.should()
global.util = require 'util'
Logger = require '../logger'
global.logger = new Logger level:Logger.DEBUG
require '../polyfill'
require '../underscore_mixins'
# Test Registry ########################################################################################################
mocha.setup 'bdd'
# tests are roughly in order of how errors should be tackled
require './string_builder.test'
require './item_slug.test'
require './inventory.test'
require './recipe.test'
require './mod_version.test'
require './mod.test'
require './mod_pack.test'
require './parser_versions/command_parser_version_base.test'
require './parser_versions/mod_version_parser_v1.test'
require './crafting_plan.test'
mocha.checkLeaks()
mocha.globals ['LiveReload']
mocha.run()
+157
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

-10
View File
@@ -1,10 +0,0 @@
schema: 1
name: Applied Energistics 2
author: AlgorithmX2
description: A technical mod which adds an advanced, computer-based storage system
homePageUrl: http://ae-mod.info/
documentationUrl: http://ae-mod.info/
downloadUrl: http://ae-mod.info/Downloads/
version: rv1-stable-1
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 667 B

Some files were not shown because too many files have changed in this diff Show More