• Jump To … +
    server.coffee src/actionknob.coffee src/autosem.coffee src/bitbucket_kba.coffee src/browserlog.coffee src/datareduction.coffee src/dci.coffee src/dciknob.coffee src/deeseeeye.coffee src/dnd.coffee src/doof.coffee src/formurla-mngr.coffee src/fractalpanel.coffee src/fractalpanel_test.coffee src/front.coffee src/ingestor.coffee src/kbabitbucket.coffee src/knobctrl.coffee src/lib_test.coffee src/nanoclock.coffee src/noodb.coffee src/noodbabstract.coffee src/noodbbrowser.coffee src/noodbbrowser_test.coffee src/noodbsec.coffee src/noorauth.coffee src/noorplugin.coffee src/noorquery.coffee src/noorvm.coffee src/noorwrite.coffee src/quadparser.coffee src/quadparsern3.coffee src/rbac.coffee src/reactor.coffee src/rebase.coffee src/rsrcidx.coffee src/sandboxactions.coffee src/screen_ctx.coffee src/spogi.coffee src/tabular_widget.coffee src/visctrl.coffee src/voicesknob.coffee src/whowhen.coffee src/xsd2native.coffee
  • reactor.coffee

  • ¶

    Reactor A reactor is a cell in a semantic spreadsheet.

    Notes: Consider using Jailed https://github.com/asvd/jailed or be inspired by it.

    Example formulae:

    1) ☾dog☽ = ☾good☽ + ☾god☽ 2) ☾dog☽ = ☾subj●predicate1☽ + ☾predicate2☽ # If a subject is not specified

    Concepts:

    • Data lookups are contained within moons: ☾☽
    • The left moon ☾ is expanded to ‘this.get(“‘
    • The right moon ☽ is expanded to ‘“).get_value()’
    • So ☾shoesize☽ becomes ‘this.get(“shoesize”).get_value()’
    • If there are two terms within moons they are subject and predicate: ☾bob●birthdate☽
    • If there is one term within moons it is understood to be a predicate: ☾shoesize☽
    • If there is no subject (eg ☾shoesize☽) then the formula relates to the current subject ie row.
    • So “☾workSessionDuration☽ = ☾workSessionEnd☽ - ☾workSessionStart☽” is expanded to the javascript: this.get(‘workSessionDuration’).set_formula(
      "return this.get_val('workSessionStart') + this.get_val('workSessionStart')")
      
      More realistically: ☾nrn:bob●foaf:firstName☽ is bob’s first name where nrn:bob ==> http://nooron.com/__/bob foaf:firstName ==> http://xmlns.com/foaf/0.1/firstName
    class Interactor
  • ¶

    Interactor are the @world argument to Reactor.constructor() and act as the interface between the Reactor and the Visualization it is in the context of. Interactor subclasses interface with particular visualizations.

      constructor: () ->
        @reactors = {}
      discover: (id) ->
        found = @reactors[id]
        if not found
          throw new Error("\"#{id}\" not found")
        found
      register: (reactor) ->
        @reactors[reactor.id] = reactor
    
    class Reactor
      constructor: (@id, @formula, @context) ->
        @err = null
        @dirty = true
        @inputs = {}
        @consumers = {}
        @value = null # should be null
        @set_func(new Function("throw new Error('no func assigned')"))
        @parse()
        if @context
          @context.register(@)
      L: '☾'
      left_expansion: 'this.get("'
      R: '☽'
      right_expansion: '").get_value()'
      S: '●' # separates subject from predicate
  • ¶
         new RegExp('☾([^☽]*)☽','u')  ES6 equiv
    
      gather_re: new RegExp('\u263e([^\u263d]*)\u263d','g')
      get: (id) ->
        input = @inputs[id]
        if input
          return input
        if @context
          input = @context.discover(id)
          if input
            @inputs[id] = input
            input.consumers[@.id] = @
            return input
        else
          throw new Error("no context so cannot .get('#{id}')")
      get_value: () ->
        if @dirty
          @fire()
        if @err
          return @err
        @value
      set_value: (v) ->
        @value = v
        @
      toString: ->
        return "#{@L}#{@id}#{@R} = #{@formula}"
      expand_ref: (ref_id) ->
        return @left_expansion + ref_id + @right_expansion
      parse: () ->
  • ¶

    TODO parsing the formula should discover the input names and create false stubs for them on @inputs

        if not @formula
          @dirty = true
          return
        match  = @formula.match(@gather_re)
        body = @formula
        match = @gather_re.exec(body)
        while match # loop through the body until all references are expanded
          if match[1]
            ref_id = match[1]
            @inputs[ref_id] = false # placeholder
            body = body.substr(0,match.index) +          # the beginning
                @expand_ref(ref_id) +
                body.substr(match.index + ref_id.length + 2) # the remainder
          match = @gather_re.exec(body)
        @body = "return " + body
        @set_func(new Function(@body))
      set_func: (f) ->
        @func = f     # it is not enough to attach it
        @func.bind(@) # it must also be bound to this so this.get_value() can work
      fire: -> # fire is called by a reactors outputs
        @started = Date.now()
        try
          v = @func()
          @set_value(v)
          @err = null
        catch e
  • ¶

    @value = e.toString()

          @err = e
        @stopped = Date.now()
        @dirty = false
        @update_consumers()
        @
      input: (id) -> # return input identified by id
        input = @inputs[id]
        if not input?
          input = @context.get_reactor(id)
          if not input?
            throw new Error("'#{id}' not found")
          @inputs[id] = input
        return input
      update_consumers: ->
        for id, consumer of @consumers
          consumer.fire()
        @
    
    class ReactorWithPuppet extends Reactor
  • ¶

    puppet: (puppet) -> # a puppet is (optionally) manipulated by the reactor if puppet? @_puppet = puppet return @_puppet

      constructor: ->
        super
        @_puppet_cb = null
      set_value: ->
        super
        console.log("set_value('#{value}')")
        @update_puppet()
        @
      update_puppet: ->
        cb = @puppet_set_value_cb()
        if cb
          cb(@value)
      puppet_getter: (cb) ->
        if cb?
          @_puppet_getter = cb
        return @_puppet_getter
      puppet_setter: (cb) ->
        if cb?
          @_puppet_setter = cb
        return @_puppet_setter
    
    class TabularInteractor extends Interactor
  • ¶

    This is an Interactor which interfaces with the TabularVisualizationController

      XXXXX_get_reactor: (id) ->
        reactor = @reactors[id] # the criterion_id normally
        if not reactor?
          reactor = new Reactor(null, @)
          @reactors[id] = reactor
        return reactor
      spawn_reactor: (datum, formula) ->
        id = datum.id()
        console.log("spawn_reactor('#{id}')")
        reactor = new ReactorWithPuppet(id, formula, @)
        reactor.puppet_setter(datum.set_value)
        reactor.puppet_getter(datum.value) # TODO should this be the native value?
    
    (exports ? this).Reactor = Reactor
    (exports ? this).Interactor = Interactor
    (exports ? this).TabularInteractor = TabularInteractor