<commit_before>'use strict';

var util = require('util');
var WildEmitter = require('wildemitter');
var async = require('async');

var WS = (require('faye-websocket') && require('faye-websocket').Client) ?
                                       require('faye-websocket').Client :
                                       window.WebSocket;

var WS_OPEN = 1;

function WSConnection(sm, stanzas) {
    var self = this;

    WildEmitter.call(this);

    self.sm = sm;
    self.closing = false;

    self.stanzas = {
        Open: stanzas.getDefinition('open', 'urn:ietf:params:xml:ns:xmpp-framing', true),
        Close: stanzas.getDefinition('close', 'urn:ietf:params:xml:ns:xmpp-framing', true),
        StreamError: stanzas.getStreamError()
    };

    self.sendQueue = async.queue(function (data, cb) {
        if (self.conn) {
            if (typeof data !== 'string') {
                data = data.toString();
            }

            data = new Buffer(data, 'utf8').toString();

            self.emit('raw:outgoing', data);
            if (self.conn.readyState === WS_OPEN) {
                self.conn.send(data);
            }
        }
        cb();
    }, 1);

    self.on('connected', function () {
        self.send(self.startHeader());
    });

    self.on('raw:incoming', function (data) {
        var stanzaObj, err;

        data = data.trim();
        if (data === '') {
            return;
        }

        try {
            stanzaObj = stanzas.parse(data);
        } catch (e) {
            err = new this.stanzas.StreamError({
                condition: 'invalid-xml'
            });
            self.emit('stream:error', err, e);
            self.send(err);
            return self.disconnect();
        }

        if (stanzaObj._name === 'openStream') {
            self.hasStream = true;
            self.stream = stanzaObj;
            return self.emit('stream:start', stanzaObj.toJSON());
        }
        if (stanzaObj._name === 'closeStream') {
            self.emit('stream:end');
            return self.disconnect();
        }

        if (!stanzaObj.lang && self.stream) {
            stanzaObj.lang = self.stream.lang;
        }

        self.emit('stream:data', stanzaObj);
    });
}

util.inherits(WSConnection, WildEmitter);

WSConnection.prototype.connect = function (opts) {
    var self = this;

    self.config = opts;

    self.hasStream = false;
    self.closing = false;

    self.conn = new WS(opts.wsURL, 'xmpp');
    self.conn.onerror = function (e) {
        e.preventDefault();
        self.emit('disconnected', self);
    };

    self.conn.onclose = function () {
        self.emit('disconnected', self);
    };

    self.conn.onopen = function () {
        self.sm.started = false;
        self.emit('connected', self);
    };

    self.conn.onmessage = function (wsMsg) {
        self.emit('raw:incoming', new Buffer(wsMsg.data, 'utf8').toString());
    };
};

WSConnection.prototype.startHeader = function () {
    return new this.stanzas.Open({
        version: this.config.version || '1.0',
        lang: this.config.lang || 'en',
        to: this.config.server
    });
};

WSConnection.prototype.closeHeader = function () {
    return new this.stanzas.Close();
};

WSConnection.prototype.disconnect = function () {
    if (this.conn && !this.closing && this.hasStream) {
        this.closing = true;
        this.send(this.closeHeader());
    } else {
        this.hasStream = false;
        this.stream = undefined;
        if (this.conn.readyState === WS_OPEN) {
            this.conn.close();
        }
        this.conn = undefined;
    }
};

WSConnection.prototype.restart = function () {
    var self = this;
    self.hasStream = false;
    self.send(this.startHeader());
};

WSConnection.prototype.send = function (data) {
    this.sendQueue.push(data);
};

module.exports = WSConnection;
<commit_msg>Fix this scope<commit_after>'use strict';

var util = require('util');
var WildEmitter = require('wildemitter');
var async = require('async');

var WS = (require('faye-websocket') && require('faye-websocket').Client) ?
                                       require('faye-websocket').Client :
                                       window.WebSocket;

var WS_OPEN = 1;

function WSConnection(sm, stanzas) {
    var self = this;

    WildEmitter.call(this);

    self.sm = sm;
    self.closing = false;

    self.stanzas = {
        Open: stanzas.getDefinition('open', 'urn:ietf:params:xml:ns:xmpp-framing', true),
        Close: stanzas.getDefinition('close', 'urn:ietf:params:xml:ns:xmpp-framing', true),
        StreamError: stanzas.getStreamError()
    };

    self.sendQueue = async.queue(function (data, cb) {
        if (self.conn) {
            if (typeof data !== 'string') {
                data = data.toString();
            }

            data = new Buffer(data, 'utf8').toString();

            self.emit('raw:outgoing', data);
            if (self.conn.readyState === WS_OPEN) {
                self.conn.send(data);
            }
        }
        cb();
    }, 1);

    self.on('connected', function () {
        self.send(self.startHeader());
    });

    self.on('raw:incoming', function (data) {
        var stanzaObj, err;

        data = data.trim();
        if (data === '') {
            return;
        }

        try {
            stanzaObj = stanzas.parse(data);
        } catch (e) {
            err = new self.stanzas.StreamError({
                condition: 'invalid-xml'
            });
            self.emit('stream:error', err, e);
            self.send(err);
            return self.disconnect();
        }

        if (stanzaObj._name === 'openStream') {
            self.hasStream = true;
            self.stream = stanzaObj;
            return self.emit('stream:start', stanzaObj.toJSON());
        }
        if (stanzaObj._name === 'closeStream') {
            self.emit('stream:end');
            return self.disconnect();
        }

        if (!stanzaObj.lang && self.stream) {
            stanzaObj.lang = self.stream.lang;
        }

        self.emit('stream:data', stanzaObj);
    });
}

util.inherits(WSConnection, WildEmitter);

WSConnection.prototype.connect = function (opts) {
    var self = this;

    self.config = opts;

    self.hasStream = false;
    self.closing = false;

    self.conn = new WS(opts.wsURL, 'xmpp');
    self.conn.onerror = function (e) {
        e.preventDefault();
        self.emit('disconnected', self);
    };

    self.conn.onclose = function () {
        self.emit('disconnected', self);
    };

    self.conn.onopen = function () {
        self.sm.started = false;
        self.emit('connected', self);
    };

    self.conn.onmessage = function (wsMsg) {
        self.emit('raw:incoming', new Buffer(wsMsg.data, 'utf8').toString());
    };
};

WSConnection.prototype.startHeader = function () {
    return new this.stanzas.Open({
        version: this.config.version || '1.0',
        lang: this.config.lang || 'en',
        to: this.config.server
    });
};

WSConnection.prototype.closeHeader = function () {
    return new this.stanzas.Close();
};

WSConnection.prototype.disconnect = function () {
    if (this.conn && !this.closing && this.hasStream) {
        this.closing = true;
        this.send(this.closeHeader());
    } else {
        this.hasStream = false;
        this.stream = undefined;
        if (this.conn.readyState === WS_OPEN) {
            this.conn.close();
        }
        this.conn = undefined;
    }
};

WSConnection.prototype.restart = function () {
    var self = this;
    self.hasStream = false;
    self.send(this.startHeader());
};

WSConnection.prototype.send = function (data) {
    this.sendQueue.push(data);
};

module.exports = WSConnection;
<|endoftext|>


<commit_before>/**
 *
 * Main process of Electron.js
 */

const electron = require('electron')
const app = electron.app

global.ROOT = __dirname
global.IMAGE_TEMP = `${global.ROOT}/img`

global.hasChanged
global.isNew
global.savePath

// This variable is used to know if the editor have to save
// images inside the tmp folder or in the RASH package
global.isWrapper

global.ASSETS_DIRECTORIES = [
  `${global.ROOT}/js`,
  `${global.ROOT}/css`,
  `${global.ROOT}/fonts`,
  IMAGE_TEMP
]

const {
  BrowserWindow,
  ipcMain,
  dialog,
  Menu
} = electron

const url = require('url')
const path = require('path')
const windowManager = require('electron-window-manager')

const TEMPLATE = 'template.html'
const SPLASH = 'splash.html'

const RAJE_FS = require('./modules/raje_fs.js')
const RAJE_MENU = require('./modules/raje_menu.js')

const EDITOR_WINDOW = 'editor'
const SPLASH_WINDOW = 'splash'

