<commit_before>var CloudCmd, Util, DOM, CloudFunc, $;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    var Buffer   = {
            log     : '',
            error   : ''
        };

    CloudCmd.Console = ConsoleProto;

    function ConsoleProto(CallBack) {
        var Name    = 'Console',
            Loading,
            jqconsole,
            Element,
            MouseBinded,
            Key     = CloudCmd.Key,
            Images  = DOM.Images,
            Notify  = DOM.Notify,
            Console = this;

        function init() {
            Loading = true;

            Util.loadOnLoad([
                Console.show,
                load,
                CloudCmd.View,
                DOM.jqueryLoad,
                DOM.socketLoad
            ]);
        }

        this.show                       = function() {
            if (!Loading) {
                Images.showLoad({top:true});

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        className   : 'console'
                    });

                    jqconsole           = $(Element).jqconsole('', '> ');
                    // Abort prompt on Ctrl+Z.
                    jqconsole.RegisterShortcut('Z', function() {
                        jqconsole.AbortPrompt();
                        handler();
                    });

                    // Handle a command.
                    var handler = function(command) {
                        var socket = CloudCmd.Socket;

                        if (command && socket) {
                            Images.showLoad({ top:true });
                            socket.send(command);
                        }

                        jqconsole.Prompt(true, handler);
                    };

                    // Initiate the first prompt.
                    handler();
                }

                CloudCmd.View.show(Element, function() {
                    var l$Console   = jqconsole.$console,
                        l$Input     = jqconsole.$input_source,
                        lFocus      = function() {
                            var x   = window.scrollX,
                                y   = window.scrollY;

                            l$Input.focus();
                            window.scrollTo(x,y);
                        };

                    lFocus();

                    if (!MouseBinded) {
                        MouseBinded = true;

                        $(l$Console).unbind('mouseup');
                        $(l$Console).mouseup(function() {
                            var top,
                                isSelection = window.getSelection().toString();

                            if (!isSelection) {
                                top        = l$Console.scrollTop();

                                lFocus();
                                l$Console.scrollTop(lTop);
                            }
                        });
                    }
                });
            }
        };

        this.log                        = function(pText) {
            log(pText, 'log');
        };

        this.error                      = function(pText) {
           log(pText, 'error');
        };

        function log(msg, status) {
            var ret;

            if (msg) {
                Buffer[status] += msg;
                ret             = Util.isContainStr(Buffer[status], '\n');

                if (jqconsole && ret) {
                    jqconsole.Write(Buffer[status], status + '-msg');
                    Notify.send(Buffer[status]);
                    Buffer[status] = '';
                }
            }
        }

        function load(pCallBack) {
            Util.time(Name + ' load');

            var lDir    =  CloudCmd.LIBDIRCLIENT + 'console/',
                lCSS    = [
                    lDir + 'jqconsole.css',
                    lDir + 'ansi.css'
                ],
                lAllCSS = CloudFunc.getJoinURL(lCSS),
                lFiles  = [
                    lDir + 'jqconsole.js',
                    lAllCSS
                ];

            DOM.anyLoadInParallel(lFiles, function() {
                Util.timeEnd(Name + ' load');
                Loading = false;

                Util.exec(pCallBack);
            });
        }

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>refactor(console) show<commit_after>var CloudCmd, Util, DOM, CloudFunc, $;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    var Buffer   = {
            log     : '',
            error   : ''
        };

    CloudCmd.Console = ConsoleProto;

    function ConsoleProto(CallBack) {
        var Name    = 'Console',
            Loading,
            jqconsole,
            Element,
            MouseBinded,
            Key     = CloudCmd.Key,
            Images  = DOM.Images,
            Notify  = DOM.Notify,
            Console = this;

        function init() {
            Loading = true;

            Util.loadOnLoad([
                Console.show,
                load,
                CloudCmd.View,
                DOM.jqueryLoad,
                DOM.socketLoad
            ]);
        }

        this.show                       = function() {
            if (!Loading) {
                Images.showLoad({top:true});

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        className   : 'console'
                    });

                    jqconsole           = $(Element).jqconsole('', '> ');
                    // Abort prompt on Ctrl+Z.
                    jqconsole.RegisterShortcut('Z', function() {
                        jqconsole.AbortPrompt();
                        handler();
                    });

                    // Handle a command.
                    var handler = function(command) {
                        var socket = CloudCmd.Socket;

                        if (command && socket) {
                            Images.showLoad({ top:true });
                            socket.send(command);
                        }

                        jqconsole.Prompt(true, handler);
                    };

                    // Initiate the first prompt.
                    handler();
                }

                CloudCmd.View.show(Element, function() {
                    var console   = jqconsole.$console,
                        input     = jqconsole.$input_source,

                        focus      = function() {
                            var x   = window.scrollX,
                                y   = window.scrollY;

                            input.focus();
                            window.scrollTo(x,y);
                        };

                    focus();

                    if (!MouseBinded) {
                        MouseBinded = true;

                        console.unbind('mouseup');
                        console.mouseup(function() {
                            var top,
                                isSelection = window.getSelection().toString();

                            if (!isSelection) {
                                top        = console.scrollTop();

                                focus();
                                console.scrollTop(top);
                            }
                        });
                    }
                });
            }
        };

        this.log                        = function(pText) {
            log(pText, 'log');
        };

        this.error                      = function(pText) {
           log(pText, 'error');
        };

        function log(msg, status) {
            var ret;

            if (msg) {
                Buffer[status] += msg;
                ret             = Util.isContainStr(Buffer[status], '\n');

                if (jqconsole && ret) {
                    jqconsole.Write(Buffer[status], status + '-msg');
                    Notify.send(Buffer[status]);
                    Buffer[status] = '';
                }
            }
        }

        function load(pCallBack) {
            Util.time(Name + ' load');

            var lDir    =  CloudCmd.LIBDIRCLIENT + 'console/',
                lCSS    = [
                    lDir + 'jqconsole.css',
                    lDir + 'ansi.css'
                ],
                lAllCSS = CloudFunc.getJoinURL(lCSS),
                lFiles  = [
                    lDir + 'jqconsole.js',
                    lAllCSS
                ];

            DOM.anyLoadInParallel(lFiles, function() {
                Util.timeEnd(Name + ' load');
                Loading = false;

                Util.exec(pCallBack);
            });
        }

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>let shelljs = require('shelljs');
let proxy = require('../core/proxy');
const Ipc = require('../core/ipc');
const constants = require('../constants.json');

class Simulator {
  constructor(options) {
    this.blockchainConfig = options.blockchainConfig;
    this.logger = options.logger;
  }

  run(options) {
    let cmds = [];

    const ganache = path.join(__dirname, '../../node_modules/.bin/ganache-cli');

    let useProxy = this.blockchainConfig.proxy || false;
    let host = (options.host || this.blockchainConfig.rpcHost || 'localhost');
    let port = (options.port || this.blockchainConfig.rpcPort || 8545);

    cmds.push("-p " + (port + (useProxy ? constants.blockchain.servicePortOnProxy : 0)));
    if (!ganache) {
      cmds.push("-h " + host);
    }
    cmds.push("-a " + (options.numAccounts || 10));
    cmds.push("-e " + (options.defaultBalance || 100));
    cmds.push("-l " + (options.gasLimit || 8000000));

    // adding mnemonic only if it is defined in the blockchainConfig or options
    let simulatorMnemonic = this.blockchainConfig.simulatorMnemonic || options.simulatorMnemonic;
    if (simulatorMnemonic) {
      cmds.push("--mnemonic \"" + (simulatorMnemonic) +"\"");
    }

    // adding blocktime only if it is defined in the blockchainConfig or options
    let simulatorBlocktime = this.blockchainConfig.simulatorBlocktime || options.simulatorBlocktime;
    if (simulatorBlocktime) {
      cmds.push("-b \"" + (simulatorBlocktime) +"\"");
    }

    const programName = 'ganache-cli';
    const program = ganache;
    console.log(`running: ${programName} ${cmds.join(' ')}`);
    shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true});

    if(useProxy){
      let ipcObject = new Ipc({ipcRole: 'client'});
      proxy.serve(ipcObject, host, port, false);
    }
  }
}

module.exports = Simulator;
<commit_msg>simulator -- defaultHost, dockerHostSwap<commit_after>let shelljs = require('shelljs');
let proxy = require('../core/proxy');
const Ipc = require('../core/ipc');
const constants = require('../constants.json');
const {defaultHost, dockerHostSwap} = require('../utils/host');

class Simulator {
  constructor(options) {
    this.blockchainConfig = options.blockchainConfig;
    this.logger = options.logger;
  }

  run(options) {
    let cmds = [];

    const ganache = path.join(__dirname, '../../node_modules/.bin/ganache-cli');

    let useProxy = this.blockchainConfig.proxy || false;
    let host = (dockerHostSwap(options.host || this.blockchainConfig.rpcHost) || defaultHost);
    let port = (options.port || this.blockchainConfig.rpcPort || 8545);

    cmds.push("-p " + (port + (useProxy ? constants.blockchain.servicePortOnProxy : 0)));
    if (!ganache) {
      cmds.push("-h " + host);
    }
    cmds.push("-a " + (options.numAccounts || 10));
    cmds.push("-e " + (options.defaultBalance || 100));
    cmds.push("-l " + (options.gasLimit || 8000000));

    // adding mnemonic only if it is defined in the blockchainConfig or options
    let simulatorMnemonic = this.blockchainConfig.simulatorMnemonic || options.simulatorMnemonic;
    if (simulatorMnemonic) {
      cmds.push("--mnemonic \"" + (simulatorMnemonic) +"\"");
    }

    // adding blocktime only if it is defined in the blockchainConfig or options
    let simulatorBlocktime = this.blockchainConfig.simulatorBlocktime || options.simulatorBlocktime;
    if (simulatorBlocktime) {
      cmds.push("-b \"" + (simulatorBlocktime) +"\"");
    }

    const programName = 'ganache-cli';
    const program = ganache;
    console.log(`running: ${programName} ${cmds.join(' ')}`);
    shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true});

    if(useProxy){
      let ipcObject = new Ipc({ipcRole: 'client'});
      proxy.serve(ipcObject, host, port, false);
    }
  }
}

