From e0c642e787ad5a525ad08eff6aa4fce2d87816b0 Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Sat, 31 Jan 2015 15:48:24 -0800 Subject: [PATCH] Store want/have in URL/local storage --- .../controllers/item_page_controller.coffee | 16 ++++++--- src/scripts/crafting_guide_router.coffee | 14 ++++++-- src/scripts/models/inventory_parser.coffee | 36 +++++++++++-------- src/scripts/models/item_page.coffee | 28 +++++++++------ src/scripts/models/storage.coffee | 24 ++++++++----- test/inventory_parser.test.coffee | 6 ++-- 6 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/scripts/controllers/item_page_controller.coffee b/src/scripts/controllers/item_page_controller.coffee index a8660719e..aeadb605c 100644 --- a/src/scripts/controllers/item_page_controller.coffee +++ b/src/scripts/controllers/item_page_controller.coffee @@ -10,6 +10,7 @@ CraftingTableController = require './crafting_table_controller' {Event} = require '../constants' ImageLoader = require './image_loader' InventoryController = require './inventory_controller' +InventoryParser = require '../models/inventory_parser' ItemPage = require '../models/item_page' ModPackController = require './mod_pack_controller' NameFinder = require '../models/name_finder' @@ -27,6 +28,7 @@ module.exports = class ItemPageController extends BaseController super options @_imageLoader = options.imageLoader + @_parser = new InventoryParser modPack:options.modPack @_storage = options.storage # Event Methods ################################################################################ @@ -38,6 +40,7 @@ module.exports = class ItemPageController extends BaseController onWillRender: -> @_storage.register 'crafting-plan', @model.plan, 'includingTools' + @_parser.parse @_storage.load('crafting-plan:have'), @model.plan.have super onDidRender: -> @@ -55,6 +58,7 @@ module.exports = class ItemPageController extends BaseController imageLoader: @_imageLoader model: @model.plan.have modPack: @model.modPack + onChange: => @_saveHaveInventory() nameFinder: new NameFinder @model.modPack, includeGatherable:true title: 'Items you have' @@ -95,10 +99,12 @@ module.exports = class ItemPageController extends BaseController # Private Methods ############################################################################## + _saveHaveInventory: -> + @_storage.store 'crafting-plan:have', @_parser.unparse @model.plan.have + _updateLocation: -> - list = @model.plan.want.toList() - if list.length is 1 - slug = if _.isArray(list[0]) then list[0][1] else list[0] - router.navigate "/item/#{slug}" + text = @_parser.unparse @model.plan.want + if @model.plan.want.isEmpty + router.navigate '/' else - router.navigate "/" + router.navigate "/item/#{text}" diff --git a/src/scripts/crafting_guide_router.coffee b/src/scripts/crafting_guide_router.coffee index 27def7ba6..c87c1a426 100644 --- a/src/scripts/crafting_guide_router.coffee +++ b/src/scripts/crafting_guide_router.coffee @@ -62,11 +62,19 @@ module.exports = class CraftingGuideRouter extends Backbone.Router root: -> params = new UrlParams recipeName:{type:'string'}, count:{type:'integer'} - @item params.recipeName, params.count - item: (name, quantity=1)-> + arg = null + if params.recipeName? + if params.count? + arg = "#{params.count}:#{params.recipeName}" + else + arg = "#{params.recipeName}" + + @item arg + + item: (inventoryText)-> controller = new ItemPageController @_defaultOptions - controller.model.params = name:name, quantity:quantity + controller.model.params = inventoryText:inventoryText @_setPage 'item', controller mod: (slug)-> diff --git a/src/scripts/models/inventory_parser.coffee b/src/scripts/models/inventory_parser.coffee index 9d97e3d39..7119cdcf0 100644 --- a/src/scripts/models/inventory_parser.coffee +++ b/src/scripts/models/inventory_parser.coffee @@ -18,7 +18,9 @@ module.exports = class InventoryParser # Class Methods ################################################################################ - @ITEM_REGEX = /^([0-9]+)(.*)$/ + @STACK_DELIMITER = ':' + + @ITEM_DELIMITER = '.' # Public Methods ############################################################################### @@ -26,25 +28,31 @@ module.exports = class InventoryParser inventory ?= new Inventory return inventory if not data? or data.length is 0 - lines = data.split '\n' - for line in lines - match = InventoryParser.ITEM_REGEX.exec line - name = if match? then match[2].trim() else line - quantity = if match? then parseInt(match[1]) else 1 + stacks = data.split InventoryParser.STACK_DELIMITER + for stackText in stacks + stackParts = stackText.split InventoryParser.ITEM_DELIMITER + if stackParts.length is 2 + quantity = parseInt stackParts[0] + slug = _.slugify stackParts[1] + else if stackParts.length is 1 + quantity = 1 + slug = _.slugify stackParts[0] + else + throw new Error "expected #{stackText} to have 0 or 1 parts" - if name.length > 0 - inventory.add _.slugify(name), quantity + if slug.length > 0 + inventory.add slug, quantity return inventory unparse: (inventory)-> if not @modPack? then throw new Error 'this.modPack is needed to unparse' - builder = new StringBuilder - for item in inventory.toList() - if _.isString item - builder.line @modPack.findName item + parts = [] + inventory.each (stack)-> + if stack.quantity is 1 + parts.push stack.slug else - builder.line item[0], ' ', @modPack.findName item[1] + parts.push "#{stack.quantity}#{InventoryParser.ITEM_DELIMITER}#{stack.slug}" - return builder.toString() \ No newline at end of file + return parts.join InventoryParser.STACK_DELIMITER diff --git a/src/scripts/models/item_page.coffee b/src/scripts/models/item_page.coffee index b3c992fca..e45380c0e 100644 --- a/src/scripts/models/item_page.coffee +++ b/src/scripts/models/item_page.coffee @@ -5,11 +5,12 @@ Copyright (c) 2014-2015 by Redwood Labs All rights reserved. ### -BaseModel = require './base_model' -CraftingPlan = require './crafting_plan' -CraftingTable = require './crafting_table' -{Event} = require '../constants' -ModPack = require './mod_pack' +BaseModel = require './base_model' +CraftingPlan = require './crafting_plan' +CraftingTable = require './crafting_table' +{Event} = require '../constants' +InventoryParser = require './inventory_parser' +ModPack = require './mod_pack' ######################################################################################################################## @@ -22,22 +23,27 @@ module.exports = class ItemPage extends BaseModel attributes.table ?= new CraftingTable plan:attributes.plan super attributes, options + @_parser = new InventoryParser + @modPack.on Event.change, => @_consumeParams() @on Event.change + ':params', => @_consumeParams() # Private Methods ############################################################################## _consumeParams: -> + logger.debug "consuming params: #{util.inspect(@params)}" return unless @params? @plan.want.clear() - if not @params?.name? + if not @params.inventoryText? @params = null else - item = @modPack.findItemByName @params.name, enableAsNeeded:true - return unless item? and item.isCraftable + inventory = @_parser.parse @params.inventoryText - quantity = if @params.quantity? then parseInt(@params.quantity) else 1 - @plan.want.add item.slug, quantity + inventory.each (stack)=> + item = @modPack.findItemByName stack.slug, enableAsNeeded:true + return unless item? and item.isCraftable + @plan.want.add stack.slug, stack.quantity + inventory.remove stack.slug - @params = null + if inventory.isEmpty then @params = null diff --git a/src/scripts/models/storage.coffee b/src/scripts/models/storage.coffee index b36864b46..d28ada82a 100644 --- a/src/scripts/models/storage.coffee +++ b/src/scripts/models/storage.coffee @@ -17,16 +17,25 @@ module.exports = class Storage # Public Methods ############################################################################### + load: (key)-> + value = @storage.getItem key + logger.verbose "loaded #{value} from #{key}" + return value + + store: (key, value)-> + @storage.setItem key, value + logger.verbose "stored #{value} into #{key}" + register: (key, model, properties...)-> modelData = @_models[key] if not modelData? then modelData = @_models[key] = model:model, properties:{} - makeStoreMethod = (k, m, p)=> return => @_store(k, m, p) + makeStoreMethod = (k, m, p)=> return => @_storeProperty(k, m, p) for property in properties continue if modelData.properties[property]? modelData.properties[property] = property - @_load key, model, property + @_loadProperty key, model, property model.on "change:#{property}", makeStoreMethod(key, model, property) unregister: (key, property)-> @@ -36,16 +45,13 @@ module.exports = class Storage # Private Methods ############################################################################## - _load: (key, model, property)-> - value = @storage.getItem "#{key}:#{property}" + _loadProperty: (key, model, property)-> + value = @load "#{key}:#{property}" value = JSON.parse(value) if value? - - logger.verbose "loaded #{value} from #{key}:#{property}" return unless value? model[property] = value - _store: (key, model, property)-> + _storeProperty: (key, model, property)-> value = JSON.stringify model[property] - @storage.setItem "#{key}:#{property}", value - logger.verbose "stored #{value} into #{key}:#{property}" + @store "#{key}:#{property}", value diff --git a/test/inventory_parser.test.coffee b/test/inventory_parser.test.coffee index ff730fedd..6f81721d6 100644 --- a/test/inventory_parser.test.coffee +++ b/test/inventory_parser.test.coffee @@ -28,15 +28,15 @@ describe 'inventory_parser.coffee', -> result.toList().should.eql ['wool'] it 'can parse a single item with quantity', -> - result = parser.parse '4 wool' + result = parser.parse '4.wool' result.toList().should.eql [[4, 'wool']] it 'can parse multiple mixed-type items', -> - result = parser.parse '4 Wool\n10 String\nBoat\n\n' + result = parser.parse '4.Wool:10.String:Boat' result.toList().should.eql ['boat', [10, 'string'], [4, 'wool']] it 're-uses the given inventory object', -> inventory = new Inventory inventory.add 'string', 8 - result = parser.parse '4 Wool', inventory + result = parser.parse '4.Wool', inventory result.toList().should.eql [[8, 'string'], [4, 'wool']]