<commit_before>var runtimes = new function()
{
  var __runtimes = {};

  var self = this;

  var registerRuntime = function(id)
  {
    if( !(id in __runtimes) )
    {
      //alert('runtime: '+ id);
      __runtimes[id] = null;
      services['ecmascript-debugger'].getRuntime( tagManager.setCB(null, parseRuntime), id );
    }
  }

  var removeRuntime = function(id)
  {
    var sc = null ;
    /*
    for( sc in __scripts )
    {
      if( __scripts[sc]['runtime-id'] == id )
      {
        delete __scripts[sc];
      }
    }
    */
    delete __runtimes[id];
  }

  this.handleRuntimesReplay = function(xml)
  {
    parseRuntime(xml);
  }

  var parseRuntime = function(xml)
  {
    var r_ts = xml.getElementsByTagName('runtime'), r_t=null, i=0;
    var runtimeId = '', runtime=null, prop = '',
      children = null, child = null, j = 0;
    var cur = '';
    for ( ; r_t = r_ts[i]; i++)
    {
      runtimeId = r_t.getNodeData('runtime-id');
      //alert('parseRuntime: '+ runtimeId);
      if(runtimeId)
      {
        runtime={};
        children = r_t.childNodes;
        for(j=0 ; child = children[j]; j++)
        {
          runtime[child.nodeName] = child.textContent;
        }
        for( cur in __runtimes )
        {
          if( __runtimes[cur] && __runtimes[cur]['uri'] == runtime['uri'] )
          {
            // copy states
            //alert("__runtimes[cur]['unfolded'] "+__runtimes[cur]['unfolded'])
            if( __runtimes[cur]['unfolded'] )
            {
              runtime['unfolded'] = __runtimes[cur]['unfolded'];
            }
            delete __runtimes[cur];
          }
        }
        __runtimes[runtimeId] = runtime;

        if(__next_runtime_id_to_select == runtimeId)
        {
          self.setSelectedRuntime(runtime);
          __next_runtime_id_to_select = '';
        }

        // update view
        views.runtimes.update();
      }
    }
  }

  var __scripts = {};

/** checks if that script is already known from a previous runtime
  * checks first for the url and the for the script data.
  * Both checks are not really reliable.
  * TODO we need a better logic to handle this
  */
  var registerScript = function(script)
  {
    var sc = null, is_known = false;
    var new_script_id = script['script-id'];
    for( sc in __scripts )
    {
      if( ( __scripts[sc]['uri'] && ( __scripts[sc]['uri'] == script['uri'] ) )|| __scripts[sc]['script-data'] == script['script-data'] )
      {
        is_known = true;
        break;
      }
    }

    if( is_known )
    {
      var old_b_ps = __scripts[sc]['breakpoints'];
      var new_b_ps = script['breakpoints'];
      for( b_p in old_b_ps )
      {
        services['ecmascript-debugger'].setBreakpoint(new_script_id, b_p, old_b_ps[b_p]);
        new_b_ps[b_p] = old_b_ps[b_p];
      }
      delete __scripts[sc];
    }

    __scripts[new_script_id] = script;

    var a ='', b='';
    for( a in __scripts ) b+=a+'; ';

  }

/*
"<new-script>"
   "<runtime-id>" UNSIGNED "</runtime-id>"
   "<script-id>" UNSIGNED "</script-id>"
   "<script-type>"
      ( "inline" | "event" | "linked" | "timeout" | "java" | "unknown" )
   "</script-type>"
   "<script-data>" TEXT "</script-data>"
   "<uri>" TEXT "</uri>"             ; present if SCRIPT-TYPE is "linked"
 "</new-script>" ;
*/

  var breakpoint_count = 1;

  var getBreakpointId = function()
  {
    return ( breakpoint_count++ ).toString();
  }

  var script_count = 1;

  var getScriptId = function()
  {
    return ( script_count++ ).toString();
  }

  this.handle = function(new_script_event)
  {
    var script = {};
    var children = new_script_event.documentElement.childNodes, child=null, i=0;
    for ( ; child = children[i]; i++)
    {
      script[child.nodeName] = child.firstChild.nodeValue;
    }
    script['breakpoints'] = {};
    registerRuntime( script['runtime-id'] );
    registerScript( script );
    views.runtimes.update();
  }

  var thread_queue = []
  var threads = {}
  var current_thread = [];

  var clear_thread_id = function(id)
  {
    var cur = '', i = 0;
    /* it seems that the order of the thread-finished events can get reversed
    if( id == current_thread[ current_thread.length - 1 ] )
    {
      current_thread.pop();
    }
    */
    for(i = 0 ; cur = current_thread[i]; i++)
    {
      if( cur == id )
      {
        current_thread.splice(i, 1);
        break;
      }
    }
    for(i = 0 ; cur = thread_queue[i]; i++)
    {
      if( cur == id )
      {
        thread_queue.splice(i, 1);
        delete threads[id];
        return true;
      }
    }
    return false;
  }

/*

  <thread-started>
    <runtime-id>3</runtime-id>
    <thread-id>3</thread-id>
    <parent-thread-id>0</parent-thread-id>
    <thread-type>inline</thread-type>
  </thread-started>

  <thread-finished>
    <runtime-id>3</runtime-id>
    <thread-id>3</thread-id>
    <status>completed</status>
    <value type="null"/>
  </thread-finished>

  */

  this.handleThreadStarted = function(xml)
  {
    var id = xml.getNodeData("thread-id");
    var parent_thread_id = xml.getNodeData("parent-thread-id");
    thread_queue[thread_queue.length] = id;
    if( !current_thread.length ||
      ( parent_thread_id != '0' && parent_thread_id == current_thread[ current_thread.length - 1 ] ) )
    {
      current_thread[current_thread.length] = id;
    }
  }

  this.handleThreadStopedAt = function(xml)
  {
    var id = xml.getNodeData("thread-id");
    // the current thread id should either be set in 'thread-started' event or
    // in shifting one from the thread event queue

    if( id == current_thread[ current_thread.length - 1 ] )
    {
      stop_at.handle(xml);
    }
    else
    {
      // there should never be more then one 'thread-stopped-at' event per runtime
      // is this really true ?
      threads[id] = xml;
    }
  }

  this.handleThreadFinished = function(xml)
  {
    /* TODO
    status "completed" | "unhandled-exception" | "aborted" | "cancelled-by-scheduler"
    */
    var id = xml.getNodeData("thread-id");
    clear_thread_id(id);
    while(thread_queue.length)
    {
      id = thread_queue.shift();
      if( threads[id] )
      {
        current_thread[current_thread.length] = id;
        stop_at.handle(threads[id]);
        break;
      }
    }
  }

  /*
  <runtime-stopped>
  <runtime-id>1</runtime-id>
</runtime-stopped>

*/
  this.handleRuntimeStoped = function(xml)
  {

    var rt_id = xml.getNodeData('runtime-id');
    if(rt_id)
    {
      removeRuntime(rt_id);
      views.runtimes.update();
      var script_id = views.js_source.getCurrentScriptId();
      if( script_id  && ( self.getScriptsRuntimeId(script_id) == rt_id ) )
      {
        views.js_source.clearView();
      }
    }

  }

  this.getRuntimes = function()
  {
    // not very clever
    return __runtimes;
  }

  this.getRuntimeIdWithURL = function(url)
  {
    var r = '';
    for( r in __runtimes )
    {
      if( __runtimes[r]['uri'] == url )
      {
        return __runtimes[r];
      }
    }
    return null;
  }

  this.getScript = function(scriptId)
  {
    return __scripts[scriptId];
  }

  this.getScriptsRuntimeId = function(scriptId)
  {
    return __scripts[scriptId] && __scripts[scriptId]['runtime-id'] || null;
  }

  this.getScriptSource = function(scriptId)
  {
    return __scripts[scriptId] && __scripts[scriptId]['script-data'] || null;
  }

  this.getScripts = function(runtime_id)
  {
    var ret=[], script = null, cur = '';
    for( cur in __scripts )
    {
      script = __scripts[cur];
      if(script['runtime-id'] == runtime_id)
      {
        ret[ret.length] = script;
      }
    }
    return ret;
  }

  this.hasBreakpoint = function(script_id, line_nr)
  {
    return (line_nr in __scripts[script_id]['breakpoints']);
  }

  this.setBreakpoint = function(script_id, line_nr)
  {
    var b_p_id = __scripts[script_id]['breakpoints'][line_nr] = getBreakpointId();
    services['ecmascript-debugger'].setBreakpoint(script_id, line_nr, b_p_id);
  }

  this.removeBreakpoint = function(script_id, line_nr)
  {
    services['ecmascript-debugger'].removeBreakpoint( __scripts[script_id]['breakpoints'][line_nr] );
    delete __scripts[script_id]['breakpoints'][line_nr];
  }

  this.getBreakpoints = function(script_id)
  {
    return __scripts[script_id] && __scripts[script_id]['breakpoints'];
  }

  this.setUnfolded = function(runtime_id, is_unfolded)
  {

    if( __runtimes[runtime_id] )
    {
      //alert(__runtimes[runtime_id]+' '+is_unfolded);
      __runtimes[runtime_id]['unfolded'] = is_unfolded;
    }
  }

  this.setObserve = function(runtime_id, observe)
  {
    if( __runtimes[runtime_id] )
    {
      __runtimes[runtime_id]['observe'] = observe;
    }
  }

  this.getObserve = function(runtime_id)
  {
    return __runtimes[runtime_id] && __runtimes[runtime_id]['observe']  || false;
  }

  // this is a temporary solution as long as we don't have a concept for tabs

  var __selected_runtime_id = '';

  var __next_runtime_id_to_select = ''

  this.setSelectedRuntime = function(runtime)
  {
    var r = '';
    for( r in __runtimes )
    {
      if( __runtimes[r] == runtime )
      {
        __runtimes[r]['selected'] = true;
        __selected_runtime_id = __runtimes[r]['runtime-id'];
      }
      else
      {
        // the runtime could be registered but not jet parsed
        if( __runtimes[r] )
        {
          __runtimes[r]['selected'] = false;
        }
      }
    }
  }

  this.setSelectedScript = function( runtime, id )
  {
    var scripts = this.getScripts(runtime['runtime-id']), script = null, i = 0;
    for( ; script = scripts[i]; i++)
    {
      script.selected = script['script-id'] == id ? true : false;
    }
  }

  this.setSelectedRuntimeId = function(id)
  {
    if(__runtimes[id])
    {
      this.setSelectedRuntime(__runtimes[id]);
      views.runtimes.update();
    }
    else
    {
      __next_runtime_id_to_select = id;
    }
  }

  this.getSelectedRuntimeId = function()
  {
    return __selected_runtime_id;
  }

}

