class Interactor
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:
"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