<commit_before>window.cls = window.cls || {};
cls.ResourceUtil = {}
/**
 * Utility class with static members and methods for the resource and network
 * views.
 */

/**
 * Return a human readable string representation of n bytes
 */
cls.ResourceUtil.bytes_to_human_readable = function(bytes)
{
  var numformatter = String
  if (window.helpers && window.helpers.pretty_print_number)
  {
    numformatter = window.helpers.pretty_print_number;
  }
  if (bytes >= 1048576) // megabytes
  {
    return "" + numformatter((bytes / 1048576).toFixed(2)) + "MB";
  }
  else if (bytes >= 10240)
  {
    return "" + numformatter(Math.ceil((bytes / 1024))) + "KB";
  }
  else
  {
    return "" + numformatter(bytes) + "B";
  }
}

/**
 * Return a human readable string representation of n millis
 */
cls.ResourceUtil.millis_to_human_readable = function(millis)
{
  if (millis > 10000) // > 10 seconds
  {
    return "" + ((millis / 1000).toFixed(1)) + "s";
  }
  else if (millis > 1000) // > 1 second
  {
    return "" + (millis / 1000).toFixed(2) + "s";
  }
  else
  {
    return "" + millis + "ms";
  }
}

/**
 * Common extensions mapped to generic type strings
 */
cls.ResourceUtil.extension_type_map = {
  png: "image",
  jpg: "image",
  bmp: "image",
  pcx: "image",
  ico: "image",
  jpeg: "image",

  oex: "extension",

  otf: "font",
  ttf: "font",
}

/**
 * Common mime types mapped to more generic strings
 */
cls.ResourceUtil.mime_type_map = {
  "text/html": "markup",
  "application/xhtml+xml": "markup",
  "application/mathml+xml": "markup",
  "application/xslt+xml": "markup",
  "text/xsl": "markup",
  "application/xml": "markup",

  "text/css": "css",

  "text/plain": "text",

  "application/x-javascript": "script",
  "application/javascript": "script",
  "text/javascript": "script",
  "application/json": "script",

  "image/png": "image",
  "image/gif": "image",
  "image/jpeg": "image",
  "image/x-icon": "image",
  "image/vnd.microsoft.icon": "image",
  "image/svg+xml": "image",
  "image/vnd.wap.wbmp": "image",

  "application/vnd.ms-fontobject": "font",
  "application/x-font-ttf": "font",
  "font/ttf": "font",
  "font/otf": "font",
  "font/opentype": "font",
  "application/x-woff": "font",

  "audio/mid": "audio",
  "audio/mpeg": "audio",
  "audio/ogg": "audio",
  "audio/vorbis": "audio",
  "audio/x-pn-realaudio": "audio",
  "audio/wav": "audio",
  "audio/x-wav": "audio",
  "audio/vnd.wave": "audio",
  "audio/x-ms-wax": "audio",
  "audio/x-ms-wma": "audio",

  "video/3gpp": "video",
  "video/x-matroska": "video",
  "video/mp4": "video",
  "video/mpeg": "video",
  "video/ogg": "video",
  "video/quicktime": "video",
  "video/webm": "video",
  "video/x-ms-wmv": "video",

  "application/rdf+xml": "data",
  "text/rdf+n3": "data",
  "application/x-turtle": "data",
  "text/turtle": "data",

  "application/atom+xml": "feed",
  "application/rss+xml": "feed",

  "application/pdf": "pdf",
  "application/postscript": "postscript",
  "application/x-shockwave-flash": "flash",
  "application/x-silverlight-app": "silverlight"
}

/**
 * Returns the most sensible way of getting this resource,
 * as datauri or string, based on the mime type.
 */
cls.ResourceUtil.mime_to_content_mode = function(mime)
{
  var type = cls.ResourceUtil.mime_to_type(mime);
  switch (type) {
    case "image":
    case "pdf":
    case "flash":
    case "font":
      return "datauri";
    case "markup":
    case "css":
    case "xml":
    case "script":
      return "text";
  }
  return "text";
}

cls.ResourceUtil.mime_to_type = function(mime, extension)
{
  return this.mime_type_map[mime];
}

cls.ResourceUtil.path_to_type = function(path)
{
  var extension = path.slice(path.lastIndexOf(".") + 1);
}

cls.ResourceUtil.url_path = function(url)
{
  if (!url) { return null; }
  var firstslash = url.replace("://", "xxx").indexOf("/");
  var querystart = url.indexOf("?");
  if (querystart == -1) { querystart = url.length; }
  var path = url.slice(firstslash, querystart);
  return path;
}

cls.ResourceUtil.url_filename = function(url)
{
  var path = cls.ResourceUtil.url_path(url);
  var lastslash = path.lastIndexOf("/");
  if (lastslash < 1) // 0 and -1 both mean there is no file name
  {
    return null;
  }
  else {
    return path.slice(lastslash+1);
  }
}

cls.ResourceUtil.url_host = function(url)
{
  if (!url) { return null; }
  var host = url.replace(/\w+?:\/\//, "");
  var firstslash = host.indexOf("/");
  host = host.slice(0, firstslash == -1 ? host.length : firstslash);
  return host;
}

cls.ResourceUtil.header_presets = [
  {name: "None", headers: ""},
  {name: "Chrome 9", headers:
    [
      "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
      "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3",
      "Accept-Encoding: gzip,deflate,sdch",
      "Accept-Language: en-GB,en-US;q=0.8,fr;q=0.6,en;q=0.4",
      "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13",
    ].join("\n")
  },
  {name: "Firefox 4 beta 11", headers:
    [
      "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
      "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7",
      "Accept-Encoding: gzip,deflate,sdch",
      "Accept-Language: en-gb,en;q=0.5",
      "Connection: keep-alive",
      "Keep-Alive: 115",
      "User-Agent: Mozilla/5.0 (Windows NT 6.0; rv:2.0b11) Gecko/20100101 Firefox/4.0b11",
    ].join("\n")
  },
  {name: "IE8 (compatibility mode)", headers:
    [
      "Accept: */*",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; chromeframe; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MDDC; .NET CLR 3.5.30729; .NET CLR 1.1.4322; .NET CLR 3.0.30729; .NET4.0C)",
    ].join("\n")
  },
  {name: "IE8", headers:
    [
      "Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-shockwave-flash, */*",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; chromeframe; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MDDC; .NET CLR 3.5.30729; .NET CLR 1.1.4322; .NET CLR 3.0.30729; .NET4.0C)",
    ].join("\n")
  },
  {name: "IE9 platform preview", headers:
    [
      "Accept: text/html, application/xhtml+xml",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)",
    ].join("\n")
  },
  {name: "Opera 11.01", headers:
    [
      "Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1",
      "Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1",
      "Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0",
      "Accept-Language: en-gb,en;q=0.9",
      "Connection: Keep-Alive, TE",
      "Keep-Alive: 115",
      "Transfer-Encoding: deflate, gzip, chunked, identity, trailers",
      "User-Agent: Opera/9.80 (Windows NT 6.0; U; en-GB) Presto/2.7.62 Version/11.01",
    ].join("\n")
  },
  {name: "Safari 5", headers:
    [
      "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-us",
      "Connection: keep-alive",
      "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
    ].join("\n")
  },
];
// copied from python's httplib.responses
cls.ResourceUtil.http_status_codes = {
  200: 'OK', 201: 'Created', 202: 'Accepted',
  203: 'Non-Authoritative Information', 204: 'No Content',
  205: 'Reset Content', 206: 'Partial Content', 400: 'Bad Request',
  401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden',
  404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable',
  407: 'Proxy Authentication Required', 408: 'Request Timeout',
  409: 'Conflict', 410: 'Gone', 411: 'Length Required',
  412: 'Precondition Failed', 413: 'Request Entity Too Large',
  414: 'Request-URI Too Long', 415: 'Unsupported Media Type',
  416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed',
  418: 'I\'m a teapot', 100: 'Continue', 101: 'Switching Protocols',
  300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found',
  303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy', 306: '(Unused)',
  307: 'Temporary Redirect', 500: 'Internal Server Error',
  501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service Unavailable',
  504: 'Gateway Timeout', 505: 'HTTP Version Not Supported'
}<commit_msg>Fixed formatting and a bug in detection of kilobytes<commit_after>window.cls = window.cls || {};
cls.ResourceUtil = {}
/**
 * Utility class with static members and methods for the resource and network
 * views.
 */

/**
 * Return a human readable string representation of n bytes
 */
cls.ResourceUtil.bytes_to_human_readable = function(bytes)
{
  var numformatter = String
  if (window.helpers && window.helpers.pretty_print_number)
  {
    numformatter = window.helpers.pretty_print_number;
  }
  if (bytes >= 1048576) // megabytes
  {
    return "" + numformatter((bytes / 1048576).toFixed(2)) + " Mb";
  }
  else if (bytes >= 1024)
  {
    return "" + numformatter(Math.ceil((bytes / 1024))) + " kb";
  }
  else
  {
    return "" + numformatter(bytes) + " B";
  }
}

/**
 * Return a human readable string representation of n millis
 */
cls.ResourceUtil.millis_to_human_readable = function(millis)
{
  if (millis > 10000) // > 10 seconds
  {
    return "" + ((millis / 1000).toFixed(1)) + " s";
  }
  else if (millis > 1000) // > 1 second
  {
    return "" + (millis / 1000).toFixed(2) + " s";
  }
  else
  {
    return "" + millis + " ms";
  }
}

/**
 * Common extensions mapped to generic type strings
 */
cls.ResourceUtil.extension_type_map = {
  png: "image",
  jpg: "image",
  bmp: "image",
  pcx: "image",
  ico: "image",
  jpeg: "image",

  oex: "extension",

  otf: "font",
  ttf: "font",
}

/**
 * Common mime types mapped to more generic strings
 */
