diff --git a/app/lib/mscript/index.js b/app/lib/mscript/index.js index bb05449..cf49273 100644 --- a/app/lib/mscript/index.js +++ b/app/lib/mscript/index.js @@ -2,49 +2,8 @@ /** @module lib/mscript */ -let fs; -let input; - -/** object mscript */ -const mscript = {}; - -/** - * Check for the presence of specific arguments in process - * argv - * - * @param {string} shrt Short version of argument or flag - * @param {string} lng Long version of argument or flag - * - * @return {boolean} Is flag present - */ -mscript.arg = function arg (shrt, lng) { - if (process.argv.indexOf(shrt) !== -1 || - process.argv.indexOf(lng) !== -1) { - return true; - } - return false; -}; - -/** - * Check for the position of specific arguments in process - * argv - * - * @param {string} shrt Short version of argument or flag - * @param {string} lng Long version of argument or flag - * - * @return {boolean} Position of arg or flag, for locating input - */ -mscript.arg_pos = function arg_pos (shrt, lng) { - var pos = -1; - pos = process.argv.indexOf(shrt); - if (pos === -1) { - pos = process.argv.indexOf(lng); - } - return pos; -}; - -mscript.black = '0,0,0'; -mscript.cmd = [ +const BLACK = '0,0,0'; +const CMD = [ 'CF', 'PF', 'BF', @@ -52,10 +11,10 @@ mscript.cmd = [ 'PB', 'BB' ]; -mscript.alts = { +const ALTS = { 'CF' : ['CAMERA FORWARD', 'CAM FORWARD'], 'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'], - 'BF': ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'], + 'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'], 'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'], 'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'], 'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'], @@ -63,392 +22,318 @@ mscript.alts = { 'F ' : ['FADE'] }; -mscript.state = {}; +class Mscript { + constructor () { + this.output = {}; + } -/** - * Clear the state object - */ -mscript.state_clear = function state_clear () { - mscript.state = { - cam : 0, - proj : 0, - color : '', - loops : [], - rec : -1 - }; -}; -/** - * - */ -mscript.alts_unique = function alts_unique () { - var ids = Object.keys(mscript.alts), - all = []; - for (var i = 0; i < ids.length; i++) { - if (all.indexOf(ids[i]) === -1) { - all.push(ids[i]); - } else { - mscript.fail("Can't compile"); + /** + * Clear the state of the script + */ + clear () { + this.cam = 0; + this.proj = 0; + this.color = ''; + this.loops = []; + this.rec = -1; + this.output = {}; + } + /** + * Main function, accepts multi-line string, parses into lines + * and interprets the instructions from the text. Returns an array + * of steps to be fed into the mcopy. + */ + interpret (text, callback) { + this.clear() + + if (typeof text === 'undefined') { + return this.fail('No input'); } - } -}; -/** - * - */ -mscript.interpret = function interpret (text, callback) { - mscript.state_clear(); - if (typeof text === 'undefined') { - mscript.fail('No input'); - } - var lines = text.split('\n'), - two = '', - arr = [], - light = [], - target = 0, - dist = 0, //? - output = {}; - for (var i = 0; i < lines.length; i++) { - lines[i] = lines[i].replace(/\t+/g, ""); //strip tabs - lines[i] = lines[i].trim(); //remove excess whitespace before and after command - two = lines[i].substring(0, 2); - if (mscript.cmd.indexOf(two) !== -1) { - if (mscript.state.loops.length > 0) { - //hold generated arr in state loop array - mscript.state.loops[mscript.state.rec].arr - .push.apply(mscript.state.loops[mscript.state.rec].arr, - mscript.str_to_arr(lines[i], - two)); - mscript.state.loops[mscript.state.rec].light - .push.apply(mscript.state.loops[mscript.state.rec].light, - mscript.light_to_arr(lines[i], - two)); - } else { - arr.push.apply(arr, mscript.str_to_arr(lines[i], two)); - light.push.apply(light, mscript.light_to_arr(lines[i], two)) - } + //split string into lines, each containing a command + let lines = text.split('\n'); + + let two = ''; + + let arr = []; + + let light = []; + + let target = 0;// move to target using CAM # or PROJ # + + let dist = 0; //? - } else if (lines[i].substring(0, 4) === 'LOOP') { - mscript.state.rec++; - mscript.state.loops[mscript.state.rec] = { - arr : [], - light : [], - cam : 0, - proj : 0, - cmd : lines[i] + '' - }; - } else if (lines[i].substring(0, 2) === 'L ') { - mscript.light_state(lines[i]); - } else if (lines[i].substring(0, 3) === 'END') { - for (var x = 0; x < mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd); x++) { - if (mscript.state.rec === 0) { - arr.push.apply(arr, mscript.state.loops[mscript.state.rec].arr); - light.push.apply(light, mscript.state.loops[mscript.state.rec].light); - } else if (mscript.state.rec >= 1) { - mscript.state.loops[mscript.state.rec - 1].arr - .push.apply(mscript.state.loops[mscript.state.rec - 1].arr, - mscript.state.loops[mscript.state.rec].arr); - mscript.state.loops[mscript.state.rec - 1].light - .push.apply(mscript.state.loops[mscript.state.rec - 1].light, - mscript.state.loops[mscript.state.rec].light); - } - } - mscript.state_update('END', mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd)); - delete mscript.state.loops[mscript.state.rec]; - mscript.state.rec--; - } else if (lines[i].substring(0, 3) === 'CAM') { //directly go to that frame (black?) - target = parseInt(lines[i].split('CAM ')[1]); - if (mscript.state.loops.length > 0) { - if (target > mscript.state.cam) { - dist = target - mscript.state.cam; - for (var x = 0; x < dist; x++) { - mscript.state.loops[mscript.state.rec].arr.push('BF'); - mscript.state.loops[mscript.state.rec].light.push(mscript.black); - mscript.state_update('BF'); - } + for (let line of lines) { + line = line.replace(/\t+/g, ""); //strip tabs + line = line.trim(); //remove excess whitespace before and after command + two = line.substring(0, 2); + if (CMD.indexOf(two) !== -1) { + + if (this.loops.length > 0) { + //hold generated arr in state loop array + this.loops[this.rec].arr + .push.apply(this.loops[this.rec].arr, + this.str_to_arr(line, + two)); + this.loops[this.rec].light + .push.apply(this.loops[this.rec].light, + this.light_to_arr(line, + two)); } else { - dist = mscript.state.cam - target; - for (var x = 0; x < dist; x++) { - mscript.state.loops[mscript.state.rec].arr.push('BB'); - mscript.state.loops[mscript.state.rec].light.push(mscript.black); - mscript.state_update('BB'); + arr.push.apply(arr, this.str_to_arr(line, two)); + light.push.apply(light, this.light_to_arr(line, two)) + } + + } else if (line.substring(0, 4) === 'LOOP') { + this.rec++; + this.loops[this.rec] = { + arr : [], + light : [], + cam : 0, + proj : 0, + cmd : line + '' + }; + } else if (line.substring(0, 2) === 'L ') { + this.light_state(line); + } else if (line.substring(0, 3) === 'END') { + for (var x = 0; x < this.loop_count(this.loops[this.rec].cmd); x++) { + if (this.rec === 0) { + arr.push.apply(arr, this.loops[this.rec].arr); + light.push.apply(light, this.loops[this.rec].light); + } else if (this.rec >= 1) { + this.loops[this.rec - 1].arr + .push.apply(this.loops[this.rec - 1].arr, + this.loops[this.rec].arr); + this.loops[this.rec - 1].light + .push.apply(this.loops[this.rec - 1].light, + this.loops[this.rec].light); } } - } else { - if (target > mscript.state.cam) { - dist = target - mscript.state.cam; - for (var x = 0; x < dist; x++) { - arr.push('BF'); - light.push(mscript.black); - mscript.state_update('BF'); - } + this.update('END', this.loop_count(this.loops[this.rec].cmd)); + delete this.loops[this.rec]; + this.rec--; + } else if (line.substring(0, 3) === 'CAM') { //directly go to that frame (black?) + target = parseInt(line.split('CAM ')[1]); + if (this.loops.length > 0) { + if (target > this.cam) { + dist = target - this.cam; + for (var x = 0; x < dist; x++) { + this.loops[this.rec].arr.push('BF'); + this.loops[this.rec].light.push(BLACK); + this.update('BF'); + } + } else { + dist = this.cam - target; + for (var x = 0; x < dist; x++) { + this.loops[this.rec].arr.push('BB'); + this.loops[this.rec].light.push(BLACK); + this.update('BB'); + } + } } else { - dist = mscript.state.cam - target; - for (var x = 0; x < dist; x++) { - arr.push('BB'); - light.push(mscript.black); - mscript.state_update('BB'); + if (target > this.cam) { + dist = target - this.cam; + for (var x = 0; x < dist; x++) { + arr.push('BF'); + light.push(BLACK); + this.update('BF'); + } + } else { + dist = this.cam - target; + for (var x = 0; x < dist; x++) { + arr.push('BB'); + light.push(BLACK); + this.update('BB'); + } } } - } - } else if (lines[i].substring(0, 4) === 'PROJ') { //directly go to that frame - target = parseInt(lines[i].split('PROJ ')[1]); - if (mscript.state.loops.length > 0) { - if (target > mscript.state.proj) { - dist = target - mscript.state.proj; - for (var x = 0; x < dist; x++) { - mscript.state.loops[mscript.state.rec].arr.push('PF'); - mscript.state.loops[mscript.state.rec].light.push(''); - mscript.state_update('PF'); - } + } else if (line.substring(0, 4) === 'PROJ') { //directly go to that frame + target = parseInt(line.split('PROJ ')[1]); + if (this.loops.length > 0) { + if (target > this.proj) { + dist = target - this.proj; + for (var x = 0; x < dist; x++) { + this.loops[this.rec].arr.push('PF'); + this.loops[this.rec].light.push(''); + this.update('PF'); + } + } else { + dist = this.proj - target; + for (var x = 0; x < dist; x++) { + this.loops[this.rec].arr.push('PB'); + this.loops[this.rec].light.push(''); + this.update('PB'); + } + } } else { - dist = mscript.state.proj - target; - for (var x = 0; x < dist; x++) { - mscript.state.loops[mscript.state.rec].arr.push('PB'); - mscript.state.loops[mscript.state.rec].light.push(''); - mscript.state_update('PB'); - } + if (target > this.proj) { + dist = target - this.proj; + for (var x = 0; x < dist; x++) { + arr.push('PF'); + light.push(''); + this.update('PF'); + } + } else { + dist = this.proj - target; + for (var x = 0; x < dist; x++) { + arr.push('PB'); + light.push(''); + this.update('PB'); + } + } } + } else if (line.substring(0, 3) === 'SET') { //set that state + if (line.substring(0, 7) === 'SET CAM') { + this.cam = parseInt(line.split('SET CAM')[1]); + } else if (line.substring(0, 8) === 'SET PROJ') { + this.proj = parseInt(line.split('SET PROJ')[1]); + } + } else if (line.substring(0, 1) === '#' || line.substring(0, 2) === '//') { + //comments + //ignore while parsing + } + } + + + this.output.success = true; + this.output.arr = arr; //all instructions + this.output.light = light; //all light instructions + this.output.cam = this.cam; + this.output.proj = this.proj; + + + if (typeof callback !== 'undefined') { + //should only be invoked by running mscript.tests() + callback(this.output); + } + } + last_loop () { + return this.loops[this.loops.length - 1]; + } + parent_loop () { + return this.loops[this.loops.length - 2]; + } + loop_count (str) { + return parseInt(str.split(' ')[1]); + } + fade_count (str) { + return parseInt(str.split(' ')[1]); + } + /** + * Increase the state of a specific object, such as the camera/projector, + * by the value defined in val + */ + update (cmd, val = 1) { + if (cmd === 'END') { + //I don't understand this loop + for (let i = 0; i < val; i++) { + if (this.rec === 0) { + this.cam += this.loops[this.rec].cam; + this.proj += this.loops[this.rec].proj; + } else if (this.rec >= 1) { + this.loops[this.rec - 1].cam += this.loops[this.rec].cam; + this.loops[this.rec - 1].proj += this.loops[this.rec].proj; + } + } + } else if (cmd === 'CF') { + if (this.loops.length < 1) { + this.cam += val; } else { - if (target > mscript.state.proj) { - dist = target - mscript.state.proj; - for (var x = 0; x < dist; x++) { - arr.push('PF'); - light.push(''); - mscript.state_update('PF'); - } - } else { - dist = mscript.state.proj - target; - for (var x = 0; x < dist; x++) { - arr.push('PB'); - light.push(''); - mscript.state_update('PB'); - } - } + this.loops[this.rec].cam += val; } - } else if (lines[i].substring(0, 3) === 'SET') { //set that state - if (lines[i].substring(0, 7) === 'SET CAM') { - mscript.state.cam = parseInt(lines[i].split('SET CAM')[1]); - } else if (lines[i].substring(0, 8) === 'SET PROJ') { - mscript.state.proj = parseInt(lines[i].split('SET PROJ')[1]); + } else if (cmd === 'CB') { + if (this.loops.length < 1) { + this.cam -= val; + } else { + this.loops[this.rec].cam--; } - } else if (lines[i].substring(0, 1) === '#' || lines[i].substring(0, 2) === '//') { - //comments - //ignore while parsing - } - } - output.success = true; - output.arr = arr; - output.light = light; - output.cam = mscript.state.cam; - output.proj = mscript.state.proj; - if (typeof callback !== 'undefined') { - //should only be invoked by running mscript.tests() - callback(output); - } else { - return mscript.output(output); - } -}; -/** - * - */ -mscript.last_loop = function last_loop () { - return mscript.state.loops[mscript.state.loops.length - 1]; -}; -/** - * - */ -mscript.parent_loop = function parent_loop () { - return mscript.state.loops[mscript.state.loops.length - 2]; -}; -/** - * - */ -mscript.state_update = function state_update (cmd, val) { - if (cmd === 'END') { - for (var i = 0; i < val; i++) { - if (mscript.state.rec === 0) { - mscript.state.cam += mscript.state.loops[mscript.state.rec].cam; - mscript.state.proj += mscript.state.loops[mscript.state.rec].proj; - } else if (mscript.state.rec >= 1) { - mscript.state.loops[mscript.state.rec - 1].cam += mscript.state.loops[mscript.state.rec].cam; - mscript.state.loops[mscript.state.rec - 1].proj += mscript.state.loops[mscript.state.rec].proj; - } - } - } else if (cmd === 'CF') { - if (mscript.state.loops.length < 1) { - mscript.state.cam++; - } else { - mscript.state.loops[mscript.state.rec].cam++; - } - } else if (cmd === 'CB') { - if (mscript.state.loops.length < 1) { - mscript.state.cam--; - } else { - mscript.state.loops[mscript.state.rec].cam--; - } - } else if (cmd === 'PF') { - if (mscript.state.loops.length < 1) { - mscript.state.proj++; - } else { - mscript.state.loops[mscript.state.rec].proj++; - } - } else if (cmd === 'PB') { - if (mscript.state.loops.length < 1) { - mscript.state.proj--; - } else { - mscript.state.loops[mscript.state.rec].proj--; - } - } else if (cmd === 'BF') { - if (mscript.state.loops.length < 1) { - mscript.state.cam++; - } else { - mscript.state.loops[mscript.state.rec].cam++; - } - } else if (cmd === 'BB') { - if (mscript.state.loops.length < 1) { - mscript.state.cam--; - } else { - mscript.state.loops[mscript.state.rec].cam++; - } - } else if (cmd === 'L ') { + } else if (cmd === 'PF') { + if (this.loops.length < 1) { + this.proj += val; + } else { + this.loops[this.rec].proj += val; + } + } else if (cmd === 'PB') { + if (this.loops.length < 1) { + this.proj -= val; + } else { + this.loops[this.rec].proj--; + } + } else if (cmd === 'BF') { + if (this.loops.length < 1) { + this.cam += val; + } else { + this.loops[this.rec].cam += val; + } + } else if (cmd === 'BB') { + if (this.loops.length < 1) { + this.cam -= val; + } else { + this.loops[this.rec].cam -= val; + } + } else if (cmd === 'L ') { - } -}; -/** - * - */ -mscript.str_to_arr = function str_to_arr (str, cmd) { - var cnt = str.split(cmd), - c = parseInt(cnt[1]), - arr = []; - if (cnt[1] === '') { - c = 1; - } else { - c = parseInt(cnt[1]); - } - for (var i = 0; i < c; i++) { - arr.push(cmd); - mscript.state_update(cmd); - } - return arr; -}; -/** - * - */ -mscript.light_state = function light_state (str) { - //add parsers for other color spaces - var color = str.replace('L ', '').trim(); - mscript.state.color = color; -}; -/** - * - */ -mscript.light_to_arr = function light_to_arr (str, cmd) { - var cnt = str.split(cmd), - c = parseInt(cnt[1]), - arr = []; - if (cnt[1] === '') { - c = 1; - } else { - c = parseInt(cnt[1]); - } - for (var i = 0; i < c; i++) { - if (cmd === 'CF' - || cmd === 'CB') { - arr.push(mscript.state.color); - } else if (cmd === 'BF' - || cmd === 'BB') { - arr.push(mscript.black); - } else { - arr.push(''); } } - return arr; -}; -/** - * - */ -mscript.loop_count = function loop_count (str) { - return parseInt(str.split(' ')[1]); -}; -mscript.fade_count = function fade_count (str) { - return parseInt(str.split(' ')[1]); + /** + * Split string on command, extract any integers from string + */ + str_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + arr = new Array(c).fill(cmd); + this.update(cmd, c); + return arr; + } + /** + * + */ + light_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + for (var i = 0; i < c; i++) { + if (cmd === 'CF' + || cmd === 'CB') { + arr.push(this.color); + } else if (cmd === 'BF' + || cmd === 'BB') { + arr.push(BLACK); + } else { + arr.push(''); + } + } + return arr; + } + /** + * + */ + light_state (str) { + //add parsers for other color spaces + const color = str.replace('L ', '').trim(); + this.color = color; + } + + /** + * + */ + fail (msg) { + throw new Error(msg); + } } -/** - * - */ -mscript.fail = function fail (reason) { - console.error(JSON.stringify({success: false, error: true, msg : reason})); - if (process) process.exit(); -}; -/** - * - */ -mscript.output = function output (data) { - var json = true; //default - if (mscript.arg('-j', '--json')) { - json = true; - } - if (mscript.arg('-t', '--text')) { - json = false; - } - - if (json) { - console.log(JSON.stringify(data)); - } else { - var ids = Object.keys(data); - for (var i = 0; i < ids.length; i++) { - console.log(ids[i] + ': ' + data[ids[i]]); - } - } -}; -/** - * - */ -mscript.init = function init () { - if (mscript.arg('-t', '--tests')) { - return mscript.tests(); - } - - if (mscript.arg('-v', '--verbose')) { - console.time('mscript'); - } - - if (mscript.arg('-c', '--cam')) { - mscript.state.cam = parseInt(process.argv[mscript.arg_pos('-c', '--cam') + 1]); - } - - if (mscript.arg('-p', '--proj')) { - mscript.state.proj = parseInt(process.argv[mscript.arg_pos('-p', '--proj') + 1]); - } - - if (mscript.arg('-f', '--file')) { - input = process.argv[mscript.arg_pos('-f', '--file') + 1]; - mscript.interpret(fs.readFileSync(input, 'utf8')); - } else { - mscript.interpret(input); - } - - if (mscript.arg('-v', '--verbose')) { - console.timeEnd('mscript'); - } -}; - -if (typeof document === 'undefined' - && typeof module !== 'undefined' - && !module.parent) { - //node script - fs = require('fs'); - input = process.argv[2]; - mscript.init(); -} else if (typeof module !== 'undefined' && module.parent) { - //module - fs = require('fs'); - module.exports = mscript; -} else { - //web -} +module.exports = Mscript; /*