const windows = {

  /**
   * Init the windowmanager and open the splash window
   */
  openSplash: function () {

    // Init the window manager
    windowManager.init()

    // Get the url to the splash window
    let splashWindowUrl = url.format({
      pathname: path.join(__dirname, SPLASH),
      protocol: 'file:',
      slashes: true
    })

    // Open the splash window
    windowManager.open(SPLASH_WINDOW, 'RAJE', splashWindowUrl, null, {
      height: 400,
      width: 500,
      resizable: false,
      movable: true,
      fullscreenable: false
    })

    // Set the menu
    Menu.setApplicationMenu(Menu.buildFromTemplate(RAJE_MENU.getSplashMenu()))
  },

  /**
   * Close the splash window
   */
  closeSplash: function () {

    windowManager.close(SPLASH_WINDOW)
  },

  /**
   * Open the editable template
   */
  openEditor: function (localRootPath, size) {

    global.hasChanged = false

    // Set the URL of the document
    let editorWindowUrl
    if (localRootPath) {

      // Remember that the document is already saved
      global.isNew = false
      global.savePath = localRootPath
      global.isWrapper = false

      // Get the URL to open the editor
      editorWindowUrl = url.format({
        pathname: path.join(localRootPath, TEMPLATE),
        protocol: 'file:',
        slashes: true
      })

    } else {

      // Remember that the document isn't saved yet
      global.isNew = true
      global.isWrapper = true

      editorWindowUrl = editorWindowUrl = url.format({
        pathname: path.join(__dirname, TEMPLATE),
        protocol: 'file:',
        slashes: true
      })
    }

    // Open the new window with the size given by the splash window
    windowManager.open(EDITOR_WINDOW, 'RAJE', editorWindowUrl, null, {
      width: size.width,
      height: size.height,
      resizable: true
    })

    // Update the app menu
    windows.updateEditorMenu(RAJE_MENU.getEditorMenu(!global.isNew))

    /**
     * Catch the close event
     */
    windowManager.get(EDITOR_WINDOW).object.on('close', event => {

      // If the document is in hasChanged mode (need to be saved)
      if (global.hasChanged) {

        // Cancel the close event
        event.preventDefault()

        // Show the dialog box "the document need to be saved"
        dialog.showMessageBox({
          type: 'warning',
          buttons: ['Save changes', 'Discard changes', 'Cancel, continue editing'],
          title: 'Unsaved changes',
          message: 'The article has been changed, do you want to save the changes?',
          cancelId: 2
        }, (response) => {
          switch (response) {

            // The user wants to save the document
            case 0:
              // TODO save the document
              global.hasChanged = false
              windowManager.get(EDITOR_WINDOW).object.close()
              break

              // The user doesn't want to save the document
            case 1:
              global.hasChanged = false
              windowManager.get(EDITOR_WINDOW).object.close()
              break
          }
        })
      }
    })
  },

  /**
   * Return true to let know that the client has Electron behind
   */
  isApp: function () {
    return true
  },

  /**
   *
   */
  updateEditorMenu: function (menu) {
    // Set the menu
    Menu.setApplicationMenu(Menu.buildFromTemplate(menu))
  }
}

/**
 * Event called when the app is ready
 */
app.on('ready', windows.openSplash)

/**
 * This event is called on OSX when the user click on icon in the dock
 */
app.on('activate', (event, hasVisibleWindows) => {

  // If there aren't any open windows
  if (!hasVisibleWindows)
    windows.openSplash()
})

/**
 * On OS X it is common for applications and their menu bar
 * to stay active until the user quits explicitly with Cmd + Q
 */
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('quit', RAJE_FS.removeImageTempFolder)

/**
 * This method is used to call the function that
 * opens the editor with the template
 *
 * Called by the splash window
 */
ipcMain.on('createArticle', (event, arg) => {

  windows.openEditor(null, arg)
  windows.closeSplash()
})

/**
 *
 */
ipcMain.on('openArticle', (event, arg) => {

  // Select the article folder
  let localRootPath = dialog.showOpenDialog({
    title: 'Open RASH article',
    properties: [
      'openDirectory'
    ]
  })[0]

  if (localRootPath) {

    RAJE_FS.checkRajeHiddenFile(localRootPath, err => {
      if (err) return

      windows.openEditor(localRootPath, arg)
      windows.closeSplash()
    })
  }
})

/**
 * This method is used to let know to the client that
 * the HTML file it's opened by Electron (not by a browser)
 *
 * If nothing is returned, tinymce isn't initialised
 *
 * Called from the renderer process
 */
ipcMain.on('isAppSync', (event, arg) => {
  event.returnValue = windows.isApp()
})

/**
 * This method is used to save the current document
 * calling the save dialog (in order to select where the document has to be saved)
 *
 * Then The article is saved by the raje_fs module
 *
 * After the save process, the url is updated loading the saved file url
 *
 * Called from the renderer process
 */
ipcMain.on('saveAsArticle', (event, arg) => {

  // Show save dialog here
  let savePath = dialog.showSaveDialog({
    title: 'Save as',
    defaultPath: arg.title,
    properties: [
      'openDirectory'
    ]
  })

  // If the user select a folder, the article is saved for the first time
  if (savePath) {
    RAJE_FS.saveAsArticle(savePath, arg.document, (err, message) => {
      if (err)
        return console.log(`Error: ${err}`)

      // Store important variables to check the save state
      global.isNew = false
      global.savePath = savePath

      windows.updateEditorMenu(RAJE_MENU.getEditorMenu(!global.isNew))

      // Notify the client
      global.sendNotification({
        text: message,
        type: 'success',
        timeout: 2000
      })
    })
  }
})

/**
 *
 */
ipcMain.on('saveArticle', (event, arg) => {

  // If the document has been saved before
  if (!global.isNew && typeof global.savePath != "undefined") {
    RAJE_FS.saveArticle(global.savePath, arg.document, (err, message) => {
      if (err) return console.log(err)

      // Notify the client
      global.sendNotification({
        text: message,
        type: 'success',
        timeout: 2000
      })
    })
  }
})

/**
 * This method is used to select the image to import in the document
 *
 * When the image is selected it's saved inside the image temporary folder
 * (which is deleted when the app is closed)
 */
ipcMain.on('selectImageSync', (event, arg) => {

  // Show the open dialog with options
  let imagePath = dialog.showOpenDialog({
    filters: [{
      name: 'Images',
      extensions: ['jpg', 'png']
    }]
  })

  // If a file is selected
  if (imagePath[0]) {

    // Save the image in the temporary folder
    RAJE_FS.saveImageTemp(imagePath[0], (err, result) => {

      if (err) return event.returnValue = err

      return event.returnValue = result
    })
  } else
    return event.returnValue = null
})

/**
 *
 */
ipcMain.on('updateDocumentState', (event, arg) => {
  global.hasChanged = arg
})

/**
 * Send a message to the renderer process
 * Start the save as process
 */
global.executeSaveAs = function () {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('executeSaveAs')
}

/**
 * Send a message to the renderer process
 * Start the save process
 */
global.executeSave = function () {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('executeSave')
}

/**
 *
 */
global.sendNotification = function (message) {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('notify', message)
}<commit_msg>"Open Article" dialog now select only html files<commit_after>/**
 *
 * Main process of Electron.js
 */

const electron = require('electron')
const app = electron.app

global.ROOT = __dirname
global.IMAGE_TEMP = `${global.ROOT}/img`

global.hasChanged
global.isNew
global.savePath

// This variable is used to know if the editor have to save
// images inside the tmp folder or in the RASH package
global.isWrapper

global.ASSETS_DIRECTORIES = [
  `${global.ROOT}/js`,
  `${global.ROOT}/css`,
  `${global.ROOT}/fonts`,
  IMAGE_TEMP
]

const {
  BrowserWindow,
  ipcMain,
  dialog,
  Menu
} = electron

const url = require('url')
const path = require('path')
const windowManager = require('electron-window-manager')

const TEMPLATE = 'template.html'
const SPLASH = 'splash.html'

const RAJE_FS = require('./modules/raje_fs.js')
const RAJE_MENU = require('./modules/raje_menu.js')

const EDITOR_WINDOW = 'editor'
const SPLASH_WINDOW = 'splash'

const windows = {

  /**
   * Init the windowmanager and open the splash window
   */
  openSplash: function () {

    // Init the window manager
    windowManager.init()

    // Get the url to the splash window
    let splashWindowUrl = url.format({
      pathname: path.join(__dirname, SPLASH),
      protocol: 'file:',
      slashes: true
    })

    // Open the splash window
    windowManager.open(SPLASH_WINDOW, 'RAJE', splashWindowUrl, null, {
      height: 400,
      width: 500,
      resizable: false,
      movable: true,
      fullscreenable: false
    })

    // Set the menu
    Menu.setApplicationMenu(Menu.buildFromTemplate(RAJE_MENU.getSplashMenu()))
  },

  /**
   * Close the splash window
   */
  closeSplash: function () {

    windowManager.close(SPLASH_WINDOW)
  },

  /**
   * Open the editable template
   */
  openEditor: function (localRootPath, size) {

    global.hasChanged = false

    // Set the URL of the document
    let editorWindowUrl
    if (localRootPath) {

      // Remember that the document is already saved
      global.isNew = false
      global.savePath = localRootPath
      global.isWrapper = false

      // Get the URL to open the editor
      editorWindowUrl = url.format({
        pathname: localRootPath,
        protocol: 'file:',
        slashes: true
      })

    } else {

      // Remember that the document isn't saved yet
      global.isNew = true
      global.isWrapper = true

      editorWindowUrl = editorWindowUrl = url.format({
        pathname: path.join(__dirname, TEMPLATE),
        protocol: 'file:',
        slashes: true
      })
    }

    // Open the new window with the size given by the splash window
    windowManager.open(EDITOR_WINDOW, 'RAJE', editorWindowUrl, null, {
      width: size.width,
      height: size.height,
      resizable: true
    })

    // Update the app menu
    windows.updateEditorMenu(RAJE_MENU.getEditorMenu(!global.isNew))

    /**
     * Catch the close event
     */
    windowManager.get(EDITOR_WINDOW).object.on('close', event => {

      // If the document is in hasChanged mode (need to be saved)
      if (global.hasChanged) {

        // Cancel the close event
        event.preventDefault()

        // Show the dialog box "the document need to be saved"
        dialog.showMessageBox({
          type: 'warning',
          buttons: ['Save changes', 'Discard changes', 'Cancel, continue editing'],
          title: 'Unsaved changes',
          message: 'The article has been changed, do you want to save the changes?',
          cancelId: 2
        }, (response) => {
          switch (response) {

            // The user wants to save the document
            case 0:
              // TODO save the document
              global.hasChanged = false
              windowManager.get(EDITOR_WINDOW).object.close()
              break

              // The user doesn't want to save the document
            case 1:
              global.hasChanged = false
              windowManager.get(EDITOR_WINDOW).object.close()
              break
          }
        })
      }
    })
  },

  /**
   * Return true to let know that the client has Electron behind
   */
  isApp: function () {
    return true
  },

  /**
   *
   */
  updateEditorMenu: function (menu) {
    // Set the menu
    Menu.setApplicationMenu(Menu.buildFromTemplate(menu))
  }
}