//<commit_msg>cleaner code in thread-finished event<commit_after>var runtimes = new function()
{
  var __runtimes = {};

  var self = this;

  var registerRuntime = function(id)
  {
    if( !(id in __runtimes) )
    {
      //alert('runtime: '+ id);
      __runtimes[id] = null;
      services['ecmascript-debugger'].getRuntime( tagManager.setCB(null, parseRuntime), id );
    }
  }

  var removeRuntime = function(id)
  {
    var sc = null ;
    /*
    for( sc in __scripts )
    {
      if( __scripts[sc]['runtime-id'] == id )
      {
        delete __scripts[sc];
      }
    }
    */
    delete __runtimes[id];
  }

  this.handleRuntimesReplay = function(xml)
  {
    parseRuntime(xml);
  }

  var parseRuntime = function(xml)
  {
    var r_ts = xml.getElementsByTagName('runtime'), r_t=null, i=0;
    var runtimeId = '', runtime=null, prop = '',
      children = null, child = null, j = 0;
    var cur = '';
    for ( ; r_t = r_ts[i]; i++)
    {
      runtimeId = r_t.getNodeData('runtime-id');
      //alert('parseRuntime: '+ runtimeId);
      if(runtimeId)
      {
        runtime={};
        children = r_t.childNodes;
        for(j=0 ; child = children[j]; j++)
        {
          runtime[child.nodeName] = child.textContent;
        }
        for( cur in __runtimes )
        {
          if( __runtimes[cur] && __runtimes[cur]['uri'] == runtime['uri'] )
          {
            // copy states
            //alert("__runtimes[cur]['unfolded'] "+__runtimes[cur]['unfolded'])
            if( __runtimes[cur]['unfolded'] )
            {
              runtime['unfolded'] = __runtimes[cur]['unfolded'];
            }
            delete __runtimes[cur];
          }
        }
        __runtimes[runtimeId] = runtime;

        if(__next_runtime_id_to_select == runtimeId)
        {
          self.setSelectedRuntime(runtime);
          __next_runtime_id_to_select = '';
        }

        // update view
        views.runtimes.update();
      }
    }
  }

  var __scripts = {};

/** checks if that script is already known from a previous runtime
  * checks first for the url and the for the script data.
  * Both checks are not really reliable.
  * TODO we need a better logic to handle this
  */
  var registerScript = function(script)
  {
    var sc = null, is_known = false;
    var new_script_id = script['script-id'];
    for( sc in __scripts )
    {
      if( ( __scripts[sc]['uri'] && ( __scripts[sc]['uri'] == script['uri'] ) )|| __scripts[sc]['script-data'] == script['script-data'] )
      {
        is_known = true;
        break;
      }
    }

    if( is_known )
    {
      var old_b_ps = __scripts[sc]['breakpoints'];
      var new_b_ps = script['breakpoints'];
      for( b_p in old_b_ps )
      {
        services['ecmascript-debugger'].setBreakpoint(new_script_id, b_p, old_b_ps[b_p]);
        new_b_ps[b_p] = old_b_ps[b_p];
      }
      delete __scripts[sc];
    }

    __scripts[new_script_id] = script;

    var a ='', b='';
    for( a in __scripts ) b+=a+'; ';

  }

/*
"<new-script>"
   "<runtime-id>" UNSIGNED "</runtime-id>"
   "<script-id>" UNSIGNED "</script-id>"
   "<script-type>"
      ( "inline" | "event" | "linked" | "timeout" | "java" | "unknown" )
   "</script-type>"
   "<script-data>" TEXT "</script-data>"
   "<uri>" TEXT "</uri>"             ; present if SCRIPT-TYPE is "linked"
 "</new-script>" ;
*/

  var breakpoint_count = 1;

  var getBreakpointId = function()
  {
    return ( breakpoint_count++ ).toString();
  }

  var script_count = 1;

  var getScriptId = function()
  {
    return ( script_count++ ).toString();
  }

  this.handle = function(new_script_event)
  {
    var script = {};
    var children = new_script_event.documentElement.childNodes, child=null, i=0;
    for ( ; child = children[i]; i++)
    {
      script[child.nodeName] = child.firstChild.nodeValue;
    }
    script['breakpoints'] = {};
    registerRuntime( script['runtime-id'] );
    registerScript( script );
    views.runtimes.update();
  }

  var thread_queue = []
  var threads = {}
  var current_thread = [];

  var clear_thread_id = function(id)
  {
    var cur = '', i = 0;
    /* it seems that the order of the thread-finished events can get reversed
    if( id == current_thread[ current_thread.length - 1 ] )
    {
      current_thread.pop();
    }
    */
    for(i = 0 ; cur = current_thread[i]; i++)
    {
      if( cur == id )
      {
        current_thread.splice(i, 1);
        break;
      }
    }
    for(i = 0 ; cur = thread_queue[i]; i++)
    {
      if( cur == id )
      {
        thread_queue.splice(i, 1);
        delete threads[id];
        return true;
      }
    }
    return false;
  }

/*

  <thread-started>
    <runtime-id>3</runtime-id>
    <thread-id>3</thread-id>
    <parent-thread-id>0</parent-thread-id>
    <thread-type>inline</thread-type>
  </thread-started>

  <thread-finished>
    <runtime-id>3</runtime-id>
    <thread-id>3</thread-id>
    <status>completed</status>
    <value type="null"/>
  </thread-finished>

  */

  this.handleThreadStarted = function(xml)
  {
    var id = xml.getNodeData("thread-id");
    var parent_thread_id = xml.getNodeData("parent-thread-id");
    thread_queue[thread_queue.length] = id;
    if( !current_thread.length ||
      ( parent_thread_id != '0' && parent_thread_id == current_thread[ current_thread.length - 1 ] ) )
    {
      current_thread[current_thread.length] = id;
    }
  }

  this.handleThreadStopedAt = function(xml)
  {
    var id = xml.getNodeData("thread-id");
    // the current thread id should either be set in 'thread-started' event or
    // in shifting one from the thread event queue

    if( id == current_thread[ current_thread.length - 1 ] )
    {
      stop_at.handle(xml);
    }
    else
    {
      // there should never be more then one 'thread-stopped-at' event per runtime
      // is this really true ?
      threads[id] = xml;
    }
  }

  this.handleThreadFinished = function(xml)
{
    /* TODO
    status "completed" | "unhandled-exception" | "aborted" | "cancelled-by-scheduler"
    */
    var id = xml.getNodeData("thread-id") , i = 0, parent_thread_id = '', thread = null;
    clear_thread_id(id);
    // opera.postError("thread finished id: " + id +' queue: '+thread_queue+' current: '+current_thread)
    for( ; id = thread_queue[i]; i++)
    {
      if( thread = threads[id] )
      {
        parent_thread_id = thread.getNodeData("parent-thread-id");
        if( !current_thread.length ||
            ( parent_thread_id != '0' && parent_thread_id == current_thread[ current_thread.length - 1 ] ) )
        {
          current_thread[current_thread.length] = id;
          stop_at.handle(threads[id]);
          break;
        }
      }
    }
  }

  /*
  <runtime-stopped>
  <runtime-id>1</runtime-id>
</runtime-stopped>

*/
  this.handleRuntimeStoped = function(xml)
  {

    var rt_id = xml.getNodeData('runtime-id');
    if(rt_id)
    {
      removeRuntime(rt_id);
      views.runtimes.update();
      var script_id = views.js_source.getCurrentScriptId();
      if( script_id  && ( self.getScriptsRuntimeId(script_id) == rt_id ) )
      {
        views.js_source.clearView();
      }
    }

  }

  this.getRuntimes = function()
  {
    // not very clever
    return __runtimes;
  }

  this.getRuntimeIdWithURL = function(url)
  {
    var r = '';
    for( r in __runtimes )
    {
      if( __runtimes[r]['uri'] == url )
      {
        return __runtimes[r];
      }
    }
    return null;
  }

  this.getScript = function(scriptId)
  {
    return __scripts[scriptId];
  }

  this.getScriptsRuntimeId = function(scriptId)
  {
    return __scripts[scriptId] && __scripts[scriptId]['runtime-id'] || null;
  }

  this.getScriptSource = function(scriptId)
  {
    return __scripts[scriptId] && __scripts[scriptId]['script-data'] || null;
  }

  this.getScripts = function(runtime_id)
  {
    var ret=[], script = null, cur = '';
    for( cur in __scripts )
    {
      script = __scripts[cur];
      if(script['runtime-id'] == runtime_id)
      {
        ret[ret.length] = script;
      }
    }
    return ret;
  }

  this.hasBreakpoint = function(script_id, line_nr)
  {
    return (line_nr in __scripts[script_id]['breakpoints']);
  }

  this.setBreakpoint = function(script_id, line_nr)
  {
    var b_p_id = __scripts[script_id]['breakpoints'][line_nr] = getBreakpointId();
    services['ecmascript-debugger'].setBreakpoint(script_id, line_nr, b_p_id);
  }

  this.removeBreakpoint = function(script_id, line_nr)
  {
    services['ecmascript-debugger'].removeBreakpoint( __scripts[script_id]['breakpoints'][line_nr] );
    delete __scripts[script_id]['breakpoints'][line_nr];
  }

  this.getBreakpoints = function(script_id)
  {
    return __scripts[script_id] && __scripts[script_id]['breakpoints'];
  }

  this.setUnfolded = function(runtime_id, is_unfolded)
  {

    if( __runtimes[runtime_id] )
    {
      //alert(__runtimes[runtime_id]+' '+is_unfolded);
      __runtimes[runtime_id]['unfolded'] = is_unfolded;
    }
  }

  this.setObserve = function(runtime_id, observe)
  {
    if( __runtimes[runtime_id] )
    {
      __runtimes[runtime_id]['observe'] = observe;
    }
  }

  this.getObserve = function(runtime_id)
  {
    return __runtimes[runtime_id] && __runtimes[runtime_id]['observe']  || false;
  }

  // this is a temporary solution as long as we don't have a concept for tabs

  var __selected_runtime_id = '';

  var __next_runtime_id_to_select = ''

  this.setSelectedRuntime = function(runtime)
  {
    var r = '';
    for( r in __runtimes )
    {
      if( __runtimes[r] == runtime )
      {
        __runtimes[r]['selected'] = true;
        __selected_runtime_id = __runtimes[r]['runtime-id'];
      }
      else
      {
        // the runtime could be registered but not jet parsed
        if( __runtimes[r] )
        {
          __runtimes[r]['selected'] = false;
        }
      }
    }
  }

  this.setSelectedScript = function( runtime, id )
  {
    var scripts = this.getScripts(runtime['runtime-id']), script = null, i = 0;
    for( ; script = scripts[i]; i++)
    {
      script.selected = script['script-id'] == id ? true : false;
    }
  }

  this.setSelectedRuntimeId = function(id)
  {
    if(__runtimes[id])
    {
      this.setSelectedRuntime(__runtimes[id]);
      views.runtimes.update();
    }
    else
    {
      __next_runtime_id_to_select = id;
    }
  }

  this.getSelectedRuntimeId = function()
  {
    return __selected_runtime_id;
  }

}

//<|endoftext|>


<commit_before>'use strict';
var request = require('request'),
    util = require('util'),
    _ = require('lodash'),
    Q = require('Q'),
    searchUtils = require('./searchutils.js');

/**
 * RDWSearch constructor
 * @class
 * @param {string} apiKey - Azure market apiKey (not necessary for this service)
 */
function RDWSearch(apiKey) {
    this.api = {};

    this.api.url = 'https://api.datamarket.azure.com/Data.ashx/opendata.rdw/VRTG.Open.Data/v1/KENT_VRTG_O_DAT';
    this.api.plateUrl = 'https://api.datamarket.azure.com/Data.ashx/opendata.rdw/VRTG.Open.Data/v1/KENT_VRTG_O_DAT(\'%s\')?$format=json';

    this.api.key = apiKey || null;

    return this;
}

/**
 * Parses a single result, converts them to proper objects based on the output
 * @private
 * @param  {object} data - Single result
 * @return {object} Parsed object
 */
