WFTDA/bouttime

View on GitHub
app/scripts/dispatcher/app_dispatcher.coffee

Summary

Maintainability
Test Coverage
invariant = require 'invariant'
Promise = require 'bluebird'
config = require '../config'
constants = require '../constants'
IO = require 'socket.io-client'
class AppDispatcher
  constructor: () ->
    @_lastId = 1
    @_callbacks = {}
    @_promises = {}
    @_dispatch = Promise.resolve()
    @_timing = {}
    @_delays = []
    @_delay = 0
    @_socket = IO(config.socketUrl)
    @_socket.on 'app dispatcher', (payload) =>
      if payload.sourceDelay?
        payload.destinationDelay = @_delay
      @dispatch(payload)
    @_socket.on 'connected', () =>
      console.log "connected"
      @syncClocks()
    @_socket.on "clocks synced", (args) =>
      @clocksSynced(args)
  syncGame: (gameId) ->
    @_socket.emit 'sync game', gameId: gameId
  syncClocks: () ->
    @_timing.A = new Date().getTime()
    @_socket.emit 'sync clocks', {}
  clocksSynced: (args) =>
    @_timing.B = new Date().getTime()
    @_timing.X = args.timeX
    @_timing.Y = args.timeY
    @_delays.push(@_timing.B - @_timing.A - (@_timing.Y - @_timing.X))
    @_delay = @_delays.reduce((b,c)->
      return b+c
    )/@_delays.length
    console.log "Delay is #{@_delay}ms"
    setTimeout(() =>
      @syncClocks()
    ,constants.CLOCK_SYNC_SAMPLE_DURATION_IN_MS*constants.CLOCK_SYNC_SAMPLE_DURATION_MULTIPLIER**@_delays.length)
  register: (callback) ->
    id = @_lastId++
    @_callbacks[id] = callback
    id
  unregister: (id) ->
    invariant(
      @_callbacks[id],
      'Dispatcher.unregister(...) `%s` does not map to a registered callback.',
      id)
    delete this_callbacks[id];
  waitFor: (ids) ->
    invariant(
      @isDispatching(),
      'Dispatcher.waitFor(...): Must be invoked while dispatching.')
    Promise.map ids, (id) =>
      invariant(
        @_callbacks[id],
        'Dispatcher.waitFor(...): `%s` does not map to a registered callback.',
        id)
      @_promises[id]
  dispatch: (payload) ->
    console.log payload
    @_dispatch = @_dispatch.then =>
      @_promises = {}
      for id, callback of @_callbacks
        @_promises[id] = callback(payload)
      @_promises
    .props()
  isDispatching: () ->
    @_dispatch?.isPending()
  emit: (payload) ->
    @_socket.emit('app dispatcher', payload)
  dispatchAndEmit: (payload) ->
    @dispatch(payload)
    @emit(payload)
  isConnected: () ->
    @_socket.connected
  addConnectionListener: (listener) ->
    for evt in ['connect', 'disconnect', 'reconnect']
      @_socket.on evt, listener
  removeConnectionListener: (listenr) ->
    for evt in ['connect', 'disconnect', 'reconnect']
      @_socket.removeListener evt, listener
module.exports = new AppDispatcher()