/**
 * Event called when the app is ready
 */
app.on('ready', windows.openSplash)

/**
 * This event is called on OSX when the user click on icon in the dock
 */
app.on('activate', (event, hasVisibleWindows) => {

  // If there aren't any open windows
  if (!hasVisibleWindows)
    windows.openSplash()
})

/**
 * On OS X it is common for applications and their menu bar
 * to stay active until the user quits explicitly with Cmd + Q
 */
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('quit', RAJE_FS.removeImageTempFolder)

/**
 * This method is used to call the function that
 * opens the editor with the template
 *
 * Called by the splash window
 */
ipcMain.on('createArticle', (event, arg) => {

  windows.openEditor(null, arg)
  windows.closeSplash()
})

/**
 *
 */
ipcMain.on('openArticle', (event, arg) => {

  // Select the article index
  let localRootPath = dialog.showOpenDialog({
    title: 'Open RASH article',
    properties: [
      'openFile'
    ],
    filters: [{
      name: 'HTML',
      extensions: ['html']
    }]
  })

  if (localRootPath) {

    // Open the first element of what the dialog returns
    windows.openEditor(localRootPath[0], arg)
    windows.closeSplash()
  }
})

/**
 * This method is used to let know to the client that
 * the HTML file it's opened by Electron (not by a browser)
 *
 * If nothing is returned, tinymce isn't initialised
 *
 * Called from the renderer process
 */
ipcMain.on('isAppSync', (event, arg) => {
  event.returnValue = windows.isApp()
})

/**
 * This method is used to save the current document
 * calling the save dialog (in order to select where the document has to be saved)
 *
 * Then The article is saved by the raje_fs module
 *
 * After the save process, the url is updated loading the saved file url
 *
 * Called from the renderer process
 */
ipcMain.on('saveAsArticle', (event, arg) => {

  // Show save dialog here
  let savePath = dialog.showSaveDialog({
    title: 'Save as',
    defaultPath: arg.title,
    properties: [
      'openDirectory'
    ]
  })

  // If the user select a folder, the article is saved for the first time
  if (savePath) {
    RAJE_FS.saveAsArticle(savePath, arg.document, (err, message) => {
      if (err)
        return console.log(`Error: ${err}`)

      // Store important variables to check the save state
      global.isNew = false
      global.savePath = savePath

      windows.updateEditorMenu(RAJE_MENU.getEditorMenu(!global.isNew))

      // Notify the client
      global.sendNotification({
        text: message,
        type: 'success',
        timeout: 2000
      })
    })
  }
})

/**
 *
 */
ipcMain.on('saveArticle', (event, arg) => {

  // If the document has been saved before
  if (!global.isNew && typeof global.savePath != "undefined") {
    RAJE_FS.saveArticle(global.savePath, arg.document, (err, message) => {
      if (err) return console.log(err)

      // Notify the client
      global.sendNotification({
        text: message,
        type: 'success',
        timeout: 2000
      })
    })
  }
})

/**
 * This method is used to select the image to import in the document
 *
 * When the image is selected it's saved inside the image temporary folder
 * (which is deleted when the app is closed)
 */
ipcMain.on('selectImageSync', (event, arg) => {

  // Show the open dialog with options
  let imagePath = dialog.showOpenDialog({
    filters: [{
      name: 'Images',
      extensions: ['jpg', 'png']
    }]
  })

  // If a file is selected
  if (imagePath[0]) {

    // Save the image in the temporary folder
    RAJE_FS.saveImageTemp(imagePath[0], (err, result) => {

      if (err) return event.returnValue = err

      return event.returnValue = result
    })
  } else
    return event.returnValue = null
})

/**
 *
 */
ipcMain.on('updateDocumentState', (event, arg) => {
  global.hasChanged = arg
})

/**
 * Send a message to the renderer process
 * Start the save as process
 */
global.executeSaveAs = function () {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('executeSaveAs')
}

/**
 * Send a message to the renderer process
 * Start the save process
 */
global.executeSave = function () {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('executeSave')
}

/**
 *
 */
global.sendNotification = function (message) {
  windowManager.get(EDITOR_WINDOW).object.webContents.send('notify', message)
}<|endoftext|>