module.exports = Simulator;
<|endoftext|>


<commit_before>const State = require('./state');
const sidTpl = require('./player/sid');
const prgTpl = require('./player/prg');
const debug = require('debug')('code_generator');

const defaultHeaderField = 'unknown';

const headerNames = ['title', 'author', 'released'];

class CodeGenerator {
  constructor(document, options) {
    if (typeof(document) === 'undefined') {
      throw new TypeError('document is required');
    }

    this.document = document;
    this.options = options || {};
  }

  generate() {
    let initialStates = this.document.initialState;

    let data = {
      debug: this.options.debug,
      headers: this._buildHeaders(),
      initialStates: initialStates,
      sequences: this._buildSequences(),
      song: this._buildSongTables(initialStates)
    };

    return this._template(data);
  }

  _buildHeaders() {
    let headers = {};

    for (let dir in this.document.directives) {
      if (headerNames.includes(dir)) {
        let value = this.document.directives[dir].trim();
        if (value.length > 32) {
          console.warn(`Argument of header #${dir.name.toUpperCase()} is ` +
            `too long (max 32 characters)`);
        }
        headers[dir.name] = value.slice(0, 32);
      }
    }

    for (let name of headerNames) {
      if (!headers[name]) {
        headers[name] = defaultHeaderField;
      }
      headers[name] = this._padRight(headers[name], 32);
    }

    return headers;
  }

  _pushSequence(sequence, i, song, state, lastState) {
    for (let cmd of sequence) {
      debug(`#${i} cmd: ${JSON.stringify(cmd)}`);

      switch (cmd.type) {
        case 'note':
        case 'rest': {
          // push commands to change from lastState to state
          let changes = this._changesFrom(state, lastState);
          debug(`#${i} changes: ${JSON.stringify(changes, null, 4)}`);

          // update lastState
          Object.assign(lastState, state);

          // push commands based on changes
          if (changes.noteLength || changes.noteLengthFrames) {
            song.push('I_NLEN', state.noteLengthFrames - 1);
          }
          if (changes.quantLength || changes.quantLengthFrames) {
            song.push('I_QLEN', state.quantLengthFrames - 1);
          }

          // increment borrow
          state.borrow += state.borrowFrames;
          debug(`#${i} borrow = ${state.borrow}`);

          // append notes
          for (let b of this._bytesFromNoteCommand(cmd, state)) {
            song.push(b);
          }

          break;
        }
        case 'set_tempo':
          state.tempo = cmd.value;
          break;
        case 'set_note_length':
          state.noteLength = cmd.value;
          break;
        case 'set_quantize':
          state.quantLength = cmd.value;
          break;
        case 'set_octave':
          song.push('I_OCTAVE', cmd.value);
          break;
        case 'inc_octave':
          song.push('I_OCT_INC');
          break;
        case 'dec_octave':
          song.push('I_OCT_DEC');
          break;
        case 'transpose': {
          let value = cmd.value & 0xff;
          if (value < 0) {
            value = (0xff + data8 + 1);
          }
          song.push('I_TRANSPOSE', value);
          break;
        }
        case 'set_volume':
          song.push('I_VOLUME', cmd.value);
          break;
        case 'inc_volume':
          if (cmd.value) {
            console.error('Warning: inc_volume argument is ignored by player');
          }
          song.push('I_VOL_INC');
          break;
        case 'dec_volume':
          if (cmd.value) {
            console.error('Warning: dec_volume argument is ignored by player');
          }
          song.push('I_VOL_DEC');
          break;
        case 'loop':
          song.push('I_LOOP_STR', cmd.times);
          this._pushSequence(cmd.body, i, song, state, lastState);
          song.push('I_LOOP_END');
          break;
        default:
          console.error(`Command not implemented yet: ${cmd.type}`);
      }
    }
  }

  _buildSongTables(initialStates) {
    let songs = [], states = [], lastStates = [];

    // create tables
    for (let i = 0; i < 3; i++) {
      songs.push([]);
      states.push(new State(initialStates[i]));
      // lastState stores the state before the last *note command*
      lastStates.push(new State(states[i]));
    }

    debug(`initialStates: ${JSON.stringify(lastStates, null, 4)}`);

    for (let elem of this.document.commands) {
      for (let channel of elem.channels) {
        let i = this._channelNumFromName(channel);
        this._pushSequence(elem.sequence, i, songs[i], states[i], lastStates[i]);
      }
    }

    for (let i = 0; i < 3; i++) {
      songs[i].push('I_EOF');
    }

    return songs;
  }

  _changesFrom(state, lastState) {
    let changes = {};

    for (let k in state) {
      if (state[k] !== lastState[k]) {
        changes[k] = state[k];
      }
    }

    if (state.noteLengthFrames !== lastState.noteLengthFrames) {
      changes.noteLengthFrames = state.noteLengthFrames;
    }
    if (state.quantLengthFrames !== lastState.quantLengthFrames) {
      changes.quantLengthFrames = state.quantLengthFrames;
    }

    return changes;
  }

  _buildSequences() {
    // TODO
    return {};
  }

  _channelNumFromName(name) {
    let n;
    if (name === 'A') { n = 0; }
    if (name === 'B') { n = 1; }
    if (name === 'C') { n = 2; }
    return n;
  }

  _bytesFromNoteCommand(command, state) {
    let bytes = [];

    let inst;
    if (command.type === 'rest') {
      inst = 'I_NOTE_REST';
    } else {
      let note = command.note.toUpperCase();
      let accidental = command.accidental === '+' ? 'S' : '';
      inst = `I_NOTE_${note}${accidental}`;
    }

    // Create a modified state based on custom note length from command
    // (if available)
    let modState = new State(state);
    Object.assign(modState, {
      noteLength: command.length || state.noteLength
    });

    let noteLen = modState.noteLengthFrames;

    // Process "dots" if its a dotted note
    let dotsLen = 2 - (1 / Math.pow(2, command.dots));

    noteLen = noteLen * dotsLen;

    // Add frames "borrow" from previous notes to compensate
    if (state.borrow >= 1) {
      state.borrow -= 1;
      noteLen += 1;
      debug(`state.borrow >= 1, so increment noteLen to ${noteLen}`);
    } else if (state.borrow <= -1) {
      state.borrow += 1;
      noteLen -= 1;
      debug(`state.borrow <= -1, so decrement noteLen to ${noteLen}`);
    }

    // If note length differs from current default note length, append note
    // length and quantization length bytes
    if (noteLen !== state.noteLengthFrames) {
      let noteQuant = modState.quantLengthFrames;
      noteQuant = noteQuant * dotsLen;
      noteQuant = Math.min(noteQuant, noteLen);

      inst = inst + '|WITH_LEN_FLAG|WITH_Q_FLAG';
      if (noteLen > 0xff) {
        inst += '|WORD_FLAG';
      }

      // decrement because player routine requires note length to be n-1
      noteQuant -= 1;
      noteLen -= 1;

      // push note command instruction and operands
      bytes.push(inst);
      bytes.push(noteLen & 0xff);
      if (noteLen > 0xff) {
        bytes.push((noteLen >> 8) & 0xff);
      }
      bytes.push(noteQuant & 0xff);
      if (noteQuant > 0xff) {
        bytes.push((noteQuant >> 8) & 0xff);
      }
    } else {
      bytes.push(inst);
    }

    return bytes;
  }

  _template(data) {
    if (this.options.player) {
      return prgTpl(data);
    } else {
      return sidTpl(data);
    }
  }

  _padRight(str, len, char) {
    return str + Array(len - str.length + 1).join(char || ' ');
  }
}

module.exports = CodeGenerator;
<commit_msg>Parse accidentals correctly, allow enharmonics<commit_after>const State = require('./state');
const sidTpl = require('./player/sid');
const prgTpl = require('./player/prg');
const debug = require('debug')('code_generator');

const defaultHeaderField = 'unknown';

const headerNames = ['title', 'author', 'released'];

const noteCommands = [
  'I_NOTE_C', 'I_NOTE_CS', 'I_NOTE_D', 'I_NOTE_DS',
  'I_NOTE_E', 'I_NOTE_F', 'I_NOTE_FS', 'I_NOTE_G',
  'I_NOTE_GS', 'I_NOTE_A', 'I_NOTE_AS', 'I_NOTE_B'
];

const noteIndexes = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 };

class CodeGenerator {
  constructor(document, options) {
    if (typeof(document) === 'undefined') {
      throw new TypeError('document is required');
    }

    this.document = document;
    this.options = options || {};
  }

  generate() {
    let initialStates = this.document.initialState;

    let data = {
      debug: this.options.debug,
      headers: this._buildHeaders(),
      initialStates: initialStates,
      sequences: this._buildSequences(),
      song: this._buildSongTables(initialStates)
    };

    return this._template(data);
  }

  _buildHeaders() {
    let headers = {};

    for (let dir in this.document.directives) {
      if (headerNames.includes(dir)) {
        let value = this.document.directives[dir].trim();
        if (value.length > 32) {
          console.warn(`Argument of header #${dir.name.toUpperCase()} is ` +
            `too long (max 32 characters)`);
        }
        headers[dir.name] = value.slice(0, 32);
      }
    }

    for (let name of headerNames) {
      if (!headers[name]) {
        headers[name] = defaultHeaderField;
      }
      headers[name] = this._padRight(headers[name], 32);
    }

    return headers;
  }

