nbarikipoulos/poppy-robot-core

View on GitHub
lib/script/ScriptEngine.js

Summary

Maintainability
A
0 mins
Test Coverage
'use strict'

const { chainPromises } = require('../../util/misc')

/**
 * Script execution engine.
 * @memberof module:poppy-robot-core
 * @inner
 */
class ScriptEngine {
  constructor (poppy) {
    this._poppy = poppy
  }

  /**
   * Execute Scripts.
   * @param {...module:poppy-robot-core~Script | Array.<module:poppy-robot-core~Script>} scripts - The scripts to execute
   * @return {Promise.<null>}
  */
  exec (...scripts) {
    const _scripts = scripts.flat(Infinity)
    return chainPromises(
      _scripts.map(script => _ => this._exec(script))
    )
  }

  /** @private */
  _exec (script) {
    const actionHandlers = script._actionHandlers

    // Transform Script objects to an array of object of kind { motor, id, values }
    const elements = actionHandlers
      .map(aHandler => {
        // The target motors
        const motors = this._poppy.toMotorNames(aHandler.motors)
        return aHandler.actions.map(action => this._mapAction(motors, action))
      })
      .flat(Infinity)

    const ppromises = elements.map(elt => {
      const object = elt.motor === undefined
        ? this._poppy
        : this._poppy[elt.motor]

      return _ => object[elt.id](...elt.values)
        .catch(err => {
          const msg = elt.motor === undefined
            ? `on motor ${elt.motor}`
            : 'poppy'
          console.log(`Error: Unable to perform '${elt.id}' on ${msg}.\n${err.message}`)
        })
    })

    return chainPromises(ppromises)
  }

  /** @private */
  _mapAction (motors, action) {
    let elements = motors
    let values = Object.values(action.param)

    switch (action.id) {
      case 'wait' :
        // 'wait' action should only apply once, not on every selected motors
        elements = [motors[0]]
        break
      case 'move':
      case 'rotate':
        elements = ['poppy']
        values = [{ motors, ...action.param }]
        break
      default:
        // Do nothing
    }

    return elements.map(elt => ({ // aka motor name or 'poppy'
      motor: elt === 'poppy' ? undefined : elt,
      id: action.id,
      values
    }))
  }
}

// ///////////////////////
// ///////////////////////
// Public API
// ///////////////////////
// ///////////////////////

module.exports = ScriptEngine