<commit_before>(function(root) {

  'use strict';

  var availity = root.availity;

  availity.ui.constant('AV_DROPDOWN', {
    OPTIONS: [
      'width',
      'minimumInputLength',
      'maximumInputLength',
      'minimumResultsForSearch',
      'maximumSelectionSize',
      'placeholderOption',
      'separator',
      'allowClear',
      'multiple',
      'closeOnSelect',
      'openOnEnter',
      'id',
      'matcher',
      'sortResults',
      'formatSelection',
      'formatResult',
      'formatResultCssClass',
      'formatNoMatches',
      'formatSearching',
      'formatAjaxError',
      'formatInputTooShort',
      'formatInputTooLong',
      'formatSelectionTooBig',
      'formatLoadMore',
      'createSearchChoice',
      'createSearchChoicePosition',
      'initSelection',
      'tokenizer',
      'tokenSeparators',
      'query',
      'ajax',
      'data',
      'tags',
      'containerCss',
      'containerCssClass',
      'dropdownCss',
      'dropdownCssClass',
      'dropdownAutoWidth',
      'adaptContainerCssClass',
      'adaptDropdownCssClass',
      'escapeMarkup',
      'selectOnBlur',
      'loadMorePadding',
      'nextSearchTerm'
    ]
  });

  availity.ui.controller('AvDropdownController', function($element, $attrs, AV_UI, AV_DROPDOWN, $log, $scope, $timeout, $parse) {

    var self = this;
    this.options = [];
    this.match = null;
    this.ngModel = null;

    this.init = function() {
      _.forEach($attrs, function(value, key) {
        if(_.contains(AV_DROPDOWN.OPTIONS, key.replace('data-', ''))) {
          self.options[key] = $scope.$eval(value);
        }
      });

      self.multiple = angular.isDefined($attrs.multiple);

      self.options.closeOnResize = self.options.closeOnResize  || true;

      if(self.options.query) {
        self.queryFn = self.options.query;
        self.options.query = self.query;
      }

    };

    this.setNgModel = function(ngModel) {
      this.ngModel = ngModel;
    };

    this.getSelected = function(model) {
      var items = this.collection($scope);

      var index = _.findIndex(items, function(item) {
        return angular.equals(item, model);
      });

      return index;

    };

    this.query = function(options) {
      self.queryFn(options).then(function(response) {
        options.callback({more: response.more, results: response.results});
      });
    };

    this.setValue = function() {
      var viewValue = self.ngModel.$viewValue;
      var selected = null;
      if(viewValue) {
        selected = this.getSelected(viewValue);
      }

      // var apply = scope.$evalAsync || $timeout;
      $timeout(function() {
        $element
          .select2('val',  (selected === null || selected === 'undefined') ? '' : selected); // null === '' for Select2
      });
    };

    this.setValues = function() {
      var viewValue = self.ngModel.$viewValue;

      if(!angular.isArray(viewValue)) {
        viewValue = [];
      }

      // var apply = scope.$evalAsync || $timeout;
      $timeout(function() {
        $element
          .select2('val', viewValue);
      });
    };

    this.ngOptions = function() {
      this.match = $attrs.ngOptions.match(AV_UI.NG_OPTIONS);
      if(!this.match) {
        throw new Error('Invalid ngOptions for avDropdown');
      }
      // AV_UI.NG_OPTIONS regex will parse into arrays like below:
      //
      // 0: "state.name for state in states"
      // 1: "state.name"
      // 2: undefined
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: undefined
      //
      // 0: "state.id as state.name for state in states"
      // 1: "state.id"
      // 2: "state.name"
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: undefined
      //
      // 0: "state.name for state in states track by state.id"
      // 1: "state.name"
      // 2: undefined
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: "state.id"
      //
      // 0: "person.fullName as (person.lastName + ', ' + person.firstName) for person in feeScheduleModel.persons"
      // 1: "person.fullName"
      // 2: "(person.lastName + ', ' + person.firstName)"
      // 3: undefined
      // 4: "person"
      // 5: undefined
      // 6: undefined
      // 7: "feeScheduleModel.persons"
      // 8: undefined
      //
      this.displayFn = $parse(this.match[2] || this.match[1]); // this is the function to retrieve the text to show as
      this.collection = $parse(this.match[7]);
      this.valueName = this.match[4] || this.match[6];
      this.valueFn = $parse(this.match[2] ? this.match[1] : this.valueName);
      this.keyName = this.match[5];

      $scope.$watchCollection(this.collection, function(newVal, oldVal) {
        if(angular.equals(newVal, oldVal)) {
          return;
        }

        self.setValue();

      }, true);

    };
  });

  availity.ui.directive('avDropdown', function($timeout, $log, $window) {
    return {
      restrict: 'A',
      require: ['ngModel', 'avDropdown'],
      controller: 'AvDropdownController',
      link: function(scope, element, attrs, controllers) {
        var ngModel = controllers[0];
        var avDropdown = controllers[1];

        avDropdown.setNgModel(ngModel);
        avDropdown.init();

        if(attrs.ngOptions) {
          avDropdown.ngOptions();
        }

        ngModel.$parsers.push(function(value) {
          var parent = element.prev();
          parent
            .toggleClass('ng-invalid', !ngModel.$valid)
            .toggleClass('ng-valid', ngModel.$valid)
            .toggleClass('ng-invalid-required', !ngModel.$valid)
            .toggleClass('ng-valid-required', ngModel.$valid)
            .toggleClass('ng-dirty', ngModel.$dirty)
            .toggleClass('ng-pristine', ngModel.$pristine);
          return value;
        });

        element.on('change', function(e) {

          // special case since the ajax handling doesn't bind to the model correctly
          // this has to do with select2 (v3.5.2) using a hidden field instead of a select for ajax
          if(!_.isNull(avDropdown.options.query)) {
            $timeout(function() {
              ngModel.$setViewValue(e.added);
            });
          }

          $log.info(e);

        });

        // fires ng-focus when select2-focus fires.
        element.on('select2-focus', function() {
          if(attrs.ngFocus) {
            scope.$eval(scope.$eval(attrs.ngFocus));
          }
        });

        // fires ng-blur when select2-blur occurs.
        element.on('select2-blur', function() {
          if(attrs.ngBlur) {
            scope.$eval(scope.$eval(attrs.ngBlur));
          }
        });

        // https://github.com/t0m/select2-bootstrap-css/issues/37#issuecomment-42714589
        element.on('select2-open', function () {
          // look for .has-success, .has-warning, .has-error
          // (really look for .has-* … which is good enough for the demo page, but obviously might interfere with other CSS-classes starting with "has-")
          if(element.parents('[class*="has-"]').length) {

            // get all CSS-classes from the element where we found "has-*" and collect them in an array
            var classNames = $(this).parents('[class*="has-"]')[0].className.split(/\s+/);

            // go through the class names, find "has-"
            for(var i = 0; i < classNames.length; ++i) {
              if(classNames[i].match('has-')) {
                $('#select2-drop').addClass(classNames[i]);
              }
            }
          }
        });

        var _$render = ngModel.$render;
        ngModel.$render = function() {
          _$render();

          if(avDropdown.multiple) {
            avDropdown.setValues();
          }else {
            avDropdown.setValue();
          }

        };

        var win = angular.element($window);

        win.bind('resize', function() {
          element.select2('close');
        });

        attrs.$observe('disabled', function (value) {
          element.select2('enable', !value);
        });

        attrs.$observe('readonly', function (value) {
          element.select2('readonly', !!value);
        });

        scope.$on('destroy', function() {
          element.select2('destroy');
        });

        $timeout(function() {
          element.select2(avDropdown.options);
        });
      }
    };
  });

})(window);
<commit_msg>Corrected a condition for the dropdown ajax handling<commit_after>(function(root) {

  'use strict';

  var availity = root.availity;

  availity.ui.constant('AV_DROPDOWN', {
    OPTIONS: [
      'width',
      'minimumInputLength',
      'maximumInputLength',
      'minimumResultsForSearch',
      'maximumSelectionSize',
      'placeholderOption',
      'separator',
      'allowClear',
      'multiple',
      'closeOnSelect',
      'openOnEnter',
      'id',
      'matcher',
      'sortResults',
      'formatSelection',
      'formatResult',
      'formatResultCssClass',
      'formatNoMatches',
      'formatSearching',
      'formatAjaxError',
      'formatInputTooShort',
      'formatInputTooLong',
      'formatSelectionTooBig',
      'formatLoadMore',
      'createSearchChoice',
      'createSearchChoicePosition',
      'initSelection',
      'tokenizer',
      'tokenSeparators',
      'query',
      'ajax',
      'data',
      'tags',
      'containerCss',
      'containerCssClass',
      'dropdownCss',
      'dropdownCssClass',
      'dropdownAutoWidth',
      'adaptContainerCssClass',
      'adaptDropdownCssClass',
      'escapeMarkup',
      'selectOnBlur',
      'loadMorePadding',
      'nextSearchTerm'
    ]
  });

  availity.ui.controller('AvDropdownController', function($element, $attrs, AV_UI, AV_DROPDOWN, $log, $scope, $timeout, $parse) {

    var self = this;
    this.options = [];
    this.match = null;
    this.ngModel = null;

    this.init = function() {
      _.forEach($attrs, function(value, key) {
        if(_.contains(AV_DROPDOWN.OPTIONS, key.replace('data-', ''))) {
          self.options[key] = $scope.$eval(value);
        }
      });

      self.multiple = angular.isDefined($attrs.multiple);

      self.options.closeOnResize = self.options.closeOnResize  || true;

      if(self.options.query) {
        self.queryFn = self.options.query;
        self.options.query = self.query;
      }

    };

    this.setNgModel = function(ngModel) {
      this.ngModel = ngModel;
    };

    this.getSelected = function(model) {
      var items = this.collection($scope);

      var index = _.findIndex(items, function(item) {
        return angular.equals(item, model);
      });

      return index;

    };

    this.query = function(options) {
      self.queryFn(options).then(function(response) {
        options.callback({more: response.more, results: response.results});
      });
    };

    this.setValue = function() {
      var viewValue = self.ngModel.$viewValue;
      var selected = null;
      if(viewValue) {
        selected = this.getSelected(viewValue);
      }

      // var apply = scope.$evalAsync || $timeout;
      $timeout(function() {
        $element
          .select2('val',  (selected === null || selected === 'undefined') ? '' : selected); // null === '' for Select2
      });
    };

    this.setValues = function() {
      var viewValue = self.ngModel.$viewValue;

      if(!angular.isArray(viewValue)) {
        viewValue = [];
      }

      // var apply = scope.$evalAsync || $timeout;
      $timeout(function() {
        $element
          .select2('val', viewValue);
      });
    };

    this.ngOptions = function() {
      this.match = $attrs.ngOptions.match(AV_UI.NG_OPTIONS);
      if(!this.match) {
        throw new Error('Invalid ngOptions for avDropdown');
      }
      // AV_UI.NG_OPTIONS regex will parse into arrays like below:
      //
      // 0: "state.name for state in states"
      // 1: "state.name"
      // 2: undefined
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: undefined
      //
      // 0: "state.id as state.name for state in states"
      // 1: "state.id"
      // 2: "state.name"
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: undefined
      //
      // 0: "state.name for state in states track by state.id"
      // 1: "state.name"
      // 2: undefined
      // 3: undefined
      // 4: "state"
      // 5: undefined
      // 6: undefined
      // 7: "states"
      // 8: "state.id"
      //
      // 0: "person.fullName as (person.lastName + ', ' + person.firstName) for person in feeScheduleModel.persons"
      // 1: "person.fullName"
      // 2: "(person.lastName + ', ' + person.firstName)"
      // 3: undefined
      // 4: "person"
      // 5: undefined
      // 6: undefined
      // 7: "feeScheduleModel.persons"
      // 8: undefined
      //
      this.displayFn = $parse(this.match[2] || this.match[1]); // this is the function to retrieve the text to show as
      this.collection = $parse(this.match[7]);
      this.valueName = this.match[4] || this.match[6];
      this.valueFn = $parse(this.match[2] ? this.match[1] : this.valueName);
      this.keyName = this.match[5];

      $scope.$watchCollection(this.collection, function(newVal, oldVal) {
        if(angular.equals(newVal, oldVal)) {
          return;
        }

        self.setValue();

      }, true);

    };
  });

  availity.ui.directive('avDropdown', function($timeout, $log, $window) {
    return {
      restrict: 'A',
      require: ['ngModel', 'avDropdown'],
      controller: 'AvDropdownController',
      link: function(scope, element, attrs, controllers) {
        var ngModel = controllers[0];
        var avDropdown = controllers[1];

        avDropdown.setNgModel(ngModel);
        avDropdown.init();

        if(attrs.ngOptions) {
          avDropdown.ngOptions();
        }

        ngModel.$parsers.push(function(value) {
          var parent = element.prev();
          parent
            .toggleClass('ng-invalid', !ngModel.$valid)
            .toggleClass('ng-valid', ngModel.$valid)
            .toggleClass('ng-invalid-required', !ngModel.$valid)
            .toggleClass('ng-valid-required', ngModel.$valid)
            .toggleClass('ng-dirty', ngModel.$dirty)
            .toggleClass('ng-pristine', ngModel.$pristine);
          return value;
        });

        element.on('change', function(e) {

          // special case since the ajax handling doesn't bind to the model correctly
          // this has to do with select2 (v3.5.2) using a hidden field instead of a select for ajax
          if(avDropdown.options.query) {
            $timeout(function() {
              ngModel.$setViewValue(e.added);
            });
          }

          $log.info(e);

        });

        // fires ng-focus when select2-focus fires.
        element.on('select2-focus', function() {
          if(attrs.ngFocus) {
            scope.$eval(scope.$eval(attrs.ngFocus));
          }
        });

        // fires ng-blur when select2-blur occurs.
        element.on('select2-blur', function() {
          if(attrs.ngBlur) {
            scope.$eval(scope.$eval(attrs.ngBlur));
          }
        });

        // https://github.com/t0m/select2-bootstrap-css/issues/37#issuecomment-42714589
        element.on('select2-open', function () {
          // look for .has-success, .has-warning, .has-error
          // (really look for .has-* … which is good enough for the demo page, but obviously might interfere with other CSS-classes starting with "has-")
          if(element.parents('[class*="has-"]').length) {

            // get all CSS-classes from the element where we found "has-*" and collect them in an array
            var classNames = $(this).parents('[class*="has-"]')[0].className.split(/\s+/);

            // go through the class names, find "has-"
            for(var i = 0; i < classNames.length; ++i) {
              if(classNames[i].match('has-')) {
                $('#select2-drop').addClass(classNames[i]);
              }
            }
          }
        });

        var _$render = ngModel.$render;
        ngModel.$render = function() {
          _$render();

          if(avDropdown.multiple) {
            avDropdown.setValues();
          }else {
            avDropdown.setValue();
          }

        };

        var win = angular.element($window);

        win.bind('resize', function() {
          element.select2('close');
        });

        attrs.$observe('disabled', function (value) {
          element.select2('enable', !value);
        });

        attrs.$observe('readonly', function (value) {
          element.select2('readonly', !!value);
        });

        scope.$on('destroy', function() {
          element.select2('destroy');
        });

        $timeout(function() {
          element.select2(avDropdown.options);
        });
      }
    };
  });

})(window);
<|endoftext|>