  _pushSequence(sequence, i, song, state, lastState) {
    for (let cmd of sequence) {
      debug(`#${i} cmd: ${JSON.stringify(cmd)}`);

      switch (cmd.type) {
        case 'note':
        case 'rest': {
          // push commands to change from lastState to state
          let changes = this._changesFrom(state, lastState);
          debug(`#${i} changes: ${JSON.stringify(changes, null, 4)}`);

          // update lastState
          Object.assign(lastState, state);

          // push commands based on changes
          if (changes.noteLength || changes.noteLengthFrames) {
            song.push('I_NLEN', state.noteLengthFrames - 1);
          }
          if (changes.quantLength || changes.quantLengthFrames) {
            song.push('I_QLEN', state.quantLengthFrames - 1);
          }

          // increment borrow
          state.borrow += state.borrowFrames;
          debug(`#${i} borrow = ${state.borrow}`);

          // append notes
          for (let b of this._bytesFromNoteCommand(cmd, state)) {
            song.push(b);
          }

          break;
        }
        case 'set_tempo':
          state.tempo = cmd.value;
          break;
        case 'set_note_length':
          state.noteLength = cmd.value;
          break;
        case 'set_quantize':
          state.quantLength = cmd.value;
          break;
        case 'set_octave':
          song.push('I_OCTAVE', cmd.value);
          break;
        case 'inc_octave':
          song.push('I_OCT_INC');
          break;
        case 'dec_octave':
          song.push('I_OCT_DEC');
          break;
        case 'transpose': {
          let value = cmd.value & 0xff;
          if (value < 0) {
            value = (0xff + data8 + 1);
          }
          song.push('I_TRANSPOSE', value);
          break;
        }
        case 'set_volume':
          song.push('I_VOLUME', cmd.value);
          break;
        case 'inc_volume':
          if (cmd.value) {
            console.error('Warning: inc_volume argument is ignored by player');
          }
          song.push('I_VOL_INC');
          break;
        case 'dec_volume':
          if (cmd.value) {
            console.error('Warning: dec_volume argument is ignored by player');
          }
          song.push('I_VOL_DEC');
          break;
        case 'loop':
          song.push('I_LOOP_STR', cmd.times);
          this._pushSequence(cmd.body, i, song, state, lastState);
          song.push('I_LOOP_END');
          break;
        default:
          console.error(`Command not implemented yet: ${cmd.type}`);
      }
    }
  }

  _buildSongTables(initialStates) {
    let songs = [], states = [], lastStates = [];

    // create tables
    for (let i = 0; i < 3; i++) {
      songs.push([]);
      states.push(new State(initialStates[i]));
      // lastState stores the state before the last *note command*
      lastStates.push(new State(states[i]));
    }

    debug(`initialStates: ${JSON.stringify(lastStates, null, 4)}`);

    for (let elem of this.document.commands) {
      for (let channel of elem.channels) {
        let i = this._channelNumFromName(channel);
        this._pushSequence(elem.sequence, i, songs[i], states[i], lastStates[i]);
      }
    }

    for (let i = 0; i < 3; i++) {
      songs[i].push('I_EOF');
    }

    return songs;
  }

  _changesFrom(state, lastState) {
    let changes = {};

    for (let k in state) {
      if (state[k] !== lastState[k]) {
        changes[k] = state[k];
      }
    }

    if (state.noteLengthFrames !== lastState.noteLengthFrames) {
      changes.noteLengthFrames = state.noteLengthFrames;
    }
    if (state.quantLengthFrames !== lastState.quantLengthFrames) {
      changes.quantLengthFrames = state.quantLengthFrames;
    }

    return changes;
  }

  _buildSequences() {
    // TODO
    return {};
  }

  _channelNumFromName(name) {
    let n;
    if (name === 'A') { n = 0; }
    if (name === 'B') { n = 1; }
    if (name === 'C') { n = 2; }
    return n;
  }

  _bytesFromNoteCommand(command, state) {
    let bytes = [];

    let inst;
    if (command.type === 'rest') {
      inst = 'I_NOTE_REST';
    } else {
      let ni = noteIndexes[command.note];
      if (command.accidental === '-') {
        ni = (ni - 1) % 12;
      } else if (command.accidental === '+') {
        ni = (ni + 1) % 12;
      }
      inst = noteCommands[ni];
    }

    // Create a modified state based on custom note length from command
    // (if available)
    let modState = new State(state);
    Object.assign(modState, {
      noteLength: command.length || state.noteLength
    });

    let noteLen = modState.noteLengthFrames;

    // Process "dots" if its a dotted note
    let dotsLen = 2 - (1 / Math.pow(2, command.dots));

    noteLen = noteLen * dotsLen;

    // Add frames "borrow" from previous notes to compensate
    if (state.borrow >= 1) {
      state.borrow -= 1;
      noteLen += 1;
      debug(`state.borrow >= 1, so increment noteLen to ${noteLen}`);
    } else if (state.borrow <= -1) {
      state.borrow += 1;
      noteLen -= 1;
      debug(`state.borrow <= -1, so decrement noteLen to ${noteLen}`);
    }

    // If note length differs from current default note length, append note
    // length and quantization length bytes
    if (noteLen !== state.noteLengthFrames) {
      let noteQuant = modState.quantLengthFrames;
      noteQuant = noteQuant * dotsLen;
      noteQuant = Math.min(noteQuant, noteLen);

      inst = inst + '|WITH_LEN_FLAG|WITH_Q_FLAG';
      if (noteLen > 0xff) {
        inst += '|WORD_FLAG';
      }

      // decrement because player routine requires note length to be n-1
      noteQuant -= 1;
      noteLen -= 1;

      // push note command instruction and operands
      bytes.push(inst);
      bytes.push(noteLen & 0xff);
      if (noteLen > 0xff) {
        bytes.push((noteLen >> 8) & 0xff);
      }
      bytes.push(noteQuant & 0xff);
      if (noteQuant > 0xff) {
        bytes.push((noteQuant >> 8) & 0xff);
      }
    } else {
      bytes.push(inst);
    }

    return bytes;
  }

  _template(data) {
    if (this.options.player) {
      return prgTpl(data);
    } else {
      return sidTpl(data);
    }
  }

  _padRight(str, len, char) {
    return str + Array(len - str.length + 1).join(char || ' ');
  }
}

module.exports = CodeGenerator;
<|endoftext|>


<commit_before>var DEFAULT_LIMIT = 2500;