cls.ResourceUtil.mime_type_map = {
  "text/html": "markup",
  "application/xhtml+xml": "markup",
  "application/mathml+xml": "markup",
  "application/xslt+xml": "markup",
  "text/xsl": "markup",
  "application/xml": "markup",

  "text/css": "css",

  "text/plain": "text",

  "application/x-javascript": "script",
  "application/javascript": "script",
  "text/javascript": "script",
  "application/json": "script",

  "image/png": "image",
  "image/gif": "image",
  "image/jpeg": "image",
  "image/x-icon": "image",
  "image/vnd.microsoft.icon": "image",
  "image/svg+xml": "image",
  "image/vnd.wap.wbmp": "image",

  "application/vnd.ms-fontobject": "font",
  "application/x-font-ttf": "font",
  "font/ttf": "font",
  "font/otf": "font",
  "font/opentype": "font",
  "application/x-woff": "font",

  "audio/mid": "audio",
  "audio/mpeg": "audio",
  "audio/ogg": "audio",
  "audio/vorbis": "audio",
  "audio/x-pn-realaudio": "audio",
  "audio/wav": "audio",
  "audio/x-wav": "audio",
  "audio/vnd.wave": "audio",
  "audio/x-ms-wax": "audio",
  "audio/x-ms-wma": "audio",

  "video/3gpp": "video",
  "video/x-matroska": "video",
  "video/mp4": "video",
  "video/mpeg": "video",
  "video/ogg": "video",
  "video/quicktime": "video",
  "video/webm": "video",
  "video/x-ms-wmv": "video",

  "application/rdf+xml": "data",
  "text/rdf+n3": "data",
  "application/x-turtle": "data",
  "text/turtle": "data",

  "application/atom+xml": "feed",
  "application/rss+xml": "feed",

  "application/pdf": "pdf",
  "application/postscript": "postscript",
  "application/x-shockwave-flash": "flash",
  "application/x-silverlight-app": "silverlight"
}

/**
 * Returns the most sensible way of getting this resource,
 * as datauri or string, based on the mime type.
 */
cls.ResourceUtil.mime_to_content_mode = function(mime)
{
  var type = cls.ResourceUtil.mime_to_type(mime);
  switch (type) {
    case "image":
    case "pdf":
    case "flash":
    case "font":
      return "datauri";
    case "markup":
    case "css":
    case "xml":
    case "script":
      return "text";
  }
  return "text";
}

cls.ResourceUtil.mime_to_type = function(mime, extension)
{
  return this.mime_type_map[mime];
}

cls.ResourceUtil.path_to_type = function(path)
{
  var extension = path.slice(path.lastIndexOf(".") + 1);
}

cls.ResourceUtil.url_path = function(url)
{
  if (!url) { return null; }
  var firstslash = url.replace("://", "xxx").indexOf("/");
  var querystart = url.indexOf("?");
  if (querystart == -1) { querystart = url.length; }
  var path = url.slice(firstslash, querystart);
  return path;
}

cls.ResourceUtil.url_filename = function(url)
{
  var path = cls.ResourceUtil.url_path(url);
  var lastslash = path.lastIndexOf("/");
  if (lastslash < 1) // 0 and -1 both mean there is no file name
  {
    return null;
  }
  else {
    return path.slice(lastslash+1);
  }
}

cls.ResourceUtil.url_host = function(url)
{
  if (!url) { return null; }
  var host = url.replace(/\w+?:\/\//, "");
  var firstslash = host.indexOf("/");
  host = host.slice(0, firstslash == -1 ? host.length : firstslash);
  return host;
}

cls.ResourceUtil.header_presets = [
  {name: "None", headers: ""},
  {name: "Chrome 9", headers:
    [
      "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
      "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3",
      "Accept-Encoding: gzip,deflate,sdch",
      "Accept-Language: en-GB,en-US;q=0.8,fr;q=0.6,en;q=0.4",
      "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13",
    ].join("\n")
  },
  {name: "Firefox 4 beta 11", headers:
    [
      "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
      "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7",
      "Accept-Encoding: gzip,deflate,sdch",
      "Accept-Language: en-gb,en;q=0.5",
      "Connection: keep-alive",
      "Keep-Alive: 115",
      "User-Agent: Mozilla/5.0 (Windows NT 6.0; rv:2.0b11) Gecko/20100101 Firefox/4.0b11",
    ].join("\n")
  },
  {name: "IE8 (compatibility mode)", headers:
    [
      "Accept: */*",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; chromeframe; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MDDC; .NET CLR 3.5.30729; .NET CLR 1.1.4322; .NET CLR 3.0.30729; .NET4.0C)",
    ].join("\n")
  },
  {name: "IE8", headers:
    [
      "Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-shockwave-flash, */*",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; chromeframe; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MDDC; .NET CLR 3.5.30729; .NET CLR 1.1.4322; .NET CLR 3.0.30729; .NET4.0C)",
    ].join("\n")
  },
  {name: "IE9 platform preview", headers:
    [
      "Accept: text/html, application/xhtml+xml",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-gb",
      "Connection: Keep-Alive",
      "User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)",
    ].join("\n")
  },
  {name: "Opera 11.01", headers:
    [
      "Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1",
      "Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1",
      "Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0",
      "Accept-Language: en-gb,en;q=0.9",
      "Connection: Keep-Alive, TE",
      "Keep-Alive: 115",
      "Transfer-Encoding: deflate, gzip, chunked, identity, trailers",
      "User-Agent: Opera/9.80 (Windows NT 6.0; U; en-GB) Presto/2.7.62 Version/11.01",
    ].join("\n")
  },
  {name: "Safari 5", headers:
    [
      "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
      "Accept-Encoding: gzip, deflate",
      "Accept-Language: en-us",
      "Connection: keep-alive",
      "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
    ].join("\n")
  },
];
// copied from python's httplib.responses
cls.ResourceUtil.http_status_codes = {
  200: 'OK', 201: 'Created', 202: 'Accepted',
  203: 'Non-Authoritative Information', 204: 'No Content',
  205: 'Reset Content', 206: 'Partial Content', 400: 'Bad Request',
  401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden',
  404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable',
  407: 'Proxy Authentication Required', 408: 'Request Timeout',
  409: 'Conflict', 410: 'Gone', 411: 'Length Required',
  412: 'Precondition Failed', 413: 'Request Entity Too Large',
  414: 'Request-URI Too Long', 415: 'Unsupported Media Type',
  416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed',
  418: 'I\'m a teapot', 100: 'Continue', 101: 'Switching Protocols',
  300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found',
  303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy', 306: '(Unused)',
  307: 'Temporary Redirect', 500: 'Internal Server Error',
  501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service Unavailable',
  504: 'Gateway Timeout', 505: 'HTTP Version Not Supported'
}<|endoftext|>


<commit_before>'use strict'