function parseResult(data) {

    var parsed = {},
        floatRegExp = /^[-+]?[0-9]*\.?[0-9]+$/,
        dateRegExp = /(\/Date\()(-?\d+)(\)\/)/,
        dateVal;

    _.each(data, function (value, key) {
        parsed[key] = value;
        if (typeof value === 'string') {
            if (dateRegExp.test(value)) {
                dateVal = parseInt(value.replace(dateRegExp, '$2'), 10);
                parsed[key] = new Date(dateVal);
            } else if (floatRegExp.test(value)) {
                parsed[key] = parseFloat(value);
            } else if (value === "Ja") {
                parsed[key] = true;
            } else if (value === "Nee") {
                parsed[key] = false;
            }
        }
    });

    return parsed;
}

/**
 * Main search method
 * @public
 * @param  {string|string[]} filterParams - The parameters for filtering. This can either be a String, or an Array
 * @returns {Object} - Promise
 */
RDWSearch.prototype.search = function (filterParams) {
    var _this = this,
        deferred = Q.defer(),
        filter = {};

    var uri = _this.api.url;

    if (!filterParams) {
        uri += '?$format=json';
    } else if (typeof filterParams === 'string') {
        uri += '?$filter=';
        uri += filterParams;
        uri += '&$format=json';
    } else if (_.isArray(filterParams)) {

        filter = searchUtils.createFilterString(filterParams);

        if (filter.error) {
            deferred.reject(filter.error);
        } else {
            uri += '?$filter=';
            uri += filter.filterString;
            uri += '&$format=json';
        }

    }

    var options = {
        'method': 'GET',
        'uri': uri
    };

    if (_this.api.key) {
        options.headers = {
            'Authorization': 'Basic ' + new Buffer(this.api.key + ':' + this.api.key).toString('base64')
        };
    }

    if (!filter.error) {
        request(options, function (error, response, body) {

            if (!error && response.statusCode === 200) {

                var data = JSON.parse(body);

                if (data.d) {

                    if (data.d.results.length === 0) {
                        deferred.reject([]);
                    } else if (data.d.results.length === 1) {
                        deferred.resolve(parseResult(data.d.results[0]));
                    } else {
                        var results = [];
                        _.each(data.d.results, function (res) {
                            results.push(parseResult(res));
                        });
                        deferred.resolve(results);
                    }
                    deferred.resolve(data.d);

                } else {
                    deferred.reject('data returned, error parsing: ' + JSON.stringify(data, true, 4));
                }

            }
            else if (error) {
                deferred.reject(error);
            }
            else {
                deferred.reject('Response code: ' + response.statusCode + '\nContent: ' + body);
            }
        });
    }

    return deferred.promise;
};

/**
 * searchPlate - Search a dutch license plate in the RDW database
 * @public
 * @param  {string}   plate - The license plate, without dashes. E.g. '1222XX' == '12-22-XX'
 * @param  {Function} callback - Callback function
 * @deprecated
 */
RDWSearch.prototype.searchPlate = function (plate, callback) {

    /*
        This method will become deprecated, leaving it in for now
    */

    var _this = this;

    if (!callback || !plate) {
        throw new Error('No callback or plate provided');
    }

    if (typeof plate !== 'string' || plate.length !== 6) {
        throw new Error('Parameter plate needs to be a string of 6 characters');
    }

    plate = plate.toUpperCase();

    _this
        .search('Kenteken eq \'' + plate + '\'')
        .then(function (data) {
            callback(null, data);
        })
        .fail(function (error) {
            callback(error);
        });

};

/**
 * searchPlateDeferred - Searches a dutch license plate, Promise style.
 * @public
 * @param  {string} plate
 * @return {object}
 */
RDWSearch.prototype.searchPlateDeferred = function (plate) {
    var _this = this;
    return _this.search('Kenteken eq \'' + plate + '\'');
};

module.exports = RDWSearch;
<commit_msg>Fixing test issues<commit_after>'use strict';
var request = require('request'),
    util = require('util'),
    _ = require('lodash'),
    Q = require('q'),
    searchUtils = require('./searchutils.js');

/**
 * RDWSearch constructor
 * @class
 * @param {string} apiKey - Azure market apiKey (not necessary for this service)
 */
function RDWSearch(apiKey) {
    this.api = {};

    this.api.url = 'https://api.datamarket.azure.com/Data.ashx/opendata.rdw/VRTG.Open.Data/v1/KENT_VRTG_O_DAT';
    this.api.plateUrl = 'https://api.datamarket.azure.com/Data.ashx/opendata.rdw/VRTG.Open.Data/v1/KENT_VRTG_O_DAT(\'%s\')?$format=json';

    this.api.key = apiKey || null;

    return this;
}

/**
 * Parses a single result, converts them to proper objects based on the output
 * @private
 * @param  {object} data - Single result
 * @return {object} Parsed object
 */
function parseResult(data) {

    var parsed = {},
        floatRegExp = /^[-+]?[0-9]*\.?[0-9]+$/,
        dateRegExp = /(\/Date\()(-?\d+)(\)\/)/,
        dateVal;

    _.each(data, function (value, key) {
        parsed[key] = value;
        if (typeof value === 'string') {
            if (dateRegExp.test(value)) {
                dateVal = parseInt(value.replace(dateRegExp, '$2'), 10);
                parsed[key] = new Date(dateVal);
            } else if (floatRegExp.test(value)) {
                parsed[key] = parseFloat(value);
            } else if (value === "Ja") {
                parsed[key] = true;
            } else if (value === "Nee") {
                parsed[key] = false;
            }
        }
    });

    return parsed;
}

/**
 * Main search method
 * @public
 * @param  {string|string[]} filterParams - The parameters for filtering. This can either be a String, or an Array
 * @returns {Object} - Promise
 */
RDWSearch.prototype.search = function (filterParams) {
    var _this = this,
        deferred = Q.defer(),
        filter = {};

    var uri = _this.api.url;

    if (!filterParams) {
        uri += '?$format=json';
    } else if (typeof filterParams === 'string') {
        uri += '?$filter=';
        uri += filterParams;
        uri += '&$format=json';
    } else if (_.isArray(filterParams)) {

        filter = searchUtils.createFilterString(filterParams);

        if (filter.error) {
            deferred.reject(filter.error);
        } else {
            uri += '?$filter=';
            uri += filter.filterString;
            uri += '&$format=json';
        }

    }

    var options = {
        'method': 'GET',
        'uri': uri
    };

    if (_this.api.key) {
        options.headers = {
            'Authorization': 'Basic ' + new Buffer(this.api.key + ':' + this.api.key).toString('base64')
        };
    }

    if (!filter.error) {
        request(options, function (error, response, body) {

            if (!error && response.statusCode === 200) {

                var data = JSON.parse(body);

                if (data.d) {

                    if (data.d.results.length === 0) {
                        deferred.reject([]);
                    } else if (data.d.results.length === 1) {
                        deferred.resolve(parseResult(data.d.results[0]));
                    } else {
                        var results = [];
                        _.each(data.d.results, function (res) {
                            results.push(parseResult(res));
                        });
                        deferred.resolve(results);
                    }
                    deferred.resolve(data.d);

                } else {
                    deferred.reject('data returned, error parsing: ' + JSON.stringify(data, true, 4));
                }

            }
            else if (error) {
                deferred.reject(error);
            }
            else {
                deferred.reject('Response code: ' + response.statusCode + '\nContent: ' + body);
            }
        });
    }

    return deferred.promise;
};

/**
 * searchPlate - Search a dutch license plate in the RDW database
 * @public
 * @param  {string}   plate - The license plate, without dashes. E.g. '1222XX' == '12-22-XX'
 * @param  {Function} callback - Callback function
 * @deprecated
 */
RDWSearch.prototype.searchPlate = function (plate, callback) {

    /*
        This method will become deprecated, leaving it in for now
    */

    var _this = this;

    if (!callback || !plate) {
        throw new Error('No callback or plate provided');
    }

    if (typeof plate !== 'string' || plate.length !== 6) {
        throw new Error('Parameter plate needs to be a string of 6 characters');
    }

    plate = plate.toUpperCase();

    _this
        .search('Kenteken eq \'' + plate + '\'')
        .then(function (data) {
            callback(null, data);
        })
        .fail(function (error) {
            callback(error);
        });

};

/**
 * searchPlateDeferred - Searches a dutch license plate, Promise style.
 * @public
 * @param  {string} plate
 * @return {object}
 */
RDWSearch.prototype.searchPlateDeferred = function (plate) {
    var _this = this;
    return _this.search('Kenteken eq \'' + plate + '\'');
};

module.exports = RDWSearch;
<|endoftext|>


<commit_before>var models = require("../../models")
var getRedisConnection = require("../../utils/getRedisConnection")
module.exports = function(token,text,files){
    // validate
    if(!text) return Promise.reject("text-is-require")
    var post = new models.posts();
    post.app = token.app;
    post.user = token.user;
    post.user.postsCount++;
    post.text = text.replace(/\n+/g,"\n");
    var file_ids = files.split(",").map(function(id){
            return new models.mongoose.Types.ObjectId(id);
    });
    console.log(file_ids);
    return models.files.find({
        _id:{$in:file_ids}
    }).then(function(files){
        console.log(files)
        if(files.length > 1) return Promise.reject("file-too-many")
        post.files = files;
        var promises = [
            post.save(),
            post.user.save(),
            models.follows.find({toUser:token.user.id})
        ]
        for(var i = 0;i < files.length;i++){ // ファイルがどこかで使われているフラグを立てる
            if(!files[i].isUse){
                files[i].isUse = true;
                promises.push(files[i].save())
            }
        }
        return Promise.all(promises);
    }).then(function(_){
        var post = _[0]
        var redis = getRedisConnection();
        redis.publish("kyoppie:posts-timeline:"+token.user.id,post.id)
        _[2].forEach(function(following){
            redis.publish("kyoppie:posts-timeline:"+following.fromUser,post.id)
        })
        redis.publish("kyoppie:posts-public_timeline",post.id);
        redis.quit();
        return Promise.resolve(post)
    });
}<commit_msg>画像を添付しないと投稿できない不具合を修正<commit_after>var models = require("../../models")
var getRedisConnection = require("../../utils/getRedisConnection")
module.exports = function(token,text,files){
    // validate
    if(!text) return Promise.reject("text-is-require")
    var post = new models.posts();
    post.app = token.app;
    post.user = token.user;
    post.user.postsCount++;
    post.text = text.replace(/\n+/g,"\n");
    var file_ids = files.split(",").map(function(id){
        if(id.length != 24) return undefined;
        return id;
    });
    console.log(file_ids);
    return models.files.find({
        _id:{$in:file_ids}
    }).then(function(files){
        console.log(files)
        if(files.length > 1) return Promise.reject("file-too-many")
        post.files = files;
        var promises = [
            post.save(),
            post.user.save(),
            models.follows.find({toUser:token.user.id})
        ]
        for(var i = 0;i < files.length;i++){ // ファイルがどこかで使われているフラグを立てる
            if(!files[i].isUse){
                files[i].isUse = true;
                promises.push(files[i].save())
            }
        }
        return Promise.all(promises);
    }).then(function(_){
        var post = _[0]
        var redis = getRedisConnection();
        redis.publish("kyoppie:posts-timeline:"+token.user.id,post.id)
        _[2].forEach(function(following){
            redis.publish("kyoppie:posts-timeline:"+following.fromUser,post.id)
        })
        redis.publish("kyoppie:posts-public_timeline",post.id);
        redis.quit();
        return Promise.resolve(post)
    });
}<|endoftext|>