module.exports = function(collectionName){

    var db = require('./db.js');
    var async = require('async');
    var ObjectID = require('mongodb').ObjectID;

    var getObjectCollection = function() {
        return db.getDb().collection(collectionName);
    };

    var insertObjects = function(objects, userId, callback) {

        if (objects instanceof Array) {
            objects.forEach(function(object) {
                object.userId = userId;
            });
        } else {
            objects.userId = userId;
        }

        getObjectCollection().insert(objects, callback);
    };

    var updateObject = function(objectIdString, object, userId, callback) {
        var objectId =  new ObjectID(objectIdString);
        object.userId = userId;
        object._id = objectId;
        getObjectCollection().update({_id: objectId}, object, { upsert : true }, callback);
    };

    var patchObject = function(objectId, object, userId, callback) {
        object.userId = userId;
        getObjectCollection().update({_id: new ObjectID(objectId)}, { $set: object }, { upsert : true}, callback);
    };

    var isObjectOwnedByUser = function(objectId, userId, callback) {
        var cursor = getObjectCollection().find({_id: objectId, user:userId});
        cursor.count(function(err, count) {
            callback(err, count > 0);
        });
    };

    var findObjects = function(query, callback) {

        var options = {
            limit: DEFAULT_LIMIT
        };

        if (query.mongoDbQuery.limit) {
            options.limit = query.mongoDbQuery.limit;
            delete query.mongoDbQuery.limit;
        }

        var cursor = getObjectCollection().find(query.mongoDbQuery, null, options).sort(query.sort);
        cursor.toArray(function(err, docs) {
            callback(err, docs);
        });
    };

    var getObjectById = function(id, callback) {
        var cursor = getObjectCollection().find({_id: new ObjectID(id) });
        cursor.nextObject(function(err, object) {
            callback(err, object);
        });
    };

    var deleteObjects = function(query, callback) {
        getObjectCollection().remove(query, function(err, count) {
            callback(err, count);
        });
    };

    var parseFloatStrict = function (value) {
        if(/^\-?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) {
            return Number(value);
        } else {
            throw "could not parse number";
        }
    }

    var parseObjectId = function(value) {
        if (/^[0-9a-fA-F]{24}$/.test(value)) {
            return new ObjectID(value);
        } else {
            throw "could not parse object id";
        }
    }

    var parseValue = function(value) {
        if (value === 'true') {
            value = true;
        } else if (value === 'false') {
            value = false;
        } else {
            try {
                value = parseFloatStrict(value);
            } catch(e) {
                try  {
                    value = parseObjectId(value);
                } catch(e) {
                    // ignore
                }
            }
        }
        return value;
    }

    var isValidOperator = function(operator) {
        var validOperator = false;
        if (operator === '$gt') {
            validOperator = true;
        } else if (operator === '$gte') {
            validOperator = true;
        } else if (operator === '$lt') {
            validOperator = true;
        } else if (operator === '$lte') {
            validOperator = true;
        }
        return validOperator;
    };

    var resolveOperatorAlias = function(alias) {
        if (alias === '$after') {
            return '$gt';
        } else if (alias === '$before') {
            return '$lt';
        }
        return alias;
    };

    var parseDollarPairKey = function(dollarPair) {
        var index = dollarPair.indexOf('$')
        return substring(0, index);
    }
    var buildQuery = function(param, userId) {

        var mongoDbQuery = {
        };
        var sort = {};

        var query = {
            mongoDbQuery: mongoDbQuery,
            sort: sort
        };

        for (key in param) {
            var value = param[key];
            var index = value.indexOf('$')

            if (key === 'sortBy') {
                if (index > 0) {
                    var field = value.substring(0, index);
                    var order = value.substring(index + 1);
                    sort[field] = order === 'desc' ? -1 : 1;
                }
            } else {

                if (index === -1) {
                    mongoDbQuery[key] =  parseValue(value);
                } else {
                    var operator = '$' + value.substring(0, index);

                    operator = resolveOperatorAlias(operator);

                    var value = value.substring(index + 1);

                    if (isValidOperator(operator)) {
                        mongoDbQuery[key] = {};
                        mongoDbQuery[key][operator] = parseValue(value);
                    }
                }
            }
        }
        mongoDbQuery.userId = userId;

        return query;
    };

    return {
        use: function (req, res, next) {
            if (req.isAuthenticated()) {
                next();
            } else {
                res.json(401, {message: 'not logged in'});
            }
        },
        get: function (req, res) {
            // respond with entire collection associated with user

            var query = buildQuery(req.query, req.user._id);

            findObjects(query, function(err, objects) {

                if (err) {
                    res.json(500, "error: database error");
                } else {

                    var jsonObject = {
                        items: objects
                    };

                    jsonObject.items = objects;
                    res.json(jsonObject);
                }
            });
        },
        put: function (req, res) {
            // replace entire collection of objects associated with user
            async.series([
                function(callback) {
                    var query = {userId: req.user._id};
                    deleteObjects(query, callback);
                }, function(callback) {
                    insertObjects(req.body, req.user._id, callback);
                }], function(err) {
                if (err) {
                    res.json(500, {message: "could not store objects"})
                } else {
                    res.json({});
                }
            });

        },
        post: function (req, res) {
            // create a new object and associated it with user
            insertObjects(req.body, req.user._id, function(err, object) {
                if (err) {
                    res.json(500, {message: "could not store object"});
                } else {
                    res.json(200, object);
                }
            });
        },
        delete : function (req, res) {
            // delete entire collection associated with user
            var query = {userId: req.user._id};
            deleteObjects(query, function(err, objects) {
                if (err) {
                    res.json(500, "error: database error");
                } else {
                    res.json({});
                }
            });
        },
        ":id": {
            get: function (req, res) {
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object == null) {
                            res.json(404, { message: "object not found"});
                        } else {
                            if (req.user._id.equals(object.userId)) {
                                res.json(object);
                            } else {
                                res.json(401, { message: "permission denied"});
                            }
                        }
                    }
                });
            },
            put: function (req, res) {
                // Replace " + req.params.id + ", or if it doesn't exist, create it.
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object === null || req.user._id.equals(object.userId)) {
                            updateObject(req.params.id, req.body, req.user._id, function(err) {
                                if (err) {
                                    res.json(500, {message: "could not update object"});
                                } else {
                                    res.json({});
                                }
                            });
                        } else {
                            res.json(401, { message: "permission denied"});
                        }
                    }
                });

            },
            patch: function (req, res) {
                // Replace " + req.params.id + ", or if it doesn't exist, create it.
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object === null || req.user._id.equals(object.userId)) {
                            patchObject(req.params.id, req.body, req.user._id, function(err) {
                                if (err) {
                                    res.json(500, {message: "could not patch object"});
                                } else {
                                    res.json({});
                                }
                            });
                        } else {
                            res.json(401, { message: "permission denied"});
                        }
                    }
                });
            },
            delete: {
                handler: function (req, res) {
                    // Delete " + req.params.id
                    getObjectById(req.params.id, function(err, object) {
                        if (err) {
                            res.json(500, { message: "could not get object"} );
                        } else {
                            if (object === null) {
                                res.json(404, { message: "object not found"});
                            } else if (req.user._id.equals(object.userId)) {
                                var query = {_id: object._id};
                                deleteObjects(query, function(err) {
                                    if (err) {
                                        res.json(500, { message: "could not delete object"} );
                                    } else {
                                        res.json({});
                                    }
                                });
                            } else {
                                res.json(401, { message: "permission denied"});
                            }
                        }
                    });
                }
            }
        }
    }

};
<commit_msg>Refactor query limit<commit_after>var DEFAULT_LIMIT = 2500;

module.exports = function(collectionName){

    var db = require('./db.js');
    var async = require('async');
    var ObjectID = require('mongodb').ObjectID;

    var getObjectCollection = function() {
        return db.getDb().collection(collectionName);
    };

    var insertObjects = function(objects, userId, callback) {

        if (objects instanceof Array) {
            objects.forEach(function(object) {
                object.userId = userId;
            });
        } else {
            objects.userId = userId;
        }

        getObjectCollection().insert(objects, callback);
    };

    var updateObject = function(objectIdString, object, userId, callback) {
        var objectId =  new ObjectID(objectIdString);
        object.userId = userId;
        object._id = objectId;
        getObjectCollection().update({_id: objectId}, object, { upsert : true }, callback);
    };

    var patchObject = function(objectId, object, userId, callback) {
        object.userId = userId;
        getObjectCollection().update({_id: new ObjectID(objectId)}, { $set: object }, { upsert : true}, callback);
    };

    var isObjectOwnedByUser = function(objectId, userId, callback) {
        var cursor = getObjectCollection().find({_id: objectId, user:userId});
        cursor.count(function(err, count) {
            callback(err, count > 0);
        });
    };

    var findObjects = function(query, callback) {

        var options = {
            limit: DEFAULT_LIMIT
        };

        if (query.limit) {
            options.limit = query.limit;
        }

        var cursor = getObjectCollection().find(query.mongoDbQuery, null, options).sort(query.sort);
        cursor.toArray(function(err, docs) {
            callback(err, docs);
        });
    };

    var getObjectById = function(id, callback) {
        var cursor = getObjectCollection().find({_id: new ObjectID(id) });
        cursor.nextObject(function(err, object) {
            callback(err, object);
        });
    };

    var deleteObjects = function(query, callback) {
        getObjectCollection().remove(query, function(err, count) {
            callback(err, count);
        });
    };

    var parseFloatStrict = function (value) {
        if(/^\-?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) {
            return Number(value);
        } else {
            throw "could not parse number";
        }
    }

    var parseObjectId = function(value) {
        if (/^[0-9a-fA-F]{24}$/.test(value)) {
            return new ObjectID(value);
        } else {
            throw "could not parse object id";
        }
    }

    var parseValue = function(value) {
        if (value === 'true') {
            value = true;
        } else if (value === 'false') {
            value = false;
        } else {
            try {
                value = parseFloatStrict(value);
            } catch(e) {
                try  {
                    value = parseObjectId(value);
                } catch(e) {
                    // ignore
                }
            }
        }
        return value;
    }

    var isValidOperator = function(operator) {
        var validOperator = false;
        if (operator === '$gt') {
            validOperator = true;
        } else if (operator === '$gte') {
            validOperator = true;
        } else if (operator === '$lt') {
            validOperator = true;
        } else if (operator === '$lte') {
            validOperator = true;
        }
        return validOperator;
    };

    var resolveOperatorAlias = function(alias) {
        if (alias === '$after') {
            return '$gt';
        } else if (alias === '$before') {
            return '$lt';
        }
        return alias;
    };

    var parseDollarPairKey = function(dollarPair) {
        var index = dollarPair.indexOf('$')
        return substring(0, index);
    }
    var buildQuery = function(param, userId) {

        var mongoDbQuery = {
        };
        var sort = {};

        var query = {
            mongoDbQuery: mongoDbQuery,
            sort: sort
        };

        for (key in param) {
            var value = param[key];
            var index = value.indexOf('$')

            if (key === 'sortBy') {
                if (index > 0) {
                    var field = value.substring(0, index);
                    var order = value.substring(index + 1);
                    sort[field] = order === 'desc' ? -1 : 1;
                }
            } else if (key === 'limit') {
                query.limit = value;
            } else {

                if (index === -1) {
                    mongoDbQuery[key] =  parseValue(value);
                } else {
                    var operator = '$' + value.substring(0, index);

                    operator = resolveOperatorAlias(operator);

                    var value = value.substring(index + 1);

                    if (isValidOperator(operator)) {
                        mongoDbQuery[key] = {};
                        mongoDbQuery[key][operator] = parseValue(value);
                    }
                }
            }
        }
        mongoDbQuery.userId = userId;

        return query;
    };

    return {
        use: function (req, res, next) {
            if (req.isAuthenticated()) {
                next();
            } else {
                res.json(401, {message: 'not logged in'});
            }
        },
        get: function (req, res) {
            // respond with entire collection associated with user

            var query = buildQuery(req.query, req.user._id);

            findObjects(query, function(err, objects) {

                if (err) {
                    res.json(500, "error: database error");
                } else {

                    var jsonObject = {
                        items: objects
                    };

                    jsonObject.items = objects;
                    res.json(jsonObject);
                }
            });
        },
        put: function (req, res) {
            // replace entire collection of objects associated with user
            async.series([
                function(callback) {
                    var query = {userId: req.user._id};
                    deleteObjects(query, callback);
                }, function(callback) {
                    insertObjects(req.body, req.user._id, callback);
                }], function(err) {
                if (err) {
                    res.json(500, {message: "could not store objects"})
                } else {
                    res.json({});
                }
            });

        },
        post: function (req, res) {
            // create a new object and associated it with user
            insertObjects(req.body, req.user._id, function(err, object) {
                if (err) {
                    res.json(500, {message: "could not store object"});
                } else {
                    res.json(200, object);
                }
            });
        },
        delete : function (req, res) {
            // delete entire collection associated with user
            var query = {userId: req.user._id};
            deleteObjects(query, function(err, objects) {
                if (err) {
                    res.json(500, "error: database error");
                } else {
                    res.json({});
                }
            });
        },
        ":id": {
            get: function (req, res) {
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object == null) {
                            res.json(404, { message: "object not found"});
                        } else {
                            if (req.user._id.equals(object.userId)) {
                                res.json(object);
                            } else {
                                res.json(401, { message: "permission denied"});
                            }
                        }
                    }
                });
            },
            put: function (req, res) {
                // Replace " + req.params.id + ", or if it doesn't exist, create it.
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object === null || req.user._id.equals(object.userId)) {
                            updateObject(req.params.id, req.body, req.user._id, function(err) {
                                if (err) {
                                    res.json(500, {message: "could not update object"});
                                } else {
                                    res.json({});
                                }
                            });
                        } else {
                            res.json(401, { message: "permission denied"});
                        }
                    }
                });

            },
            patch: function (req, res) {
                // Replace " + req.params.id + ", or if it doesn't exist, create it.
                getObjectById(req.params.id, function(err, object) {
                    if (err) {
                        res.json(500, {message: "could not get object"});
                    } else {
                        if (object === null || req.user._id.equals(object.userId)) {
                            patchObject(req.params.id, req.body, req.user._id, function(err) {
                                if (err) {
                                    res.json(500, {message: "could not patch object"});
                                } else {
                                    res.json({});
                                }
                            });
                        } else {
                            res.json(401, { message: "permission denied"});
                        }
                    }
                });
            },
            delete: {
                handler: function (req, res) {
                    // Delete " + req.params.id
                    getObjectById(req.params.id, function(err, object) {
                        if (err) {
                            res.json(500, { message: "could not get object"} );
                        } else {
                            if (object === null) {
                                res.json(404, { message: "object not found"});
                            } else if (req.user._id.equals(object.userId)) {
                                var query = {_id: object._id};
                                deleteObjects(query, function(err) {
                                    if (err) {
                                        res.json(500, { message: "could not delete object"} );
                                    } else {
                                        res.json({});
                                    }
                                });
                            } else {
                                res.json(401, { message: "permission denied"});
                            }
                        }
                    });
                }
            }
        }
    }

};
<|endoftext|>