define([
    'file-saver',
    'src/util/api',
    'src/util/ui',
    './libs'
] , function (fileSaver, API, UI, libs) {

    var SD=libs.SD;
    var CCE=libs.CCE;

    class Nmr1dManager {
        constructor() {
            this.spectra = {};
        }

        handleAction(action) {
            switch (action.name) {
                case 'updateRanges':
                    this.updateIntegrals();
                    break;
                case 'downloadSVG':
                    var blob = new Blob([action.value+""], {type: "application/jcamp-dx;charset=utf-8"});
                    fileSaver(blob, 'spectra.svg');
                    break;
                case 'toggleNMR1hAdvancedOptions':
                    var advancedOptions1H = ! API.cache("nmr1hAdvancedOptions");
                    API.cache("nmr1hAdvancedOptions", advancedOptions1H);
                    if (advancedOptions1H) {
                        API.createData("nmr1hOndeTemplate", API.getData("nmr1hOndeTemplates").full);
                    } else {
                        API.createData("nmr1hOndeTemplate", API.getData("nmr1hOndeTemplates").short);
                    }

                    break;
                case 'resetNMR1d':
                    var type = action.name.replace(/[^0-9]/g,'');

                    type = type + 'd';
                    API.createData('blackNMR' + type, null);
                    API.createData('annotationNMR' + type, null);
                    API.createData('acsNMR' + type, null);
                    break;

                case 'switchNMRLayer': {
                    var layer = API.getActiveLayerName();
                    var goToLayer = action.value.dimension > 1 ? 'nmr2D' : 'Default layer';
                    if(layer !== goToLayer) {
                        API.switchToLayer(goToLayer);
                    }
                    if(action.value.dimension > 1) {
                        API.createData('blackNMR2d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR1d', action.value.jcamp.data);
                    }
                    break;
                }
                case 'executePeakPicking':
                    // Execute pickPeacking button was clicked
                    var currentNmr = API.getData('currentNmr');
                    if (currentNmr.dimension>1) {
                        if (typeof UI != "undefined") {
                            UI.showNotification('Peak picking can only be applied on 1D spectra','warning');
                        }
                        return;
                    }
                    this._autoRanges(currentNmr);
                    break;
                case 'nmrChanged':
                    if(action.value.dimension <= 1) {
                        this.executePeakPicking(action.value);
                    }
                    break;
                default:
                    return false;
            }
            return true;
        }

        executePeakPicking(nmr) {
            if(!nmr.range || ! nmr.range.length) {
                this._autoRanges(nmr);
            } else {
                this._updateAnnotations(nmr);
            }
        }

        _updateAnnotations(nmr) {
            var ppOptions = API.getData('nmr1hOptions');
            this._getSpectrum(nmr).then(spectrum => {
                spectrum.updateIntegrals(nmr.getChildSync(['range']), {nH: Number(ppOptions.integral)});
                this._createNMRannotationsAndACS(nmr);
            });
        }

        updateIntegrals() {
            var ppOptions = API.getData("nmr1hOptions");
            var currentRanges = API.getData("currentNmrRanges");
            SD.formatter.updateIntegrals(currentRanges, {sum: Number(ppOptions.integral)});
            currentRanges.triggerChange(true); // no bubbling
        }

        _getSpectrum(nmr) {
            var spectrum;
            var filename = String(nmr.getChildSync(['jcamp', 'filename']));
            return nmr.getChild(['jcamp', 'data']).then((jcamp) => {
                if(filename && this.spectra[filename]) {
                    console.log('load spectrum from cache', filename);
                    spectrum = this.spectra[filename];
                } else {
                    jcamp = String(jcamp.get());
                    var spectrum = SD.NMR.fromJcamp(jcamp);
                    if(filename) {
                        this.spectra[filename] = spectrum;
                    }
                }
                return spectrum;
            });
        }

        _autoRanges(nmr) {
            this._getSpectrum(nmr).then(spectrum => {
                var ppOptions = API.getData("nmr1hOptions").resurrect();
                var intFN = 0;
                if(ppOptions.integralFn=="peaks"){
                    intFN=1;
                }
                var peakPicking = spectrum.nmrPeakDetection({
                    nH:ppOptions.integral,
                    realTop:true,
                    thresholdFactor:ppOptions.noiseFactor,
                    clean:ppOptions.clean,
                    compile:ppOptions.compile,
                    optimize:ppOptions.optimize,
                    integralFn:intFN,
                    idPrefix:spectrum.getNucleus()+"",
                    gsdOptions:{minMaxRatio:0.001, smoothY:false, broadWidth:0},
                    format:"new"
                });
                nmr.setChildSync(['range'], peakPicking);
                this._createNMRannotationsAndACS(nmr);
            });
        }

        _createNMRannotationsAndACS(nmr) {
            console.log('create annoations');
            var peakPicking = JSON.parse(JSON.stringify(nmr.getChildSync(['range'])));

            // TODO : this code hsould not be here !
            //Recompile multiplicity
            for (var i=0; i<peakPicking.length; i++){
                var peak = peakPicking[i];
                for (var j=0; j<peak.signal.length; j++){
                    var signal = peak.signal[j];
                    if (signal.j && ! signal.multiplicity) {
                        signal.multiplicity = "";
                        for (var k=0; k<signal.j.length;k++){
                            signal.multiplicity+=signal.j[k].multiplicity;
                        }
                    }
                }
            }
            //SD.formatter.update(peakPicking);

            API.createData("annotationsNMR1d", SD.GUI.annotations1D(peakPicking, {
                line:1,
                fillColor:"green",
                strokeWidth:0
            }));
            API.createData("acsNMR1d",SD.formatter.toACS(peakPicking, {
                rangeForMultiplet:true,
                nucleus:nmr.nucleus[0],
                observe:Math.round(nmr.frequency/10)*10
            }));

             //Is this possible. I need to add the highligth on the ranges
            nmr.setChildSync(['range'], peakPicking);
        }

        updateIntegral() {
            var chemcalc=CCE.analyseMF(API.getData('mf')+'');
            if (chemcalc && chemcalc.atoms && chemcalc.atoms.H) {
                var nmr1hOptions=API.getData('nmr1hOptions');
                if (nmr1hOptions) nmr1hOptions.integral=chemcalc.atoms.H;
                nmr1hOptions.triggerChange();
            }
        }

        updateHighlights(ranges) {
            ranges = ranges || API.getData("currentNmrRanges");
            if(!ranges) return;
            for(var i=0; i<ranges.length; i++) {
                var range = ranges[i];
                // range._highlight = [];
                Object.defineProperty(range, '_highlight', {
                    enumerable: false,
                    writable: true
                });
                range._highlight = [];
                if(!range.signal) continue;
                for(var j=0; j<range.signal.length; j++) {
                    var signal = range.signal[j];
                    if(!signal.diaID) continue;
                    for(var k=0; k<signal.diaID.length; k++) {
                        var diaID = signal.diaID[k];
                        range._highlight.push(diaID);
                    }
                }
            }
        }

        initializeNMRAssignment(nmr) {
            if(nmr && nmr.length) {
                for(var i=0; i<nmr.length; i++) {
                    this.updateHighlights(nmr[i].range);
                }
            }
            var promise = Promise.resolve();
            promise = promise.then(() => API.createData('nmr1hOptions', {
                    "noiseFactor": 0.8,
                    "clean": true,
                    "compile": true,
                    "optimize": false,
                    "integralFn": "sum",
                    "integral": 30,
                    "type": "1H"
                })
            );

            promise=promise.then(() => API.createData('nmr1hOndeTemplates', {
                "full": {
                    "type": "object",
                    "properties": {
                        "integral": {
                            "type": "number",
                            "title": "value to fit the spectrum integral",
                            "label": "Integral"
                        },
                        "noiseFactor": {
                            "type": "number",
                            "title": "Mutiplier of the auto-detected noise level",
                            "label": "noiseFactor"
                        },
                        "clean": {
                            "type": "boolean",
                            "title": "Delete signals with integration less than 0.5",
                            "label": "clean"
                        },
                        "compile": {
                            "type": "boolean",
                            "title": "Compile the multiplets",
                            "label": "compile"
                        },
                        "optimize": {
                            "type": "boolean",
                            "title": "Optimize the peaks to fit the spectrum",
                            "label": "optimize"
                        },
                        "integralFn": {
                            "type": "string",
                            "title": "Type of integration",
                            "label": "Integral type",
                            "enum": [
                                "sum",
                                "peaks"
                            ]
                        },
                        "type": {
                            "type": "string",
                            "title": "Nucleus",
                            "label": "Nucleus",
                            "editable": false
                        }
                    }
                },
                "short": {
                    "type": "object",
                    "properties": {
                        "integral": {
                            "type": "number",
                            "title": "value to fit the spectrum integral",
                            "label": "Integral"
                        }
                    }
                }
            }));
            promise=promise.then((nmr1hOndeTemplates) => API.createData('nmr1hOndeTemplate', nmr1hOndeTemplates.short));
            promise=promise.then(() => {
                this.updateIntegral();
            });
            return promise;
        }
    }

    return Nmr1dManager;
});

<commit_msg>Update Nmr1dManager.js<commit_after>'use strict'