<commit_before>/**
 * windows-cpu - Tests for windows-cpu functionality
 * @author Kyle Ross <kylerross1324@gmail.com>
 * @requires mocha
 * @requires should
 */

var should = require('should'),
    cpu;

beforeEach(function() {
    cpu = require('../');
});

describe('totalLoad function', function() {
    it('should call the callback with an array of number(s)', function(done) {
        cpu.totalLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Array;

                if (results.length <= 0) {
                    done('results length should be greater than 0');
                }

                results.forEach(function(v) {
                    v.should.be.an.Number.and.be.within(0, 100);
                });
                done();
            }
        });
    });
});

describe('nodeLoad function', function() {
    it('should call the callback with an object', function(done) {
        cpu.nodeLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });
});

describe('processLoad function', function() {
    it('should call the callback with an object', function(done) {
        cpu.processLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.should.have.a.lengthOf(1);

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });
});

describe('findLoad function', function() {

   var loadIntervalPtr;
   var loadInterval = 1;

    before(function(){

        loadIntervalPtr = setInterval(function(){
          var randomOpResult = ((Math.random() * Math.random()) * 100) % 10;
        }, loadInterval);

      });

      after(function(){
        clearInterval(loadIntervalPtr);
      });

    it('should call the callback with an object', function(done) {
        cpu.findLoad('system', function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });

     it('should call the callback with an object, for this process', function(done) {
        cpu.findLoad(process.pid, function(error, results) {
            if (error) {
                done(error);
            } else {

                console.log('results: ', results);

                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });

    it('should call the callback with an error', function(done) {
        cpu.findLoad('someprocess', function(error, results) {
            if (error) {
                done();
            } else {
                done('Result should have been an error.');
            }
        });
    });
});

describe('cpuInfo function', function() {
    it('should call the callback with an array', function(done) {
        cpu.cpuInfo(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Array;

                if (results.length <= 0) {
                    done('results length should be greater than 0');
                }

                results.forEach(function(v) {
                    v.should.be.a.String.and.not.be.empty;
                });
                done();
            }
        });
    });
});

describe('totalMemoryUsage function', function() {
    it('should call the callback with an object', function(done) {
        cpu.totalMemoryUsage(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('usageInKb', 'usageInMb' , 'usageInGb');

                results.usageInKb.should.be.an.Number;
                results.usageInMb.should.be.an.Number;
                results.usageInGb.should.be.an.Number;

                done();
            }
        });
    });
});
<commit_msg>testing<commit_after>/**
 * windows-cpu - Tests for windows-cpu functionality
 * @author Kyle Ross <kylerross1324@gmail.com>
 * @requires mocha
 * @requires should
 */

var should = require('should'),
    cpu;

beforeEach(function() {
    cpu = require('../');
});

describe('totalLoad function', function() {
    it('should call the callback with an array of number(s)', function(done) {
        cpu.totalLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Array;

                if (results.length <= 0) {
                    done('results length should be greater than 0');
                }

                results.forEach(function(v) {
                    v.should.be.an.Number.and.be.within(0, 100);
                });
                done();
            }
        });
    });
});

describe('nodeLoad function', function() {
    it('should call the callback with an object', function(done) {
        cpu.nodeLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });
});

describe('processLoad function', function() {
    it('should call the callback with an object', function(done) {
        cpu.processLoad(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.should.have.a.lengthOf(1);

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });
});

describe('findLoad function', function() {

   var loadIntervalPtr;
   var loadInterval = 1;
   var loadCounter = 1;

    before(function(){

        loadIntervalPtr = setInterval(function(){
          var randomOpResult = ((Math.random() * Math.random()) * 100) % 10;
          if (loadCounter % 50 == 0)
            console.log('loadCounter: ', loadCounter);
          loadCounter++;
        }, loadInterval);

      });

      after(function(){
        clearInterval(loadIntervalPtr);
      });

    it('should call the callback with an object', function(done) {
        cpu.findLoad('system', function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });

     it('should call the callback with an object, for this process', function(done) {
        cpu.findLoad(process.pid, function(error, results) {
            if (error) {
                done(error);
            } else {

                console.log('results: ', results);

                results.should.be.an.Object.with.properties('load', 'found');

                results.load.should.be.an.Number.and.be.within(0, 100);
                results.found.should.be.an.Array;

                if (results.found.length <= 0) {
                    done('results.found length should be greater than 0');
                }

                results.found.forEach(function(v) {
                    v.should.be.an.Object.with.properties('pid', 'process', 'load');
                    v.pid.should.be.an.Number;
                    v.process.should.be.a.String.and.not.be.empty;
                    v.load.should.be.an.Number;
                });
                done();
            }
        });
    });

    it('should call the callback with an error', function(done) {
        cpu.findLoad('someprocess', function(error, results) {
            if (error) {
                done();
            } else {
                done('Result should have been an error.');
            }
        });
    });
});

describe('cpuInfo function', function() {
    it('should call the callback with an array', function(done) {
        cpu.cpuInfo(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Array;

                if (results.length <= 0) {
                    done('results length should be greater than 0');
                }

                results.forEach(function(v) {
                    v.should.be.a.String.and.not.be.empty;
                });
                done();
            }
        });
    });
});

describe('totalMemoryUsage function', function() {
    it('should call the callback with an object', function(done) {
        cpu.totalMemoryUsage(function(error, results) {
            if (error) {
                done(error);
            } else {
                results.should.be.an.Object.with.properties('usageInKb', 'usageInMb' , 'usageInGb');

                results.usageInKb.should.be.an.Number;
                results.usageInMb.should.be.an.Number;
                results.usageInGb.should.be.an.Number;

                done();
            }
        });
    });
});
<|endoftext|>


<commit_before>var React = require('react');

import {
  getConversionsForUnit,
  unitChoice
} from '../settings/conversions'

var size = 400;
var half = size / 2;
var arcWidth = half * 0.15;
var largeTick = half * 0.15;
var smallTick = half * 0.075;

var pathsCovered = [
  'environment.wind.angleApparent',
  'environment.wind.angleTrue',
  'environment.wind.speedApparent',
  'environment.wind.speedTrue'
]

