Code coverage report for code/models/codap-connect.coffee

Statements: 7.81% (5 / 64)      Branches: 0% (0 / 18)      Functions: 6.67% (1 / 15)      Lines: 6.67% (4 / 60)      Ignored: none     

All files » code/models/ » codap-connect.coffee
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 1781 1 1 1                                                                                                                                                                                                                                                                                                                                                            
IframePhoneRpcEndpoint = (require 'iframe-phone').IframePhoneRpcEndpoint
CodapStore = require "../stores/codap-store"
tr = require '../utils/translate'
module.exports = class CodapConnect
 
  name: 'Building Models Tool'
 
  codapPhone: null
 
  initAccomplished: false
 
  @instances: {} # map of context -> instance
 
  @instance: (context) ->
    CodapConnect.instances[context] ?= new CodapConnect context
    CodapConnect.instances[context]
 
  constructor: (context) ->
    log.info 'CodapConnect: initializing'
    GraphStore = require '../stores/graph-store'
    @graphStore = GraphStore.store
 
    @codapPhone = new IframePhoneRpcEndpoint( @codapRequestHandler,
      'codap-game', window.parent )
 
    @codapPhone.call( {
      action: 'initGame'
      args:
        name: @name
        dimensions:
          width: 800
          height: 600
        collections: [
          {
            name: 'Simulation'
            attrs: [
              {
                name: 'steps'
                type: 'numeric'
                description: tr '~CODAP.SIMULATION.STEPS.DESCRIPTION'
                precision: 0
              }
            ]
          }
        ]
        contextType: 'DG.DataContext'
    }, @initGameHandler)
 
 
 
  sendSimulationData: (data) ->
    # First column definition is the time index
    sampleDataAttrs = [
      {
        name: "time"
        type: "numeric"
      }
    ]
 
    # Append node names to column descriptions.
    _.each data.nodeNames, (name) ->
      sampleDataAttrs.push
        name: name
        type: 'numeric'
 
    # Fill in the sample data values (node values array)
    sampleData = _.map data.frames, (frame) ->
      sample     = [frame.time]
      _.each frame.nodes, (n) -> sample.push n.value
      sample
 
    # see: https://github.com/concord-consortium/codap/wiki/Data-Interactive-API#createcollection
    @codapPhone.call
      action: 'createCollection'
      args:
        name: 'Samples'
        attrs: sampleDataAttrs
 
    # called by CODAP when 'openCase' is received.
    openCaseCallback = (result) =>
      if result
        if result.success
          @codapPhone.call
            action: 'createCases'
            args: {
              collection: 'Samples',
              parent: result.caseID,
              values: sampleData
            }
        else
          log.info "CODAP returned an error on 'createCase'"
      else
        log.info "Unable to call 'createCase' in CODAP (phone timeout?)"
 
    @codapPhone.call( {
      action: 'openCase'
      args: {
        collection: 'Simulation',
        values: [data.steps]
        }
    }, openCaseCallback)
 
  sendUndoableActionPerformed: ->
    @codapPhone.call
      action: 'undoableActionPerformed'
 
  codapRequestHandler: (cmd, callback) =>
    operation = cmd.operation
    args = cmd.args
    paletteManager = require '../stores/palette-store'
    switch operation
      when 'saveState'
        log.info 'Received saveState request from CODAP.'
        callback
          success: true
          state: @graphStore.serialize paletteManager.store.palette
 
      when 'restoreState'
        log.info 'Received restoreState request from CODAP.'
        @graphStore.deleteAll()
        @graphStore.loadData args.state
        callback
          success: true
 
      when 'externalUndoAvailable'
        log.info 'Received externalUndoAvailable request from CODAP.'
        CodapStore.actions.hideUndoRedo()
 
      when 'undoAction'
        log.info 'Received undoAction request from CODAP.'
        successes = @graphStore.undo()
        callback {success: @reduceSuccesses successes}
 
      when 'redoAction'
        log.info 'Received redoAction request from CODAP.'
        successes = @graphStore.redo()
        callback {success: @reduceSuccesses successes}
 
      else
        log.info 'Unknown request received from CODAP: ' + operation
 
  # undo/redo events can return an array of successes
  # this reduces that array to true iff every element is true
  reduceSuccesses: (successes) ->
    return successes unless successes.length
    return false for s in successes when s is false
    return true
 
  initGameHandler: (result) =>
    if result and result.success
      @initAccomplished = true
      CodapStore.actions.codapLoaded()
 
  #
  # Requests a CODAP action, if the Building Models tool is configured to reside
  # in CODAP. For actions that may be requested, see
  # https://github.com/concord-consortium/codap/wiki/Data-Interactive-API .
  #
  # Similarly to the Google Drive API, this method will report results of its
  # asynchronous request either by invoking the provided callback, or, if no
  # callback is provided, will return a Promise.
  #
  # Example:
  #   codapConnect.request('logAction', {formatStr: 'test message'}).then ->
  #     log.info 'received log reply!'
  #
 
  request: (action, args, callback) ->
    promise = new Promise (resolve, reject) =>
      @codapPhone.call { action: action, args: args }, (reply) ->
        if callback
          callback reply
        if reply and reply.success
          resolve reply
        else
          reject 'CODAP request error'
    promise