define([
    'file-saver',
    'src/util/api',
    'src/util/ui',
    './libs'
] , function (fileSaver, API, UI, libs) {

    var SD=libs.SD;
    var CCE=libs.CCE;

    class Nmr1dManager {
        constructor() {
            this.spectra = {};
        }

        handleAction(action) {
            switch (action.name) {
                case 'updateRanges':
                    this.updateIntegrals();
                    break;
                case 'downloadSVG':
                    var blob = new Blob([action.value+""], {type: "application/jcamp-dx;charset=utf-8"});
                    fileSaver(blob, 'spectra.svg');
                    break;
                case 'toggleNMR1hAdvancedOptions':
                    var advancedOptions1H = ! API.cache("nmr1hAdvancedOptions");
                    API.cache("nmr1hAdvancedOptions", advancedOptions1H);
                    if (advancedOptions1H) {
                        API.createData("nmr1hOndeTemplate", API.getData("nmr1hOndeTemplates").full);
                    } else {
                        API.createData("nmr1hOndeTemplate", API.getData("nmr1hOndeTemplates").short);
                    }

                    break;
                case 'resetNMR1d':
                    var type = action.name.replace(/[^0-9]/g,'');

                    type = type + 'd';
                    API.createData('blackNMR' + type, null);
                    API.createData('annotationNMR' + type, null);
                    API.createData('acsNMR' + type, null);
                    break;

                case 'switchNMRLayer': {
                    var layer = API.getActiveLayerName();
                    var goToLayer = action.value.dimension > 1 ? 'nmr2D' : 'Default layer';
                    if(layer !== goToLayer) {
                        API.switchToLayer(goToLayer);
                    }
                    if(action.value.dimension > 1) {
                        API.createData('blackNMR2d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR1d', action.value.jcamp.data);
                    }
                    break;
                }
                case 'executePeakPicking':
                    // Execute pickPeacking button was clicked
                    var currentNmr = API.getData('currentNmr');
                    if (currentNmr.dimension>1) {
                        if (typeof UI != "undefined") {
                            UI.showNotification('Peak picking can only be applied on 1D spectra','warning');
                        }
                        return;
                    }
                    this._autoRanges(currentNmr);
                    break;
                case 'nmrChanged':
                    if(action.value.dimension <= 1) {
                        this.executePeakPicking(action.value);
                    }
                    break;
                default:
                    return false;
            }
            return true;
        }

        executePeakPicking(nmr) {
            if(!nmr.range || ! nmr.range.length) {
                this._autoRanges(nmr);
            } else {
                this._updateAnnotations(nmr);
            }
        }

        _updateAnnotations(nmr) {
            var ppOptions = API.getData('nmr1hOptions');
            this._getSpectrum(nmr).then(spectrum => {
                spectrum.updateIntegrals(nmr.getChildSync(['range']), {nH: Number(ppOptions.integral)});
                this._createNMRannotationsAndACS(nmr);
            });
        }

        updateIntegrals() {
            var ppOptions = API.getData("nmr1hOptions");
            var currentRanges = API.getData("currentNmrRanges");
            SD.formatter.updateIntegrals(currentRanges, {sum: Number(ppOptions.integral)});
            currentRanges.triggerChange(true); // no bubbling
        }

        _getSpectrum(nmr) {
            var spectrum;
            var filename = String(nmr.getChildSync(['jcamp', 'filename']));
            return nmr.getChild(['jcamp', 'data']).then((jcamp) => {
                if(filename && this.spectra[filename]) {
                    console.log('load spectrum from cache', filename);
                    spectrum = this.spectra[filename];
                } else {
                    jcamp = String(jcamp.get());
                    var spectrum = SD.NMR.fromJcamp(jcamp);
                    if(filename) {
                        this.spectra[filename] = spectrum;
                    }
                }
                return spectrum;
            });
        }

        _autoRanges(nmr) {
            this._getSpectrum(nmr).then(spectrum => {
                var ppOptions = API.getData("nmr1hOptions").resurrect();
                var intFN = 0;
                if(ppOptions.integralFn=="peaks"){
                    intFN=1;
                }
                var peakPicking = spectrum.nmrPeakDetection({
                    nH:ppOptions.integral,
                    realTop:true,
                    thresholdFactor:ppOptions.noiseFactor,
                    clean:ppOptions.clean,
                    compile:ppOptions.compile,
                    optimize:ppOptions.optimize,
                    integralFn:intFN,
                    idPrefix:spectrum.getNucleus()+"",
                    gsdOptions:{minMaxRatio:0.001, smoothY:false, broadWidth:0},
                    format:"new"
                });
                //nmr.setChildSync(['range'], peakPicking);
                this._createNMRannotationsAndACS(peakPicking);
                //Is this possible. I need to add the highligth on the ranges
                nmr.setChildSync(['range'], peakPicking);
            });
        }

        _createNMRannotationsAndACS(peakPicking) {
            console.log('create annoations');
           // var peakPicking = JSON.parse(JSON.stringify(nmr.getChildSync(['range'])));

            // TODO : this code hsould not be here !
            //Recompile multiplicity
            for (var i=0; i<peakPicking.length; i++){
                var peak = peakPicking[i];
                for (var j=0; j<peak.signal.length; j++){
                    var signal = peak.signal[j];
                    if (signal.j && ! signal.multiplicity) {
                        signal.multiplicity = "";
                        for (var k=0; k<signal.j.length;k++){
                            signal.multiplicity+=signal.j[k].multiplicity;
                        }
                    }
                }
            }
            //SD.formatter.update(peakPicking);

            API.createData("annotationsNMR1d", SD.GUI.annotations1D(peakPicking, {
                line:1,
                fillColor:"green",
                strokeWidth:0
            }));
            API.createData("acsNMR1d",SD.formatter.toACS(peakPicking, {
                rangeForMultiplet:true,
                nucleus:nmr.nucleus[0],
                observe:Math.round(nmr.frequency/10)*10
            }));
        }

        updateIntegral() {
            var chemcalc=CCE.analyseMF(API.getData('mf')+'');
            if (chemcalc && chemcalc.atoms && chemcalc.atoms.H) {
                var nmr1hOptions=API.getData('nmr1hOptions');
                if (nmr1hOptions) nmr1hOptions.integral=chemcalc.atoms.H;
                nmr1hOptions.triggerChange();
            }
        }

        updateHighlights(ranges) {
            ranges = ranges || API.getData("currentNmrRanges");
            if(!ranges) return;
            for(var i=0; i<ranges.length; i++) {
                var range = ranges[i];
                // range._highlight = [];
                Object.defineProperty(range, '_highlight', {
                    enumerable: false,
                    writable: true
                });
                range._highlight = [];
                if(!range.signal) continue;
                for(var j=0; j<range.signal.length; j++) {
                    var signal = range.signal[j];
                    if(!signal.diaID) continue;
                    for(var k=0; k<signal.diaID.length; k++) {
                        var diaID = signal.diaID[k];
                        range._highlight.push(diaID);
                    }
                }
            }
        }

        initializeNMRAssignment(nmr) {
            if(nmr && nmr.length) {
                for(var i=0; i<nmr.length; i++) {
                    this.updateHighlights(nmr[i].range);
                }
            }
            var promise = Promise.resolve();
            promise = promise.then(() => API.createData('nmr1hOptions', {
                    "noiseFactor": 0.8,
                    "clean": true,
                    "compile": true,
                    "optimize": false,
                    "integralFn": "sum",
                    "integral": 30,
                    "type": "1H"
                })
            );

            promise=promise.then(() => API.createData('nmr1hOndeTemplates', {
                "full": {
                    "type": "object",
                    "properties": {
                        "integral": {
                            "type": "number",
                            "title": "value to fit the spectrum integral",
                            "label": "Integral"
                        },
                        "noiseFactor": {
                            "type": "number",
                            "title": "Mutiplier of the auto-detected noise level",
                            "label": "noiseFactor"
                        },
                        "clean": {
                            "type": "boolean",
                            "title": "Delete signals with integration less than 0.5",
                            "label": "clean"
                        },
                        "compile": {
                            "type": "boolean",
                            "title": "Compile the multiplets",
                            "label": "compile"
                        },
                        "optimize": {
                            "type": "boolean",
                            "title": "Optimize the peaks to fit the spectrum",
                            "label": "optimize"
                        },
                        "integralFn": {
                            "type": "string",
                            "title": "Type of integration",
                            "label": "Integral type",
                            "enum": [
                                "sum",
                                "peaks"
                            ]
                        },
                        "type": {
                            "type": "string",
                            "title": "Nucleus",
                            "label": "Nucleus",
                            "editable": false
                        }
                    }
                },
                "short": {
                    "type": "object",
                    "properties": {
                        "integral": {
                            "type": "number",
                            "title": "value to fit the spectrum integral",
                            "label": "Integral"
                        }
                    }
                }
            }));
            promise=promise.then((nmr1hOndeTemplates) => API.createData('nmr1hOndeTemplate', nmr1hOndeTemplates.short));
            promise=promise.then(() => {
                this.updateIntegral();
            });
            return promise;
        }
    }

    return Nmr1dManager;
});

<|endoftext|>


<commit_before>/*
 * basex-standalone
 * https://github.com/alxarch/basex-standalone
 *
 * Copyright (c) 2013 Alexandros Sigalas
 * Licensed under the MIT license.
 */

'use strict';

module.exports = (function(){

var _ = require('lodash')
  , Q = require('q')
  , spawn = require('child_process').spawn
  , ident = _.identity
  , Job = require('./job.js')
  , slice = Array.prototype.slice
  , cat = Array.prototype.concat
  , arr = function(){
        return cat.apply([], slice.apply(arguments)).filter(ident)
    }
  , args = function(opt){
        opt = opt || {}

        var com = arr(opt.commands).join(';')

        return arr(
              opt.debug && '-d'
            , opt.newline && '-L'
            , opt.whitespace && '-w'
            , opt.update && '-u'
            , o2a(opt.bind, 'b')
            , opt.input && ['-i', opt.input]
            , opt.output && ['-o', opt.output]
            , o2a(opt.serializer, 's')
            , com && [ '-c', com]
            , opt.xquery && [ '-q', opt.xquery]
            , opt.run instanceof Job ? opt.run.render() : opt.run
            , (opt.run || com || opt.xquery) ? '' : '()'
        )
    }
  , val = function(opt){
        return _.isPlainObject(opt) ?
        _(opt)
          .map(function(value, name){
            return name+'='+value
          })
          .valueOf()
          .join(',')
        :
        opt
    }
  , o2a = function(obj, a){
        a = a || ''
        return _(obj).map(function(v, n) {
            return a ? ['-'+a, n+'='+val(v)] : ['-'+n, val(v)]
        }).flatten().valueOf()
    }
  , BaseXEnvironment = function(options){
      if(_.isString(options) || options instanceof Job)
          options = {run: options}
      this._defaults = options || {}
    }
  , BaseX = function(options){
        if (this instanceof BaseX)
            return BaseX.partial(options)
        else
            return (new BaseXEnvironment(options)).op()
    }

BaseX.partial = function(options){
  var defaults = _.clone(options, true),
      basex = new BaseXEnvironment(options),
      partial = function(options){
        return basex.op(options)
      }

  basex.reset = function(){
    this._defaults = _.clone(defaults, true)
  }
  _.bindAll(basex)
  _.assign(partial, basex)

  return partial
}

var defaults = {
  debug: false
, newline: false
, serializer: {}
, update: false
, whitespace: false
, bind: {}
, input: null
, output: null
, commands: []
, xquery: null
, run: null
, java: '/usr/bin/env java'
, basexpath: null
, classpath: null

}

// Export for testing
BaseX._args = args

BaseXEnvironment.prototype = {
  defaults: function(){
    var arg

    if(arguments.length > 0){

      arg = arguments[0]

      if(arguments.length > 1){
        if(_.isString(arg))
          this._defaults[arg] = arguments[1]
      }

      else if(_.isString(arg))
        return this._defaults[arg]

      if(_.isPlainObject(arg))
        _.assign(this._defaults, arg)
    }

    return _.clone(this._defaults, true)
  }

, spawn: function(options){

    if(_.isString(options) || options instanceof Job) options = {run: options}

    var opt = _.assign({}, defaults, BaseX._defaults, this._defaults || {}, options || {})
      , classpath = arr(opt.classpath).join(':')
      , baseargs = arr(
          opt.java.split(' ')
        , o2a(opt.jvmargs || {}, '')
        , classpath && ['-cp', classpath]
        , opt.basexpath && '-Dorg.basex.path='+opt.basexpath
        , 'org.basex.BaseX'
        )

      , cmd = baseargs.shift()
      , arg = args(opt)
      , cp = spawn(cmd, baseargs.concat(arg), opt)

    cp.stdout.setEncoding('utf-8')
    cp.stderr.setEncoding('utf-8')

    return cp
  }
, op: function(options){

    var cp = this.spawn(options)
      , out = []
      , err = []
      , def = Q.defer()

    cp.stdout.on('data', function(data){
      out.push(data)
    })

    cp.stderr.on('data', function(data){
      err.push(data)
    })

    cp.on('error', function(error){
      def.reject(error)
    })

    cp.on('close', function(code){

      if(code === 0)
        def.resolve(out.join("\n"))
      else
        def.reject(err.join("\n") || 'Unknown Reason')
    })

    return def.promise
  }
}

// Resets module defaults to private defaults
BaseX.reset = function(){
  this._defaults = _.clone(defaults, true)
}

BaseX.reset()
// Copy the api to the module.
BaseX.defaults = _.bind(BaseXEnvironment.prototype.defaults, BaseX)
BaseX.spawn = function(options){
  return BaseX.partial().spawn(options)
}
BaseX.op = function(options){
  return BaseX.partial().op(options)
}

BaseX.Job = Job

return BaseX

})()
<commit_msg>Fix newline issues with json files at 4096 bytes chunk<commit_after>/*
 * basex-standalone
 * https://github.com/alxarch/basex-standalone
 *
 * Copyright (c) 2013 Alexandros Sigalas
 * Licensed under the MIT license.
 */

'use strict';

