Load all data files from a single archive

This commit is contained in:
Andrew Miner
2016-04-27 22:47:44 -07:00
parent 35bb12de6a
commit 7d83552013
7 changed files with 179 additions and 14 deletions
+21 -9
View File
@@ -19,10 +19,10 @@ module.exports = class BaseModel extends Backbone.Model
continue if name is 'id'
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
@fileCache = options.fileCache or null
@loading = null
@logEvents = options.logEvents or false
@state = c.modelState.unloaded
@loading = null
@state = c.modelState.unloaded
Object.defineProperties this,
isUnloaded: { get:-> @state is c.modelState.unloaded }
@@ -60,12 +60,24 @@ module.exports = class BaseModel extends Backbone.Model
@state = c.modelState.loading
@trigger c.event.request, this
@loading = w.promise (resolve, reject)=>
$.ajax
url: url
dataType: 'text'
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
loadFromServer = =>
w.promise (resolve, reject)=>
$.ajax
url: url
dataType: 'text'
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
if @fileCache?
@loading = @fileCache.loading.then =>
if @fileCache.hasFile url
@onLoadSucceeded @fileCache.getFile(url), 'success', {url:url}
return w.resolve(true)
else
@loading = loadFromServer()
else
@loading = loadFromServer()
@loading.catch (e)-> # do nothing
return @loading
+3 -3
View File
@@ -1,9 +1,9 @@
###
#
# Crafting Guide - event_recorder.coffee
#
# Copyright (c) 2014-2015 by Redwood Labs
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
###
#
util = require 'util'
+1
View File
@@ -129,6 +129,7 @@ module.exports = class Mod extends BaseModel
@_modVersions.push modVersion
@listenTo modVersion, c.event.change, => @trigger c.event.change, this
modVersion.fileCache = this.fileCache
modVersion.mod = this
@trigger c.event.add + ':modVersion', modVersion, this
+86
View File
@@ -0,0 +1,86 @@
#
# Crafting Guide - file_cache.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
########################################################################################################################
module.exports = class FileCache extends Backbone.Events
@::FILE_TOKEN = '#file='
constructor: (url)->
@_ajax = $.ajax
@_files = {}
@_loading = w.resolve(true)
if url? then @loadArchive(url).catch(->)
# Public Methods ###############################################################################
getFile: (file)->
return null unless @hasFile file
return @_files[file]
hasFile: (file)->
return @_files[file]?
loadArchive: (url)->
if not _.isFunction(@_ajax) then throw new Error '$.ajax is required'
newLoading = w.promise (resolve, reject)=>
@_ajax
url: url
dataType: 'text'
success: (text, status, xhr)=> resolve @_onLoadSuccess text, status, xhr
error: (xhr, status, error)=> resolve @_onLoadError error, status, xhr
@_loading = w.join @_loading, newLoading
# Property Methods #############################################################################
Object.defineProperties @prototype,
loading:
get: -> return @_loading
# Private Methods ##############################################################################
_onLoadError: (error, status, xhr)->
console.error "Failed to load archive: #{xhr.responseText}"
return false
_onLoadSuccess: (text, status, xhr)->
return @_parseArchive text
_parseArchive: (text)->
file = null
tokenIndex = nameStartIndex = nameEndIndex = fileStartIndex = fileEndIndex = 0
fileCount = 0
while true
tokenIndex = text.indexOf @FILE_TOKEN, fileStartIndex
if tokenIndex is -1
if file?
@_files[file] = text.substring fileStartIndex, text.length
fileCount += 1
break
if file?
fileEndIndex = tokenIndex - 1
@_files[file] = text.substring fileStartIndex, fileEndIndex
fileCount += 1
nameStartIndex = tokenIndex + @FILE_TOKEN.length
nameEndIndex = text.indexOf '\n', nameStartIndex
if nameEndIndex is -1
file = text.substring nameStartIndex, text.length
@_files[file] = ''
break
file = text.substring nameStartIndex, nameEndIndex
fileStartIndex = nameEndIndex + '\n'.length
return fileCount > 0
@@ -0,0 +1,63 @@
FileCache = require './file_cache'
########################################################################################################################
describe 'file_cache.coffee', ->
beforeEach ->
@cache = new FileCache
makeTestAjax = (text)->
return (options)->
options.success text, 'success', {url:options.url}
it 'can load an archive with a single file', ->
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie delta'
@cache.loadArchive 'http://test'
.then =>
@cache.hasFile('alpha').should.equal true
@cache.getFile('alpha').should.equal 'bravo charlie delta'
it 'can load an archive with multiple files', ->
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
@cache.loadArchive 'http://test'
.then =>
@cache.hasFile('alpha').should.equal true
@cache.getFile('alpha').should.equal 'bravo charlie'
@cache.hasFile('delta').should.equal true
@cache.getFile('delta').should.equal 'echo foxtrot'
it 'can cope with an empty file in the middle of an archive', ->
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\n#file=echo\nfoxtrot golf'
@cache.loadArchive 'http://test'
.then =>
@cache.hasFile('alpha').should.equal true
@cache.getFile('alpha').should.equal 'bravo charlie'
@cache.hasFile('delta').should.equal true
@cache.getFile('delta').should.equal '\n'
@cache.hasFile('echo').should.equal true
@cache.getFile('echo').should.equal 'foxtrot golf'
it 'can cope with an empty file at the end of an archive', ->
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta'
@cache.loadArchive 'http://test'
.then =>
@cache.hasFile('alpha').should.equal true
@cache.getFile('alpha').should.equal 'bravo charlie'
@cache.hasFile('delta').should.equal true
@cache.getFile('delta').should.equal ''
it 'can load multiple, non-overlapping archives', ->
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
@cache.loadArchive 'http://test'
@cache._ajax = makeTestAjax '#file=golf\nhotel india'
@cache.loadArchive 'http://test2'
.then =>
@cache.hasFile('alpha').should.equal true
@cache.getFile('alpha').should.equal 'bravo charlie'
@cache.hasFile('delta').should.equal true
@cache.getFile('delta').should.equal 'echo foxtrot'
@cache.hasFile('golf').should.equal true
@cache.getFile('golf').should.equal 'hotel india'