<commit_before>'use strict';

var restify = require('restify'),

  exec = require('child_process').exec,

  utils = require('./../common/utils');

/**
 * Parses a line of output generated by the `df` command.
 *
 * @param {String} data - Line generated by `df`.
 *
 * @returns {Object} Object with `mountPoint`, `spaceUsed`, and `spaceAvailable` properties, with
 *                   the unit of the latter two being bytes.
 */
function parseDiskInformation(data) {
  try {
    var split = data.replace(/\s+/g, ' ').split(' ');
    return split.length <= 5 ? null : {
      mountPoint: split[5],
      spaceUsed: split[2],
      spaceAvailable: split[3]
    };
  } catch (err) {
    // we're not really interested in the error...
    return null;
  }
}

/**
 * Handles reqests to GET /status/system/disk.
 */
function getSystemDiskUsage(req, res, next) {
  exec('df -x tmpfs -x devtmpfs | tail -n +2', function (err, stdout, stderr) {
    if (err || stderr) {
      req.log.error("Couldn't read disk usage (err: %s, stderr: %s)", err, stderr);
      return new restify.InternalServerError('Error while running native command.');
    }

    var data = stdout.split('\n').map(parseDiskInformation).filter(disk => disk);

    utils.sendOkResponse('Information about ' + data.length + ' disks retrieved',
        data, res, next, 'http://' + req.headers.host + req.url);
  });
}

exports.getSystemDiskUsage = getSystemDiskUsage;