module.exports = (function(){

var _ = require('lodash')
  , Q = require('q')
  , spawn = require('child_process').spawn
  , ident = _.identity
  , Job = require('./job.js')
  , slice = Array.prototype.slice
  , cat = Array.prototype.concat
  , arr = function(){
        return cat.apply([], slice.apply(arguments)).filter(ident)
    }
  , args = function(opt){
        opt = opt || {}

        var com = arr(opt.commands).join(';')

        return arr(
              opt.debug && '-d'
            , opt.newline && '-L'
            , opt.whitespace && '-w'
            , opt.update && '-u'
            , o2a(opt.bind, 'b')
            , opt.input && ['-i', opt.input]
            , opt.output && ['-o', opt.output]
            , o2a(opt.serializer, 's')
            , com && [ '-c', com]
            , opt.xquery && [ '-q', opt.xquery]
            , opt.run instanceof Job ? opt.run.render() : opt.run
            , (opt.run || com || opt.xquery) ? '' : '()'
        )
    }
  , val = function(opt){
        return _.isPlainObject(opt) ?
        _(opt)
          .map(function(value, name){
            return name+'='+value
          })
          .valueOf()
          .join(',')
        :
        opt
    }
  , o2a = function(obj, a){
        a = a || ''
        return _(obj).map(function(v, n) {
            return a ? ['-'+a, n+'='+val(v)] : ['-'+n, val(v)]
        }).flatten().valueOf()
    }
  , BaseXEnvironment = function(options){
      if(_.isString(options) || options instanceof Job)
          options = {run: options}
      this._defaults = options || {}
    }
  , BaseX = function(options){
        if (this instanceof BaseX)
            return BaseX.partial(options)
        else
            return (new BaseXEnvironment(options)).op()
    }

BaseX.partial = function(options){
  var defaults = _.clone(options, true),
      basex = new BaseXEnvironment(options),
      partial = function(options){
        return basex.op(options)
      }

  basex.reset = function(){
    this._defaults = _.clone(defaults, true)
  }
  _.bindAll(basex)
  _.assign(partial, basex)

  return partial
}

var defaults = {
  debug: false
, newline: false
, serializer: {}
, update: false
, whitespace: false
, bind: {}
, input: null
, output: null
, commands: []
, xquery: null
, run: null
, java: '/usr/bin/env java'
, basexpath: null
, classpath: null

}

// Export for testing
BaseX._args = args

BaseXEnvironment.prototype = {
  defaults: function(){
    var arg

    if(arguments.length > 0){

      arg = arguments[0]

      if(arguments.length > 1){
        if(_.isString(arg))
          this._defaults[arg] = arguments[1]
      }

      else if(_.isString(arg))
        return this._defaults[arg]

      if(_.isPlainObject(arg))
        _.assign(this._defaults, arg)
    }

    return _.clone(this._defaults, true)
  }

, spawn: function(options){

    if(_.isString(options) || options instanceof Job) options = {run: options}

    var opt = _.assign({}, defaults, BaseX._defaults, this._defaults || {}, options || {})
      , classpath = arr(opt.classpath).join(':')
      , baseargs = arr(
          opt.java.split(' ')
        , o2a(opt.jvmargs || {}, '')
        , classpath && ['-cp', classpath]
        , opt.basexpath && '-Dorg.basex.path='+opt.basexpath
        , 'org.basex.BaseX'
        )

      , cmd = baseargs.shift()
      , arg = args(opt)
      , cp = spawn(cmd, baseargs.concat(arg), opt)

    cp.stdout.setEncoding('utf-8')
    cp.stderr.setEncoding('utf-8')

    return cp
  }
, op: function(options){

    var cp = this.spawn(options)
      , out = []
      , err = []
      , def = Q.defer()

    cp.stdout.on('data', function(data){
      out.push(data)
    })

    cp.stderr.on('data', function(data){
      err.push(data)
    })

    cp.on('error', function(error){
      def.reject(error)
    })

    cp.on('close', function(code){

      if(code === 0)
        def.resolve(out.join(""))
      else
        def.reject(err.join("") || 'Unknown Reason')
    })

    return def.promise
  }
}

// Resets module defaults to private defaults
BaseX.reset = function(){
  this._defaults = _.clone(defaults, true)
}

BaseX.reset()
// Copy the api to the module.
BaseX.defaults = _.bind(BaseXEnvironment.prototype.defaults, BaseX)
BaseX.spawn = function(options){
  return BaseX.partial().spawn(options)
}
BaseX.op = function(options){
  return BaseX.partial().op(options)
}

BaseX.Job = Job

return BaseX

})()
<|endoftext|>


<commit_before>(function() {

  ViewTest = TestCase("ViewTest");

  ViewTest.prototype.testSetVariable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#template").get(0));
    view.set("variable", "value");
    assertEquals("Variable was not set", $("#template .variable").html(), "value");
  };

  ViewTest.prototype.testAddIterable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#templateIterable").get(0));

    view.add("thing", {"variable": "value"});
    view.add("thing", {"variable": "value2"});

    jstestdriver.console.log($("#templateIterable").get(0).innerHTML);

    assertEquals("Variable was not set", $("#templateIterable li:nth-child(1) .variable").html(), "value");
    assertEquals("Variable was not set", $("#templateIterable li:nth-child(2) .variable").html(), "value2");
  };
}());
<commit_msg>added deleteing to live view<commit_after>(function() {
  ViewTest = TestCase("ViewTest");

  ViewTest.prototype.testSetVariable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#template").get(0));
    view.update("variable", "value");
    assertEquals("Variable was not set", $("#template .variable").html(), "value");
  };

  ViewTest.prototype.testAddIterable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#templateIterable").get(0));

    view.add("thing", {"variable": "value"});
    view.add("thing", {"variable": "value2"});

    assertEquals("Variable was not set", $("#templateIterable li:nth-child(1) .variable").html(), "value");
    assertEquals("Variable was not set", $("#templateIterable li:nth-child(2) .variable").html(), "value2");
  };

  ViewTest.prototype.testUpdateIterable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#templateIterable").get(0));

    var thing = view.add("thing", {"variable": "value"});
    thing.update({"variable": "newValue"});
    assertEquals("Variable was not set", $("#templateIterable .variable").html(), "newValue");
  };

  ViewTest.prototype.testDeleteIterable = function() {
    /*:DOC +=

*/
    var view = new LiveView($("#templateIterable").get(0));

    var thing = view.add("thing", {"variable": "value"});
    var thing2 = view.add("thing", {"variable": "value2"});

    thing.remove();
    assertEquals("Not deleted", 1, $("#templateIterable .variable").length);
    assertEquals("Deleted wrong thing", $("#templateIterable .variable").html(), "value2");
  };

}());
<|endoftext|>


