Add remaining commands

This commit is contained in:
Andrew Miner
2016-04-15 21:22:10 -07:00
parent 31f6e12844
commit 9ddbd5cda7
14 changed files with 417 additions and 54 deletions
+42 -1
View File
@@ -26,6 +26,7 @@ module.exports = class ParserData
create: (command, type, id=null)-> create: (command, type, id=null)->
id ?= _.uniqueId "#{type}-" id ?= _.uniqueId "#{type}-"
@clearCurrent type
typeData = @_findOrCreateType type typeData = @_findOrCreateType type
itemData = @_current = typeData['current'] = typeData[id] = id:id, command:command, type:type itemData = @_current = typeData['current'] = typeData[id] = id:id, command:command, type:type
@@ -37,9 +38,49 @@ module.exports = class ParserData
clear: -> clear: ->
@_current = null @_current = null
@_data = {} @_data =
mod: {}
modVersion: {}
tutorial: {}
itemGroup: {}
item: {}
multiblock: {}
recipe: {}
@_errors = [] @_errors = []
clearCurrent: (type)->
switch type
when 'mod'
delete @_data.mod.current
delete @_data.modVersion.current
delete @_data.tutorial.current
delete @_data.itemGroup.current
delete @_data.item.current
delete @_data.multiblock.current
delete @_data.recipe.current
when 'modVersion'
delete @_data.modVersion.current
delete @_data.tutorial.current
delete @_data.itemGroup.current
delete @_data.item.current
delete @_data.multiblock.current
delete @_data.recipe.current
when 'tutorial'
delete @_data.tutorial.current
when 'itemGroup'
delete @_data.itemGroup.current
delete @_data.item.current
delete @_data.multiblock.current
delete @_data.recipe.current
when 'item'
delete @_data.item.current
delete @_data.multiblock.current
delete @_data.recipe.current
when 'multiblock'
delete @_data.multiblock.current
when 'recipe'
delete @_data.recipe.current
get: (type, id)-> get: (type, id)->
typeData = @_findOrCreateType type typeData = @_findOrCreateType type
itemData = typeData[id] or null itemData = typeData[id] or null
@@ -55,6 +55,14 @@ module.exports = class ParserExtension
return false return false
incompatibleField: (command, obj, field, otherCommandName)->
otherCommandName ?= field
if obj[field]?
@data.addError "#{command.name} cannot be used with #{otherCommandName}"
return true
return false
missingCurrent: (command, type)-> missingCurrent: (command, type)->
obj = @data.getCurrent type obj = @data.getCurrent type
if not obj? if not obj?
@@ -77,6 +85,13 @@ module.exports = class ParserExtension
return false return false
invalidVerb: (command, verb)->
if not verb in ['mod', 'item']
@data.addError command, "#{command.name} only applies to either `mod` or `item`"
return true
return false
tooFewArguments: (command, minimum)-> tooFewArguments: (command, minimum)->
if command.args.length < minimum if command.args.length < minimum
@data.addError command, "#{command.name} requires at least #{minimum} arguments" @data.addError command, "#{command.name} requires at least #{minimum} arguments"
@@ -13,19 +13,13 @@ module.exports = class CurrentParserExtensionV1 extends ParserExtension
constructor: (data)-> constructor: (data)->
super data, null, super data, null,
documentationUrl: @_command_documentationUrl description: @_command_description
description: @_command_description name: @_command_name
name: @_command_name officialUrl: @_command_officialUrl
video: @_command_video
# Command Methods ############################################################################## # Command Methods ##############################################################################
_command_documentationUrl: (command)->
current = @data.getCurrent()
return if @duplicateField command, current, 'documentationUrl'
return if @missingArgText command
current.documentationUrl = command.argText
_command_description: (command)-> _command_description: (command)->
current = @data.getCurrent() current = @data.getCurrent()
return if @duplicateField command, current, 'description' return if @duplicateField command, current, 'description'
@@ -39,3 +33,18 @@ module.exports = class CurrentParserExtensionV1 extends ParserExtension
return if @missingArgText command return if @missingArgText command
current.name = command.argText current.name = command.argText
_command_officialUrl: (command)->
current = @data.getCurrent()
return if @duplicateField command, current, 'officialUrl'
return if @missingArgText command
current.officialUrl = command.argText
_command_video: (command)->
current = @data.getCurrent()
return if @missingArgs command
return if @tooFewArguments command, 2
current.videos ?= []
current.videos.push youTubeId:command.args[0], caption:command.args[1..].join(', ')
@@ -22,13 +22,6 @@ describe 'current_pe_v1.coffee', ->
state.create {}, 'alpha' state.create {}, 'alpha'
describe 'documentationUrl', ->
it 'assigns to the current object', ->
parser.execute name:'documentationUrl', argText:'bravo'
state.getCurrent().documentationUrl.should.equal 'bravo'
state.errors.should.eql []
describe 'description', -> describe 'description', ->
it 'assigns to the current object', -> it 'assigns to the current object', ->
@@ -42,3 +35,25 @@ describe 'current_pe_v1.coffee', ->
parser.execute name:'name', argText:'bravo' parser.execute name:'name', argText:'bravo'
state.getCurrent().name.should.equal 'bravo' state.getCurrent().name.should.equal 'bravo'
state.errors.should.eql [] state.errors.should.eql []
describe 'officialUrl', ->
it 'assigns to the current object', ->
parser.execute name:'officialUrl', argText:'bravo'
state.getCurrent().officialUrl.should.equal 'bravo'
state.errors.should.eql []
describe 'video', ->
it 'assigns to the current object', ->
parser.execute name:'video', args:['alpha', 'bravo']
videos = state.getCurrent().videos
videos[0].youTubeId.should.equal 'alpha'
videos[0].caption.should.equal 'bravo'
state.errors.should.eql []
it 'can assign multiple videos', ->
parser.execute name:'video', args:['alpha', 'bravo']
parser.execute name:'video', args:['charlie', 'delta']
state.getCurrent().videos.length.should.equal 2
state.errors.should.eql []
@@ -15,6 +15,7 @@ module.exports = class ItemParserExtensionV1 extends ParserExtension
super data, 'item', super data, 'item',
gatherable: @_command_gatherable gatherable: @_command_gatherable
item: @_command_item item: @_command_item
update: @_command_update
# ParserExtensions Overrides ################################################################### # ParserExtensions Overrides ###################################################################
@@ -31,11 +32,10 @@ module.exports = class ItemParserExtensionV1 extends ParserExtension
_command_gatherable: (command)-> _command_gatherable: (command)->
return if @missingArgText command return if @missingArgText command
return if @missingCurrent command, 'item' return if @missingCurrent command, 'item'
item = @data.getCurrent 'item' item = @data.getCurrent 'item'
return if @duplicateField command, 'gatherable', item return if @duplicateField command, item, 'gatherable'
gatherable = @parseBoolean command, command.argText gatherable = @parseBoolean command, command.argText
return unless gatherable? return unless gatherable?
@@ -49,17 +49,19 @@ module.exports = class ItemParserExtensionV1 extends ParserExtension
item = @data.create command, 'item', command.argText item = @data.create command, 'item', command.argText
item.name = command.argText item.name = command.argText
item.isUpdate = false
group = @data.getCurrent 'itemGroup' group = @data.getCurrent 'itemGroup'
if group? then item.group = group if group? then item.group = group
item.modVersion = @data.getCurrent 'modVersion' item.modVersion = @data.getCurrent 'modVersion'
_command_video: (command)-> _command_update: (command)->
return if @missingArgs command return if @missingArgText command
return if @missingCurrent command, 'item' return if @missingCurrent command, 'modVersion'
return if @tooFewArguments command, 2 return if @alreadyExists command, 'item', command.argText
item = @data.getCurrent 'item' item = @data.create command, 'item', command.argText
item.videos ?= [] item.name = command.argText
item.videos.push youTubeId:command.args[0], caption:command.args[1..].join(', ') item.isUpdate = true
item.modVersion = @data.getCurrent 'modVersion'
@@ -39,6 +39,16 @@ describe 'item_pe_v1.coffee', ->
parser.execute name:'item', argText:'alpha' parser.execute name:'item', argText:'alpha'
item = data.getCurrent 'item' item = data.getCurrent 'item'
item.id.should.equal 'alpha' item.id.should.equal 'alpha'
item.isUpdate.should.equal false
item.name.should.equal 'alpha' item.name.should.equal 'alpha'
item.modVersion.id.should.equal 0 item.modVersion.id.should.equal 0
item.group.id.should.equal 2 item.group.id.should.equal 2
data.getErrors().should.eql []
describe 'update', ->
it 'creates an item update', ->
parser.execute name:'update', argText:'alpha'
item = data.getCurrent 'item'
item.isUpdate.should.equal true
data.getErrors().should.eql []
@@ -13,10 +13,11 @@ module.exports = class ModParserExtensionV1 extends ParserExtension
constructor: (data)-> constructor: (data)->
super data, 'mod', super data, 'mod',
author: @_command_author author: @_command_author
downloadUrl: @_command_downloadUrl documentationUrl: @_command_documentationUrl
homePageUrl: @_command_homePageUrl downloadUrl: @_command_downloadUrl
mod: @_command_mod homePageUrl: @_command_homePageUrl
mod: @_command_mod
# Command Methods ############################################################################## # Command Methods ##############################################################################
@@ -29,6 +30,13 @@ module.exports = class ModParserExtensionV1 extends ParserExtension
mod.author = command.argText mod.author = command.argText
_command_documentationUrl: (command)->
current = @data.getCurrent()
return if @duplicateField command, current, 'documentationUrl'
return if @missingArgText command
current.documentationUrl = command.argText
_command_downloadUrl: (command)-> _command_downloadUrl: (command)->
return if @missingCurrent command, 'mod' return if @missingCurrent command, 'mod'
@@ -51,4 +59,4 @@ module.exports = class ModParserExtensionV1 extends ParserExtension
return if @missingArgText command return if @missingArgText command
return if @alreadyExists command, 'mod', command.argText return if @alreadyExists command, 'mod', command.argText
@data.create command, 'mod', command.argText @data.create command, 'mod', command.argText
@@ -29,6 +29,13 @@ describe 'mod_pe_v1.coffee', ->
data.getCurrent('mod').author.should.equal 'alpha' data.getCurrent('mod').author.should.equal 'alpha'
data.errors.should.eql [] data.errors.should.eql []
describe 'documentationUrl', ->
it 'assigns to the current mod', ->
parser.execute name:'documentationUrl', argText:'alpha'
data.getCurrent('mod').documentationUrl.should.equal 'alpha'
data.errors.should.eql []
describe 'downloadUrl', -> describe 'downloadUrl', ->
it 'assigns to the current mod', -> it 'assigns to the current mod', ->
@@ -0,0 +1,38 @@
#
# Crafting Guide - multiblock_pe_v1.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
ParserExtension = require '../parser_extension'
########################################################################################################################
module.exports = class MultiblockParserExtensionV1 extends ParserExtension
constructor: (data)->
super data, 'multiblock',
layer: @_command_layer
multiblock: @_command_multiblock
# Command Methods ##############################################################################
_command_layer: (command)->
return if @missingCurrent command, 'multiblock'
return if @missingArgText command
multiblock = @data.getCurrent 'multiblock'
multiblock.layers ?= []
multiblock.layers.push command.argText
_command_multiblock: (command)->
return if @missingCurrent command, 'item'
item = @data.getCurrent 'item'
return if @duplicateField command, item, 'multiblock'
return if @incompatibleField command, item, 'recipe'
return if @incompatibleField command, item, 'gatherable'
multiblock = @data.create command, 'multiblock'
multiblock.item = item
@@ -0,0 +1,48 @@
#
# Crafting Guide - multiblock_pe_v1.test.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
MultiblockParserExtensionV1 = require './multiblock_pe_v1'
ParserData = require '../parser_data'
########################################################################################################################
parser = data = null
########################################################################################################################
describe 'multiblock_pe_v1.coffee', ->
beforeEach ->
data = new ParserData
parser = new MultiblockParserExtensionV1 data
data.create {}, 'item', 1
describe 'layer', ->
it 'creates a new layer in the current multiblock', ->
data.create {}, 'multiblock', 2
parser.execute name:'layer', argText:'alpha'
multiblock = data.getCurrent 'multiblock'
multiblock.layers.length.should.equal 1
multiblock.layers[0].should.equal 'alpha'
it 'can create multiple layers', ->
data.create {}, 'multiblock', 2
parser.execute name:'layer', argText:'alpha'
parser.execute name:'layer', argText:'bravo'
multiblock = data.getCurrent 'multiblock'
multiblock.layers.should.eql ['alpha', 'bravo']
describe 'multiblock', ->
it 'creates a new multiblock', ->
parser.execute name:'multiblock'
multiblock = data.getCurrent 'multiblock'
multiblock.item.id.should.equal 1
@@ -13,12 +13,14 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension
constructor: (data)-> constructor: (data)->
super data, 'recipe', super data, 'recipe',
extras: @_command_extras extras: @_command_extras
input: @_command_input ignoreDuringCrafting: @_command_ignoreDuringCrafting
pattern: @_command_pattern input: @_command_input
recipe: @_command_recipe onlyIf: @_command_onlyIf
quantity: @_command_quantity pattern: @_command_pattern
tools: @_command_tools recipe: @_command_recipe
quantity: @_command_quantity
tools: @_command_tools
# Class Methods ################################################################################ # Class Methods ################################################################################
@@ -47,14 +49,48 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension
recipe.extras = command.args recipe.extras = command.args
_command_ignoreDuringCrafting: (command)->
return if @missingArgText command
return if @missingCurrent command, 'recipe'
recipe = @data.getCurrent 'recipe'
return if @duplicateField command, recipe, 'ignoreDuringCrafting'
ignoreDuringCrafting = @parseBoolean command, command.argText
return unless ignoreDuringCrafting?
recipe.ignoreDuringCrafting = ignoreDuringCrafting
_command_input: (command)-> _command_input: (command)->
return if @missingCurrent command, 'recipe' return if @missingCurrent command, 'recipe'
return if @missingArgs command return if @missingArgs command
recipe = @data.getCurrent 'recipe' recipe = @data.getCurrent 'recipe'
return if @duplicateField command, 'input', recipe multiblock = @data.getCurrent 'multiblock'
recipe.input = (@_parseStack(arg) for arg in command.args) target = if multiblock? then multiblock else recipe
return if @duplicateField command, 'input', target
target.input = (@_parseStack(arg) for arg in command.args)
_command_onlyIf: (command)->
return if @missingCurrent command, 'recipe'
return if @missingArgText command
recipe = @data.getCurrent 'recipe'
return if @duplicateField command, recipe, 'condition'
words = command.argText.split ' '
inverted = false
if words[0] is 'not'
inverted = true
words.shift()
verb = words[0]
noun = words[1..].join ' '
return if @invalidVerb command, verb
recipe.condition = verb:verb, noun:noun, inverted:inverted
_command_pattern: (command)-> _command_pattern: (command)->
return if @missingCurrent command, 'recipe' return if @missingCurrent command, 'recipe'
@@ -66,12 +102,6 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension
recipe.pattern = command.argText recipe.pattern = command.argText
_command_recipe: (command)->
return if @missingCurrent command, 'item'
recipe = @data.create command, 'recipe'
recipe.item = @data.getCurrent 'item'
_command_quantity: (command)-> _command_quantity: (command)->
return if @missingCurrent command, 'recipe' return if @missingCurrent command, 'recipe'
return if @missingArgText command return if @missingArgText command
@@ -84,6 +114,12 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension
recipe.quantity = value recipe.quantity = value
_command_recipe: (command)->
return if @missingCurrent command, 'item'
recipe = @data.create command, 'recipe'
recipe.item = @data.getCurrent 'item'
_command_tools: (command)-> _command_tools: (command)->
return if @missingCurrent command, 'recipe' return if @missingCurrent command, 'recipe'
return if @missingArgs command return if @missingArgs command
@@ -32,6 +32,16 @@ describe 'recipe_pe_v1.coffee', ->
recipe.extras.should.eql ['bravo'] recipe.extras.should.eql ['bravo']
data.errors.should.eql [] data.errors.should.eql []
describe 'ignoreDuringCrafting', ->
it 'assigns to the current recipe', ->
data.create {}, 'recipe'
parser.execute name:'ignoreDuringCrafting', argText:'yes'
recipe = data.getCurrent 'recipe'
recipe.ignoreDuringCrafting.should.equal true
data.errors.should.eql []
describe 'input', -> describe 'input', ->
it 'correctly reads a single item', -> it 'correctly reads a single item', ->
@@ -58,6 +68,16 @@ describe 'recipe_pe_v1.coffee', ->
recipe.input.should.eql [name:'bravo', quantity:10] recipe.input.should.eql [name:'bravo', quantity:10]
data.errors.should.eql [] data.errors.should.eql []
describe 'onlyIf', ->
it 'assigns to the current recipe', ->
data.create {}, 'recipe'
parser.execute name:'onlyIf', argText:'not mod Alpha'
recipe = data.getCurrent 'recipe'
recipe.condition.should.eql verb:'mod', noun:'Alpha', inverted:true
data.errors.should.eql []
describe 'pattern', -> describe 'pattern', ->
it 'assigns to the current recipe', -> it 'assigns to the current recipe', ->
@@ -76,14 +96,6 @@ describe 'recipe_pe_v1.coffee', ->
expect(recipe.pattern).to.be.undefined expect(recipe.pattern).to.be.undefined
(e.message for e in data.errors).should.eql ['invalid pattern: "alpha"'] (e.message for e in data.errors).should.eql ['invalid pattern: "alpha"']
describe 'recipe', ->
it 'creates a new recipe', ->
parser.execute name:'recipe'
recipe = data.getCurrent 'recipe'
recipe.item.id.should.equal 0
data.errors.should.eql []
describe 'quantity', -> describe 'quantity', ->
it 'assigns to the current recipe', -> it 'assigns to the current recipe', ->
@@ -94,6 +106,14 @@ describe 'recipe_pe_v1.coffee', ->
recipe.quantity.should.equal 42 recipe.quantity.should.equal 42
data.errors.should.eql [] data.errors.should.eql []
describe 'recipe', ->
it 'creates a new recipe', ->
parser.execute name:'recipe'
recipe = data.getCurrent 'recipe'
recipe.item.id.should.equal 0
data.errors.should.eql []
describe 'tools', -> describe 'tools', ->
it 'assigns to the current recipe', -> it 'assigns to the current recipe', ->
@@ -0,0 +1,51 @@
#
# Crafting Guide - tutorial_pe_v1.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
ParserExtension = require '../parser_extension'
########################################################################################################################
module.exports = class TutorialParserExtensionV1 extends ParserExtension
constructor: (data)->
super data, 'tutorial',
content: @_command_content
section: @_command_section
title: @_command_title
tutorial: @_command_tutorial
# Command Methods ##############################################################################
_command_content: (command)->
return if @missingCurrent command, 'tutorial'
return if @missingArgText command
section = @data.getCurrent 'section'
section.content = command.argText
_command_section: (command)->
return if @missingCurrent command, 'tutorial'
section = @data.create command, 'section'
section.tutorial = @data.getCurrent 'tutorial'
_command_title: (command)->
return if @missingCurrent command, 'section'
return if @missingArgText command
section = @data.getCurrent 'section'
return if @duplicateField command, section, 'title'
section.title = command.argText
_command_tutorial: (command)->
return if @missingCurrent command, 'modVersion'
return if @missingArgText command
tutorial = @data.create command, 'tutorial', command.argText
tutorial.name = command.argText
tutorial.modVersion = @data.getCurrent 'modVersion'
@@ -0,0 +1,63 @@
#
# Crafting Guide - tutorial_pe_v1.test.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
TutorialParserExtensionV1 = require './tutorial_pe_v1'
ParserData = require '../parser_data'
########################################################################################################################
parser = data = null
########################################################################################################################
describe 'tutorial_pe_v1.coffee', ->
beforeEach ->
data = new ParserData
parser = new TutorialParserExtensionV1 data
data.create {}, 'modVersion', 1
describe 'content', ->
it 'assigns content to the current section', ->
data.create {}, 'tutorial', 2
data.create {}, 'section', 3
parser.execute name:'content', argText:'alpha'
data.errors.should.eql []
section = data.getCurrent 'section'
section.content.should.equal 'alpha'
describe 'section', ->
it 'creates a section in the current tutorial', ->
data.create {}, 'tutorial', 2
parser.execute name:'section'
data.errors.should.eql []
section = data.getCurrent 'section'
section.tutorial.id.should.equal 2
describe 'title', ->
it 'assigns a title to the current tutorial', ->
data.create {}, 'tutorial', 2
data.create {}, 'section', 3
parser.execute name:'title', argText:'alpha'
data.errors.should.eql []
section = data.getCurrent 'section'
section.title.should.equal 'alpha'
describe 'tutorial', ->
it 'creates a new tutorial', ->
parser.execute name:'tutorial', argText:'alpha'
data.errors.should.eql []
tutorial = data.getCurrent 'tutorial'
tutorial.name.should.equal 'alpha'