<commit_before>/**
 * Created by axetroy on 17-2-14.
 */

const path = require('path');
const process = require('process');

const _ = require('lodash');
const prettyjson = require('prettyjson');
const Promise = require('bluebird');
const co = require('co');
const fs = Promise.promisifyAll(require('fs-extra'));
const log4js = require('log4js');
const logger = log4js.getLogger('RELINK');
const gitUrlParse = require("git-url-parse");

const config = require('../config');
const {isGitRepoDir, parseGitConfigAsync} = require('../utils');

function coRuntime(func) {
  return function () {
    let args = arguments;
    let __this__ = this;
    co(function *() {
      yield func.apply(__this__, args);
    }).catch(function (err) {
      console.error(err);
    });
  }
}

function *relink(options) {
  const configJSON = yield fs.readJsonAsync(config.paths.config);
  const basePath = path.join(process.env.HOME, configJSON.base);

  const lockJSON = {repos: []};

  _.each(yield fs.readdirAsync(basePath), coRuntime(function *(source) {
    _.each(yield fs.readdirAsync(path.join(basePath, source)), coRuntime(function*(owner) {
      _.each(yield fs.readdirAsync(path.join(basePath, source, owner)), coRuntime(function *(repo) {
        const dist = path.join(basePath, source, owner, repo);
        if (!(yield isGitRepoDir(dist))) return;

        let gitConfig = yield parseGitConfigAsync({
          cwd: dist,
          path: path.join('.git', 'config')
        });
        const origin = gitConfig[`remote "origin"`] || {};

        if (!origin.url || _.isEmpty(origin)) return;

        const gitInfo = gitUrlParse(origin.url);

        lockJSON.repos.push(_.extend({}, gitInfo, {path: dist, href: origin.url}));

        yield fs.writeJSONAsync(config.paths.lock, lockJSON);

        logger.info(`link repository: ${origin.url.green} >>> ${dist.yellow}`);

      }));
    }));

  }));

}

module.exports = function (options) {
  return relink(options);
};<commit_msg>fix(relink): fix it will recover the other config before<commit_after>/**
 * Created by axetroy on 17-2-14.
 */

const path = require('path');
const process = require('process');

const _ = require('lodash');
const prettyjson = require('prettyjson');
const Promise = require('bluebird');
const co = require('co');
const fs = Promise.promisifyAll(require('fs-extra'));
const log4js = require('log4js');
const logger = log4js.getLogger('RELINK');
const gitUrlParse = require("git-url-parse");

const config = require('../config');
const {isGitRepoDir, parseGitConfigAsync} = require('../utils');

function *relink(options) {
  const configJSON = yield fs.readJsonAsync(config.paths.config);
  const basePath = path.join(process.env.HOME, configJSON.base);

  const __lockJSON__ = yield fs.readJsonAsync(config.paths.lock);
  const lockJSON = _.extend({}, __lockJSON__, {repos: []});

  yield fs.ensureDirAsync(basePath);
  const sources = yield fs.readdirAsync(basePath) || [];
  if (_.isEmpty(sources)) {
    logger.error(`You did't have any repository to relink, please add it first.`);
    return;
  }

  while (sources.length) {
    const source = sources.shift();
    const owners = yield yield fs.readdirAsync(path.join(basePath, source));
    while (owners.length) {
      const owner = owners.shift();
      const repos = yield fs.readdirAsync(path.join(basePath, source, owner));
      while (repos.length) {
        const repo = repos.shift();
        const dist = path.join(basePath, source, owner, repo);
        if (!(yield isGitRepoDir(dist))) return;

        let gitConfig = yield parseGitConfigAsync({cwd: dist, path: path.join('.git', 'config')});
        const origin = gitConfig[`remote "origin"`] || {};

        if (!origin.url || _.isEmpty(origin)) return;

        const gitInfo = gitUrlParse(origin.url);

        lockJSON.repos.push(_.extend({}, gitInfo, {path: dist, href: origin.url}));

        yield fs.writeJSONAsync(config.paths.lock, lockJSON);

        logger.info(`link repository: ${origin.url.green} >>> ${dist.yellow}`);
      }
    }
  }

}

module.exports = function (options) {
  return relink(options);
};<|endoftext|>


<commit_before>/**
 * Encodes and decodes commands
 * e.g.
 *
 * var config = {
 *     dfcg: {
 *         command: {
 *             name: 'DCFG',
 *             title: 'Device Configuration Message',
 *             description: 'Configures the device, only first transmitter can send',
 *             code: 0x12
 *         },
 *         fields: [
 *             {name: 'cat', type: 'int', length: 2},
 *             {name: 'dog', type: 'string', length: 12},
 *             {name: 'signals', type: 'int', length: 2, repeats: 6}
 *         ]
 *     }
 * };
 *
 * var message = {cat: 256, dog: 'You smell', signals: [2, 17, 257, 33, 1, 1000]}
 * var buffer = CommandManager.encode(config.dfcg, message);
 * var message2 = CommandManager.decode(config.dfcg, buffer);
 * assert(message == message2);
 */