<commit_before>// Karma configuration

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: 'apps/openassessment/xblock/static/js',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'lib/jquery.min.js',
      'lib/*.js',
      'src/*.js',
      'spec/*.js',

      // fixtures
      {
        pattern: 'fixtures/*.html',
        served: true, included: false
      },
    ],

    // list of files to exclude
    exclude: [

    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/*.js': 'coverage'
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    coverageReporter: {
        type : 'text'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Firefox'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true

  });

};
<commit_msg>Exclude design.js from test execution<commit_after>// Karma configuration

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: 'apps/openassessment/xblock/static/js',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'lib/jquery.min.js',
      'lib/*.js',
      'src/*.js',
      'spec/*.js',

      // fixtures
      {
        pattern: 'fixtures/*.html',
        served: true, included: false
      },
    ],

    // list of files to exclude
    exclude: [
      'src/design*.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/*.js': 'coverage'
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    coverageReporter: {
        type : 'text'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Firefox'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true

  });

};
<|endoftext|>


<commit_before>import fileSaver from 'file-saver';
import API from 'src/util/api';
import UI from 'src/util/ui';
import {getData} from './jpaths';
import SD from './libs/SD';
import * as GUI from './nmrGUI';
import CCE from './libs/CCE';

const Ranges = SD.Ranges;
const NMR = SD.NMR;

class Nmr1dManager {
    constructor(sample) {
        this.spectra = {};
        this.sample = sample;
    }

    handleAction(action) {
        switch (action.name) {
            case 'updateRanges':
                this.updateIntegrals();
                break;
            case 'downloadSVG':
                var blob = new Blob([action.value + ''], {type: 'application/jcamp-dx;charset=utf-8'});
                fileSaver(blob, 'spectra.svg');
                break;
            case 'toggleNMR1hAdvancedOptions':
                var advancedOptions1H = !API.cache('nmr1hAdvancedOptions');
                API.cache('nmr1hAdvancedOptions', advancedOptions1H);
                if (advancedOptions1H) {
                    API.createData('nmr1hOndeTemplate', API.getData('nmr1hOndeTemplates').full);
                } else {
                    API.createData('nmr1hOndeTemplate', API.getData('nmr1hOndeTemplates').short);
                }

                break;
            case 'resetNMR1d':
                var type = action.name.replace(/[^0-9]/g, '');

                type = type + 'd';
                API.createData('blackNMR' + type, null);
                API.createData('annotationNMR' + type, null);
                API.createData('acsNMR' + type, null);
                break;

            case 'switchNMRLayer':
                var goToLayer = action.value.dimension > 1 ? 'nmr2D' : 'Default layer';
                API.switchToLayer(goToLayer);
                if (action.value.dimension > 1) {
                    if (action.value.jcamp) {
                        API.createData('blackNMR2d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR2d', null);
                    }

                } else {
                    if (action.value.jcamp) {
                        API.createData('blackNMR1d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR1d', null);
                    }
                }
                break;
            case 'executePeakPicking':
                var currentNmr = API.getData('currentNmr');
                if (currentNmr.dimension > 1) {
                    if (typeof UI !== 'undefined') {
                        UI.showNotification('Peak picking can only be applied on 1D spectra', 'warning');
                    }
                    return false;
                }
                this._autoRanges(currentNmr);
                break;
            case 'nmrChanged':
                if (action.value.dimension <= 1) {
                    this.executePeakPicking(action.value, true);
                }
                break;
            default:
                return false;
        }
        return true;
    }

    executePeakPicking(nmr, updateIntegral) {
        if (nmr.dimension > 1) {
            return false;
        }
        if (nmr.nucleus && nmr.nucleus[0].replace(/[0-9]/,'')!=='H' ) {
            return false;
        }

        if (!nmr.range || !nmr.range.length) {
            this.updateIntegral({mf: true});
            this._autoRanges(nmr);
        } else {
            if (updateIntegral) {
                this.updateIntegral({range: nmr.range});
            }
        }
    }

    updateIntegrals(integral) {
        var ppOptions = API.getData('nmr1hOptions');
        var currentRanges = API.getData('currentNmrRanges');
        if (!currentRanges) return;

        // We initialize ranges with the DataObject so that
        // the integral update is inplace
        var ranges = new Ranges(currentRanges);
        ranges.updateIntegrals({sum: Number(ppOptions.integral || integral)});
    }

    _getNMR(currentNMRLine) {
        var filename = String(currentNMRLine.getChildSync(['jcamp', 'filename']));
        return currentNMRLine.getChild(['jcamp', 'data']).then((jcamp) => {
            if (filename && this.spectra[filename]) {
                var spectrum = this.spectra[filename];
            } else {
                if (jcamp) {
                    jcamp = String(jcamp.get());
                    spectrum = NMR.fromJcamp(jcamp);
                    if (filename) {
                        this.spectra[filename] = spectrum;
                    }
                } else {
                    spectrum = new NMR();
                }
            }
            return spectrum;
        });
    }

    _autoRanges(nmrLine) {
        this._getNMR(nmrLine).then(nmrSpectrum => {
            var ppOptions = API.getData('nmr1hOptions').resurrect();
            var removeImpurityOptions = {};
            if (ppOptions.removeImpurities.useIt) {
                removeImpurityOptions = {solvent: nmrLine.solvent, nH: Number(ppOptions.integral), error: ppOptions.removeImpurities.error};
            }
            var ranges = nmrSpectrum.getRanges({
                nH: Number(ppOptions.integral),
                realTop: true,
                thresholdFactor: Number(ppOptions.noiseFactor),
                clean: ppOptions.clean,
                compile: ppOptions.compile,
                from: ppOptions.from,
                to: ppOptions.to,
                optimize: ppOptions.optimize,
                integralType: ppOptions.integralFn,
                gsdOptions: {minMaxRatio: 0.001, smoothY: false, broadWidth: 0.004},
                removeImpurity: removeImpurityOptions
            });
            nmrLine.setChildSync(['range'], ranges);
        });
    }

    async _createNMRannotationsAndACS(ranges) {
        var nmrLine=API.getData('currentNmr');
        var nmrSpectrum = await this._getNMR(nmrLine);
        var nucleus = nmrLine.nucleus[0];
        var observe = nmrLine.frequency;
        if (nmrSpectrum && nmrSpectrum.sd) {
            nucleus = nmrSpectrum.getNucleus(0);
            observe = nmrSpectrum.observeFrequencyX();
        }

        if (nmrSpectrum) {
            API.createData('annotationsNMR1d', GUI.annotations1D(ranges, {
                line: 1,
                fillColor: 'lightgreen',
                strokeWidth: 0
            }));
        }

        API.createData('acsNMR1d', SD.getACS(ranges, {
            rangeForMultiplet: true,
            nucleus,
            observe
        }));
    }

    updateIntegral(opts) {
        opts = opts || {};
        var integral;
        if (opts.range) {
            let sum = 0;
            for (const range of opts.range) {
                sum += range.integral;
            }
            integral = Math.round(sum);
        } else {
            const mf = getData(this.sample, 'mf') + '';
            if (mf) {
                const chemcalc = CCE.analyseMF(mf);
                if (chemcalc && chemcalc.atoms && chemcalc.atoms.H) {
                    integral = chemcalc.atoms.H;
                }
            }
        }

        if (typeof integral !== 'number' || Number.isNaN(integral) || ! integral) {
            integral = 100;
        }
        const nmr1hOptions = API.getData('nmr1hOptions');
        nmr1hOptions.integral = integral;
        nmr1hOptions.triggerChange();
        this.updateIntegrals();
    }

    rangesHasChanged(ranges) {
        ranges = ranges || API.getData('currentNmrRanges');

        if (!ranges) return;

        var rangesWasChanged = GUI.ensureRangesHighlight(ranges);
        if (rangesWasChanged) {
            ranges.triggerChange();
        }
        this._createNMRannotationsAndACS(ranges);
        return rangesWasChanged;
    }

    async initializeNMRAssignment(nmr) {
        if (nmr && nmr.length) {
            for (var i = 0; i < nmr.length; i++) {
                if (!nmr[i].range) {
                    nmr[i].range = [];
                }
             //   this.rangesHasChanged(nmr.getChildSync([i, 'range']));
            }
        }

        await API.createData('nmr1hOptions', {
            noiseFactor: 0.8,
            clean: 0.5,
            compile: true,
            optimize: false,
            integralType: 'sum',
            integral: 100,
            type: '1H',
            removeImpurities: {
                useIt: false,
                error: 0.025
            }
        });

        var nmr1hOndeTemplates = await API.createData('nmr1hOndeTemplates', {
            full: {
                type: 'object',
                properties: {
                    integral: {
                        type: 'number',
                        title: 'value to fit the spectrum integral',
                        label: 'Integral'
                    },
                    noiseFactor: {
                        type: 'number',
                        title: 'Mutiplier of the auto-detected noise level',
                        label: 'noiseFactor'
                    },
                    clean: {
                        type: 'number',
                        title: 'Delete signals with integration less than input value',
                        label: 'clean'
                    },
                    compile: {
                        type: 'boolean',
                        title: 'Compile the multiplets',
                        label: 'compile'
                    },
                    optimize: {
                        type: 'boolean',
                        title: 'Optimize the peaks to fit the spectrum',
                        label: 'optimize'
                    },
                    integralFn: {
                        type: 'string',
                        title: 'Type of integration',
                        label: 'Integral type',
                        enum: [
                            'sum',
                            'peaks'
                        ]
                    },
                    type: {
                        type: 'string',
                        title: 'Nucleus',
                        label: 'Nucleus',
                        editable: false
                    },
                    removeImpurities: {
                        type: 'object',
                        label: 'Remove solvent impurities',
                        properties: {
                            useIt: {
                                type: 'boolean',
                                label: 'Remove Impurities',
                            },
                            error: {
                                type: 'number',
                                label: 'Tolerance',
                                title: 'Allowed error in ppm'
                            }
                        }
                    }
                }
            },
            short: {
                type: 'object',
                properties: {
                    integral: {
                        type: 'number',
                        title: 'Total integral value',
                        label: 'Integral'
                    },
                    removeImpurities: {
                        type: 'object',
                        label: 'Remove solvent impurities',
                        properties: {
                            useIt: {
                                type: 'boolean',
                                label: 'Remove Impurities',
                            },
                            error: {
                                type: 'number',
                                label: 'Tolerance',
                                title: 'Allowed error in ppm'
                            }
                        }
                    }
                }
            }
        });
        await API.createData('nmr1hOndeTemplate', nmr1hOndeTemplates.short);

        var currentNmr = API.getData('currentNmr');
        if (currentNmr) {
            this.updateIntegral({range: currentNmr.getChildSync(['range'])});
        }
    }
}

module.exports = Nmr1dManager;
<commit_msg>add trigger change when updating integral<commit_after>import fileSaver from 'file-saver';
import API from 'src/util/api';
import UI from 'src/util/ui';
import {getData} from './jpaths';
import SD from './libs/SD';
import * as GUI from './nmrGUI';
import CCE from './libs/CCE';

const Ranges = SD.Ranges;
const NMR = SD.NMR;

class Nmr1dManager {
    constructor(sample) {
        this.spectra = {};
        this.sample = sample;
    }

    handleAction(action) {
        switch (action.name) {
            case 'updateRanges':
                this.updateIntegrals();
                break;
            case 'downloadSVG':
                var blob = new Blob([action.value + ''], {type: 'application/jcamp-dx;charset=utf-8'});
                fileSaver(blob, 'spectra.svg');
                break;
            case 'toggleNMR1hAdvancedOptions':
                var advancedOptions1H = !API.cache('nmr1hAdvancedOptions');
                API.cache('nmr1hAdvancedOptions', advancedOptions1H);
                if (advancedOptions1H) {
                    API.createData('nmr1hOndeTemplate', API.getData('nmr1hOndeTemplates').full);
                } else {
                    API.createData('nmr1hOndeTemplate', API.getData('nmr1hOndeTemplates').short);
                }

                break;
            case 'resetNMR1d':
                var type = action.name.replace(/[^0-9]/g, '');

                type = type + 'd';
                API.createData('blackNMR' + type, null);
                API.createData('annotationNMR' + type, null);
                API.createData('acsNMR' + type, null);
                break;

            case 'switchNMRLayer':
                var goToLayer = action.value.dimension > 1 ? 'nmr2D' : 'Default layer';
                API.switchToLayer(goToLayer);
                if (action.value.dimension > 1) {
                    if (action.value.jcamp) {
                        API.createData('blackNMR2d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR2d', null);
                    }

                } else {
                    if (action.value.jcamp) {
                        API.createData('blackNMR1d', action.value.jcamp.data);
                    } else {
                        API.createData('blackNMR1d', null);
                    }
                }
                break;
            case 'executePeakPicking':
                var currentNmr = API.getData('currentNmr');
                if (currentNmr.dimension > 1) {
                    if (typeof UI !== 'undefined') {
                        UI.showNotification('Peak picking can only be applied on 1D spectra', 'warning');
                    }
                    return false;
                }
                this._autoRanges(currentNmr);
                break;
            case 'nmrChanged':
                if (action.value.dimension <= 1) {
                    this.executePeakPicking(action.value, true);
                }
                break;
            default:
                return false;
        }
        return true;
    }

    executePeakPicking(nmr, updateIntegral) {
        if (nmr.dimension > 1) {
            return false;
        }
        if (nmr.nucleus && nmr.nucleus[0].replace(/[0-9]/,'')!=='H' ) {
            return false;
        }

        if (!nmr.range || !nmr.range.length) {
            this.updateIntegral({mf: true});
            this._autoRanges(nmr);
        } else {
            if (updateIntegral) {
                this.updateIntegral({range: nmr.range});
            }
        }
    }

    updateIntegrals(integral) {
        var ppOptions = API.getData('nmr1hOptions');
        var currentRanges = API.getData('currentNmrRanges');
        if (!currentRanges) return;

        // We initialize ranges with the DataObject so that
        // the integral update is inplace
        var ranges = new Ranges(currentRanges);
        ranges.updateIntegrals({sum: Number(ppOptions.integral || integral)});
        currentRanges.triggerChange();
    }

    _getNMR(currentNMRLine) {
        var filename = String(currentNMRLine.getChildSync(['jcamp', 'filename']));
        return currentNMRLine.getChild(['jcamp', 'data']).then((jcamp) => {
            if (filename && this.spectra[filename]) {
                var spectrum = this.spectra[filename];
            } else {
                if (jcamp) {
                    jcamp = String(jcamp.get());
                    spectrum = NMR.fromJcamp(jcamp);
                    if (filename) {
                        this.spectra[filename] = spectrum;
                    }
                } else {
                    spectrum = new NMR();
                }
            }
            return spectrum;
        });
    }

    _autoRanges(nmrLine) {
        this._getNMR(nmrLine).then(nmrSpectrum => {
            var ppOptions = API.getData('nmr1hOptions').resurrect();
            var removeImpurityOptions = {};
            if (ppOptions.removeImpurities.useIt) {
                removeImpurityOptions = {solvent: nmrLine.solvent, nH: Number(ppOptions.integral), error: ppOptions.removeImpurities.error};
            }
            var ranges = nmrSpectrum.getRanges({
                nH: Number(ppOptions.integral),
                realTop: true,
                thresholdFactor: Number(ppOptions.noiseFactor),
                clean: ppOptions.clean,
                compile: ppOptions.compile,
                from: ppOptions.from,
                to: ppOptions.to,
                optimize: ppOptions.optimize,
                integralType: ppOptions.integralFn,
                gsdOptions: {minMaxRatio: 0.001, smoothY: false, broadWidth: 0.004},
                removeImpurity: removeImpurityOptions
            });
            nmrLine.setChildSync(['range'], ranges);
        });
    }

    async _createNMRannotationsAndACS(ranges) {
        var nmrLine=API.getData('currentNmr');
        var nmrSpectrum = await this._getNMR(nmrLine);
        var nucleus = nmrLine.nucleus[0];
        var observe = nmrLine.frequency;
        if (nmrSpectrum && nmrSpectrum.sd) {
            nucleus = nmrSpectrum.getNucleus(0);
            observe = nmrSpectrum.observeFrequencyX();
        }

        if (nmrSpectrum) {
            API.createData('annotationsNMR1d', GUI.annotations1D(ranges, {
                line: 1,
                fillColor: 'lightgreen',
                strokeWidth: 0
            }));
        }

        API.createData('acsNMR1d', SD.getACS(ranges, {
            rangeForMultiplet: true,
            nucleus,
            observe
        }));
    }

    updateIntegral(opts) {
        opts = opts || {};
        var integral;
        if (opts.range) {
            let sum = 0;
            for (const range of opts.range) {
                sum += range.integral;
            }
            integral = Math.round(sum);
        } else {
            const mf = getData(this.sample, 'mf') + '';
            if (mf) {
                const chemcalc = CCE.analyseMF(mf);
                if (chemcalc && chemcalc.atoms && chemcalc.atoms.H) {
                    integral = chemcalc.atoms.H;
                }
            }
        }

        if (typeof integral !== 'number' || Number.isNaN(integral) || ! integral) {
            integral = 100;
        }
        const nmr1hOptions = API.getData('nmr1hOptions');
        nmr1hOptions.integral = integral;
        nmr1hOptions.triggerChange();
        this.updateIntegrals();
    }

    rangesHasChanged(ranges) {
        ranges = ranges || API.getData('currentNmrRanges');

        if (!ranges) return;

        var rangesWasChanged = GUI.ensureRangesHighlight(ranges);
        if (rangesWasChanged) {
            ranges.triggerChange();
        }
        this._createNMRannotationsAndACS(ranges);
        return rangesWasChanged;
    }

    async initializeNMRAssignment(nmr) {
        if (nmr && nmr.length) {
            for (var i = 0; i < nmr.length; i++) {
                if (!nmr[i].range) {
                    nmr[i].range = [];
                }
             //   this.rangesHasChanged(nmr.getChildSync([i, 'range']));
            }
        }

        await API.createData('nmr1hOptions', {
            noiseFactor: 0.8,
            clean: 0.5,
            compile: true,
            optimize: false,
            integralType: 'sum',
            integral: 100,
            type: '1H',
            removeImpurities: {
                useIt: false,
                error: 0.025
            }
        });

        var nmr1hOndeTemplates = await API.createData('nmr1hOndeTemplates', {
            full: {
                type: 'object',
                properties: {
                    integral: {
                        type: 'number',
                        title: 'value to fit the spectrum integral',
                        label: 'Integral'
                    },
                    noiseFactor: {
                        type: 'number',
                        title: 'Mutiplier of the auto-detected noise level',
                        label: 'noiseFactor'
                    },
                    clean: {
                        type: 'number',
                        title: 'Delete signals with integration less than input value',
                        label: 'clean'
                    },
                    compile: {
                        type: 'boolean',
                        title: 'Compile the multiplets',
                        label: 'compile'
                    },
                    optimize: {
                        type: 'boolean',
                        title: 'Optimize the peaks to fit the spectrum',
                        label: 'optimize'
                    },
                    integralFn: {
                        type: 'string',
                        title: 'Type of integration',
                        label: 'Integral type',
                        enum: [
                            'sum',
                            'peaks'
                        ]
                    },
                    type: {
                        type: 'string',
                        title: 'Nucleus',
                        label: 'Nucleus',
                        editable: false
                    },
                    removeImpurities: {
                        type: 'object',
                        label: 'Remove solvent impurities',
                        properties: {
                            useIt: {
                                type: 'boolean',
                                label: 'Remove Impurities',
                            },
                            error: {
                                type: 'number',
                                label: 'Tolerance',
                                title: 'Allowed error in ppm'
                            }
                        }
                    }
                }
            },
            short: {
                type: 'object',
                properties: {
                    integral: {
                        type: 'number',
                        title: 'Total integral value',
                        label: 'Integral'
                    },
                    removeImpurities: {
                        type: 'object',
                        label: 'Remove solvent impurities',
                        properties: {
                            useIt: {
                                type: 'boolean',
                                label: 'Remove Impurities',
                            },
                            error: {
                                type: 'number',
                                label: 'Tolerance',
                                title: 'Allowed error in ppm'
                            }
                        }
                    }
                }
            }
        });
        await API.createData('nmr1hOndeTemplate', nmr1hOndeTemplates.short);

        var currentNmr = API.getData('currentNmr');
        if (currentNmr) {
            this.updateIntegral({range: currentNmr.getChildSync(['range'])});
        }
    }
}

module.exports = Nmr1dManager;
<|endoftext|>


<commit_before>'use strict';

// Load modules

const Url = require('url');
const Async = require('async');
const Boom = require('boom');
const Traverse = require('traverse');
const Hoek = require('hoek');
const Joi = require('joi');

// Declare internals

const internals = {};

module.exports.config = function (settings) {

    return {
        handler: function (request, reply) {

            const requestRegex = /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g;
            const payloadRegex = /^\$(\d+)(?:\.([^\s\$]*))?/;
            const requests = [];
            const payloads = [];
            const resultsData = {
                results: [],
                resultsMap: []
            };

            let errorMessage = null;

            request.payload.requests.every((req, idx) => {

                const requestParts = [];
                const result = req.path.replace(requestRegex, (match, p1, p2) => {

                    if (!p1) {
                        requestParts.push({ type: 'text', value: p2 });
                        return '';
                    }

                    if (p1 < idx) {
                        requestParts.push({ type: 'ref', index: p1, value: p2 });
                        return '';
                    }

                    errorMessage = 'Request reference is beyond array size: ' + idx;
                    return match;
                });

                // Make sure entire string was processed (empty)

                if (result === '') {
                    requests.push(requestParts);
                }
                else {
                    errorMessage = errorMessage || 'Invalid request format in item: ' + idx;
                    return false;
                }

                const payloadParts = internals.parsePayload(payloadRegex, req.payload);

                payloads.push(payloadParts || []);
                return true;
            });

            if (errorMessage !== null) {
                return reply(Boom.badRequest(errorMessage));
            }

            internals.process(request, requests, payloads, resultsData, reply);
        },
        notes: settings.notes,
        description: settings.description,
        validate: {
            payload: Joi.object({
                requests: Joi.array().items(Joi.object({
                    method: Joi.string().required(),
                    path: Joi.string().required(),
                    query: [Joi.object().unknown().allow(null),Joi.string()],
                    payload: [Joi.object().unknown().allow(null),Joi.string()]
                }).label('BatchRequest')).min(1).required()
            }).required().label('BatchRequestPayload')
        },
        auth: settings.auth,
        tags: settings.tags
    };
};

internals.process = function (request, requests, payloads, resultsData, reply) {

    const fnsParallel = [];
    const fnsSerial = [];

    requests.forEach((requestParts, idx) => {

        const payloadParts = payloads[idx];
        if (internals.hasRefPart(requestParts) || payloadParts.length) {
            return fnsSerial.push((callback) => {

                internals.batch(request, resultsData, idx, requestParts, payloadParts, callback);
            });
        }

        fnsParallel.push((callback) => {

            internals.batch(request, resultsData, idx, requestParts, undefined, callback);
        });
    });

    Async.series([
        (callback) => {

            Async.parallel(fnsParallel, callback);
        },
        (callback) => {

            Async.series(fnsSerial, callback);
        }
    ], (err) => {

        if (err) {
            reply(err);
        }
        else {
            reply(resultsData.results);
        }
    });
};

internals.hasRefPart = function (parts) {

    return parts.some((part) => part.type === 'ref');
};

internals.buildPath = function (resultsData, pos, parts) {

    let path = '';
    let error = null;
    let i = 0;
    const il = parts.length;

    for ( ; i < il; ++i) {
        path += '/';

        if (parts[i].type === 'ref') {
            const ref = resultsData.resultsMap[parts[i].index];

            if (ref) {
                const value = Hoek.reach(ref, parts[i].value);

                if (value !== null && value !== undefined) {

                    if (/^[\w:]+$/.test(value)) {
                        path += value;
                    }
                    else {
                        error = new Error('Reference value includes illegal characters');
                        break;
                    }
                }
                else {
                    error = new Error('Reference not found');
                    break;
                }
            }
            else {
                error = new Error('Missing reference response');
                break;
            }
        }
        else {
            path += parts[i].value;
        }
    }

    return error ? error : path;
};

internals.parsePayload = function (re, obj) {

    const payloadParts = [];

    if (!obj) {
        return null;
    }

    Traverse(obj).forEach(function (value) {

        if (typeof value === 'string') {
            const match = value.match(re);
            if (match) {
                payloadParts.push({
                    path: this.path,
                    resultIndex: match[1],
                    resultPath: match[2]
                });
            }
        }
    });

    return payloadParts;
};

internals.evalResults = function (results, index, path) {

    let result = results[index];

    if (path) {
        result = Hoek.reach(result, path) || {};
    }

    return result;
};

internals.buildPayload = function (payload, resultsData, parts) {

    let i = 0;
    const il = parts.length;
    for ( ; i < il; ++i) {

        const result = internals.evalResults(resultsData.resultsMap, parts[i].resultIndex, parts[i].resultPath);

        if (parts[i].path.length) {
            Traverse(payload).set(parts[i].path, result);
        }
        else {
            payload = result;
        }
    }

    return payload;
};

internals.batch = function (batchRequest, resultsData, pos, requestParts, payloadParts, callback) {

    const path = internals.buildPath(resultsData, pos, requestParts);

    if (path instanceof Error) {
        resultsData.results[pos] = path;
        return callback(path);
    }

    // Make request
    batchRequest.payload.requests[pos].path = path;

    if (payloadParts && payloadParts.length) {
        const payload = internals.buildPayload(
            batchRequest.payload.requests[pos].payload,
            resultsData,
            payloadParts
        );

        // Make payload
        batchRequest.payload.requests[pos].payload = payload;
    }

    internals.dispatch(batchRequest, batchRequest.payload.requests[pos], (data) => {

        // If redirection
        if (('' + data.statusCode).indexOf('3') === 0) {
            batchRequest.payload.requests[pos].path = data.headers.location;
            internals.dispatch(batchRequest, batchRequest.payload.requests[pos], (batchData) => {

                const batchResult = batchData.result;

                resultsData.results[pos] = batchResult;
                resultsData.resultsMap[pos] = batchResult;
                callback(null, batchResult);
            });
            return;
        }

        const result = data.result;
        resultsData.results[pos] = result;
        resultsData.resultsMap[pos] = result;
        callback(null, result);
    });
};

internals.dispatch = function (batchRequest, request, callback) {

    let path = request.path;

    if (request.query) {
        const urlObject = {
            pathname: request.path,
            query: request.query
        };
        path = Url.format(urlObject);
    }

    const body = (request.payload !== null && request.payload !== undefined ? JSON.stringify(request.payload) : null);     // payload can be '' or 0
    const injectOptions = {
        url: path,
        method: request.method,
        headers: batchRequest.headers,
        payload: body,
        session: batchRequest.session
    };
    if (batchRequest.server.connections.length === 1) {
        batchRequest.server.inject(injectOptions, callback);
    }
    else {
        batchRequest.connection.inject(injectOptions, callback);
    }
};
<commit_msg>finishing up code cleanup<commit_after>'use strict';

// Load modules

const Url = require('url');
const Async = require('async');
const Boom = require('boom');
const Traverse = require('traverse');
const Hoek = require('hoek');
const Joi = require('joi');

// Declare internals

const internals = {};

module.exports.config = function (settings) {

    return {
        handler: function (request, reply) {

            const requests = [];
            const payloads = [];
            const resultsData = {
                results: [],
                resultsMap: []
            };

            let errorMessage = null;

            request.payload.requests.every((req, idx) => {

                const requestParts = [];
                const result = req.path.replace(internals.requestRegex, (match, p1, p2) => {

                    if (!p1) {
                        requestParts.push({ type: 'text', value: p2 });
                        return '';
                    }

                    if (p1 < idx) {
                        requestParts.push({ type: 'ref', index: p1, value: p2 });
                        return '';
                    }

                    errorMessage = 'Request reference is beyond array size: ' + idx;
                    return match;
                });

                // Make sure entire string was processed (empty)

                if (result === '') {
                    requests.push(requestParts);
                }
                else {
                    errorMessage = errorMessage || 'Invalid request format in item: ' + idx;
                    return false;
                }

                const payloadParts = internals.parsePayload(req.payload);

                payloads.push(payloadParts || []);
                return true;
            });

            if (errorMessage !== null) {
                return reply(Boom.badRequest(errorMessage));
            }

            internals.process(request, requests, payloads, resultsData, reply);
        },
        notes: settings.notes,
        description: settings.description,
        validate: {
            payload: Joi.object({
                requests: Joi.array().items(Joi.object({
                    method: Joi.string().required(),
                    path: Joi.string().required(),
                    query: [Joi.object().unknown().allow(null),Joi.string()],
                    payload: [Joi.object().unknown().allow(null),Joi.string()]
                }).label('BatchRequest')).min(1).required()
            }).required().label('BatchRequestPayload')
        },
        auth: settings.auth,
        tags: settings.tags
    };
};

internals.process = function (request, requests, payloads, resultsData, reply) {

    const fnsParallel = [];
    const fnsSerial = [];

    requests.forEach((requestParts, idx) => {

        const payloadParts = payloads[idx];
        if (internals.hasRefPart(requestParts) || payloadParts.length) {
            return fnsSerial.push((callback) => {

                internals.batch(request, resultsData, idx, requestParts, payloadParts, callback);
            });
        }

        fnsParallel.push((callback) => {

            internals.batch(request, resultsData, idx, requestParts, undefined, callback);
        });
    });

    Async.series([
        (callback) => {

            Async.parallel(fnsParallel, callback);
        },
        (callback) => {

            Async.series(fnsSerial, callback);
        }
    ], (err) => {

        if (err) {
            reply(err);
        }
        else {
            reply(resultsData.results);
        }
    });
};

internals.hasRefPart = function (parts) {

    return parts.some((part) => part.type === 'ref');
};

internals.buildPath = function (resultsData, pos, parts) {

    let path = '';
    let error = null;
    let ref;
    let value;
    let part;
    const partsLength = parts.length;

    for (let i = 0; i < partsLength; ++i) {
        path += '/';
        part = parts[i];

        if (part.type !== 'ref') {
            path += part.value;
            continue;
        }

        ref = resultsData.resultsMap[part.index];

        if (!ref) {
            error = new Error('Missing reference response');
            break;
        }

        value = Hoek.reach(ref, part.value);

        if (value === null || value === undefined) {
            error = new Error('Reference not found');
            break;
        }

        if (!/^[\w:]+$/.test(value)) {
            error = new Error('Reference value includes illegal characters');
            break;
        }

        path += value;

    }

    return error ? error : path;
};

internals.payloadRegex = /^\$(\d+)(?:\.([^\s\$]*))?/;

internals.requestRegex = /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g;

internals.parsePayload = function (obj) {

    const payloadParts = [];

    if (!obj) {
        return null;
    }

    Traverse(obj).forEach(function (value) {

        if (typeof value !== 'string') {
            return;
        }

        const match = internals.payloadRegex.exec(value);

        if (!match) {
            return;
        }

        payloadParts.push({
            path: this.path,
            resultIndex: match[1],
            resultPath: match[2]
        });
    });

    return payloadParts;
};

internals.evalResults = function (results, index, path) {

    const result = results[index];

    if (!path) {
        return result;
    }

    return Hoek.reach(result, path) || {};
};

internals.buildPayload = function (payload, resultsData, parts) {

    const partsLength = parts.length;
    let result;
    let part;
    for ( let i = 0; i < partsLength; ++i) {

        part = parts[i];
        result = internals.evalResults(resultsData.resultsMap, part.resultIndex, part.resultPath);

        if (!part.path.length) {
            payload = result;
        }
        else {
            Traverse(payload).set(part.path, result);
        }
    }

    return payload;
};

internals.batch = function (batchRequest, resultsData, pos, requestParts, payloadParts, callback) {

    const path = internals.buildPath(resultsData, pos, requestParts);

    if (path instanceof Error) {
        resultsData.results[pos] = path;
        return callback(path);
    }

    // Make request
    const request = batchRequest.payload.requests[pos];

    request.path = path;

    if (payloadParts && payloadParts.length) {

        // Make payload
        request.payload = internals.buildPayload(
            request.payload,
            resultsData,
            payloadParts
        );
    }

    internals.dispatch(batchRequest, request, (data) => {

        // If redirection
        if (('' + data.statusCode).indexOf('3') === 0) {
            request.path = data.headers.location;
            internals.dispatch(batchRequest, request, (batchData) => {

                const batchResult = batchData.result;

                resultsData.results[pos] = batchResult;
                resultsData.resultsMap[pos] = batchResult;
                callback(null, batchResult);
            });
            return;
        }

        const result = data.result;
        resultsData.results[pos] = result;
        resultsData.resultsMap[pos] = result;
        callback(null, result);
    });
};

internals.dispatch = function (batchRequest, request, callback) {

    let path;

    if (request.query) {
        path = Url.format({
            pathname: request.path,
            query: request.query
        });
    }
    else {
        path = request.path;
    }

    const body = (request.payload !== null && request.payload !== undefined ? JSON.stringify(request.payload) : null);
    const injectOptions = {
        url: path,
        method: request.method,
        headers: batchRequest.headers,
        payload: body,
        session: batchRequest.session
    };
    if (batchRequest.server.connections.length === 1) {
        batchRequest.server.inject(injectOptions, callback);
    }
    else {
        batchRequest.connection.inject(injectOptions, callback);
    }
};
<|endoftext|>