<commit_msg>Correctly handle whitespaces in disk names (#12)<commit_after>'use strict';

var restify = require('restify'),

  exec = require('child_process').exec,

  utils = require('./../common/utils');

/**
 * Parses a line of output generated by the `df` command.
 *
 * @param {String} data - Line generated by `df`.
 *
 * @returns {Object} Object with `mountPoint`, `spaceUsed`, and `spaceAvailable` properties, with
 *                   the unit of the latter two being bytes.
 */
function parseDiskInformation(data) {
  try {
    var split = data.replace(/\s+/g, ' ').split(' ');
    return split.length <= 5 ? null : {
      mountPoint: split.slice(5).join(' '),
      spaceUsed: split[2],
      spaceAvailable: split[3]
    };
  } catch (err) {
    // we're not really interested in the error...
    return null;
  }
}

/**
 * Handles reqests to GET /status/system/disk.
 */
function getSystemDiskUsage(req, res, next) {
  exec('df -x tmpfs -x devtmpfs | tail -n +2', function (err, stdout, stderr) {
    if (err || stderr) {
      req.log.error("Couldn't read disk usage (err: %s, stderr: %s)", err, stderr);
      return new restify.InternalServerError('Error while running native command.');
    }

    var data = stdout.split('\n').map(parseDiskInformation).filter(disk => disk);

    utils.sendOkResponse('Information about ' + data.length + ' disks retrieved',
        data, res, next, 'http://' + req.headers.host + req.url);
  });
}

exports.getSystemDiskUsage = getSystemDiskUsage;

<|endoftext|>


<commit_before>export function tetris () {
  var value = 0x8988;
  return function() {
    var bit1 = (value >> 1) & 1;
    var bit9 = (value >> 9) & 1;
    var leftmostBit = bit1 ^ bit9;
    return (value = ((leftmostBit << 15) | (value >>> 1)) >>> 0);
  }
}

export function rngFloat (rng) {
  return () => {
    const v = (rng() - 2) / (65534 - 2);
    console.log(v);
    return v;
  }
}
<commit_msg>remove extraneous console.log<commit_after>export function tetris () {
  var value = 0x8988;
  return function() {
    var bit1 = (value >> 1) & 1;
    var bit9 = (value >> 9) & 1;
    var leftmostBit = bit1 ^ bit9;
    return (value = ((leftmostBit << 15) | (value >>> 1)) >>> 0);
  }
}

export function rngFloat (rng) {
  return () => {
    const v = (rng() - 2) / (65534 - 2);
    return v;
  }
}
<|endoftext|>


<commit_before>/* Thunk
   Creates a thunk representing the given closure.
   Since we want automatic memoization of as many expressions as possible, we
   use a JS object as a sort of tagged pointer, where the member x denotes the
   object actually pointed to. If a "pointer" points to a thunk, it has a
   member 't' which is set to true; if it points to a value, be it a function,
   a value of an algebraic type of a primitive value, it has no member 't'.
*/

function T(f) {
    this.f = f;
}

/* Apply
   Applies the function f to the arguments args. If the application is under-
   saturated, a closure is returned, awaiting further arguments. If it is over-
   saturated, the function is fully applied, and the result (assumed to be a
   function) is then applied to the remaining arguments.
*/
function A(f, args) {
    f = f instanceof T ? E(f) : f;
    // Closure does some funny stuff with functions that occasionally
    // results in non-functions getting applied, so we have to deal with
    // it.
    if(!f.apply) {
        return f;
    }

    if(f.arity === undefined) {
        f.arity = f.length;
    }
    if(args.length === f.arity) {
        return f.apply(null, args);
    }
    if(args.length > f.arity) {
        var first = args.splice(0, f.arity);
        return A(f.apply(null, first), args);
    } else {
        var g = function() {
            var as = args.concat(Array.prototype.slice.call(arguments));
            return A(f, as);
        };
        g.arity = f.arity - args.length;
        return g;
    }
}

/* Eval
   Evaluate the given thunk t into head normal form.
   If the "thunk" we get isn't actually a thunk, just return it.
*/
function E(t) {
    if(t instanceof T) {
        if(t.f) {
            t.x = t.f();
            t.f = 0;
        }
        return t.x;
    }
    return t;
}

/* Throw an error.
   We need to be able to use throw as an exception so we wrap it in a function.
*/
function die(err) {
    throw err;
}

function quot(a, b) {
    return (a-a%b)/b;
}

function quotRemI(a, b) {
    return [0, (a-a%b)/b, a%b];
}

// 32 bit integer multiplication, with correct overflow behavior
// note that |0 or >>>0 needs to be applied to the result, for int and word
// respectively.
function imul(a, b) {
  // ignore high a * high a as the result will always be truncated
  var lows = (a & 0xffff) * (b & 0xffff); // low a * low b
  var aB = (a & 0xffff) * (b & 0xffff0000); // low a * high b
  var bA = (a & 0xffff0000) * (b & 0xffff); // low b * high a
  return lows + aB + bA; // sum will not exceed 52 bits, so it's safe
}

function addC(a, b) {
    var x = a+b;
    return [0, x & 0xffffffff, x > 0x7fffffff];
}

function subC(a, b) {
    var x = a-b;
    return [0, x & 0xffffffff, x < -2147483648];
}

function sinh (arg) {
    return (Math.exp(arg) - Math.exp(-arg)) / 2;
}

function tanh (arg) {
    return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
}

function cosh (arg) {
    return (Math.exp(arg) + Math.exp(-arg)) / 2;
}

// Scratch space for byte arrays.
var rts_scratchBuf = new ArrayBuffer(8);
var rts_scratchW32 = new Uint32Array(rts_scratchBuf);
var rts_scratchFloat = new Float32Array(rts_scratchBuf);
var rts_scratchDouble = new Float64Array(rts_scratchBuf);

function decodeFloat(x) {
    rts_scratchFloat[0] = x;
    var sign = x < 0 ? -1 : 1;
    var exp = ((rts_scratchW32[0] >> 23) & 0xff) - 150;
    var man = rts_scratchW32[0] & 0x7fffff;
    if(exp === 0) {
        ++exp;
    } else {
        man |= (1 << 23);
    }
    return [0, sign*man, exp];
}

function decodeDouble(x) {
    rts_scratchDouble[0] = x;
    var sign = x < 0 ? -1 : 1;
    var manHigh = rts_scratchW32[1] & 0xfffff;
    var manLow = rts_scratchW32[0];
    var exp = ((rts_scratchW32[1] >> 20) & 0x7ff) - 1075;
    if(exp === 0) {
        ++exp;
    } else {
        manHigh |= (1 << 20);
    }
    return [0, sign, manHigh, manLow, exp];
}

function err(str) {
    die(toJSStr(str)[1]);
}

/* unpackCString#
   NOTE: update constructor tags if the code generator starts munging them.
*/
function unCStr(str) {return unAppCStr(str, [0]);}

function unFoldrCStr(str, f, z) {
    var acc = z;
    for(var i = str.length-1; i >= 0; --i) {
        acc = A(f, [[0, str.charCodeAt(i)], acc]);
    }
    return acc;
}

function unAppCStr(str, chrs) {
    var i = arguments[2] ? arguments[2] : 0;
    if(i >= str.length) {
        return E(chrs);
    } else {
        return [1,[0,str.charCodeAt(i)],new T(function() {
            return unAppCStr(str,chrs,i+1);
        })];
    }
}

function charCodeAt(str, i) {return str.charCodeAt(i);}

function fromJSStr(str) {
    return unCStr(E(str)[1]);
}

function toJSStr(hsstr) {
    var s = '';
    for(var str = E(hsstr); str[0] == 1; str = E(str[2])) {
        s += String.fromCharCode(E(str[1])[1]);
    }
    return [0,s];
}

// newMutVar
function nMV(val) {
    return ({x: val});
}

// readMutVar
function rMV(mv) {
    return mv.x;
}

// writeMutVar
function wMV(mv, val) {
    mv.x = val;
}

function localeEncoding() {
    var le = newByteArr(5);
    le['b']['i8'] = 'U'.charCodeAt(0);
    le['b']['i8'] = 'T'.charCodeAt(0);
    le['b']['i8'] = 'F'.charCodeAt(0);
    le['b']['i8'] = '-'.charCodeAt(0);
    le['b']['i8'] = '8'.charCodeAt(0);
    return le;
}

var isFloatNaN = isDoubleNaN = isNaN;

function isDoubleInfinite(d) {
    return (d === Infinity);
}
var isFloatInfinite = isDoubleInfinite;

function isDoubleNegativeZero(x) {
    return (x===0 && (1/x)===-Infinity);
}
var isFloatNegativeZero = isDoubleNegativeZero;

function strEq(a, b) {
    return a == b;
}

function strOrd(a, b) {
    if(a < b) {
        return [0];
    } else if(a == b) {
        return [1];
    }
    return [2];
}

function jsCatch(act, handler) {
    try {
        return A(act,[0]);
    } catch(e) {
        return A(handler,[e, 0]);
    }
}

function hs_eqWord64(a, b) {
    return (a[0] == b[0] && a[1] == b[1]);
}

// Word64# representation: (Word, Word)
function hs_wordToWord64(low) {
    return [0, low];
}

function hs_mkWord64(high, low) {
    return [high, low];
}

var coercionToken = undefined;

/* Haste represents constructors internally using 1 for the first constructor,
   2 for the second, etc.
   However, dataToTag should use 0, 1, 2, etc. Also, booleans might be unboxed.
 */
function dataToTag(x) {
    if(x instanceof Array) {
        return x[0];
    } else {
        return x;
    }
}

function __word_encodeDouble(d, e) {
    return d * Math.pow(2,e);
}

var __word_encodeFloat = __word_encodeDouble;
var jsRound = Math.round; // Stupid GHC doesn't like periods in FFI IDs...
if(typeof _ == 'undefined') {
    var _ = undefined;
}
<commit_msg>Slightly optimize A() again.<commit_after>/* Thunk
   Creates a thunk representing the given closure.
   Since we want automatic memoization of as many expressions as possible, we
   use a JS object as a sort of tagged pointer, where the member x denotes the
   object actually pointed to. If a "pointer" points to a thunk, it has a
   member 't' which is set to true; if it points to a value, be it a function,
   a value of an algebraic type of a primitive value, it has no member 't'.
*/

function T(f) {
    this.f = f;
}

/* Apply
   Applies the function f to the arguments args. If the application is under-
   saturated, a closure is returned, awaiting further arguments. If it is over-
   saturated, the function is fully applied, and the result (assumed to be a
   function) is then applied to the remaining arguments.
*/
function A(f, args) {
    if(f instanceof T) {
        f = E(f);
    }
    // Closure does some funny stuff with functions that occasionally
    // results in non-functions getting applied, so we have to deal with
    // it.
    if(f.apply === undefined) {
        return f;
    }

    if(f.arity === undefined) {
        f.arity = f.length;
    }
    if(args.length === f.arity) {
        return f.arity === 1 ? f(args[0]) : f.apply(null, args);
    } else if(args.length > f.arity) {
        return f.arity === 1 ? A(f(args.shift()), args)
                             : A(f.apply(null, args.splice(0, f.arity)), args);
    } else {
        var g = function() {
            return A(f, args.concat(Array.prototype.slice.call(arguments)));
        };
        g.arity = f.arity - args.length;
        return g;
    }
}

/* Eval
   Evaluate the given thunk t into head normal form.
   If the "thunk" we get isn't actually a thunk, just return it.
*/
function E(t) {
    if(t instanceof T) {
        if(t.f) {
            t.x = t.f();
            t.f = 0;
        }
        return t.x;
    }
    return t;
}

/* Throw an error.
   We need to be able to use throw as an exception so we wrap it in a function.
*/
function die(err) {
    throw err;
}

function quot(a, b) {
    return (a-a%b)/b;
}

function quotRemI(a, b) {
    return [0, (a-a%b)/b, a%b];
}

// 32 bit integer multiplication, with correct overflow behavior
// note that |0 or >>>0 needs to be applied to the result, for int and word
// respectively.
function imul(a, b) {
  // ignore high a * high a as the result will always be truncated
  var lows = (a & 0xffff) * (b & 0xffff); // low a * low b
  var aB = (a & 0xffff) * (b & 0xffff0000); // low a * high b
  var bA = (a & 0xffff0000) * (b & 0xffff); // low b * high a
  return lows + aB + bA; // sum will not exceed 52 bits, so it's safe
}

function addC(a, b) {
    var x = a+b;
    return [0, x & 0xffffffff, x > 0x7fffffff];
}

function subC(a, b) {
    var x = a-b;
    return [0, x & 0xffffffff, x < -2147483648];
}

function sinh (arg) {
    return (Math.exp(arg) - Math.exp(-arg)) / 2;
}

function tanh (arg) {
    return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
}

function cosh (arg) {
    return (Math.exp(arg) + Math.exp(-arg)) / 2;
}

// Scratch space for byte arrays.
var rts_scratchBuf = new ArrayBuffer(8);
var rts_scratchW32 = new Uint32Array(rts_scratchBuf);
var rts_scratchFloat = new Float32Array(rts_scratchBuf);
var rts_scratchDouble = new Float64Array(rts_scratchBuf);

function decodeFloat(x) {
    rts_scratchFloat[0] = x;
    var sign = x < 0 ? -1 : 1;
    var exp = ((rts_scratchW32[0] >> 23) & 0xff) - 150;
    var man = rts_scratchW32[0] & 0x7fffff;
    if(exp === 0) {
        ++exp;
    } else {
        man |= (1 << 23);
    }
    return [0, sign*man, exp];
}

function decodeDouble(x) {
    rts_scratchDouble[0] = x;
    var sign = x < 0 ? -1 : 1;
    var manHigh = rts_scratchW32[1] & 0xfffff;
    var manLow = rts_scratchW32[0];
    var exp = ((rts_scratchW32[1] >> 20) & 0x7ff) - 1075;
    if(exp === 0) {
        ++exp;
    } else {
        manHigh |= (1 << 20);
    }
    return [0, sign, manHigh, manLow, exp];
}

function err(str) {
    die(toJSStr(str)[1]);
}

/* unpackCString#
   NOTE: update constructor tags if the code generator starts munging them.
*/
function unCStr(str) {return unAppCStr(str, [0]);}

function unFoldrCStr(str, f, z) {
    var acc = z;
    for(var i = str.length-1; i >= 0; --i) {
        acc = A(f, [[0, str.charCodeAt(i)], acc]);
    }
    return acc;
}

function unAppCStr(str, chrs) {
    var i = arguments[2] ? arguments[2] : 0;
    if(i >= str.length) {
        return E(chrs);
    } else {
        return [1,[0,str.charCodeAt(i)],new T(function() {
            return unAppCStr(str,chrs,i+1);
        })];
    }
}

function charCodeAt(str, i) {return str.charCodeAt(i);}

function fromJSStr(str) {
    return unCStr(E(str)[1]);
}

function toJSStr(hsstr) {
    var s = '';
    for(var str = E(hsstr); str[0] == 1; str = E(str[2])) {
        s += String.fromCharCode(E(str[1])[1]);
    }
    return [0,s];
}

// newMutVar
function nMV(val) {
    return ({x: val});
}

// readMutVar
function rMV(mv) {
    return mv.x;
}

// writeMutVar
function wMV(mv, val) {
    mv.x = val;
}

function localeEncoding() {
    var le = newByteArr(5);
    le['b']['i8'] = 'U'.charCodeAt(0);
    le['b']['i8'] = 'T'.charCodeAt(0);
    le['b']['i8'] = 'F'.charCodeAt(0);
    le['b']['i8'] = '-'.charCodeAt(0);
    le['b']['i8'] = '8'.charCodeAt(0);
    return le;
}

var isFloatNaN = isDoubleNaN = isNaN;

function isDoubleInfinite(d) {
    return (d === Infinity);
}
var isFloatInfinite = isDoubleInfinite;

function isDoubleNegativeZero(x) {
    return (x===0 && (1/x)===-Infinity);
}
var isFloatNegativeZero = isDoubleNegativeZero;

function strEq(a, b) {
    return a == b;
}

function strOrd(a, b) {
    if(a < b) {
        return [0];
    } else if(a == b) {
        return [1];
    }
    return [2];
}

function jsCatch(act, handler) {
    try {
        return A(act,[0]);
    } catch(e) {
        return A(handler,[e, 0]);
    }
}

function hs_eqWord64(a, b) {
    return (a[0] == b[0] && a[1] == b[1]);
}

// Word64# representation: (Word, Word)
function hs_wordToWord64(low) {
    return [0, low];
}

function hs_mkWord64(high, low) {
    return [high, low];
}

var coercionToken = undefined;

/* Haste represents constructors internally using 1 for the first constructor,
   2 for the second, etc.
   However, dataToTag should use 0, 1, 2, etc. Also, booleans might be unboxed.
 */
function dataToTag(x) {
    if(x instanceof Array) {
        return x[0];
    } else {
        return x;
    }
}

function __word_encodeDouble(d, e) {
    return d * Math.pow(2,e);
}

var __word_encodeFloat = __word_encodeDouble;
var jsRound = Math.round; // Stupid GHC doesn't like periods in FFI IDs...
if(typeof _ == 'undefined') {
    var _ = undefined;
}
<|endoftext|>


<commit_before>var path = require('path');
var helpers = require('./helpers');
var log = require('./log');
var glob = require('glob');
var watchr = require('watchr');
var decache = require('decache');

function requireHook(hook, extraPath) {
  if (! extraPath) {
    extraPath = '';
  }

  if (typeof hook === 'object') {
    var hookPath = hook.path;
    delete hook.path;

    require(path.join(extraPath, hookPath))(hook);
  } else {
    require(path.join(extraPath, hook));
  }
}

function runTests(paths, options) {
  log.begin(options);

  if (options.compiler) {
    requireHook(options.compiler);
  }

  if (options.before) {
    requireHook(options.before, options.cwd);
  }

  paths.forEach(function (file) {
    if (options.watch) {
      helpers.uncache(file);
    }
    require(file);
  });

  if (options.after) {
    requireHook(options.after, options.cwd);
  }

  return log.finish();
}

module.exports = function (files, options) {
  options = helpers.merge({
    before: null,
    after: null,
    reporter: './reporters/dot',
    cwd: process.cwd(),
    compiler: null,
    watch: false,
    watchFiles: []
  }, options);

  var testFiles = [];
  files.forEach(function (f) {
    var files = glob.sync(f, {
      cwd: options.cwd
    });
    files.forEach(function (file) {
      testFiles.push(path.join(options.cwd, file));
    });
  });

  var status = runTests(testFiles, options);

  if (options.watch === true) {
    var watchFiles = [];
    if (options.watchFiles.length > 0) {
      options.watchFiles.forEach(function (f) {

        if (/(\*)/.test(f)) {
          var files = glob.sync(f, {
            cwd: options.cwd
          });
          files.forEach(function (file) {
            watchFiles.push(path.join(options.cwd, file));
          });
        } else {
          watchFiles.push(path.join(options.cwd, f));
        }
      });
    } else {
      watchFiles = testFiles;
    }

    log.beginWatch();

    watchr.watch({
      paths: watchFiles,
      listeners: {
        error: function (err) {
          if (err) {
            throw err;
          }
        },
        change: function (changeType, filePath) {
          if (changeType !== 'delete') {
            var status = runTests(testFiles, helpers.merge({watchedRun: true}, options));
          }
        }
      },
      next: function (err, watchers) {
        if (err) {
          throw err;
        }
      }
    })
  }

  return status;
};
<commit_msg>fix weird edge case causing watching to stop<commit_after>var path = require('path');
var helpers = require('./helpers');
var log = require('./log');
var glob = require('glob');
var watchr = require('watchr');
var decache = require('decache');

function requireHook(hook, extraPath) {
  if (! extraPath) {
    extraPath = '';
  }

  if (typeof hook === 'object') {
    var hookPath = hook.path;
    delete hook.path;

    require(path.join(extraPath, hookPath))(hook);
    hook.path = hookPath;
  } else {
    require(path.join(extraPath, hook));
  }
}

function runTests(paths, options) {
  log.begin(options);

  if (options.compiler) {
    requireHook(options.compiler);
  }

  if (options.before) {
    requireHook(options.before, options.cwd);
  }

  paths.forEach(function (file) {
    if (options.watch) {
      helpers.uncache(file);
    }
    require(file);
  });

  if (options.after) {
    requireHook(options.after, options.cwd);
  }

  return log.finish();
}

module.exports = function (files, options) {
  options = helpers.merge({
    before: null,
    after: null,
    reporter: './reporters/dot',
    cwd: process.cwd(),
    compiler: null,
    watch: false,
    watchFiles: []
  }, options);

  var testFiles = [];
  files.forEach(function (f) {
    var files = glob.sync(f, {
      cwd: options.cwd
    });
    files.forEach(function (file) {
      testFiles.push(path.join(options.cwd, file));
    });
  });

  var status = runTests(testFiles, options);

  if (options.watch === true) {
    var watchFiles = [];
    if (options.watchFiles.length > 0) {
      options.watchFiles.forEach(function (f) {

        if (/(\*)/.test(f)) {
          var files = glob.sync(f, {
            cwd: options.cwd
          });
          files.forEach(function (file) {
            watchFiles.push(path.join(options.cwd, file));
          });
        } else {
          watchFiles.push(path.join(options.cwd, f));
        }
      });
    } else {
      watchFiles = testFiles;
    }

    log.beginWatch();

    watchr.watch({
      paths: watchFiles,
      listeners: {
        error: function (err) {
          if (err) {
            throw err;
          }
        },
        change: function (changeType, filePath) {
          if (changeType !== 'delete') {
            var status = runTests(testFiles, helpers.merge({watchedRun: true}, options));
          }
        }
      },
      next: function (err, watchers) {
        if (err) {
          throw err;
        }
      }
    })
  }

  return status;
};
<|endoftext|>


<commit_before>// Copyright 2013 Bobby Powers. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

// XXX: this sim module can't depend on the model module, as model
// imports sim, and we don't want circular dependencies.
define(['./util', './vars', './common'], function(util, vars, common) {

    var tmpl = "\n\
importScripts('{{&importURL}}');\n\
\n\
var {{&name}}Initials = {{&initialVals}};\n\
\n\
var {{&name}}Timespec = {{&timespecVals}};\n\
\n\
var {{&className}} = function {{&className}}(name, coord) {\n\
    this.init(name, coord, {{&name}}Initials, {{&name}}Timespec);\n\
};\n\
{{&className}}.prototype = new Simulation();\n\
{{&className}}.prototype.calcInitial = function(dt) {\n\
    {{&calcI}}\n\
};\n\
{{&className}}.prototype.calcFlows = function(dt) {\n\
    this.curr['births'] = this.curr['population'] * this.curr['birth_rate']\n\
    this.curr['deaths'] = this.curr['population'] / this.curr['average_lifespan']\n\
};\n\
{{&className}}.prototype.calcStocks = function(dt) {\n\
    {{&calcS}}\n\
};\n\
\n\
var main = new {{&className}}('main', coord);\n\
\n\
var cmds = initCmds(coord, main);\n\
\n\
onmessage = handleMessage;\n\
";

    var Sim = function Sim(model) {
        this.model = model;
        this.seq = 1; // message id sequence
        this.promised = {}; //callback storage, keyed by message id
        var initials = {};
        var ci = [], cv = [], cs = [];
        var i, v, n;
        for (i = 0; i < model.initials.length; i++) {
            v = model.initials[i];
            n = util.eName(v.name);
            initials[n] = v.eqn;
            ci.push("this.curr['" + n + "'] = " + vars.Variable.prototype.equation.apply(v) + ';');
        }
        for (i = 0; i < model.stocks.length; i++) {
            v = model.stocks[i];
            n = util.eName(v.name);
            initials[n] = v.eqn;
            cs.push("this.next['" + n + "'] = " + v.equation() + ';');
        }
        var name = util.eName(model.name);
        var source = Mustache.render(tmpl, {
            'importURL': window.location.origin + '/js/runtime.js',
            'name': name,
            'className': util.titleCase(name),
            'initialVals': JSON.stringify(initials, null, '\t'),
            'timespecVals': JSON.stringify(model.timespec, null, '\t'),
            'calcI': ci.join('\n    '),
            'calcS': cs.join('\n    '),
        });
        var blob = new Blob([source], {type: 'text/javascript'});
        this.worker = new Worker(window.URL.createObjectURL(blob));
        var s = this;
        this.worker.addEventListener('message', function(e) {
            var id = e.data[0];
            var result = e.data[1];
            var deferred = s.promised[id];
            delete s.promised[id];
            if (deferred) {
                if (result[1])
                    deferred.reject(result[1]);
                else
                    deferred.resolve(result[0]);
            }
        });
    }
    Sim.prototype._post = function() {
        var id = this.seq++;
        var args = [id];
        var i;
        for (i = 0; i < arguments.length; i++)
            args.push(arguments[i]);

        var deferred = Q.defer();
        this.promised[id] = deferred;
        this.worker.postMessage(args);
        return deferred.promise;
    }
    Sim.prototype.close = function() {
        this.worker.terminate();
        this.worker = null;
    }
    Sim.prototype.setValue = function(name, val) {
        return this._post('set_val', name, val);
    }
    Sim.prototype.value = function() {
        args = ['get_val'].concat(Array.prototype.slice.call(arguments));
        return this._post.apply(this, args);
    }
    Sim.prototype.series = function() {
        args = ['get_series'].concat(Array.prototype.slice.call(arguments));
        return this._post.apply(this, args);
    }
    Sim.prototype.runTo = function(time) {
        return this._post('run_to', time);
    }
    Sim.prototype.runToEnd = function() {
        return this._post('run_to_end');
    }

    return {
        'Sim': Sim,
    };
});
<commit_msg>sim: full template<commit_after>// Copyright 2013 Bobby Powers. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

// XXX: this sim module can't depend on the model module, as model
// imports sim, and we don't want circular dependencies.
define(['./util', './vars', './common', './lex'], function(util, vars, common, lex) {

    var tmpl = "\n\
importScripts('{{&importURL}}');\n\
\n\
var {{&name}}Initials = {{&initialVals}};\n\
\n\
var {{&name}}Timespec = {{&timespecVals}};\n\
\n\
var {{&className}} = function {{&className}}(name, coord) {\n\
    this.init(name, coord, {{&name}}Initials, {{&name}}Timespec);\n\
};\n\
{{&className}}.prototype = new Simulation();\n\
{{&className}}.prototype.calcInitial = function(dt) {\n\
    {{&calcI}}\n\
};\n\
{{&className}}.prototype.calcFlows = function(dt) {\n\
    {{&calcF}}\n\
};\n\
{{&className}}.prototype.calcStocks = function(dt) {\n\
    {{&calcS}}\n\
};\n\
\n\
var main = new {{&className}}('main', coord);\n\
\n\
var cmds = initCmds(coord, main);\n\
\n\
onmessage = handleMessage;\n\
";

    var varEqn = function(v) {
        const scanner = new lex.Scanner(v.eqn);
        const result = [];
        var tok;
        while ((tok = scanner.getToken())) {
            if (tok.type !== lex.IDENT || tok.tok in common.builtins)
                result.push(tok.tok);
            else
                result.push("this.curr['" + tok.tok + "']")
        }
        return result.join(' ');
    }

    var Sim = function Sim(model) {
        this.model = model;
        this.seq = 1; // message id sequence
        this.promised = {}; //callback storage, keyed by message id
        var initials = {};
        var ci = [], cf = [], cs = [];
        var i, v, n;
        for (i = 0; i < model.initials.length; i++) {
            v = model.initials[i];
            n = util.eName(v.name);
            initials[n] = v.eqn;
            ci.push("this.curr['" + n + "'] = " + vars.Variable.prototype.equation.apply(v) + ';');
        }
        for (i = 0; i < model.flows.length; i++) {
            v = model.flows[i];
            n = util.eName(v.name);
            cf.push("this.curr['" + n + "'] = " + varEqn(v) + ';');
        }
        for (i = 0; i < model.stocks.length; i++) {
            v = model.stocks[i];
            n = util.eName(v.name);
            cs.push("this.next['" + n + "'] = " + v.equation() + ';');
        }
        var name = util.eName(model.name);
        var source = Mustache.render(tmpl, {
            'importURL': window.location.origin + '/js/runtime.js',
            'name': name,
            'className': util.titleCase(name),
            'initialVals': JSON.stringify(initials, null, '\t'),
            'timespecVals': JSON.stringify(model.timespec, null, '\t'),
            'calcI': ci.join('\n    '),
            'calcF': cf.join('\n    '),
            'calcS': cs.join('\n    '),
        });
        var blob = new Blob([source], {type: 'text/javascript'});
        this.worker = new Worker(window.URL.createObjectURL(blob));
        var s = this;
        this.worker.addEventListener('message', function(e) {
            var id = e.data[0];
            var result = e.data[1];
            var deferred = s.promised[id];
            delete s.promised[id];
            if (deferred) {
                if (result[1])
                    deferred.reject(result[1]);
                else
                    deferred.resolve(result[0]);
            }
        });
    }
    Sim.prototype._post = function() {
        var id = this.seq++;
        var args = [id];
        var i;
        for (i = 0; i < arguments.length; i++)
            args.push(arguments[i]);

        var deferred = Q.defer();
        this.promised[id] = deferred;
        this.worker.postMessage(args);
        return deferred.promise;
    }
    Sim.prototype.close = function() {
        this.worker.terminate();
        this.worker = null;
    }
    Sim.prototype.setValue = function(name, val) {
        return this._post('set_val', name, val);
    }
    Sim.prototype.value = function() {
        args = ['get_val'].concat(Array.prototype.slice.call(arguments));
        return this._post.apply(this, args);
    }
    Sim.prototype.series = function() {
        args = ['get_series'].concat(Array.prototype.slice.call(arguments));
        return this._post.apply(this, args);
    }
    Sim.prototype.runTo = function(time) {
        return this._post('run_to', time);
    }
    Sim.prototype.runToEnd = function() {
        return this._post('run_to_end');
    }

    return {
        'Sim': Sim,
    };
});
<|endoftext|>


<commit_before>var events = require('events');
var util = require('util');

var _ = require('lodash');
var logging = require('omega-logger');
var pg = require('pg');
var Promise = require('bluebird');

// --------------------------------------------------------------------------------------------------------------------

var logger = logging.loggerFor(module);

// --------------------------------------------------------------------------------------------------------------------

/**
 * Connect to the given database.
 *
 * @todo Document parameters.
 */
function connect(connectionInfo)
{
    return new Promise(function(resolve, reject)
    {
        pg.connect(connectionInfo, function(error, client, done)
        {
            if(error)
            {
                logger.error("Error connecting to %j: %s", connectionInfo, error.stack || error);

                return reject(error);
            } // end if

            logger.info("Connected to %j", connectionInfo);

            resolve(new Connection(client, done));
        }); // end pg.connect callback
    }); // end Promise callback
} // end connect

// --------------------------------------------------------------------------------------------------------------------

/**
 * Wraps a PostgreSQL connection.
 *
 * @param {pg.Client} client - the `node-postgres` client
 * @param {function} done - the function to release the client to the `node-postgres` pool
 */
function Connection(client, done)
{
    this.client = client;
    this.done = done;
} // end Connection

util.inherits(Connection, events.EventEmitter);

/**
 * The definition of a PostgreSQL query.
 *
 * @typedef {object} Connection#QueryDef
 * @see {@link https://github.com/brianc/node-postgres/wiki/Prepared-Statements}
 *
 * @property {*} queryID - the ID of the query (an arbitrary value provided by the client)
 * @property {string} [name] - if supplied, creates or uses a prepared statement with the given name
 * @property {string} [text] - the text of the SQL query to run or prepare (required unless using a prepared statement)
 * @property {Array} [values] - the values of the query parameters
 */

/**
 * A row has been generated by a database query.
 *
 * @event Connection#row
 *
 * @param {*} queryID - the ID of the query that generated this row
 * @param {object} row - the row
 */

/**
 * An error occurred on this connection.
 *
 * @event Connection#error
 *
 * @param {object} error - the error that occurred
 */

/**
 * "Close" this connection.
 *
 * Actually, this releases the underlying client back to the to the `node-postgres` pool.
 */
Connection.prototype.close = function()
{
    this.done();

    delete this.client;
    delete this.done;
}; // end Connection#close

/**
 * Execute a query on this PostgreSQL connection.
 *
 * @param {Connection#QueryDef} queryDef - the definition of the query to run
 *
 * @returns {Promise.<{rows: number, affected: number}>} - a promise for the statistics of the query once it's finished
 */
Connection.prototype.query = function(queryDef)
{
    var self = this;

    var queryID = queryDef.queryID;
    delete queryDef.queryID;
    queryDef.rowMode = "array";

    return new Promise(function(resolve, reject)
    {
        logger.info("Running query %j...", queryID);
        logger.trace("Query %j: %s", queryID, logger.dump(queryDef));

        var startTime = process.hrtime();
        var query = self.client.query(queryDef)
            .on('error', onError)
            .on('row', onRow)
            .on('end', onEnd);

        function onError(error)
        {
            logger.error("Query %j got error: %s", queryID, error.stack || error);

            reject(error);

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onError

        var returnedFields = false;

        function onRow(row, result)
        {
            if(!returnedFields)
            {
                self.emit('fields', queryID, result.fields);
                returnedFields = true;
            } // end if

            result.returnedRowCount = (result.returnedRowCount || 0) + 1;

            self.emit('row', queryID, row);
        } // end onRow

        function onEnd(result)
        {
            var totalTime = process.hrtime(startTime);
            var totalTimeMS = totalTime[0] * 1e3 + totalTime[1] / 1e6;

            result.returnedRowCount = result.returnedRowCount || 0;

            logger.info("Query %j finished. (%s row%s returned, %s row%s affected)", queryID,
                result.returnedRowCount, result.returnedRowCount == 1 ? '' : 's',
                result.rowCount, result.rowCount == 1 ? '' : 's'
            );
            logger.trace("result: %s", logger.dump(result));

            if(!returnedFields)
            {
                self.emit('fields', queryID, result.fields);
                returnedFields = true;
            } // end if

            resolve(_.assign({ rows: result.returnedRowCount, affected: result.rowCount, totalTimeMS: totalTimeMS },
                _.omit(result, 'returnedRowCount', 'rowCount')));

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onEnd
    }); // end Promise callback
}; // end Connection#query

// --------------------------------------------------------------------------------------------------------------------

module.exports = {
    connect: connect,
    Connection: Connection
};
<commit_msg>Discover data types at connection time, and map data type IDs to names in 'fields' events.<commit_after>var events = require('events');
var util = require('util');

var _ = require('lodash');
var logging = require('omega-logger');
var pg = require('pg');
var Promise = require('bluebird');

// --------------------------------------------------------------------------------------------------------------------

var logger = logging.loggerFor(module);

// --------------------------------------------------------------------------------------------------------------------

/**
 * Connect to the given database.
 *
 * @todo Document parameters.
 */
function connect(connectionInfo)
{
    return new Promise(function(resolve, reject)
    {
        pg.connect(connectionInfo, function(error, client, done)
        {
            if(error)
            {
                logger.error("Error connecting to %j: %s", connectionInfo, error.stack || error);

                return reject(error);
            } // end if

            logger.info("Connected to %j", connectionInfo);

            var conn = new Connection(client, done);

            resolve(conn.getTypes().return(conn));
        }); // end pg.connect callback
    }); // end Promise callback
} // end connect

// --------------------------------------------------------------------------------------------------------------------

/**
 * Wraps a PostgreSQL connection.
 *
 * @param {pg.Client} client - the `node-postgres` client
 * @param {function} done - the function to release the client to the `node-postgres` pool
 */
function Connection(client, done)
{
    this.client = client;
    this.done = done;
} // end Connection

util.inherits(Connection, events.EventEmitter);

/**
 * The definition of a PostgreSQL query.
 *
 * @typedef {object} Connection#QueryDef
 * @see {@link https://github.com/brianc/node-postgres/wiki/Prepared-Statements}
 *
 * @property {*} queryID - the ID of the query (an arbitrary value provided by the client)
 * @property {string} [name] - if supplied, creates or uses a prepared statement with the given name
 * @property {string} [text] - the text of the SQL query to run or prepare (required unless using a prepared statement)
 * @property {Array} [values] - the values of the query parameters
 */

/**
 * A row has been generated by a database query.
 *
 * @event Connection#row
 *
 * @param {*} queryID - the ID of the query that generated this row
 * @param {object} row - the row
 */

/**
 * An error occurred on this connection.
 *
 * @event Connection#error
 *
 * @param {object} error - the error that occurred
 */

/**
 * "Close" this connection.
 *
 * Actually, this releases the underlying client back to the to the `node-postgres` pool.
 */
Connection.prototype.close = function()
{
    this.done();

    delete this.client;
    delete this.done;
}; // end Connection#close

Connection.prototype.getTypes = function()
{
    var self = this;
    this.types = {};

    return new Promise(function(resolve, reject)
    {
        var queryDef = {text: "SELECT oid, typname FROM pg_type WHERE typtype = 'b' ORDER BY oid"};
        var query = self.client.query(queryDef)
            .on('error', onError)
            .on('row', onRow)
            .on('end', onEnd);

        function onError(error)
        {
            logger.error("Connection#getTypes got error: %s", error.stack || error);

            reject(error);

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onError

        function onRow(row)
        {
            self.types[row.oid] = row.typname;
        } // end onRow

        function onEnd()
        {
            resolve(self.types);

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onEnd
    });
}; // end Connection#getTypes

/**
 * Execute a query on this PostgreSQL connection.
 *
 * @param {Connection#QueryDef} queryDef - the definition of the query to run
 *
 * @returns {Promise.<{rows: number, affected: number}>} - a promise for the statistics of the query once it's finished
 */
Connection.prototype.query = function(queryDef)
{
    var self = this;

    var queryID = queryDef.queryID;
    delete queryDef.queryID;
    queryDef.rowMode = "array";

    return new Promise(function(resolve, reject)
    {
        logger.info("Running query %j...", queryID);
        logger.trace("Query %j: %s", queryID, logger.dump(queryDef));

        var startTime = process.hrtime();
        var query = self.client.query(queryDef)
            .on('error', onError)
            .on('row', onRow)
            .on('end', onEnd);

        function onError(error)
        {
            logger.error("Query %j got error: %s", queryID, error.stack || error);

            reject(error);

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onError

        var fieldsEmitted = false;
        function emitFields(fields)
        {
            if(!fieldsEmitted)
            {
                self.emit('fields', queryID, fields.map(function(field)
                {
                    field.dataType = self.types[field.dataTypeID];
                    return field;
                }));

                fieldsEmitted = true;
            } // end if
        } // end emitFields

        function onRow(row, result)
        {
            emitFields(result.fields);

            result.returnedRowCount = (result.returnedRowCount || 0) + 1;

            self.emit('row', queryID, row);
        } // end onRow

        function onEnd(result)
        {
            var totalTime = process.hrtime(startTime);
            var totalTimeMS = totalTime[0] * 1e3 + totalTime[1] / 1e6;

            result.returnedRowCount = result.returnedRowCount || 0;

            logger.info("Query %j finished. (%s row%s returned, %s row%s affected)", queryID,
                result.returnedRowCount, result.returnedRowCount == 1 ? '' : 's',
                result.rowCount, result.rowCount == 1 ? '' : 's'
            );
            logger.trace("result: %s", logger.dump(result));

            emitFields(result.fields);

            resolve(_.assign({ rows: result.returnedRowCount, affected: result.rowCount, totalTimeMS: totalTimeMS },
                _.omit(result, 'returnedRowCount', 'rowCount')));

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onEnd
    }); // end Promise callback
}; // end Connection#query

// --------------------------------------------------------------------------------------------------------------------

module.exports = {
    connect: connect,
    Connection: Connection
};
<|endoftext|>


<commit_before>var events = require('events');
var util = require('util');

var pg = require('pg');
var Promise = require('bluebird');

// --------------------------------------------------------------------------------------------------------------------

/**
 * Connect to the given database.
 *
 * @todo Document parameters.
 */
function connect(connectionInfo)
{
    return new Promise(function(resolve, reject)
    {
        pg.connect(connectionInfo, function(error, client, done)
        {
            if(error)
            {
                console.error("Error connecting to %j: %s", connectionInfo, error.stack || error);

                return reject(error);
            } // end if

            console.log("Connected to %j", connectionInfo);

            resolve(new Connection(client, done));
        }); // end pg.connect callback
    }); // end Promise callback
} // end connect

// --------------------------------------------------------------------------------------------------------------------

/**
 * Wraps a PostgreSQL connection.
 *
 * @param {pg.Client} client - the `node-postgres` client
 * @param {function} done - the function to release the client to the `node-postgres` pool
 */
function Connection(client, done)
{
    this.client = client;
    this.done = done;
} // end Connection

util.inherits(Connection, events.EventEmitter);

/**
 * The definition of a PostgreSQL query.
 *
 * @typedef {object} Connection#QueryDef
 * @see {@link https://github.com/brianc/node-postgres/wiki/Prepared-Statements}
 *
 * @property {*} queryID - the ID of the query (an arbitrary value provided by the client)
 * @property {string} [name] - if supplied, creates or uses a prepared statement with the given name
 * @property {string} [text] - the text of the SQL query to run or prepare (required unless using a prepared statement)
 * @property {Array} [values] - the values of the query parameters
 */

/**
 * A row has been generated by a database query.
 *
 * @event Connection#row
 *
 * @param {*} queryID - the ID of the query that generated this row
 * @param {object} row - the row
 */

/**
 * An error occurred on this connection.
 *
 * @event Connection#error
 *
 * @param {object} error - the error that occurred
 */

/**
 * "Close" this connection.
 *
 * Actually, this releases the underlying client back to the to the `node-postgres` pool.
 */
Connection.prototype.close = function()
{
    this.done();

    delete this.client;
    delete this.done;
}; // end Connection#close

/**
 * Execute a query on this PostgreSQL connection.
 *
 * @param {Connection#QueryDef} queryDef - the definition of the query to run
 *
 * @returns {Promise.<{rows: number, affected: number}>} - a promise for the statistics of the query once it's finished
 */
Connection.prototype.query = function(queryDef)
{
    var self = this;

    var queryID = queryDef.queryID;
    delete queryDef.queryID;

    return new Promise(function(resolve, reject)
    {
        console.log("Running query %j: %j", queryID, queryDef);

        self.client.query(queryDef)
            .on('error', function(error)
            {
                console.error("Query %j got error: %s", queryID, error.stack || error);

                reject(error);
            }) // end 'error' handler

            .on('row', function(row, result)
            {
                result.returnedRowCount = (result.returnedRowCount || 0) + 1;

                self.emit('row', queryID, row);
            }) // end 'row' handler

            .on('end', function(result)
            {
                console.log("Query %j finished. (%s row%s returned, %s row%s affected)", queryID,
                    result.returnedRowCount, result.returnedRowCount == 1 ? '' : 's',
                    result.rowCount, result.rowCount == 1 ? '' : 's'
                );

                resolve({ rows: result.returnedRowCount, affected: result.rowCount });
            }); // end 'end' handler

    }); // end Promise callback
}; // end Connection#query

// --------------------------------------------------------------------------------------------------------------------

module.exports = {
    connect: connect,
    Connection: Connection
};
<commit_msg>Restructured and cleaned up event handling in lib/sql.js.<commit_after>var events = require('events');
var util = require('util');

var logging = require('omega-logger');
var pg = require('pg');
var Promise = require('bluebird');

// --------------------------------------------------------------------------------------------------------------------

var logger = logging.loggerFor(module);

// --------------------------------------------------------------------------------------------------------------------

/**
 * Connect to the given database.
 *
 * @todo Document parameters.
 */
function connect(connectionInfo)
{
    return new Promise(function(resolve, reject)
    {
        pg.connect(connectionInfo, function(error, client, done)
        {
            if(error)
            {
                logger.error("Error connecting to %j: %s", connectionInfo, error.stack || error);

                return reject(error);
            } // end if

            logger.info("Connected to %j", connectionInfo);

            resolve(new Connection(client, done));
        }); // end pg.connect callback
    }); // end Promise callback
} // end connect

// --------------------------------------------------------------------------------------------------------------------

/**
 * Wraps a PostgreSQL connection.
 *
 * @param {pg.Client} client - the `node-postgres` client
 * @param {function} done - the function to release the client to the `node-postgres` pool
 */
function Connection(client, done)
{
    this.client = client;
    this.done = done;
} // end Connection

util.inherits(Connection, events.EventEmitter);

/**
 * The definition of a PostgreSQL query.
 *
 * @typedef {object} Connection#QueryDef
 * @see {@link https://github.com/brianc/node-postgres/wiki/Prepared-Statements}
 *
 * @property {*} queryID - the ID of the query (an arbitrary value provided by the client)
 * @property {string} [name] - if supplied, creates or uses a prepared statement with the given name
 * @property {string} [text] - the text of the SQL query to run or prepare (required unless using a prepared statement)
 * @property {Array} [values] - the values of the query parameters
 */

/**
 * A row has been generated by a database query.
 *
 * @event Connection#row
 *
 * @param {*} queryID - the ID of the query that generated this row
 * @param {object} row - the row
 */

/**
 * An error occurred on this connection.
 *
 * @event Connection#error
 *
 * @param {object} error - the error that occurred
 */

/**
 * "Close" this connection.
 *
 * Actually, this releases the underlying client back to the to the `node-postgres` pool.
 */
Connection.prototype.close = function()
{
    this.done();

    delete this.client;
    delete this.done;
}; // end Connection#close

/**
 * Execute a query on this PostgreSQL connection.
 *
 * @param {Connection#QueryDef} queryDef - the definition of the query to run
 *
 * @returns {Promise.<{rows: number, affected: number}>} - a promise for the statistics of the query once it's finished
 */
Connection.prototype.query = function(queryDef)
{
    var self = this;

    var queryID = queryDef.queryID;
    delete queryDef.queryID;

    return new Promise(function(resolve, reject)
    {
        logger.info("Running query %j...", queryID);
        logger.trace("Query %j: %s", queryID, logger.dump(queryDef));

        var query = self.client.query(queryDef)
            .on('error', onError)
            .on('row', onRow)
            .on('end', onEnd);

        function onError(error)
        {
            logger.error("Query %j got error: %s", queryID, error.stack || error);

            reject(error);

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onError

        function onRow(row, result)
        {
            result.returnedRowCount = (result.returnedRowCount || 0) + 1;

            self.emit('row', queryID, row);
        } // end onRow

        function onEnd(result)
        {
            logger.info("Query %j finished. (%s row%s returned, %s row%s affected)", queryID,
                result.returnedRowCount, result.returnedRowCount == 1 ? '' : 's',
                result.rowCount, result.rowCount == 1 ? '' : 's'
            );
            logger.trace("result: %s", logger.dump(result));

            resolve({ rows: result.returnedRowCount, affected: result.rowCount });

            query
                .removeListener('error', onError)
                .removeListener('row', onRow)
                .removeListener('end', onEnd);
        } // end onEnd
    }); // end Promise callback
}; // end Connection#query

// --------------------------------------------------------------------------------------------------------------------

module.exports = {
    connect: connect,
    Connection: Connection
};
<|endoftext|>


<commit_before>var ipc = require('node-ipc');
var utils = require('./utils');
var configs = require('./beacon-configs');

var remoteIPC = new ipc.IPC();
configs.configureRemoteIPC(remoteIPC);
ipc.klyngRemote = remoteIPC;

/*
 * connects to a remote beacon via ip:port
 * @param ip {String}
 * @param port {Number}
 * @return {Promise}: promise of the connection to be made
 */
 function connectTo(ip, port) {
     return new Promise(function(resolve, reject) {
         var id = "sock_" + ip + ":" + port;

         remoteIPC.connectToNet(id, ip, port, function() {
             remoteIPC.of[id].on('connect', function() {
                 resolve(remoteIPC.of[id]);
             });

             remoteIPC.of[id].on('error', function(error) {
                if(remoteIPC.of[id].retriesRemaining === 0) {
                    reject(error);
                }
             });
         });
     });
 }

 /*
  * disconnects from a remote beacon identified by ip:port
  * @param ip {String}
  * @param port {Number}
  */
  function disconnectFrom(ip, port) {
      var id = "sock_" + ip + ":" + port;
      remoteIPC.disconnect(id);
  }

  /*
   * carries the key exchange process between the communicating nodes
   * @param connection {Socket}: the socket to between the nodes
   * @return {Promise}: a promise of the shared secret
   */
  function exchangeKeyOver(connection) {
      return new Promise(function(resolve, reject) {
          var dhObj = utils.diffieHellman();
          var sharedPrime = dhObj.prime;
          var publicKey = dhObj.publicKey;

          connection.emit('KEY-EXT:PARAMS', {prime: sharedPrime, key: publicKey});
          connection.on('KEY-EXT:PUBLIC', function(data) {
              var sharedSecret = dhObj.computeSecret(data.key);
              resolve({connection: connection, secret: sharedSecret});
          });
      });
  }

  /*
   * authenticates and authorize access to remote node with password
   * @param connection {Socket}: the socket connecting to the remote node
   * @param secret {String}: the encryption seceret key
   * @param passwd {String}: the remote node password
   */
  function authOver(connection, secret, passwd) {
     return new Promise(function(resolve, reject) {
         connection.emit('AUTH', utils.secure({data: passwd}, secret));
         connection.on('AUTH:STATUS', function(data) {
             resolve({connection: connection, secret: secret, status: data.status});
         });
     });
  }

  /*
   * sends a job descriptor securly to a remote beacon over a given connection
   * @param connection {Socket}: the socket connection to the remote node
   * @param secret {String}: the encryption secret key
   * @param job {Object}: the job descriptor object
   * @param plan {Object}: the job plan object
   * @return {Promise}
  */
  function sendJobOver(connection, secret, job, plan) {
      return new Promise(function(resolve, reject) {

          var target_params = connection.path + "@" + connection.port;
          var modified_plan = {};

          for(var host in plan) {
              if(host === "local") {
                  // replace local with parent to refer to the parent node in target node
                  modified_plan.parent = plan.local;
              }
              else if(host === target_params) {
                  // replace the target node params in the plan with local
                  modified_plan.local = plan[host];
              }
              else {
                  // keep irrelevant hosts intact
                  modified_plan[host] = plan[host];
              }
          }

          job.plan = modified_plan;

          connection.emit('KLYNG:JOB', utils.secure({data: job}, secret));
          connection.on('JOB:ACK', function(data) {
              if(!data.status) {
                  reject(new Error(data.error));
              }
              else {
                  resolve(true);
              }
          });
      });
  }

  module.exports = {
      connectTo: connectTo,
      disconnectFrom: disconnectFrom,
      exchangeKeyOver: exchangeKeyOver,
      authOver: authOver,
      sendJobOver: sendJobOver
  };
<commit_msg>removed excess indtations<commit_after>var ipc = require('node-ipc');
var utils = require('./utils');
var configs = require('./beacon-configs');

var remoteIPC = new ipc.IPC();
configs.configureRemoteIPC(remoteIPC);
ipc.klyngRemote = remoteIPC;

/*
 * connects to a remote beacon via ip:port
 * @param ip {String}
 * @param port {Number}
 * @return {Promise}: promise of the connection to be made
 */
function connectTo(ip, port) {
    return new Promise(function(resolve, reject) {
        var id = "sock_" + ip + ":" + port;

        remoteIPC.connectToNet(id, ip, port, function() {
            remoteIPC.of[id].on('connect', function() {
                resolve(remoteIPC.of[id]);
            });

            remoteIPC.of[id].on('error', function(error) {
                if(remoteIPC.of[id].retriesRemaining === 0) {
                    reject(error);
                }
            });
        });
    });
}

/*
 * disconnects from a remote beacon identified by ip:port
 * @param ip {String}
 * @param port {Number}
 */
function disconnectFrom(ip, port) {
    var id = "sock_" + ip + ":" + port;
    remoteIPC.disconnect(id);
}

/*
 * carries the key exchange process between the communicating nodes
 * @param connection {Socket}: the socket to between the nodes
 * @return {Promise}: a promise of the shared secret
 */
function exchangeKeyOver(connection) {
    return new Promise(function(resolve, reject) {
        var dhObj = utils.diffieHellman();
        var sharedPrime = dhObj.prime;
        var publicKey = dhObj.publicKey;

        connection.emit('KEY-EXT:PARAMS', {prime: sharedPrime, key: publicKey});
        connection.on('KEY-EXT:PUBLIC', function(data) {
            var sharedSecret = dhObj.computeSecret(data.key);
            resolve({connection: connection, secret: sharedSecret});
        });
    });
}

/*
 * authenticates and authorize access to remote node with password
 * @param connection {Socket}: the socket connecting to the remote node
 * @param secret {String}: the encryption seceret key
 * @param passwd {String}: the remote node password
 */
function authOver(connection, secret, passwd) {
    return new Promise(function(resolve, reject) {
        connection.emit('AUTH', utils.secure({data: passwd}, secret));
        connection.on('AUTH:STATUS', function(data) {
            resolve({connection: connection, secret: secret, status: data.status});
        });
    });
}

/*
 * sends a job descriptor securly to a remote beacon over a given connection
 * @param connection {Socket}: the socket connection to the remote node
 * @param secret {String}: the encryption secret key
 * @param job {Object}: the job descriptor object
 * @param plan {Object}: the job plan object
 * @return {Promise}
 */
function sendJobOver(connection, secret, job, plan) {
    return new Promise(function(resolve, reject) {

        var target_params = connection.path + "@" + connection.port;
        var modified_plan = {};

        for(var host in plan) {
            if(host === "local") {
                // replace local with parent to refer to the parent node in target node
                modified_plan.parent = plan.local;
            }
            else if(host === target_params) {
                // replace the target node params in the plan with local
                modified_plan.local = plan[host];
            }
            else {
                // keep irrelevant hosts intact
                modified_plan[host] = plan[host];
            }
        }

        job.plan = modified_plan;

        connection.emit('KLYNG:JOB', utils.secure({data: job}, secret));
        connection.on('JOB:ACK', function(data) {
            if(!data.status) {
                reject(new Error(data.error));
            }
            else {
                resolve(true);
            }
        });
    });
}

module.exports = {
    connectTo: connectTo,
    disconnectFrom: disconnectFrom,
    exchangeKeyOver: exchangeKeyOver,
    authOver: authOver,
    sendJobOver: sendJobOver
};
<|endoftext|>