module.exports = function(commands) {

    var crc = require('crc');
    var fs = require('fs');
    var Buffer = require('buffer').Buffer;
    var CommandManager = {commands: commands};

    // 2 frame bytes are required at the start of each message
    var frame = [0xAA, 0xBB];

    // Finds a command from its code
    var findCommand = function(code) {
        for (i in CommandManager.commands) {
            if (CommandManager.commands[i].command.code == code) {
                return i;
            }
        }
    };

    // Encodes values
    var encoders = {
        int: function(buffer, offset, value, length) {
            if (length == 1) {
                buffer.writeUInt8(value, offset);
                return offset + 1;
            }
            if (length == 2) {
                buffer.writeUInt16BE(value, offset);
                return offset + 2;
            }
            if (length == 4) {
                buffer.writeUInt32BE(value, offset);
                return offset + 4;
            }

            throw 'Unsupported integer length '+length;
        },

        string: function(buffer, offset, value, length) {
            for (var i = 0; i < length ; i++) {
                offset = encoders.int(buffer, offset, value[i] ? value.charCodeAt(i) : 0, 1);
            }

            return offset;
        },

        null: function(buffer, offset, value, length) {
            for (var i = 0; i < length ; i++) {
                offset = encoders.int(buffer, offset, 0, 1);
            }
            return offset;
        },

        boolean: function(buffer, offset, value, length) {
            return encoders.int(buffer, offset, value ? 1 : 0, 1);
        }
    };

    // Encodes values
    var decoders = {
        int: function(buffer, offset, data, key, length) {
            if (length == 1) {
                data[key] = buffer.readUInt8(offset);
                return offset + 1;
            }
            if (length == 2) {
                data[key] = buffer.readUInt16BE(offset);
                return offset + 2;
            }
            if (length == 4) {
                data[key] = buffer.readUInt32BE(offset);
                return offset + 4;
            }

            throw 'Unsupported integer length '+length;
        },

        string: function(buffer, offset, data, key, length) {
            var blankCode = ' '.charCodeAt(0);
            var string = [];
            for (var i = 0; i < length ; i++) {
                offset = decoders.int(buffer, offset, string, i, 1);
            }
            data[key] = String.fromCharCode.apply(this, string).replace(/\u0000.*$/g, "");
            return offset;
        },

        null: function(buffer, offset, data, key, length) {
            return offset + length;
        },

        boolean: function(buffer, offset, data, key, length) {
            offset = decoders.int(buffer, offset, data, key, 1);
            data[key] = data[key] == 1;
            return offset;
        }
    };

    CommandManager.encode = function(command, data) {

        var config = CommandManager.commands[command];
        if (!config) throw 'Unknown command "'+command+'" to encode';

        // Compute buffer length
        var length = config.fields.reduce(function(a, b) {
            return a + (b.length || 1) * (b.repeats || 1);
        }, 0);

        // Actual buffer length must include frame, command, length and CRC
        var buffer = new Buffer(6 + length);
        var offset = 0;

        // Add frame to the buffer
        offset = encoders.int(buffer, offset, frame[0], 1);
        offset = encoders.int(buffer, offset, frame[1], 1);
        offset = encoders.int(buffer, offset, config.command.code, 1);
        offset = encoders.int(buffer, offset, length, 1);

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown encoder "'+field.type+'"';

            if (field.repeats) {
                if (field.repeats !== data[field.name].length) {
                    throw 'Field "'+field.name+'" must have '+field.repeats+' values';
                }

                for (var i = 0; i < field.repeats; i++) {
                    offset = encoders[field.type](buffer, offset, data[field.name][i], field.length || 1);
                }
            }
            else offset = encoders[field.type](buffer, offset, data[field.name], field.length || 1);
        });

        // Find CRC
        encoders.int(buffer, offset, crc.crc16(buffer.slice(2, offset)), 2);

        return buffer;
    };

    CommandManager.decode = function(buffer) {

        var code = buffer.readUInt8(2);
        var command = findCommand(code);
        var config = CommandManager.commands[command];
        if (!config) throw 'Unknown command code "'+code+'" to decode';

        var data = {command: command};
        var offset = 4;

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown decoder "'+field.type+'"';

            if (field.repeats) {
                var array = [];
                for (var i = 0; i < field.repeats; i++) {
                    offset = decoders[field.type](buffer, offset, array, i, field.length || 1);
                }
                data[field.name] = array;
            }
            else offset = decoders[field.type](buffer, offset, data, field.name, field.length || 1);
        });

        // TODO: validate checksum here

        return data;
    };

    CommandManager.decodeJpeg = function(buffer) {
        var config = CommandManager.commands.jpegStream;
        var data = {};
        var offset = 0;

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown decoder "'+field.type+'"';

            if (field.repeats) {
                var array = [];
                for (var i = 0; i < field.repeats; i++) {
                    offset = decoders[field.type](buffer, offset, array, i, field.length || 1);
                }
                data[field.name] = array;
            }
            else offset = decoders[field.type](buffer, offset, data, field.name, field.length || 1);
        });

        // TODO: This only supports one packet per frame
        data.image = buffer.slice(16);

        return data;

    };

    return CommandManager;
};
<commit_msg>Fixed crc output<commit_after>/**
 * Encodes and decodes commands
 * e.g.
 *
 * var config = {
 *     dfcg: {
 *         command: {
 *             name: 'DCFG',
 *             title: 'Device Configuration Message',
 *             description: 'Configures the device, only first transmitter can send',
 *             code: 0x12
 *         },
 *         fields: [
 *             {name: 'cat', type: 'int', length: 2},
 *             {name: 'dog', type: 'string', length: 12},
 *             {name: 'signals', type: 'int', length: 2, repeats: 6}
 *         ]
 *     }
 * };
 *
 * var message = {cat: 256, dog: 'You smell', signals: [2, 17, 257, 33, 1, 1000]}
 * var buffer = CommandManager.encode(config.dfcg, message);
 * var message2 = CommandManager.decode(config.dfcg, buffer);
 * assert(message == message2);
 */

module.exports = function(commands) {

    var crc = require('crc');
    var fs = require('fs');
    var Buffer = require('buffer').Buffer;
    var CommandManager = {commands: commands};

    // 2 frame bytes are required at the start of each message
    var frame = [0xAA, 0xBB];

    // Finds a command from its code
    var findCommand = function(code) {
        for (i in CommandManager.commands) {
            if (CommandManager.commands[i].command.code == code) {
                return i;
            }
        }
    };

    // Encodes values
    var encoders = {
        int: function(buffer, offset, value, length) {
            if (length == 1) {
                buffer.writeUInt8(value, offset);
                return offset + 1;
            }
            if (length == 2) {
                buffer.writeUInt16BE(value, offset);
                return offset + 2;
            }
            if (length == 4) {
                buffer.writeUInt32BE(value, offset);
                return offset + 4;
            }

            throw 'Unsupported integer length '+length;
        },

        string: function(buffer, offset, value, length) {
            for (var i = 0; i < length ; i++) {
                offset = encoders.int(buffer, offset, value[i] ? value.charCodeAt(i) : 0, 1);
            }

            return offset;
        },

        null: function(buffer, offset, value, length) {
            for (var i = 0; i < length ; i++) {
                offset = encoders.int(buffer, offset, 0, 1);
            }
            return offset;
        },

        boolean: function(buffer, offset, value, length) {
            return encoders.int(buffer, offset, value ? 1 : 0, 1);
        }
    };

    // Encodes values
    var decoders = {
        int: function(buffer, offset, data, key, length) {
            if (length == 1) {
                data[key] = buffer.readUInt8(offset);
                return offset + 1;
            }
            if (length == 2) {
                data[key] = buffer.readUInt16BE(offset);
                return offset + 2;
            }
            if (length == 4) {
                data[key] = buffer.readUInt32BE(offset);
                return offset + 4;
            }

            throw 'Unsupported integer length '+length;
        },

        string: function(buffer, offset, data, key, length) {
            var blankCode = ' '.charCodeAt(0);
            var string = [];
            for (var i = 0; i < length ; i++) {
                offset = decoders.int(buffer, offset, string, i, 1);
            }
            data[key] = String.fromCharCode.apply(this, string).replace(/\u0000.*$/g, "");
            return offset;
        },

        null: function(buffer, offset, data, key, length) {
            return offset + length;
        },

        boolean: function(buffer, offset, data, key, length) {
            offset = decoders.int(buffer, offset, data, key, 1);
            data[key] = data[key] == 1;
            return offset;
        }
    };

    CommandManager.encode = function(command, data) {

        var config = CommandManager.commands[command];
        if (!config) throw 'Unknown command "'+command+'" to encode';

        // Compute buffer length
        var length = config.fields.reduce(function(a, b) {
            return a + (b.length || 1) * (b.repeats || 1);
        }, 0);

        // Actual buffer length must include frame, command, length and CRC
        var buffer = new Buffer(6 + length);
        var offset = 0;

        // Add frame to the buffer
        offset = encoders.int(buffer, offset, frame[0], 1);
        offset = encoders.int(buffer, offset, frame[1], 1);
        offset = encoders.int(buffer, offset, config.command.code, 1);
        offset = encoders.int(buffer, offset, length, 1);

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown encoder "'+field.type+'"';

            if (field.repeats) {
                if (field.repeats !== data[field.name].length) {
                    throw 'Field "'+field.name+'" must have '+field.repeats+' values';
                }

                for (var i = 0; i < field.repeats; i++) {
                    offset = encoders[field.type](buffer, offset, data[field.name][i], field.length || 1);
                }
            }
            else offset = encoders[field.type](buffer, offset, data[field.name], field.length || 1);
        });

        // Find CRC
        encoders.int(buffer, offset, parseInt(crc.crc16(buffer.slice(2, offset)), 16), 2);

        return buffer;
    };

    CommandManager.decode = function(buffer) {

        var code = buffer.readUInt8(2);
        var command = findCommand(code);
        var config = CommandManager.commands[command];
        if (!config) throw 'Unknown command code "'+code+'" to decode';

        var data = {command: command};
        var offset = 4;

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown decoder "'+field.type+'"';

            if (field.repeats) {
                var array = [];
                for (var i = 0; i < field.repeats; i++) {
                    offset = decoders[field.type](buffer, offset, array, i, field.length || 1);
                }
                data[field.name] = array;
            }
            else offset = decoders[field.type](buffer, offset, data, field.name, field.length || 1);
        });

        // TODO: validate checksum here

        return data;
    };

    CommandManager.decodeJpeg = function(buffer) {
        var config = CommandManager.commands.jpegStream;
        var data = {};
        var offset = 0;

        // Encode values into the buffer
        config.fields.map(function(field) {
            if (!encoders[field.type]) throw 'Unknown decoder "'+field.type+'"';

            if (field.repeats) {
                var array = [];
                for (var i = 0; i < field.repeats; i++) {
                    offset = decoders[field.type](buffer, offset, array, i, field.length || 1);
                }
                data[field.name] = array;
            }
            else offset = decoders[field.type](buffer, offset, data, field.name, field.length || 1);
        });

        // TODO: This only supports one packet per frame
        data.image = buffer.slice(16);

        return data;

    };

    return CommandManager;
};
<|endoftext|>


<commit_before>var Fs = require('fs');
var Path = require('path');
var FindRoot = require('find-root');
var Offline = require('../offline');
var jwtDecode = require('jsonwebtoken').decode;

exports.help = [
    'Checks your project\'s dependencies for vulnerabilities by submitting your package.json (and npm-shrinkwrap.json if it exists) to requiresafe for validation.',
    'Note that if npm-shrinkwrap exists, it will be considered the authority for your project and your package.json will be ignored.'
];