var subscribes = {
  'environment.wind.angleApparent': function(sourceId, stream) {
    if (!this.widget.props.activeStreams['environment.wind.angleApparent']) {
      var that = this;
      let theStream = stream
      const conversion = getConversionsForUnit('rad')['deg']
      if (conversion) {
        theStream = stream.map(conversion)
      }
      this.widget.props.activeStreams['environment.wind.angleApparent'] = theStream.onValue(function(value) {
        that.widget.props.holder.setState({
          angle: value
        })
      })
    }
  },
  'environment.wind.angleTrue': function() {},
  'environment.wind.speedApparent': function(sourceId, stream) {
    var that = this;
    if (!this.widget.props.activeStreams['environment.wind.speedApparent']) {
      let theStream = stream
      if (this.options.convertTo) {
        const conversion = getConversionsForUnit('m/s')[this.options.convertTo]
        if (conversion) {
          theStream = stream.map(conversion)
        }
      }
      this.widget.props.activeStreams['environment.wind.speedApparent'] = theStream.onValue(function(value) {
        that.widget.props.holder.setState({
          speed: value
        })
      })
    }
  },
  'environment.wind.speedTrue': function() {}
}

var ticks = [];

for (var i = 0; i < 180; i += 10) {
  var stroke = 1;
  var dash = smallTick;

  if(i % 30 === 0) {
    stroke = 3;
    dash = largeTick;
  }

  ticks.push(
    <path key={"tick-" + i} d={"M 200 0 L 200 " + dash + " M 200 " + (400-dash) + " L 200 400"}
      strokeWidth={stroke} transform={centerRotate(i)} />
  );
}

var yOffset = 0.85 * size;
for (var i = 0; i < 190; i += 30) {
  ticks.push(
    <g key={"text-" + i} transform={centerRotate(180 + i)}>
      <text x="200" y={yOffset + 10} textAnchor="middle" dominantBaseline="central" style={{"fontSize":"28px"}}
        transform={"rotate(" + (-i - 180) + " " + half + " " + yOffset + ")"}>{i}</text>
    </g>
  );
  ticks.push(
    <g key={"text--" + i} transform={centerRotate(180 - i)}>
      <text x="200" y={yOffset + 10} textAnchor="middle" dominantBaseline="central" style={{"fontSize":"28px"}}
       transform={"rotate(" + (i - 180) + " " + half + " " + yOffset + ")"}>{i}</text>
    </g>
  )
}

var componentClass = React.createClass({
  getInitialState: function() {
    return {
      activeStreams: {},
      angle: 0,
      speed: 0
    };
  },

  getShadow: function() {
    return ({ __html:
      '<filter id="f1">' +
      '<feGaussianBlur in="SourceAlpha" stdDeviation="2" />' +
      '<feOffset dx="2.4" dy="1.6" />' +
      '<feMerge><feMergeNode /><feMergeNode in="SourceGraphic" /></feMerge>' +
      '</filter>'
    });
  },

  render: function() {
    var sx = half;
    var sy = arcWidth / 2;
    var ar = half - sy;
    var ex = ar * Math.sin(Math.PI / 3); // 60°
    var ey = ar * Math.cos(Math.PI / 3); // 60°

    return (
      <svg height="100%" width="100%" viewBox="0 0 400 400">
        <svg dangerouslySetInnerHTML={this.getShadow()} />
        <g stroke="black" transform="scale(0.9) translate(20 40)">
          <path d={["M", sx, sy, "a", ar, ar, "0 0 1", ex, ey].join(" ")}
            style={{"fill":"none", "stroke":"green", "strokeWidth":arcWidth}} />
          <path d={["M", sx, sy, "a", ar, ar, "0 0 0", -ex, ey].join(" ")}
            style={{"fill":"none", "stroke":"red", "strokeWidth":arcWidth}} />
          {ticks}
          <rect width="150" height="50" x="125" y="135" rx="5" ry="5" fill="rgba(255,255,255,0.8)" />
          <text x="200" y="172" textAnchor="middle" fontSize="38" dominantBaseline="middle">
            {getDisplayWindAngle(this.state.angle)}
          </text>
          <rect width="150" height="50" x="125" y="215" rx="5" ry="5" fill="rgba(255,255,255,0.8)" />
          <text x="200" y="252" textAnchor="middle" fontSize="38" dominantBaseline="middle">
            {safeFixed(this.state.speed)}
          </text>
          <text x="200" y="292" textAnchor="middle" fontSize="25" dominantBaseline="middle">
            {this.props.convertTo ? this.props.convertTo : 'm/s'}
          </text>
          <polygon points="200,20 190,200 200,215 210,200"
            fill="rgba(221, 221, 221, 0.6)" stroke="#333" strokeWidth="1"
            transform={centerRotate(this.state.angle)} style={{"filter":"url(#f1)"}} />
        </g>
        <text x="200" y="24" textAnchor="middle" fontSize="20">{this.props.label}</text>
      </svg>
    )
  },
  componentDidMount: function() {
    this.props.holder.setState = this.setState.bind(this)
  },
  componentWillUnmount: function() {
    //disable updates when component not mounted
    this.props.holder.setState = function(d) {};
  }
});

var BaseWidget = require('./basewidget');
require('util').inherits(WindMeter, BaseWidget);

function WindMeter(id, options, streamBundle, instrumentPanel) {
  BaseWidget.call(this, id, options, streamBundle, instrumentPanel);
  this.options.activeSources = {};
  this.options.initialDimensions = this.options.initialDimensions || {h: 4};
  this.active = true;

  // no-op setState to disable updates of deserialized but currently unmounted
  //components
  this.widget = React.createElement(componentClass,{
    key: id,
    initPath: options.path,
    convertTo: options.convertTo,
    label: 'Apparent Wind',
    activeStreams: {},
    holder: {
      setState: function() {}
    }
  });
}

WindMeter.prototype.updateStream = function(widget, valueStream) {
  this.handleNewSource({
    sourceId: widget.options.sourceId,
    path: widget.options.path,
    key: widget.options.key,
    stream: valueStream
  })
  widget.widget = React.cloneElement(widget.widget,{
    streamBundle: valueStream,
  });
  widget.instrumentPanel.pushGridChanges();
}

WindMeter.prototype.handleNewSource = function(newSource) {
  if (subscribes[newSource.path]) {
    subscribes[newSource.path].call(this, newSource.sourceId, newSource.stream)
    this.options.activeSources[newSource.key] = {
      path: newSource.path,
      sourceId: newSource.sourceId,
      key: newSource.key
    };
    return true;
  }
}

function getDisplayWindAngle(value) {
  return value >= 0 && value <= 180 ? value.toFixed(0):
         value > 180 ? Math.abs(value - 360).toFixed(0) * -1:
         Math.abs(value).toFixed(0) * -1;
}

function safeFixed(value) {
  try {
    return Number(value).toFixed(1);
  } catch (e) {
    console.error("Could not round:" + value);
  }
  return "-";
}

WindMeter.prototype.getReactElement = function() {
  return this.widget;
}

WindMeter.prototype.getType = function() {
  return "windmeter";
}

WindMeter.prototype.getHandledSources = function() {
  return Object.values(this.options.activeSources);
}

WindMeter.prototype.getOptions = function() {
  return this.options;
}

WindMeter.prototype.getInitialDimensions = function() {
  return {w:2, h:4};
}

function centerRotate(deg) {
  return ["rotate(", deg, half, half, ")"].join(" ");
}

const SettingsPanel = (props) => {
  return (

      {props.unit != '' ? unitChoice('m/s', props.onUnitChange, props.options.convertTo) : undefined}

  )
}

WindMeter.prototype.getSettingsElement = function() {
  var that = this;
  return SettingsPanel({
    options: this.options,
    onUnitChange: function(event) {
      that.options.convertTo = event.target.value ==='m/s' ? undefined : event.target.value;
      that.instrumentPanel.persist();
      that.instrumentPanel.pushGridChanges();
    }
  });
}

module.exports = {
  constructor: WindMeter,
  type: 'windmeter',
  paths: pathsCovered
}
<commit_msg>feature: add windTue/speedTrue in windmeter<commit_after>var React = require('react');

import {
  getConversionsForUnit,
  unitChoice
} from '../settings/conversions'

var size = 400;
var half = size / 2;
var arcWidth = half * 0.15;
var largeTick = half * 0.15;
var smallTick = half * 0.075;

var pathsCovered = [
  'environment.wind.angleApparent',
  'environment.wind.angleTrueGround',
  'environment.wind.angleTrueWater',
  'environment.wind.speedApparent',
  'environment.wind.speedOverGround',
  'environment.wind.speedTrue'
]

const displayApparent = 0;
const displayTrueGround = 1;
const displayTrueWater = 2;

var getValuesForDisplayModeIndex = [
  function(values) { //displayApp
    return {
      angle: values.angleApparent,
      speed: values.speedApparent,
      label: 'Apparent Wind'
    }
  },
  function(values) { //displayTrueGround
    return {
      angle: values.angleTrueGround,
      speed: values.speedOverGround,
      label: 'True Wind over Ground'
    }
  },
  function(values) { //displayTrueWater
    return {
      angle: values.angleTrueWater,
      speed: values.speedTrue,
      label: 'True Wind through Water'
    }
  }
]

function getNextDisplayModeIndex(displayModeIndex) {
  displayModeIndex += 1;
  const nextDisplayModeIndex = (displayModeIndex >= getValuesForDisplayModeIndex.length)? 0 : displayModeIndex;
  return nextDisplayModeIndex;
}