exports.run = function (config) {

    var root = FindRoot(process.cwd());
    var result = {};
    var packageFile = Path.join(root, 'package.json');
    var shrinkWrap = Path.join(root, 'npm-shrinkwrap.json');
    var loggedIn = config.token && config.token.length > 1;

    var logResults = function (results) {

        if (results.data === 'OK') {
            return '✔ No known vulnerabilities found';
        }

        return [results.data, 1];
    };

    var tokenData = loggedIn && jwtDecode(config.token);

    try {
        result.package = JSON.parse(Fs.readFileSync(packageFile, 'utf8'));
    }
    catch (err) {
        return callback(new Error('Unable to read package.json file: ' + packageFile));
    }

    try {
        result.shrinkWrap = JSON.parse(Fs.readFileSync(shrinkWrap, 'utf8'));
    }
    catch (err) {
        if (err.code !== 'ENOENT') {
            return callback(new Error('Unable to read npm-shrinkwrap.json file: ' + shrinkWrap));
        }
    }

    if (config.codeclimate) {
        return Offline.check(result);
    }

    if (loggedIn &&
        tokenData.entity !== 'app' &&
        !config.org) {

        return config.api.get('/users/me').then(function (me) {

            if (me.data.orgs.length === 0) {
                throw new Error('You do not belong to any orgs');
            }

            if (me.data.orgs.length === 1) {
                return config.api.post('/orgs/' + me.data.orgs[0].id + '/projects/check', { project: result }).then(logResults);
            }

            throw new Error('You belong to multiple orgs, you need to specify one on the command line');
        });
    }

    if (tokenData.entity === 'app') {
        return config.api.post('/orgs/' + tokenData.app.org_id + '/projects/check', { project: result }).then(logResults);
    }

    return config.api.post('/projects/check', { project: result }).then(logResults);
};
<commit_msg>cleanup<commit_after>var Fs = require('fs');
var Path = require('path');
var FindRoot = require('find-root');
var Offline = require('../offline');
var jwtDecode = require('jsonwebtoken').decode;

exports.help = [
    'Checks your project\'s dependencies for vulnerabilities by submitting your package.json (and npm-shrinkwrap.json if it exists) to requiresafe for validation.',
    'Note that if npm-shrinkwrap exists, it will be considered the authority for your project and your package.json will be ignored.'
];

exports.run = function (config) {

    try {
        var root = FindRoot(process.cwd());
    }
    catch (e) {
        return ['package.json missing', 1];
    }

    var result = {};
    var packageFile = Path.join(root, 'package.json');
    var shrinkWrap = Path.join(root, 'npm-shrinkwrap.json');
    var loggedIn = config.token && config.token.length > 1;

    var logResults = function (results) {

        if (results.data === 'OK') {
            return '✔ No known vulnerabilities found';
        }

        return [results.data, 1];
    };

    var tokenData = loggedIn && jwtDecode(config.token);

    try {
        result.package = JSON.parse(Fs.readFileSync(packageFile, 'utf8'));
    }
    catch (err) {
        throw new Error('Unable to read package.json file: ' + packageFile);
    }

    try {
        result.shrinkWrap = JSON.parse(Fs.readFileSync(shrinkWrap, 'utf8'));
    }
    catch (err) {
        if (err.code !== 'ENOENT') {
            throw new Error('Unable to read npm-shrinkwrap.json file: ' + shrinkWrap);
        }
    }

    if (config.codeclimate) {
        return Offline.check(result);
    }

    if (loggedIn &&
        tokenData.entity !== 'app' &&
        !config.org) {

        return config.api.get('/users/me').then(function (me) {

            if (me.data.orgs.length === 0) {
                throw new Error('You do not belong to any orgs');
            }

            if (me.data.orgs.length === 1) {
                return config.api.post('/orgs/' + me.data.orgs[0].id + '/projects/check', { project: result }).then(logResults);
            }

            throw new Error('You belong to multiple orgs, you need to specify one on the command line');
        });
    }

    if (tokenData.entity === 'app') {
        return config.api.post('/orgs/' + tokenData.app.org_id + '/projects/check', { project: result }).then(logResults);
    }

    return config.api.post('/projects/check', { project: result }).then(logResults);
};
<|endoftext|>


<commit_before>'use strict'

const connect = require('connect')
const serveStatic = require('serve-static')
const Renderer = require('docsify-server-renderer')
const util = require('../util/index')
const chalk = require('chalk')
const LRU = require('lru-cache')

const defaultConfig = {
  template: `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Doc</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css" title="vue">
</head>
<body>
  <!--inject-app-->
  <!--inject-config-->
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
</body>
</html>`
}

function loadConfig(config) {
  try {
    return require(util.cwd(config))
  } catch (e) {
    console.log(chalk.red(`${e.message} in ${config}`))
    process.exit(1)
  }
}

module.exports = function (path, configFile, port) {
  let config = defaultConfig
  const pkg = util.pkg()
  const ctx = util.cwd('.')

  path = path || './'

  if (configFile) {
    config = loadConfig(configFile)
    config.template = /\.html$/.test(config.template) ?
      util.read(util.resolve(ctx, config.template)) :
      defaultConfig.template
  } else if (pkg.docsify) {
    const tpl = pkg.docsify.template

    config = pkg.docsify
    config.template =
      tpl && util.exists(util.resolve(ctx, tpl)) ?
        util.read(tpl) :
        defaultConfig.template
  }

  const renderer = new Renderer(Object.assign(defaultConfig, config))
  const server = connect()
  const cached = new LRU(config.maxAge || 0)

  server.use(serveStatic(path))
  server.use(function (req, res) {
    serveStatic(path)(req, res, function () {
      if (
        /\.(jpg|jpeg|gif|png|svg|ico|mp4|webm|ogg|ogv|js|css|md)(?:\?v=[0-9.]+)?$/.test(
          req.url
        )
      ) {
        res.writeHead(404)
        res.end()
      }

      Promise.resolve(cached.get(req.url) || renderer.renderToString(req.url))
        .then(function (html) {
          cached.set(req.url)
          res.end(html)
        })
        .catch(function (err) {
          console.error(err)
          res.writeHead(404)
          res.end()
        })
    })
  })
  server.listen(port || 4000)

  const msg =
    '\n' +
    chalk.blue('[SSR]') +
    ' Serving ' +
    chalk.green(`${path}`) +
    ' now.\n' +
    'Listening at ' +
    chalk.green(`http://localhost:${port}`) +
    '\n'

  console.log(msg)
}
<commit_msg>refactor: ignore explicit index file reference<commit_after>'use strict'

const connect = require('connect')
const serveStatic = require('serve-static')
const Renderer = require('docsify-server-renderer')
const util = require('../util')
const chalk = require('chalk')
const LRU = require('lru-cache')

const defaultConfig = {
  template: `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Doc</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css" title="vue">
</head>
<body>
  <!--inject-app-->
  <!--inject-config-->
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
</body>
</html>`
}

function loadConfig(config) {
  try {
    return require(util.cwd(config))
  } catch (e) {
    console.log(chalk.red(`${e.message} in ${config}`))
    process.exit(1)
  }
}

module.exports = function (path, configFile, port) {
  let config = defaultConfig
  const pkg = util.pkg()
  const ctx = util.cwd('.')

  path = path || './'

  if (configFile) {
    config = loadConfig(configFile)
    config.template = /\.html$/.test(config.template) ?
      util.read(util.resolve(ctx, config.template)) :
      defaultConfig.template
  } else if (pkg.docsify) {
    const tpl = pkg.docsify.template

    config = pkg.docsify
    config.template =
      tpl && util.exists(util.resolve(ctx, tpl)) ?
        util.read(tpl) :
        defaultConfig.template
  }

  const renderer = new Renderer(Object.assign(defaultConfig, config))
  const server = connect()
  const cached = new LRU(config.maxAge || 0)

  server.use(serveStatic(path))
  server.use(function (req, res) {
    serveStatic(path)(req, res, function () {
      if (
        /\.(jpg|jpeg|gif|png|svg|ico|mp4|webm|ogg|ogv|js|css|md)(?:\?v=[0-9.]+)?$/.test(
          req.url
        )
      ) {
        res.writeHead(404)
        res.end()
      }

      Promise.resolve(cached.get(req.url) || renderer.renderToString(req.url))
        .then(function (html) {
          cached.set(req.url)
          res.end(html)
        })
        .catch(function (err) {
          console.error(err)
          res.writeHead(404)
          res.end()
        })
    })
  })
  server.listen(port || 4000)

  const msg =
    '\n' +
    chalk.blue('[SSR]') +
    ' Serving ' +
    chalk.green(`${path}`) +
    ' now.\n' +
    'Listening at ' +
    chalk.green(`http://localhost:${port}`) +
    '\n'

  console.log(msg)
}
<|endoftext|>


<commit_before>const Command          = require('./-command');
const Hook             = require('../tasks/run-hook');
const logger           = require('../utils/logger');
const CordovaTarget    = require('../targets/cordova/target');
const CordovaRaw       = require('../targets/cordova/tasks/raw');
const editXml          = require('../targets/cordova/utils/edit-xml');
const getNetworkIp     = require('../utils/get-network-ip');
const requireFramework = require('../utils/require-framework');
const RSVP             = require('rsvp');
const Promise          = RSVP.Promise;
const flatten          = require('lodash').flatten;

const listAndroidEms   = require('../targets/android/tasks/list-emulators');
const listAndroidDevices = require('../targets/android/tasks/list-devices');
const AndroidTarget    = require('../targets/android/target');
const listIOSEms       = require('../targets/ios/tasks/list-emulators');
const IOSTarget        = require('../targets/ios/target');

const CreateLiveReloadShell = require('../tasks/create-livereload-shell');

module.exports = Command.extend({
  name: 'start',
  aliases: [ 'start' ],
  description: 'Run app on device/emulator /w livereload',
  works: 'insideProject',

  /* eslint-disable max-len */
  availableOptions: [
    { name: 'platform',   type: String },
    { name: 'emulator',   type: String,  default: '' },
    { name: 'emulatorid', type: String },
    { name: 'build',      type: Boolean },
    { name: 'reload-url', type: String,  aliases: ['r'] },
    { name: 'port',       type: Number,  aliases: ['p'] },
    { name: 'skip-framework-build', type: Boolean, default: false, aliases: ['sfb'] },
    { name: 'skip-cordova-build',   type: Boolean, default: false, aliases: ['scb'] }
  ],
  /* eslint-enable max-len */

  getReloadUrl(port, reloadUrl, framework) {
    if (reloadUrl) { return reloadUrl; }

    if (port === undefined) {
      port = framework.port;
    }

    let networkAddress = getNetworkIp();
    return 'http://' + networkAddress + ':' + port;
  },

  selectDevice(opts, installedPlatforms) {
    let foundDevices = [];
    if (opts.platform !== 'ios' && installedPlatforms.includes('android')) {
      foundDevices.push(listAndroidEms());
      foundDevices.push(listAndroidDevices());
    }

    if (opts.platform !== 'android' && installedPlatforms.includes('ios')) {
      foundDevices.push(listIOSEms());
    }

    return RSVP.all(foundDevices).then((devices) => {
      devices = flatten(devices);
      if (opts.emulator === '') {
        let promptOpts = {
          type: 'list',
          name: 'device',
          message: 'Select a device/emulator',
          pageSize: 30,
          choices: []
        };

        devices.forEach((em, i) => {
          promptOpts.choices.push({
            key: i,
            name: em.label(),
            value: em
          });
        });

        return this.ui.prompt(promptOpts).then((selected) => {
          return selected.device;
        });
      } else {
        //Preference --emulator vs emulatorID if passed
        let device;
        if (opts.emulator) {
          device = devices.find(function(d) {
            if (d.name === opts.emulator) { return d; }
          });
        }

        return Promise.resolve(device);
      }
    });
  },

  validatePlatform(installedPlatforms, targetPlatform) {
    //If no target platfor mshow all installed platforms
    if (targetPlatform && !installedPlatforms.includes(targetPlatform)) {
      logger.error(`
        You are passing platform=${targetPlatform} which is not installed.
        Try running corber platform add ${targetPlatform}`);
    }
  },

  run(opts) {
    this._super.apply(this, arguments);
    logger.info('Corber Starting');

    let cdvTarget = new CordovaTarget({
      project: this.project
    });

    let installedPlatforms = cdvTarget.installedPlatforms();
    this.validatePlatform(installedPlatforms, opts.platform);

    return this.selectDevice(opts, installedPlatforms).then((device) => {
      //supports webpack addon
      this.project.targetIsCordova = true;
      this.project.CORBER_PLATFORM = device.platform;
      this.project.targetIsCordovaLivereload = true;

      cdvTarget.platform = device.platform;

      let platformTarget;
      if (device.platform === 'ios') {
        platformTarget = new IOSTarget({
          device: device,
          project: this.project
        });
      } else if (device.platform === 'android') {
        platformTarget = new AndroidTarget({
          device: device,
          project: this.project
        });
      }

      let framework = requireFramework(this.project);
      let reloadUrl = this.getReloadUrl(opts.port, opts.reloadUrl, framework);

      let createLivereloadShell = new CreateLiveReloadShell({
        project: this.project
      });

      let prepare = new CordovaRaw({
        project: this.project,
        api: 'prepare'
      });

      let hook = new Hook({
        project: this.project
      });

      return new Promise((resolve, reject) => {
        hook.run('beforeBuild')
          .then(() => editXml.addNavigation(this.project, reloadUrl))
          .then(() => cdvTarget.validateServe())
          .then(() => framework.validateServe(opts))
          .then(() => createLivereloadShell.run(reloadUrl))
          .then(() => prepare.run({ platforms: [device.platform] }))
          .then(function() {
            if (opts.skipCordovaBuild !== true) {
              return platformTarget.build();
            }
          })
          .then(() => hook.run('afterBuild'))
          .then(() => platformTarget.run())
          .then(() => {
            if (opts.skipFrameworkBuild !== true) {
              return framework.serve(opts, this.ui);
            }
          })
          .then(resolve).catch(reject);
      });
    });
  }
});
<commit_msg>fix(ember-start): set livereload to true, fixes #466<commit_after>const Command          = require('./-command');
const Hook             = require('../tasks/run-hook');
const logger           = require('../utils/logger');
const CordovaTarget    = require('../targets/cordova/target');
const CordovaRaw       = require('../targets/cordova/tasks/raw');
const editXml          = require('../targets/cordova/utils/edit-xml');
const getNetworkIp     = require('../utils/get-network-ip');
const requireFramework = require('../utils/require-framework');
const RSVP             = require('rsvp');
const Promise          = RSVP.Promise;
const flatten          = require('lodash').flatten;

const listAndroidEms   = require('../targets/android/tasks/list-emulators');
const listAndroidDevices = require('../targets/android/tasks/list-devices');
const AndroidTarget    = require('../targets/android/target');
const listIOSEms       = require('../targets/ios/tasks/list-emulators');
const IOSTarget        = require('../targets/ios/target');

const CreateLiveReloadShell = require('../tasks/create-livereload-shell');

module.exports = Command.extend({
  name: 'start',
  aliases: [ 'start' ],
  description: 'Run app on device/emulator /w livereload',
  works: 'insideProject',

  /* eslint-disable max-len */
  availableOptions: [
    { name: 'platform',   type: String },
    { name: 'emulator',   type: String,  default: '' },
    { name: 'emulatorid', type: String },
    { name: 'build',      type: Boolean },
    { name: 'reload-url', type: String,  aliases: ['r'] },
    { name: 'live-reload', type: Boolean, default: true,          aliases: ['lr'] },
    { name: 'port',       type: Number,  aliases: ['p'] },
    { name: 'skip-framework-build', type: Boolean, default: false, aliases: ['sfb'] },
    { name: 'skip-cordova-build',   type: Boolean, default: false, aliases: ['scb'] }
  ],
  /* eslint-enable max-len */

  getReloadUrl(port, reloadUrl, framework) {
    if (reloadUrl) { return reloadUrl; }

    if (port === undefined) {
      port = framework.port;
    }

    let networkAddress = getNetworkIp();
    return 'http://' + networkAddress + ':' + port;
  },

  selectDevice(opts, installedPlatforms) {
    let foundDevices = [];
    if (opts.platform !== 'ios' && installedPlatforms.includes('android')) {
      foundDevices.push(listAndroidEms());
      foundDevices.push(listAndroidDevices());
    }

    if (opts.platform !== 'android' && installedPlatforms.includes('ios')) {
      foundDevices.push(listIOSEms());
    }

    return RSVP.all(foundDevices).then((devices) => {
      devices = flatten(devices);
      if (opts.emulator === '') {
        let promptOpts = {
          type: 'list',
          name: 'device',
          message: 'Select a device/emulator',
          pageSize: 30,
          choices: []
        };

        devices.forEach((em, i) => {
          promptOpts.choices.push({
            key: i,
            name: em.label(),
            value: em
          });
        });

        return this.ui.prompt(promptOpts).then((selected) => {
          return selected.device;
        });
      } else {
        //Preference --emulator vs emulatorID if passed
        let device;
        if (opts.emulator) {
          device = devices.find(function(d) {
            if (d.name === opts.emulator) { return d; }
          });
        }

        return Promise.resolve(device);
      }
    });
  },

  validatePlatform(installedPlatforms, targetPlatform) {
    //If no target platfor mshow all installed platforms
    if (targetPlatform && !installedPlatforms.includes(targetPlatform)) {
      logger.error(`
        You are passing platform=${targetPlatform} which is not installed.
        Try running corber platform add ${targetPlatform}`);
    }
  },

  run(opts) {
    this._super.apply(this, arguments);
    logger.info('Corber Starting');

    let cdvTarget = new CordovaTarget({
      project: this.project
    });

    let installedPlatforms = cdvTarget.installedPlatforms();
    this.validatePlatform(installedPlatforms, opts.platform);

    return this.selectDevice(opts, installedPlatforms).then((device) => {
      //supports webpack addon
      this.project.targetIsCordova = true;
      this.project.CORBER_PLATFORM = device.platform;
      this.project.targetIsCordovaLivereload = true;

      cdvTarget.platform = device.platform;

      let platformTarget;
      if (device.platform === 'ios') {
        platformTarget = new IOSTarget({
          device: device,
          project: this.project
        });
      } else if (device.platform === 'android') {
        platformTarget = new AndroidTarget({
          device: device,
          project: this.project
        });
      }

      let framework = requireFramework(this.project);
      let reloadUrl = this.getReloadUrl(opts.port, opts.reloadUrl, framework);

      let createLivereloadShell = new CreateLiveReloadShell({
        project: this.project
      });

      let prepare = new CordovaRaw({
        project: this.project,
        api: 'prepare'
      });

      let hook = new Hook({
        project: this.project
      });

      return new Promise((resolve, reject) => {
        hook.run('beforeBuild')
          .then(() => editXml.addNavigation(this.project, reloadUrl))
          .then(() => cdvTarget.validateServe())
          .then(() => framework.validateServe(opts))
          .then(() => createLivereloadShell.run(reloadUrl))
          .then(() => prepare.run({ platforms: [device.platform] }))
          .then(function() {
            if (opts.skipCordovaBuild !== true) {
              return platformTarget.build();
            }
          })
          .then(() => hook.run('afterBuild'))
          .then(() => platformTarget.run())
          .then(() => {
            if (opts.skipFrameworkBuild !== true) {
              return framework.serve(opts, this.ui);
            }
          })
          .then(resolve).catch(reject);
      });
    });
  }
});
<|endoftext|>