var subscribes = {
  'environment.wind.angleApparent': function(sourceId, stream) {
    if (!this.widget.props.activeStreams['environment.wind.angleApparent']) {
      var that = this;
      let theStream = stream
      const conversion = getConversionsForUnit('rad')['deg']
      if (conversion) {
        theStream = stream.map(conversion)
      }
      this.widget.props.activeStreams['environment.wind.angleApparent'] = theStream.onValue(function(value) {
        that.widget.props.values.angleApparent = value;
        if (that.options.displayModeIndex === displayApparent) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  },
  'environment.wind.angleTrueGround': function(sourceId, stream) {
    if (!this.widget.props.activeStreams['environment.wind.angleTrueGround']) {
      var that = this;
      let theStream = stream
      const conversion = getConversionsForUnit('rad')['deg']
      if (conversion) {
        theStream = stream.map(conversion)
      }
      this.widget.props.activeStreams['environment.wind.angleTrueGround'] = theStream.onValue(function(value) {
        that.widget.props.values.angleTrueGround = value;
        if (that.options.displayModeIndex === displayTrueGround) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  },
  'environment.wind.angleTrueWater': function(sourceId, stream) {
    if (!this.widget.props.activeStreams['environment.wind.angleTrueWater']) {
      var that = this;
      let theStream = stream
      const conversion = getConversionsForUnit('rad')['deg']
      if (conversion) {
        theStream = stream.map(conversion)
      }
      this.widget.props.activeStreams['environment.wind.angleTrueWater'] = theStream.onValue(function(value) {
        that.widget.props.values.angleTrueWater = value;
        if (that.options.displayModeIndex === displayTrueWater) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  },
  'environment.wind.speedApparent': function(sourceId, stream) {
    var that = this;
    if (!this.widget.props.activeStreams['environment.wind.speedApparent']) {
      let theStream = stream
      if (this.options.convertTo) {
        const conversion = getConversionsForUnit('m/s')[this.options.convertTo]
        if (conversion) {
          theStream = stream.map(conversion)
        }
      }
      this.widget.props.activeStreams['environment.wind.speedApparent'] = theStream.onValue(function(value) {
        that.widget.props.values.speedApparent = value;
        if (that.options.displayModeIndex === displayApparent) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  },
  'environment.wind.speedOverGround': function(sourceId, stream) {
    var that = this;
    if (!this.widget.props.activeStreams['environment.wind.speedOverGround']) {
      let theStream = stream
      if (this.options.convertTo) {
        const conversion = getConversionsForUnit('m/s')[this.options.convertTo]
        if (conversion) {
          theStream = stream.map(conversion)
        }
      }
      this.widget.props.activeStreams['environment.wind.speedOverGround'] = theStream.onValue(function(value) {
        that.widget.props.values.speedOverGround = value;
        if (that.options.displayModeIndex === displayTrueGround) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  },
  'environment.wind.speedTrue': function(sourceId, stream) {
    var that = this;
    if (!this.widget.props.activeStreams['environment.wind.speedTrue']) {
      let theStream = stream
      if (this.options.convertTo) {
        const conversion = getConversionsForUnit('m/s')[this.options.convertTo]
        if (conversion) {
          theStream = stream.map(conversion)
        }
      }
      this.widget.props.activeStreams['environment.wind.speedTrue'] = theStream.onValue(function(value) {
        that.widget.props.values.speedTrue = value;
        if (that.options.displayModeIndex === displayTrueWater) {
          that.widget.props.holder.setState({displayModeIndex: that.options.displayModeIndex})
        }
      })
    }
  }
}

var ticks = [];

for (var i = 0; i < 180; i += 10) {
  var stroke = 1;
  var dash = smallTick;

  if(i % 30 === 0) {
    stroke = 3;
    dash = largeTick;
  }

  ticks.push(
    <path key={"tick-" + i} d={"M 200 0 L 200 " + dash + " M 200 " + (400-dash) + " L 200 400"}
      strokeWidth={stroke} transform={centerRotate(i)} />
  );
}

var yOffset = 0.85 * size;
for (var i = 0; i < 190; i += 30) {
  ticks.push(
    <g key={"text-" + i} transform={centerRotate(180 + i)}>
      <text x="200" y={yOffset + 10} textAnchor="middle" dominantBaseline="central" style={{"fontSize":"28px"}}
        transform={"rotate(" + (-i - 180) + " " + half + " " + yOffset + ")"}>{i}</text>
    </g>
  );
  ticks.push(
    <g key={"text--" + i} transform={centerRotate(180 - i)}>
      <text x="200" y={yOffset + 10} textAnchor="middle" dominantBaseline="central" style={{"fontSize":"28px"}}
       transform={"rotate(" + (i - 180) + " " + half + " " + yOffset + ")"}>{i}</text>
    </g>
  )
}

var componentClass = React.createClass({
  getInitialState: function() {
    return {
      displayModeIndex: this.props.options.displayModeIndex
    };
  },
  getShadow: function() {
    return ({ __html:
      '<filter id="f1">' +
      '<feGaussianBlur in="SourceAlpha" stdDeviation="2" />' +
      '<feOffset dx="2.4" dy="1.6" />' +
      '<feMerge><feMergeNode /><feMergeNode in="SourceGraphic" /></feMerge>' +
      '</filter>'
    });
  },
  changeDisplayMode: function() {
      const newDisplayModeIndex = getNextDisplayModeIndex(this.state.displayModeIndex);
      this.setState({ displayModeIndex: newDisplayModeIndex});
      this.props.options.displayModeIndex = newDisplayModeIndex;
      this.props.instrumentPanel.persist();
  },
  render: function() {
    var sx = half;
    var sy = arcWidth / 2;
    var ar = half - sy;
    var ex = ar * Math.sin(Math.PI / 3); // 60°
    var ey = ar * Math.cos(Math.PI / 3); // 60°
    var displayValues = getValuesForDisplayModeIndex[this.state.displayModeIndex](this.props.values);
    return (
      <svg onClick={this.changeDisplayMode} height="100%" width="100%" viewBox="0 0 400 400">
        <svg dangerouslySetInnerHTML={this.getShadow()} />
        <g stroke="black" transform="scale(0.9) translate(20 40)">
          <path d={["M", sx, sy, "a", ar, ar, "0 0 1", ex, ey].join(" ")}
            style={{"fill":"none", "stroke":"green", "strokeWidth":arcWidth}} />
          <path d={["M", sx, sy, "a", ar, ar, "0 0 0", -ex, ey].join(" ")}
            style={{"fill":"none", "stroke":"red", "strokeWidth":arcWidth}} />
          {ticks}
          <rect width="150" height="50" x="125" y="135" rx="5" ry="5" fill="rgba(255,255,255,0.8)" />
          <text x="200" y="172" textAnchor="middle" fontSize="38" dominantBaseline="middle">
            {getDisplayWindAngle(displayValues.angle)}
          </text>
          <rect width="150" height="50" x="125" y="215" rx="5" ry="5" fill="rgba(255,255,255,0.8)" />
          <text x="200" y="252" textAnchor="middle" fontSize="38" dominantBaseline="middle">
            {safeFixed(displayValues.speed)}
          </text>
          <text x="200" y="292" textAnchor="middle" fontSize="25" dominantBaseline="middle">
            {this.props.convertTo ? this.props.convertTo : 'm/s'}
          </text>
          <polygon points="200,20 190,200 200,215 210,200"
            fill="rgba(221, 221, 221, 0.6)" stroke="#333" strokeWidth="1"
            transform={centerRotate(displayValues.angle)} style={{"filter":"url(#f1)"}} />
        </g>
        <text x="200" y="24" textAnchor="middle" fontSize="20">{displayValues.label}</text>
      </svg>
    )
  },
  componentDidMount: function() {
    this.props.holder.setState = this.setState.bind(this)
  },
  componentWillUnmount: function() {
    //disable updates when component not mounted
    this.props.holder.setState = function(d) {};
  }
});

var BaseWidget = require('./basewidget');
require('util').inherits(WindMeter, BaseWidget);

function WindMeter(id, options, streamBundle, instrumentPanel) {
  BaseWidget.call(this, id, options, streamBundle, instrumentPanel);
  this.options.activeSources = {};
  this.options.initialDimensions = this.options.initialDimensions || {h: 4};
  this.active = true;
  if ((typeof this.options.displayModeIndex === "undefined") ||
       (this.options.displayModeIndex < 0) ||
       (this.options.displayModeIndex > getValuesForDisplayModeIndex.length -1)) {
    this.options.displayModeIndex = 0;
  }
  var values = {
      angleApparent: 0,
      angleTrueGround: 0,
      angleTrueWater: 0,
      speedApparent: 0,
      speedOverGround: 0,
      speedTrue: 0
  };

  // no-op setState to disable updates of deserialized but currently unmounted
  //components
  this.widget = React.createElement(componentClass,{
    key: id,
    initPath: options.path,
    convertTo: options.convertTo,
    options: options,
    instrumentPanel: this.instrumentPanel,
    values: values,
    activeStreams: {},
    holder: {
      setState: function() {}
    }
  });
}

WindMeter.prototype.handleNewSource = function(newSource) {
  if (subscribes[newSource.path]) {
    subscribes[newSource.path].call(this, newSource.sourceId, newSource.stream)
    this.options.activeSources[newSource.key] = {
      path: newSource.path,
      sourceId: newSource.sourceId,
      key: newSource.key
    };
    return true;
  }
}

function getDisplayWindAngle(value) {
  return value >= 0 && value <= 180 ? value.toFixed(0):
         value > 180 ? Math.abs(value - 360).toFixed(0) * -1:
         Math.abs(value).toFixed(0) * -1;
}

function safeFixed(value) {
  try {
    return Number(value).toFixed(1);
  } catch (e) {
    console.error("Could not round:" + value);
  }
  return "-";
}

WindMeter.prototype.getReactElement = function() {
  return this.widget;
}

WindMeter.prototype.getType = function() {
  return "windmeter";
}

WindMeter.prototype.getHandledSources = function() {
  return Object.values(this.options.activeSources);
}

WindMeter.prototype.getOptions = function() {
  return this.options;
}

WindMeter.prototype.getInitialDimensions = function() {
  return {w:2, h:4};
}

function centerRotate(deg) {
  return ["rotate(", deg, half, half, ")"].join(" ");
}

const SettingsPanel = (props) => {
  return (

      {props.unit != '' ? unitChoice('m/s', props.onUnitChange, props.options.convertTo) : undefined}

  )
}

WindMeter.prototype.getSettingsElement = function() {
  var that = this;
  return SettingsPanel({
    options: this.options,
    onUnitChange: function(event) {
      that.options.convertTo = event.target.value ==='m/s' ? undefined : event.target.value;
      that.instrumentPanel.persist();
      that.instrumentPanel.pushGridChanges();
    }
  });
}

module.exports = {
  constructor: WindMeter,
  type: 'windmeter',
  paths: pathsCovered
}
<|endoftext|>


<commit_before>/**
 * Created by Gerard on 12/11/2014.
 */
module.exports.generateToken = function (options, client_id, user_id, token_fields, token_options) {
    token_options = token_options || {};
    var issued_at = new Date();
    var expires_at = new Date(issued_at.getSeconds() + (options.token_expiration || 3600));
    var plainAccessToken = {
        type: 'accesstoken',
        user_id: user_id,
        client_id: client_id,
        issued_at: issued_at.toISOString(),
        expires_at: expires_at.toISOString(),
        custom_fields: token_fields
    };

    var refreshToken = null;
    if (options.refresh_token) {
        var plainRefreshToken = {
            type: 'refreshtoken',
            user_id: user_id,
            client_id: client_id,
            custom_fields: token_fields
        };
        refreshToken = options.serializer.stringify(plainRefreshToken);
    }
    var out = mergeObjects(token_options, {
        access_token: options.serializer.stringify(plainAccessToken),
        refresh_token: refreshToken,
        issued_at: issued_at,
        expires_in: options.token_expiration || 3600
    });
    return out;
};

var mergeObjects = function () {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};<commit_msg>Split token generation between access and refresh<commit_after>var serializer = require('serializer');

module.exports.generateToken = function (options, user_id, client_id, client_secret, scope, token_fields, token_options) {
    token_options = token_options || {};
    var issued_at = new Date();
    var expires_at = new Date(issued_at.getSeconds() + (options.token_expiration || 3600));
    var plainAccessToken = generateAccessToken(user_id, client_id, issued_at, expires_at, scope, token_fields);

    var refreshToken = null;
    if (options.refresh_token) {
        var plainRefreshToken = generateRefreshToken(user_id, client_id, client_secret, scope, token_fields);
        refreshToken = options.serializer.stringify(plainRefreshToken);
    }
    var out = mergeObjects(token_options, {
        access_token: options.serializer.stringify(plainAccessToken),
        refresh_token: refreshToken,
        issued_at: issued_at,
        expires_in: options.token_expiration || 3600
    });
    return out;
};

var mergeObjects = function () {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};

var generateAccessToken = function (user_id, client_id, issued_at, expires_at, scope, token_fields) {
    var plainAccessToken = {
        type: 'access_token',
        user_id: user_id,
        client_id: client_id,
        issued_at: issued_at.toISOString(),
        expires_at: expires_at.toISOString(),
        scope: scope,
        custom_fields: token_fields
    };
    return plainAccessToken;
};

var generateRefreshToken = function (user_id, client_id, client_secret, scope, token_fields) {
    var plainRefreshToken = {
        type: 'refresh_token',
        user_id: user_id,
        client_id: client_id,
        client_secret: client_secret,
        scope: scope,
        custom_fields: token_fields
    };
    return plainRefreshToken;
};

var generateCode = function () {
    return serializer.randomString(128);
};<|endoftext|>


<commit_before>#!/usr/bin/env node

var allFiles = require("all-files")
var args = require("optimist").argv
var tape = require("tape")
var fs = require("fs")
var ospath = require("path")

var builder = require("../index")

var config = args.c || args.config
var path = args.p || args.path
var single = args.s || args.single

if (!(path || config) || (path && config)) {
    printHelp()
} else {

    if (config) {
        runTests(filesFromConfig(config))
    } else if (args.p || args.path) {
        runTests(allFiles(path), single)
    }
}

function runTests(fileList, singleFile) {
    var scenario = builder()

    fileList.forEach(function (fileName) {
        var featureFile = relquire(fileName)
        featureFile(scenario)
    })

    var filterList = null

    if (singleFile) {
        var singleTest = relquire(singleFile)
        var singleScenario = builder()
        singleTest(singleScenario)
        filterList = singleScenario.scenarios()
    }

    var tests = scenario.build()

    if (filterList) {
        tests = tests.filter(function (test) {
            return filterList.indexOf(test.scenario) >= 0
        })
    }

    tests.forEach(function (test) {
        test(tape)
    })
}

function filesFromConfig(configPath) {
    var config = relquire(configPath)

    if (!Array.isArray(config)) {
        throw new Error("Config " +
            configPpath +
            " file is not a valid JSON array")
    }

    return config
}

function printHelp() {
    var help = fs.createReadStream(ospath.join(__dirname, "scenario.usage.txt"))

    help.on("open", function () {
        help.pipe(process.stdout)
    })
}

function relquire(file) {
    return require(ospath.relative(__dirname, file))
}
<commit_msg>ack typo<commit_after>#!/usr/bin/env node

var allFiles = require("all-files")
var args = require("optimist").argv
var tape = require("tape")
var fs = require("fs")
var ospath = require("path")

var builder = require("../index")

var config = args.c || args.config
var path = args.p || args.path
var single = args.s || args.single

if (!(path || config) || (path && config)) {
    printHelp()
} else {

    if (config) {
        runTests(filesFromConfig(config))
    } else if (args.p || args.path) {
        runTests(allFiles(path), single)
    }
}

function runTests(fileList, singleFile) {
    var scenario = builder()

    fileList.forEach(function (fileName) {
        var featureFile = relquire(fileName)
        featureFile(scenario)
    })

    var filterList = null

    if (singleFile) {
        var singleTest = relquire(singleFile)
        var singleScenario = builder()
        singleTest(singleScenario)
        filterList = singleScenario.scenarios()
    }

    var tests = scenario.build()

    if (filterList) {
        tests = tests.filter(function (test) {
            return filterList.indexOf(test.scenario) >= 0
        })
    }

    tests.forEach(function (test) {
        test(tape)
    })
}

function filesFromConfig(configPath) {
    var config = relquire(configPath)

    if (!Array.isArray(config)) {
        throw new Error("Config " +
            configPath +
            " file is not a valid JSON array")
    }

    return config
}

function printHelp() {
    var help = fs.createReadStream(ospath.join(__dirname, "scenario.usage.txt"))

    help.on("open", function () {
        help.pipe(process.stdout)
    })
}

function relquire(file) {
    return require(ospath.relative(__dirname, file))
}
<|endoftext|>


<commit_before>module.exports = {
  area: 'FI', // see http://www.nordpoolspot.com/maps/
  currency: 'EUR', // can also be 'DKK', 'NOK', 'SEK'
  highTreshold: 60, // send event when price > highTreshold EUR/MWh
  lowTreshold: 30, // send event when price < lowTreshold EUR/MWh
  maxHighHours: 24, // max consecutive high hours
  maxLowHours: 24, // max consecutive low hours
  vatPercent: 24, // if you want prices including value-added tax (VAT), enter the percentage here
  iftttKey: 'CHANGE' // see https://ifttt.com/services/maker_webhooks/settings
};
<commit_msg>using ES6 export<commit_after>const config = {
  area: 'FI', // see http://www.nordpoolspot.com/maps/
  currency: 'EUR', // can also be 'DKK', 'NOK', 'SEK'
  highTreshold: 60, // send event when price > highTreshold EUR/MWh
  lowTreshold: 30, // send event when price < lowTreshold EUR/MWh
  maxHighHours: 24, // max consecutive high hours
  maxLowHours: 24, // max consecutive low hours
  vatPercent: 24, // if you want prices including value-added tax (VAT), enter the percentage here
  iftttKey: 'CHANGE' // see https://ifttt.com/services/maker_webhooks/settings
};

export {config};
<|endoftext|>