<commit_before>/**
 * @file Host detection, non-UMD loader
 * @since 0.1.5
 */
/*#ifndef(UMD)*/
"use strict";
/*exported _GPF_HOST*/ // Host types
/*exported _GpfFunc*/ // Function
/*exported _gpfBootImplByHost*/ // Boot host specific implementation per host
/*exported _gpfDosPath*/ // DOS-like path
/*exported _gpfEmptyFunc*/ // An empty function
/*exported _gpfExit*/ // Exit function
/*exported _gpfHost*/ // Host type
/*exported _gpfIgnore*/ // Helper to remove unused parameter warning
/*exported _gpfMainContext*/ // Main context object
/*exported _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*exported _gpfNodeFs*/ // Node/PhantomJS require("fs")
/*exported _gpfSyncReadSourceJSON*/ // Reads a source json file (only in source mode)
/*exported _gpfVersion*/ // GPF version
/*exported _gpfWebDocument*/ // Browser document object
/*exported _gpfWebWindow*/ // Browser window object
/*eslint-disable no-unused-vars*/
/*#endif*/

/*jshint browser: true, node: true, phantom: true, rhino: true, wsh: true*/
/*eslint-env browser, node, phantomjs, rhino, wsh*/

// An empty function
function _gpfEmptyFunc () {}

var
    /**
     * GPF Version
     * @since 0.1.5
     */
    _gpfVersion = "0.2.6-alpha",

    /**
     * Host constants
     * @since 0.1.5
     */
    _GPF_HOST = {
        BROWSER:    "browser",
        NASHORN:    "nashorn",
        NODEJS:     "nodejs",
        PHANTOMJS:  "phantomjs",
        RHINO:      "rhino",
        UNKNOWN:    "unknown",
        WSCRIPT:    "wscript"
    },

    /**
     * Current host type
     *
     * @type {_GPF_HOST}
     * @since 0.1.5
     */
    _gpfHost = _GPF_HOST.UNKNOWN,

    /**
     * Indicates that paths are DOS-like (i.e. case insensitive with /)
     * @since 0.1.5
     */
    _gpfDosPath = false,

    // https://github.com/jshint/jshint/issues/525
    _GpfFunc = Function, // avoid JSHint error

    /*jshint -W040*/ // This is the common way to get the global context
    /**
     * Main context object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfMainContext = new _GpfFunc("return this")(), // Non-strict function returns global context
    /*jshint +W040*/

    /**
     * Helper to ignore unused parameter
     *
     * @param {*} param
     * @since 0.1.5
     */
    /*gpf:nop*/ _gpfIgnore = _gpfEmptyFunc,

    /**
     * Exit function
     *
     * @param {Number} code
     * @since 0.1.5
     */
    _gpfExit = _gpfEmptyFunc,

    /**
     * Browser window object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfWebWindow,

    /**
     * Browser [document](https://developer.mozilla.org/en-US/docs/Web/API/Document) object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfWebDocument,

    /**
     * [Scripting.FileSystemObject](https://msdn.microsoft.com/en-us/library/aa711216(v=vs.71).aspx) Object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfMsFSO,

    /**
     * Node [require("fs")](https://nodejs.org/api/fs.html)
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfNodeFs,

    /**
     * Boot host specific implementation per host
     *
     * @type {Object}
     * @since 0.2.1
     */
    _gpfBootImplByHost = {};

/*#ifdef(DEBUG)*/

_gpfVersion += "-debug";

/*#endif*/

/*#ifndef(UMD)*/

_gpfVersion += "-source";

/**
 * Synchronous read function
 *
 * @param {String} srcFileName
 * @return {String} content of the srcFileName
 * @since 0.1.5
 */
var _gpfSyncReadForBoot;

/*#endif*/

/* Host detection */

// Microsoft cscript / wscript
if ("undefined" !== typeof WScript) {
    _gpfHost = _GPF_HOST.WSCRIPT;

    /*#ifndef(UMD)*/
    /*eslint-disable new-cap*/

    _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");

    _gpfSyncReadForBoot = function (srcFileName) {
        var srcFile = _gpfMsFSO.OpenTextFile(srcFileName, 1),
            srcContent = srcFile.ReadAll();
        srcFile.Close();
        return srcContent;
    };

    /*eslint-enable new-cap*/
    /*#endif*/

} else if ("undefined" !== typeof print && "undefined" !== typeof java) {

    if ("undefined" === typeof readFile) {
        _gpfHost = _GPF_HOST.NASHORN;

        /*#ifndef(UMD)*/

        _gpfSyncReadForBoot = function (srcFileName) {
            return [].join.call(java.nio.file.Files.readAllLines(java.nio.file.Paths.get(srcFileName)), "\n");
        };

        /*#endif*/

    } else {
        _gpfHost = _GPF_HOST.RHINO;

        /*#ifndef(UMD)*/

        _gpfSyncReadForBoot = readFile;

        /*#endif*/

    }

// PhantomJS - When used as a command line (otherwise considered as a browser)
} else if ("undefined" !== typeof phantom && phantom.version && !document.currentScript) {
    _gpfHost = _GPF_HOST.PHANTOMJS;
    _gpfMainContext = window;

    /*#ifndef(UMD)*/

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.read(srcFileName);
    };

    /*#endif*/

// Nodejs
} else if ("undefined" !== typeof module && module.exports) {
    _gpfHost = _GPF_HOST.NODEJS;
    _gpfMainContext = global;

    /*#ifndef(UMD)*/
    /*eslint-disable no-sync*/ // Simpler this way

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.readFileSync(srcFileName).toString();
    };

    /*#endif*/

// Browser
/* istanbul ignore else */ // unknown.1
} else if ("undefined" !== typeof window) {
    _gpfHost = _GPF_HOST.BROWSER;
    _gpfMainContext = window;

    /*#ifndef(UMD)*/

    _gpfSyncReadForBoot = function (srcFileName) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", srcFileName, false);
        xhr.send();
        return xhr.responseText;
    };

    /*#endif*/

}

/*#ifndef(UMD)*/

/**
 * Loading sources occurs here for the non UMD version.
 * UMD versions (debug / release) will have everything concatenated.
 * @since 0.1.5
 */

// Need to create the gpf name 'manually'
_gpfMainContext.gpf = {
    internals: {} // To support testable internals
};

/**
 * Contains the root path of GPF sources
 *
 * @name gpfSourcesPath
 * @type {String}
 * @private
 * @since 0.0.1
 */

/**
 * Reads a source file (only in source mode)
 *
 * NOTE this method is available only when running the source version
 *
 * @param {String} sourceFileName Source file name (relative to src folder)
 * @return {String} Source content
 * @since 0.1.7
 */
function _gpfSyncReadSourceJSON (sourceFileName) {
    /*jslint evil: true*/
    var result;
    eval("result = " + _gpfSyncReadForBoot(gpfSourcesPath + sourceFileName) + ";"); //eslint-disable-line no-eval
    return result;
}

function _gpfProcessSource (source, allContent) {
    if (source.load !== false) {
        allContent.push(_gpfSyncReadForBoot(gpfSourcesPath + source.name + ".js"));
    }
}

/**
 * Load content of all sources
 *
 * @return {String} Consolidated sources
 * @since 0.1.9
 */
function _gpfLoadSources () { //jshint ignore:line
    var sourceListContent = _gpfSyncReadForBoot(gpfSourcesPath + "sources.json"),
        _gpfSources = _GpfFunc("return " + sourceListContent)(),
        allContent = [],
        idx = 0;
    for (; idx < _gpfSources.length; ++idx) {
        _gpfProcessSource(_gpfSources[idx], allContent);
    }
    return allContent.join("\n");
}

/*jshint ignore:start*/ // Best way I found
eval(_gpfLoadSources()); //eslint-disable-line no-eval
/*jshint ignore:end*/

/*#endif*/
<commit_msg>Removes _gpfBootImplByHost<commit_after>/**
 * @file Host detection, non-UMD loader
 * @since 0.1.5
 */
/*#ifndef(UMD)*/
"use strict";
/*exported _GPF_HOST*/ // Host types
/*exported _GpfFunc*/ // Function
/*exported _gpfDosPath*/ // DOS-like path
/*exported _gpfEmptyFunc*/ // An empty function
/*exported _gpfExit*/ // Exit function
/*exported _gpfHost*/ // Host type
/*exported _gpfIgnore*/ // Helper to remove unused parameter warning
/*exported _gpfMainContext*/ // Main context object
/*exported _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*exported _gpfNodeFs*/ // Node/PhantomJS require("fs")
/*exported _gpfSyncReadSourceJSON*/ // Reads a source json file (only in source mode)
/*exported _gpfVersion*/ // GPF version
/*exported _gpfWebDocument*/ // Browser document object
/*exported _gpfWebWindow*/ // Browser window object
/*eslint-disable no-unused-vars*/
/*#endif*/

/*jshint browser: true, node: true, phantom: true, rhino: true, wsh: true*/
/*eslint-env browser, node, phantomjs, rhino, wsh*/

// An empty function
function _gpfEmptyFunc () {}

var
    /**
     * GPF Version
     * @since 0.1.5
     */
    _gpfVersion = "0.2.6-alpha",

    /**
     * Host constants
     * @since 0.1.5
     */
    _GPF_HOST = {
        BROWSER:    "browser",
        NASHORN:    "nashorn",
        NODEJS:     "nodejs",
        PHANTOMJS:  "phantomjs",
        RHINO:      "rhino",
        UNKNOWN:    "unknown",
        WSCRIPT:    "wscript"
    },

    /**
     * Current host type
     *
     * @type {_GPF_HOST}
     * @since 0.1.5
     */
    _gpfHost = _GPF_HOST.UNKNOWN,

    /**
     * Indicates that paths are DOS-like (i.e. case insensitive with /)
     * @since 0.1.5
     */
    _gpfDosPath = false,

    // https://github.com/jshint/jshint/issues/525
    _GpfFunc = Function, // avoid JSHint error

    /*jshint -W040*/ // This is the common way to get the global context
    /**
     * Main context object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfMainContext = new _GpfFunc("return this")(), // Non-strict function returns global context
    /*jshint +W040*/

    /**
     * Helper to ignore unused parameter
     *
     * @param {*} param
     * @since 0.1.5
     */
    /*gpf:nop*/ _gpfIgnore = _gpfEmptyFunc,

    /**
     * Exit function
     *
     * @param {Number} code
     * @since 0.1.5
     */
    _gpfExit = _gpfEmptyFunc,

    /**
     * Browser window object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfWebWindow,

    /**
     * Browser [document](https://developer.mozilla.org/en-US/docs/Web/API/Document) object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfWebDocument,

    /**
     * [Scripting.FileSystemObject](https://msdn.microsoft.com/en-us/library/aa711216(v=vs.71).aspx) Object
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfMsFSO,

    /**
     * Node [require("fs")](https://nodejs.org/api/fs.html)
     *
     * @type {Object}
     * @since 0.1.5
     */
    _gpfNodeFs;

/*#ifdef(DEBUG)*/

_gpfVersion += "-debug";

/*#endif*/

/*#ifndef(UMD)*/

_gpfVersion += "-source";

/**
 * Synchronous read function
 *
 * @param {String} srcFileName
 * @return {String} content of the srcFileName
 * @since 0.1.5
 */
var _gpfSyncReadForBoot;

/*#endif*/

/* Host detection */

// Microsoft cscript / wscript
if ("undefined" !== typeof WScript) {
    _gpfHost = _GPF_HOST.WSCRIPT;

    /*#ifndef(UMD)*/
    /*eslint-disable new-cap*/

    _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");

    _gpfSyncReadForBoot = function (srcFileName) {
        var srcFile = _gpfMsFSO.OpenTextFile(srcFileName, 1),
            srcContent = srcFile.ReadAll();
        srcFile.Close();
        return srcContent;
    };

    /*eslint-enable new-cap*/
    /*#endif*/

} else if ("undefined" !== typeof print && "undefined" !== typeof java) {

    if ("undefined" === typeof readFile) {
        _gpfHost = _GPF_HOST.NASHORN;

        /*#ifndef(UMD)*/

        _gpfSyncReadForBoot = function (srcFileName) {
            return [].join.call(java.nio.file.Files.readAllLines(java.nio.file.Paths.get(srcFileName)), "\n");
        };

        /*#endif*/

    } else {
        _gpfHost = _GPF_HOST.RHINO;

        /*#ifndef(UMD)*/

        _gpfSyncReadForBoot = readFile;

        /*#endif*/

    }

// PhantomJS - When used as a command line (otherwise considered as a browser)
} else if ("undefined" !== typeof phantom && phantom.version && !document.currentScript) {
    _gpfHost = _GPF_HOST.PHANTOMJS;
    _gpfMainContext = window;

    /*#ifndef(UMD)*/

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.read(srcFileName);
    };

    /*#endif*/

// Nodejs
} else if ("undefined" !== typeof module && module.exports) {
    _gpfHost = _GPF_HOST.NODEJS;
    _gpfMainContext = global;

    /*#ifndef(UMD)*/
    /*eslint-disable no-sync*/ // Simpler this way

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.readFileSync(srcFileName).toString();
    };

    /*#endif*/

// Browser
/* istanbul ignore else */ // unknown.1
} else if ("undefined" !== typeof window) {
    _gpfHost = _GPF_HOST.BROWSER;
    _gpfMainContext = window;

    /*#ifndef(UMD)*/

    _gpfSyncReadForBoot = function (srcFileName) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", srcFileName, false);
        xhr.send();
        return xhr.responseText;
    };

    /*#endif*/

}

/*#ifndef(UMD)*/

/**
 * Loading sources occurs here for the non UMD version.
 * UMD versions (debug / release) will have everything concatenated.
 * @since 0.1.5
 */

// Need to create the gpf name 'manually'
_gpfMainContext.gpf = {
    internals: {} // To support testable internals
};

/**
 * Contains the root path of GPF sources
 *
 * @name gpfSourcesPath
 * @type {String}
 * @private
 * @since 0.0.1
 */

/**
 * Reads a source file (only in source mode)
 *
 * NOTE this method is available only when running the source version
 *
 * @param {String} sourceFileName Source file name (relative to src folder)
 * @return {String} Source content
 * @since 0.1.7
 */
function _gpfSyncReadSourceJSON (sourceFileName) {
    /*jslint evil: true*/
    var result;
    eval("result = " + _gpfSyncReadForBoot(gpfSourcesPath + sourceFileName) + ";"); //eslint-disable-line no-eval
    return result;
}

function _gpfProcessSource (source, allContent) {
    if (source.load !== false) {
        allContent.push(_gpfSyncReadForBoot(gpfSourcesPath + source.name + ".js"));
    }
}

/**
 * Load content of all sources
 *
 * @return {String} Consolidated sources
 * @since 0.1.9
 */
function _gpfLoadSources () { //jshint ignore:line
    var sourceListContent = _gpfSyncReadForBoot(gpfSourcesPath + "sources.json"),
        _gpfSources = _GpfFunc("return " + sourceListContent)(),
        allContent = [],
        idx = 0;
    for (; idx < _gpfSources.length; ++idx) {
        _gpfProcessSource(_gpfSources[idx], allContent);
    }
    return allContent.join("\n");
}

/*jshint ignore:start*/ // Best way I found
eval(_gpfLoadSources()); //eslint-disable-line no-eval
/*jshint ignore:end*/

/*#endif*/
<|endoftext|>


<commit_before>const theme = require('./theme');

function filterByStandardDeviation(data, standardDeviationFactor) {
  let sum = 0;
  let sumOfSquares = 0;
  for (let i = 0; i < data.length; i++) {
    sum += data[i].duration;
    sumOfSquares += data[i].duration * data[i].duration;
  }
  const mean = sum / data.length;
  const variance = sumOfSquares / data.length - mean * mean;
  const standardDeviation = Math.sqrt(variance);
  const filteredData = [];
  for (let i = 0; i < data.length; i++) {
    if (mean - standardDeviationFactor * standardDeviation < data[i].duration &&
      data[i].duration < mean + standardDeviationFactor * standardDeviation) {
      filteredData.push(data[i]);
    }
  }
  return filteredData;
}

function* renderBuildTimes(res, data, title, metric) {
  const filteredData = filterByStandardDeviation(data, 3);
  const chart = {
    type: 'bar',
    data: {
      labels: filteredData.map(value => new Date(value.timestamp).toLocaleDateString()),
      datasets: [
        {
          label: 'Successful builds',
          data: filteredData.map(value => (value.result === 'SUCCESS' ? value.duration : null)),
          backgroundColor: theme.buildResultToBackgroundColor('SUCCESS'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('SUCCESS')
        },
        {
          label: 'Unstable builds',
          data: filteredData.map(value => (value.result === 'UNSTABLE' ? value.duration : null)),
          backgroundColor: theme.buildResultToBackgroundColor('UNSTABLE'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('UNSTABLE')
        }
      ]
    },
    options: {
      title: {
        text: title,
        display: true
      },
      scales: {
        xAxes: [{
          stacked: true
        }],
        yAxes: [{
          stacked: true,
          ticks: {}
        }]
      },
      maintainAspectRatio: false
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric,
    isFirefox: res.state.userAgent.isFirefox
  };
  yield res.render('templates/charts/_buildtimes', templateParameters);
}

function* renderTestResults(res, data, title, metric) {
  const chart = {
    type: 'bar',
    data: {
      labels: data.map(value => new Date(value.timestamp).toLocaleDateString()),
      datasets: [
        {
          label: 'Successful tests',
          data: data.map(value => value.successful),
          backgroundColor: theme.buildResultToBackgroundColor('SUCCESS'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('SUCCESS')
        },
        {
          label: 'Failed tests',
          data: data.map(value => value.failed),
          backgroundColor: theme.buildResultToBackgroundColor('FAILURE'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('FAILURE')
        },
        {
          label: 'Skipped tests',
          data: data.map(value => value.skipped),
          backgroundColor: theme.buildResultToBackgroundColor('ABORTED'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('ABORTED')
        }
      ]
    },
    options: {
      title: {
        text: title,
        display: true
      },
      scales: {
        xAxes: [{
          stacked: true
        }],
        yAxes: [{
          stacked: true
        }]
      },
      maintainAspectRatio: false
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric,
    isFirefox: res.state.userAgent.isFirefox
  };
  yield res.render('templates/charts/_chart', templateParameters);
}

function* renderTestResultDistribution(res, data, title, metric) {
  const labels = ['SUCCESSFUL', 'FAILED', 'SKIPPED'];
  const chart = {
    type: 'pie',
    data: {
      labels,
      datasets: [{
        data: [data.successful, data.failed, data.skipped],
        backgroundColor: labels.map(theme.testResultToBackgroundColor),
        hoverBackgroundColor: labels.map(theme.testResultToHoverBackgroundColor)
      }]
    },
    options: {
      title: {
        display: true,
        text: title
      },
      maintainAspectRatio: true
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric
  };
  yield res.render('templates/charts/_buildresults', templateParameters);
}

function* renderBuildResults(res, data, title, metric) {
  const chart = createBuildResultPieChart(title,
    data.map(value => value.group),
    data.map(value => value.reduction));
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric
  };
  yield res.render('templates/charts/_buildresults', templateParameters);
}

function createBuildResultPieChart(title, labels, values) {
  return {
    type: 'pie',
    data: {
      labels,
      datasets: [{
        data: values,
        backgroundColor: labels.map(theme.buildResultToBackgroundColor),
        hoverBackgroundColor: labels.map(theme.buildResultToHoverBackgroundColor)
      }]
    },
    options: {
      title: {
        display: true,
        text: title
      },
      maintainAspectRatio: true
    }
  };
}

module.exports = {
  renderBuildTimes,
  renderBuildResults,
  renderTestResults,
  renderTestResultDistribution
};
<commit_msg>Rename the labels on Successful and unsuccessful builds to singular build, looks more logical on the labels.<commit_after>const theme = require('./theme');

function filterByStandardDeviation(data, standardDeviationFactor) {
  let sum = 0;
  let sumOfSquares = 0;
  for (let i = 0; i < data.length; i++) {
    sum += data[i].duration;
    sumOfSquares += data[i].duration * data[i].duration;
  }
  const mean = sum / data.length;
  const variance = sumOfSquares / data.length - mean * mean;
  const standardDeviation = Math.sqrt(variance);
  const filteredData = [];
  for (let i = 0; i < data.length; i++) {
    if (mean - standardDeviationFactor * standardDeviation < data[i].duration &&
      data[i].duration < mean + standardDeviationFactor * standardDeviation) {
      filteredData.push(data[i]);
    }
  }
  return filteredData;
}

function* renderBuildTimes(res, data, title, metric) {
  const filteredData = filterByStandardDeviation(data, 3);
  const chart = {
    type: 'bar',
    data: {
      labels: filteredData.map(value => new Date(value.timestamp).toLocaleDateString()),
      datasets: [
        {
          label: 'Successful build',
          data: filteredData.map(value => (value.result === 'SUCCESS' ? value.duration : null)),
          backgroundColor: theme.buildResultToBackgroundColor('SUCCESS'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('SUCCESS')
        },
        {
          label: 'Unstable build',
          data: filteredData.map(value => (value.result === 'UNSTABLE' ? value.duration : null)),
          backgroundColor: theme.buildResultToBackgroundColor('UNSTABLE'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('UNSTABLE')
        }
      ]
    },
    options: {
      title: {
        text: title,
        display: true
      },
      scales: {
        xAxes: [{
          stacked: true
        }],
        yAxes: [{
          stacked: true,
          ticks: {}
        }]
      },
      maintainAspectRatio: false
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric,
    isFirefox: res.state.userAgent.isFirefox
  };
  yield res.render('templates/charts/_buildtimes', templateParameters);
}

function* renderTestResults(res, data, title, metric) {
  const chart = {
    type: 'bar',
    data: {
      labels: data.map(value => new Date(value.timestamp).toLocaleDateString()),
      datasets: [
        {
          label: 'Successful tests',
          data: data.map(value => value.successful),
          backgroundColor: theme.buildResultToBackgroundColor('SUCCESS'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('SUCCESS')
        },
        {
          label: 'Failed tests',
          data: data.map(value => value.failed),
          backgroundColor: theme.buildResultToBackgroundColor('FAILURE'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('FAILURE')
        },
        {
          label: 'Skipped tests',
          data: data.map(value => value.skipped),
          backgroundColor: theme.buildResultToBackgroundColor('ABORTED'),
          hoverBackgroundColor: theme.buildResultToHoverBackgroundColor('ABORTED')
        }
      ]
    },
    options: {
      title: {
        text: title,
        display: true
      },
      scales: {
        xAxes: [{
          stacked: true
        }],
        yAxes: [{
          stacked: true
        }]
      },
      maintainAspectRatio: false
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric,
    isFirefox: res.state.userAgent.isFirefox
  };
  yield res.render('templates/charts/_chart', templateParameters);
}

function* renderTestResultDistribution(res, data, title, metric) {
  const labels = ['SUCCESSFUL', 'FAILED', 'SKIPPED'];
  const chart = {
    type: 'pie',
    data: {
      labels,
      datasets: [{
        data: [data.successful, data.failed, data.skipped],
        backgroundColor: labels.map(theme.testResultToBackgroundColor),
        hoverBackgroundColor: labels.map(theme.testResultToHoverBackgroundColor)
      }]
    },
    options: {
      title: {
        display: true,
        text: title
      },
      maintainAspectRatio: true
    }
  };
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric
  };
  yield res.render('templates/charts/_buildresults', templateParameters);
}

function* renderBuildResults(res, data, title, metric) {
  const chart = createBuildResultPieChart(title,
    data.map(value => value.group),
    data.map(value => value.reduction));
  const templateParameters = {
    chart,
    jobName: res.params.jobName,
    metric
  };
  yield res.render('templates/charts/_buildresults', templateParameters);
}

function createBuildResultPieChart(title, labels, values) {
  return {
    type: 'pie',
    data: {
      labels,
      datasets: [{
        data: values,
        backgroundColor: labels.map(theme.buildResultToBackgroundColor),
        hoverBackgroundColor: labels.map(theme.buildResultToHoverBackgroundColor)
      }]
    },
    options: {
      title: {
        display: true,
        text: title
      },
      maintainAspectRatio: true
    }
  };
}

module.exports = {
  renderBuildTimes,
  renderBuildResults,
  renderTestResults,
  renderTestResultDistribution
};
<|endoftext|>


<commit_before>var fs = require('fs');
var ursa = require('ursa');
var dgram = require('dgram');
var tls = require('tls');
var net = require('net');
var mongoose = require('mongoose');

mongoose.connect("mongodb://localhost/raspi");

json_scheme = {
	name : String,
	id : String
};

var raschi_data = mongoose.model("raschi_data", new mongoose.Schema(json_scheme) );

/**
 * 公開鍵と秘密鍵と証明書ファイルへのパスを指定します。
 *

 *
{@link children_client~create_tlsclient}
 *
{@link children_client~register_client_with_mongodb}
 *
{@link children_client~register_to_db}
 *
{@link children_client~start_udp_server}
 *
{@link children_client~send_to_mpserver}
 *
{@link children_client~connect_to_mpserver}
 *
{@link children_client~listen_tcp_server}
 *
{@link children_client~connect_to_children}
 *
{@link children_client~send_command_to_children}
 *
{@link children_client.message_parse}
 *
{@link children_client.start}
 *

 * @constructor
 * @classdesc 子機との通信を管理するクラス
 * @param {string} public_key_path - 公開鍵へのパス
 * @param {string} private_key_path - 秘密鍵へのパス
 * @param {string} crt_file_path - 証明書へのパス
 */
var children_client = function(public_key_path,private_key_path,crt_file_path){
	var th = this;

	/* -------------------------- SSL Module ----------------------*/
	//ssl module class

	/**
	 * 秘密鍵と公開鍵へのパスを指定します。
	 *

	 *
 {@link ssl_module.decrypt}
	 *
 {@link ssl_module.encrypt}
	 *

	 * @constructor
	 * @classdesc UDPの通信の際に送られてきたデータを復号化するクラスです。
	 * @param {string} pubpath - 公開鍵へのパス
	 * @param {string} pripath - 秘密鍵へのパス
	 */
	var ssl_module = function(pubpath,pripath){
		/**
		 * 復号化に利用する秘密鍵オブジェクト
		 */
		var key = ursa.createPrivateKey(fs.readFileSync(pripath));

		/**
		 * 暗号化に利用する公開鍵オブジェクト
		 */
		var crt = ursa.createPublicKey(fs.readFileSync(pubpath));

		/**
		 * メッセージを復号化する
		 * @param {string} msg - 復号化する文字列
		 * @return {string} 復号化した文字列
		 */
		this.decrypt = function(msg){
			return key.decrypt(msg,'base64','utf8');
		};

		/**
		 * メッセージを暗号化する
		 * @param {string} msg - 暗号化する文字列
		 * @return {string} 暗号化した文字列
		 */
		this.encrypt = function(msg){
			return crt.encrypt(msg,'utf8','base64');
		};
	};

	/**
	 * {@link ssl_module} のインスタンス
	 * @type {ssl_module}
	 */
	var sslm = new ssl_module(public_key_path,private_key_path);

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

	/*-------------------------- TLS CLient -----------------------*/
	//tls_client class
	//
	/**
	 * 子機に接続しているソケットとその子機のguidを指定します。
	 *

	 *
{@link tls_client.write}
	 *

	 * @constructor
	 * @classdesc 子機との通信をするTLSのクライアントのクラス
	 * @param {tls.TLSSocket} socket - [tls.TLSSocket]{@link http://u111u.info/mnHq} のインスタンス
	 * @param {string} guid - 接続している子機のguid
	 */
	var tls_client = function(socket,guid){
		/**
		 * tlsのソケット
		 */
		this.socket = socket;
		/**
		 * 接続状態の確認
		 */

		var connection = true;
		/**
		 * 子機のGUID
		 * @type {string}
		 */
		this.guid = guid;
		/**
		 * メッセージを送信します
		 * @param {string} str - 送信する文字列
		 */
		this.write = function(str){
			if(connection){
				try{
					this.socket.write(str,'utf-8');
				}catch(ex){
					console.log("[CHILDREN CLIENT] [TLS CLIENT] Message Write Error: " + ex.stack);
				}
			}
			return connection;
		};

		/**
		 * ソケットでエラーが発生した場合の関数
		 * @method
		 * @listens error
		 */
		this.socket.on("error",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET]  " + ex.stack);
		});

		/**
		 * ソケットがオープンした時
		 */
		var socket_this = this;
		this.socket.on("connect",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET]  Open Connection " + socket_this.guid);
		});

		/**
		 * ソケットがクローズした場合
		 */
		this.socket.on("close",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET] Close Connection to " + socket_this.guid);
			connection = false;
		});

		/**
		 * ソケットからデータが来た場合の関数
		 */
		this.socket.on('data',function(str){
			console.log("[CHILDREN CLIENT] [TLS CLIENT] Message recived:" + str);
			th.message_parse(str);
		});
	};

	/**
	 * tls_clientの設定
	 */
	var option = {
		ca: fs.readFileSync(crt_file_path),
		rejectUnauthorized:false
	};

	/**
	 * {@link tls_client}のインスタンス
	 */
	var tls_clients = {};
	/**
	 * 子機と接続するtls_clientを作成します
	 *
	 * @param {string} guid - 子機のguid
	 * @param {dgram.rinfo} rinfo - 子機のアドレス情報 {@link http://u111u.info/momf}
	 */
	var create_tlsclient = function(guid,port,rinfo){
			var socket = tls.connect(port,rinfo.address,option);
			//TODO
			//子機に命令を送るときにtls_clientsのguidから判別するのではなくいい感じにtls_client.guidから判別したい
			tls_clients[guid] = new tls_client(socket,guid);
	};
	//-------------------------------------------------------------------

	/*------------------------- Mongoose -------------------------------*/

	/**
	 * 子機情報をmongodbに保存
	 * @param {Object} obj - 子機情報のjson
	 */
	var register_client_with_mongodb = function(obj){
		var item = new raschi_data(
				{name:obj["name"],id:obj["guid"]}
				);
		item.save(function(e){console.log("add:"+JSON.stringify(item));});
	};

	/**
	 * 子機情報をデータベースに保存するかどうかを判定する
	 * @param {Object} obj - 子機情報のjson
	 */
	var register_to_db = function(obj){
		raschi_data.find({},function(err,docs){
			var id = -1;
			for(var i=0,size =docs.length;i < size; ++i){
				if(docs[i].id == obj["guid"]) id = docs[i].id;
			}
			console.log(id);
			if(id == -1){
				register_client_with_mongodb(obj);
			}
		});
	};

	/**
	 * guidから子機の名前を取り出します
	 * @param {string} guid - 子機のid
	 */
	var search_name_from_db = function(guid){
		raschi_data.find({},function(err,docs){
			var name = "";
			for(var i=0,size = docs.length; i< size; ++i){
				if(docs[i].id = guid) name = docs[i].name;
			}
			return name;
		});
	};

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

	/* ------------------------- UDP Server -----------------------------*/

	/**
	 * udpのサーバーのポート番号
	 * @type {num}
	 */
	var udp_server_port = 8000;
	/**
	 * udpのサーバーのインスタンス
	 */
	var udp_server = dgram.createSocket("udp4");

	/**
	 * udp_serverでエラーが起きた際のプログラム
	 */
	udp_server.on("error",function(err){
		console.log("[CHILDREN CLIENT] [UDP SERVER] Server error: " + err.stack);
	});

	/**
	 * updサーバーでメッセージを受け取った時のプログラム
	 */
	udp_server.on("message",function(msg,rinfo){
		console.log("[CHILDREN CLIENT] [UDP SERVER] message comming:");
		connect_to_children(msg,rinfo);
	});

	/**
	 * UDPサーバーをスタートさせます
	 */
	var start_udp_server = function(){
		udp_server.bind(8000,"0.0.0.0");
		console.log("[CHILDREN CLIENT] [UDP SERVER] OPEN UDP SERVER");
	};

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

	/* ------------------ TCP Server And Client ----------------*/
	// Client

	/**
	 * メッセージサーバーのポート番号
	 * @type {num}
	 */
	var tcp_client_port = 12000;
	/**
	 * メッセージパーサーサーバーに接続するクライアント
	 */
	var tcp_client = new net.Socket({readable:true,writable:true});

	/**
	 * メッセージパーサーに接続するのが失敗した時
	 */
	tcp_client.on('error',function(error){
		tcp_client.connect({port:th.tcp_client_port});
	});

	/**
	 * メッセージサーバーにメッセージを送信するプログラム
	 *
	 * @param {string} str - 送信する文字列
	 */
	var send_to_mpserver = function(str){
		return tcp_client.write(str);
	};

	/**
	 * メッセージパーサーサーバーに接続します
	 */
	var connect_to_mpserver = function(){
		tcp_client.connect({port:tcp_client_port},function(){
			console.log("[CHILDREN CLIENT] [TCP CLIENT] CONNECT TO MPSERVER");
		});
	};

	// Server

	/**
	 * メッセージパーサからのクライアントを受け付けるサーバーのポート番号
	 * @type {num}
	 */
	var tcp_server_port = 20000;

	/**
	 * メッセージパーサー用TCPサーバーのインスタンス
	 */
	var tcp_server = new net.Server(function(socket){
		console.log("[CHILDREN CLIENT] [TCP SERVER] CONNECT CLIENT");
		connect_to_mpserver();
		socket.on('error',function(){
			console.log("[CHILDREN CLIENT] [TCP SERVER] SOCKET ERROR");
		});
		socket.on('data',function(str){
			send_command_to_children(str);
		});
	});

	/**
	 * メッセージサーバー用サーバーがエラーを起こした時
	 */
	tcp_server.on('error',function(){
		console.log("[CHILDREN CLIENT] [TCP SERVER] SERVER ERROR");
	});
	/**
	 * メッセージサーバー用TCPサーバーの待機を始める
	 */
	var listen_tcp_server = function(){
		tcp_server.listen(tcp_server_port,function(){
			console.log("[CHILDREN CLIENT] [TCP SERVER] SERVER LISTEN START");
		});
	};

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

	/**
	 * UDPサーバーで受け取ったデータを元に子機に接続する
	 *
	 * @param {string} str - UDPで受信したメッセージ
	 * @param {dgram.rinfo} client_info - 子機のアドレス情報 {@link http://u111u.info/momf}
	 */
	var connect_to_children = function(str,client_info){
		json_str = sslm.decrypt(str.toString('utf8',0,client_info.size));
		obj = JSON.parse(json_str);
		register_to_db(obj);
		create_tlsclient(obj.guid,obj.port,client_info);
	};
	/**
	 * 子機に命令を送信する
	 *
	 * @param {string} str - 子機に送る命令の文字列
	 */
	var send_command_to_children = function(str){
		json_obj = JSON.parse(str);
		message = JSON.stringify(json_obj["message"]);
		if(!tls_clients[json_obj.id].write(message)){
			var error_obj = new Error("Connection Refused");
			var name = search_name_from_db(json_obj.id);
			var obj = {
					"type" : "result",
					"value": {
						"id" : json_obj.id,
						"name" : name,
						"value" : {
							"functionName" : json_obj.function,
							"hasError" : true,
							"cancelled" : true,
							"error" : error_obj,
							"result" : undefined
						}
					}
			};
			send_to_mpserver(JSON.stringify(obj));
		}
	};

	/**
	 * メッセージをパースする
	 *
	 * @param {string} str - パースする文字列
	 */
	this.message_parse = function(str){
		send_to_mpserver(str);
	};

	/**
	 * UDPサーバーとTCPサーバーをスタートさせる
	 */
	this.start = function(){
		start_udp_server();
		listen_tcp_server();
	};
};

module.exports = children_client;
<commit_msg>Add jsondoc comment and console.log udp message<commit_after>var fs = require('fs');
var ursa = require('ursa');
var dgram = require('dgram');
var tls = require('tls');
var net = require('net');
var mongoose = require('mongoose');

mongoose.connect("mongodb://localhost/raspi");

json_scheme = {
	name : String,
	id : String
};

var raschi_data = mongoose.model("raschi_data", new mongoose.Schema(json_scheme) );

/**
 * 公開鍵と秘密鍵と証明書ファイルへのパスを指定します。
 *

 *
{@link children_client~create_tlsclient}
 *
{@link children_client~register_client_with_mongodb}
 *
{@link children_client~register_to_db}
 *
{@link children_client~start_udp_server}
 *
{@link children_client~send_to_mpserver}
 *
{@link children_client~connect_to_mpserver}
 *
{@link children_client~listen_tcp_server}
 *
{@link children_client~connect_to_children}
 *
{@link children_client~send_command_to_children}
 *
{@link children_client.message_parse}
 *
{@link children_client.start}
 *

 * @constructor
 * @classdesc 子機との通信を管理するクラス
 * @param {string} public_key_path - 公開鍵へのパス
 * @param {string} private_key_path - 秘密鍵へのパス
 * @param {string} crt_file_path - 証明書へのパス
 */
var children_client = function(public_key_path,private_key_path,crt_file_path){
	var th = this;

	/* -------------------------- SSL Module ----------------------*/
	//ssl module class

	/**
	 * 秘密鍵と公開鍵へのパスを指定します。
	 *

	 *
 {@link ssl_module.decrypt}
	 *
 {@link ssl_module.encrypt}
	 *

	 * @constructor
	 * @classdesc UDPの通信の際に送られてきたデータを復号化するクラスです。
	 * @param {string} pubpath - 公開鍵へのパス
	 * @param {string} pripath - 秘密鍵へのパス
	 */
	var ssl_module = function(pubpath,pripath){
		/**
		 * 復号化に利用する秘密鍵オブジェクト
		 */
		var key = ursa.createPrivateKey(fs.readFileSync(pripath));

		/**
		 * 暗号化に利用する公開鍵オブジェクト
		 */
		var crt = ursa.createPublicKey(fs.readFileSync(pubpath));

		/**
		 * メッセージを復号化する
		 * @param {string} msg - 復号化する文字列
		 * @return {string} 復号化した文字列
		 */
		this.decrypt = function(msg){
			return key.decrypt(msg,'base64','utf8');
		};

		/**
		 * メッセージを暗号化する
		 * @param {string} msg - 暗号化する文字列
		 * @return {string} 暗号化した文字列
		 */
		this.encrypt = function(msg){
			return crt.encrypt(msg,'utf8','base64');
		};
	};

	/**
	 * {@link ssl_module} のインスタンス
	 * @type {ssl_module}
	 */
	var sslm = new ssl_module(public_key_path,private_key_path);

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

	/*-------------------------- TLS CLient -----------------------*/
	//tls_client class
	//
	/**
	 * 子機に接続しているソケットとその子機のguidを指定します。
	 *

	 *
{@link tls_client.write}
	 *

	 * @constructor
	 * @classdesc 子機との通信をするTLSのクライアントのクラス
	 * @param {tls.TLSSocket} socket - [tls.TLSSocket]{@link http://u111u.info/mnHq} のインスタンス
	 * @param {string} guid - 接続している子機のguid
	 */
	var tls_client = function(socket,guid){
		/**
		 * tlsのソケット
		 */
		this.socket = socket;
		/**
		 * 接続状態の確認
		 */

		var connection = true;
		/**
		 * 子機のGUID
		 * @type {string}
		 */
		this.guid = guid;
		/**
		 * メッセージを送信します
		 * @param {string} str - 送信する文字列
		 */
		this.write = function(str){
			if(connection){
				try{
					this.socket.write(str,'utf-8');
				}catch(ex){
					console.log("[CHILDREN CLIENT] [TLS CLIENT] Message Write Error: " + ex.stack);
				}
			}
			return connection;
		};

		/**
		 * ソケットでエラーが発生した場合の関数
		 * @method
		 * @listens error
		 */
		this.socket.on("error",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET]  " + ex.stack);
		});

		/**
		 * ソケットがオープンした時
		 */
		var socket_this = this;
		this.socket.on("connect",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET]  Open Connection " + socket_this.guid);
		});

		/**
		 * ソケットがクローズした場合
		 */
		this.socket.on("close",function(ex){
			console.log("[CHILDREN CLIENT] [TLS CLINET] Close Connection to " + socket_this.guid);
			connection = false;
		});

		/**
		 * ソケットからデータが来た場合の関数
		 */
		this.socket.on('data',function(str){
			console.log("[CHILDREN CLIENT] [TLS CLIENT] Message recived:" + str);
			th.message_parse(str);
		});
	};

	/**
	 * tls_clientの設定
	 */
	var option = {
		ca: fs.readFileSync(crt_file_path),
		rejectUnauthorized:false
	};

	/**
	 * {@link tls_client}のインスタンス
	 */
	var tls_clients = {};
	/**
	 * 子機と接続するtls_clientを作成します
	 *
	 * @param {string} guid - 子機のguid
	 * @param {dgram.rinfo} rinfo - 子機のアドレス情報 {@link http://u111u.info/momf}
	 * @param {num} port - ポート番号
	 */
	var create_tlsclient = function(guid,port,rinfo){
			var socket = tls.connect(port,rinfo.address,option);
			//TODO
			//子機に命令を送るときにtls_clientsのguidから判別するのではなくいい感じにtls_client.guidから判別したい
			tls_clients[guid] = new tls_client(socket,guid);
	};
	//-------------------------------------------------------------------

	/*------------------------- Mongoose -------------------------------*/

	/**
	 * 子機情報をmongodbに保存
	 * @param {Object} obj - 子機情報のjson
	 */
	var register_client_with_mongodb = function(obj){
		var item = new raschi_data(
				{name:obj["name"],id:obj["guid"]}
				);
		item.save(function(e){console.log("add:"+JSON.stringify(item));});
	};

	/**
	 * 子機情報をデータベースに保存するかどうかを判定する
	 * @param {Object} obj - 子機情報のjson
	 */
	var register_to_db = function(obj){
		raschi_data.find({},function(err,docs){
			var id = -1;
			for(var i=0,size =docs.length;i < size; ++i){
				if(docs[i].id == obj["guid"]) id = docs[i].id;
			}
			console.log(id);
			if(id == -1){
				register_client_with_mongodb(obj);
			}
		});
	};

	/**
	 * guidから子機の名前を取り出します
	 * @param {string} guid - 子機のid
	 */
	var search_name_from_db = function(guid){
		raschi_data.find({},function(err,docs){
			var name = "";
			for(var i=0,size = docs.length; i< size; ++i){
				if(docs[i].id = guid) name = docs[i].name;
			}
			return name;
		});
	};

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

	/* ------------------------- UDP Server -----------------------------*/

	/**
	 * udpのサーバーのポート番号
	 * @type {num}
	 */
	var udp_server_port = 8000;
	/**
	 * udpのサーバーのインスタンス
	 */
	var udp_server = dgram.createSocket("udp4");

	/**
	 * udp_serverでエラーが起きた際のプログラム
	 */
	udp_server.on("error",function(err){
		console.log("[CHILDREN CLIENT] [UDP SERVER] Server error: " + err.stack);
	});

	/**
	 * updサーバーでメッセージを受け取った時のプログラム
	 */
	udp_server.on("message",function(msg,rinfo){
		console.log("[CHILDREN CLIENT] [UDP SERVER] message comming:");
		connect_to_children(msg,rinfo);
	});

	/**
	 * UDPサーバーをスタートさせます
	 */
	var start_udp_server = function(){
		udp_server.bind(8000,"0.0.0.0");
		console.log("[CHILDREN CLIENT] [UDP SERVER] OPEN UDP SERVER");
	};

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

	/* ------------------ TCP Server And Client ----------------*/
	// Client

	/**
	 * メッセージサーバーのポート番号
	 * @type {num}
	 */
	var tcp_client_port = 12000;
	/**
	 * メッセージパーサーサーバーに接続するクライアント
	 */
	var tcp_client = new net.Socket({readable:true,writable:true});

	/**
	 * メッセージパーサーに接続するのが失敗した時
	 */
	tcp_client.on('error',function(error){
		tcp_client.connect({port:th.tcp_client_port});
	});

	/**
	 * メッセージサーバーにメッセージを送信するプログラム
	 *
	 * @param {string} str - 送信する文字列
	 */
	var send_to_mpserver = function(str){
		return tcp_client.write(str);
	};

	/**
	 * メッセージパーサーサーバーに接続します
	 */
	var connect_to_mpserver = function(){
		tcp_client.connect({port:tcp_client_port},function(){
			console.log("[CHILDREN CLIENT] [TCP CLIENT] CONNECT TO MPSERVER");
		});
	};

	// Server

	/**
	 * メッセージパーサからのクライアントを受け付けるサーバーのポート番号
	 * @type {num}
	 */
	var tcp_server_port = 20000;

	/**
	 * メッセージパーサー用TCPサーバーのインスタンス
	 */
	var tcp_server = new net.Server(function(socket){
		console.log("[CHILDREN CLIENT] [TCP SERVER] CONNECT CLIENT");
		connect_to_mpserver();
		socket.on('error',function(){
			console.log("[CHILDREN CLIENT] [TCP SERVER] SOCKET ERROR");
		});
		socket.on('data',function(str){
			send_command_to_children(str);
		});
	});

	/**
	 * メッセージサーバー用サーバーがエラーを起こした時
	 */
	tcp_server.on('error',function(){
		console.log("[CHILDREN CLIENT] [TCP SERVER] SERVER ERROR");
	});
	/**
	 * メッセージサーバー用TCPサーバーの待機を始める
	 */
	var listen_tcp_server = function(){
		tcp_server.listen(tcp_server_port,function(){
			console.log("[CHILDREN CLIENT] [TCP SERVER] SERVER LISTEN START");
		});
	};

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

	/**
	 * UDPサーバーで受け取ったデータを元に子機に接続する
	 *
	 * @param {string} str - UDPで受信したメッセージ
	 * @param {dgram.rinfo} client_info - 子機のアドレス情報 {@link http://u111u.info/momf}
	 */
	var connect_to_children = function(str,client_info){
		json_str = sslm.decrypt(str.toString('utf8',0,client_info.size));
		console.log(json_str);
		obj = JSON.parse(json_str);
		register_to_db(obj);
		create_tlsclient(obj.guid,obj.port,client_info);
	};
	/**
	 * 子機に命令を送信する
	 *
	 * @param {string} str - 子機に送る命令の文字列
	 */
	var send_command_to_children = function(str){
		json_obj = JSON.parse(str);
		message = JSON.stringify(json_obj["message"]);
		if(!tls_clients[json_obj.id].write(message)){
			var error_obj = new Error("Connection Refused");
			var name = search_name_from_db(json_obj.id);
			var obj = {
					"type" : "result",
					"value": {
						"id" : json_obj.id,
						"name" : name,
						"value" : {
							"functionName" : json_obj.function,
							"hasError" : true,
							"cancelled" : true,
							"error" : error_obj,
							"result" : undefined
						}
					}
			};
			send_to_mpserver(JSON.stringify(obj));
		}
	};

	/**
	 * メッセージをパースする
	 *
	 * @param {string} str - パースする文字列
	 */
	this.message_parse = function(str){
		send_to_mpserver(str);
	};

	/**
	 * UDPサーバーとTCPサーバーをスタートさせる
	 */
	this.start = function(){
		start_udp_server();
		listen_tcp_server();
	};
};

module.exports = children_client;
<|endoftext|>


<commit_before>/*global $, castform, clone, isArray, has, seq, throttle, extend, load, check, pass, submit */

/**
 * Easy to validate form fields on change with synchronous and asyncrhonous
 * validation functions.
 *
 * Requirements
 * * jQuery
 * * twitter bootstrap
 *
 * Optional
 * * jStorage - optional
 */

/**
 * Creates a function that validates a string from a given RegExp.
 *
 * @param {RegExp} regexp
 * @return {Function(String)}
 */
function createRegexpValidator(regexp) {
  return function regexpValidator(a) {
    return regexp.test(a);
  };
}

/**
 * Creates a function that will be used for sequential execution.
 *
 * @param {Object} validate Options for validating a field.
 * @param {String} fieldValue
 * @return {Function(Function)}
 */
function createSeqFn(validate, fieldValue) {
  if (validate.async) {
    return function(callback) {
      validate.fn(fieldValue, function(pass, msg) {
        var v = clone(validate);
        v.msg = msg || v.msg;
        callback(pass, v);
      });
    };

  } else {
    return function(callback) {
      callback(validate.fn(fieldValue), validate);
    };
  }
}

/**
 * Give continuous validity feedback on a single-item text input form
 *
 * @param {jQuery} $submit Submit button.
 * @param {String} name
 * @param {Object} options Options that includes the element to watch.
 * @param {Object} parentOptions
 */
function bindValidation($submit, name, options, parentOptions) {
  var $field = options.$field;

  extend(options, parentOptions);

  if (!isArray(options.validate)) {
    options.validate = [options.validate];
  }

  // Check validation settings.
  for (var i = 0, len = options.validate.length; i < len; i++) {
    var v = options.validate[i];
    if (v instanceof RegExp || typeof v === 'function') {
      v = options.validate[i] = { fn: v };
    }

    // Throttle async functions to half a second by default.
    if (v.fn.length > 1) {
      v.fn = throttle(v.fn, v.delay || 500);
      v.async = true;
      /*
    } else if (v.delay) {
      v.fn = throttle(v.fn, v.delay);
      v.async = true;
      */
    }

    // Allow regexps for validation.
    if (v.fn instanceof RegExp) {
      v.fn = createRegexpValidator(v.fn);
    }

    // Add a default error message.
    if (!v.msg) {
      v.msg = 'Validation failed';
    }
  }

  var success = createSuccess($submit, $field, options);
  var fail = createFail($submit, $field, options);
  var check = createCheckFieldValue($field, name, options,
    success, fail);

  // Listen for the field changing value.
  $field.on('keypress input paste', check);

  // Use session storage if available and enabled.
  if ($.jStorage) {
    if (options.storage.session) {
      var storedValue = $.jStorage.get(name);
      if (storedValue && (options.storage.force || !$field.val())) {
        $field.val(storedValue);
      }
    }

    // Restore stored results if available.
    if (options.cache && options.storage.cache) {
      options.storage.keys = $.jStorage.get(name + '::keys', []);
      for (i = 0, len = options.storage.length; i < len; i++) {
        var key = options.storage.keys[i];
        var storageKey = name + '::result::' + key;
        options.cache[key] = $.jStorage.get(storageKey);
      }
      console.log('local cache');
      console.log(options.cache);
    }
  }

  // Call check function once when the page loads.
  if (options.load) {
    options.load($field, options);
  }
  check(null, true);
}

/**
 * Returns a function that when called considers a field to pass validation.
 *
 * @param {jQuery} $submit
 * @param {jQuery} $field
 * @param {Object} options
 * @returns {Function(Boolean)}
 */
function createSuccess($submit, $field, options) {
  return function success(pageLoad) {
    $field.data('validating', false);
    $field.data('errMsg', null);

    // Call given pass function.
    options.pass($field, options, pageLoad, true);

    // Check if submit button can be enabled by checking if every field
    // in the form is either not required or not currently validating and
    // its current value did not fail validation.
    for (var key in options.fields) {
      if (has(options.fields, key)) {
        var field = options.fields[key];
        var $element = field.$field;
        if (field.required &&
            (!$element.val() || $element.data('validating') ||
             $element.data('errMsg'))) return;
      }
    }

    $submit.removeAttr('disabled');
  };
}

/**
 * Returns a function that when called considers a field to have failed
 * validation.
 *
 * @param {jQuery} $submit
 * @param {jQuery} $field
 * @param {Object} options
 * @returns {Function(string)}
 */
function createFail($submit, $field, options) {
  return function fail(pageLoad, validate) {
    $field.data('errMsg', validate.msg);

    // Call the pass function.
    options.pass($field, options, pageLoad, false, validate);

    // Since there was an error, disable submit button.
    $submit.attr('disabled', 'disabled');
  };
}

/**
 * Returns a function that when called checks value
 * of a field and validates it.
 *
 * @param {jQuery} $field
 * @param {String} name
 * @param {Object} options Options that includes the element to watch.
 * @param {Function} success
 * @param {Function} failure
 * @returns {Function(Event, Boolean)}
 */
function createCheckFieldValue($field, name, options, success, fail) {
  var validate = options.validate;
  var lastValue;

  // Called when finish validating.
  var onValidate = createValidationFinished(name, options, success, fail);

  return function check(event, pageLoad) {
    var fieldValue = $field.val();

    // Check value does not equal last value.
    if (fieldValue === lastValue) return;
    lastValue = fieldValue;

    // Check cache.
    if (options.cache) {
      var cachedResult = options.cache[fieldValue];
      if (cachedResult) {
        // Use last cached result if available.
        onValidate(fieldValue, false, pageLoad,
          cachedResult[0], { msg: cachedResult[1] });
        return;
      }
    }

    // Store in browser session.
    if (options.storage.session && $.jStorage) {
      $.jStorage.set(name, fieldValue);
    }

    if (!fieldValue) {
      if (options.required) {
        fail(pageLoad, { msg: 'This field is required' });

      } else {
        success(pageLoad);
      }
      return;
    }

    var asyncInvolved = false;
    var funcs = [];
    for (var i = 0, len = validate.length; i < len; i++) {
      var v = validate[i];
      funcs[i] = createSeqFn(v, fieldValue);
      if (v.async) {
        asyncInvolved = true;
      }
    }

    // Mark this field as validating.
    $field.data('validating', true);

    // Let the `check` option know that this field is being checked.
    if (options.check) {
      options.check($field, options, pageLoad, asyncInvolved);
    }

    // Call validation functions in sequential order.
    seq(funcs, function(pass, msg) {
      onValidate(fieldValue, asyncInvolved, pageLoad, pass, msg);
    });
  };
}

/**
 * Returns a function that is called when all of a field's
 * validating functions have finished.
 *
 * @param {String} field
 * @param {Object} options
 * @param {Function} success
 * @param {Function} fail
 * @returns {Function(string, boolean, boolean, string)}
 */
function createValidationFinished(field, options, success, fail) {
  var $field = options.$field;

  return function validationFinished(value, async, pageLoad, pass, validate) {
    if (options.cache) {
      var result = [pass, validate ? validate.msg : null];
      options.cache[value] = result;

      if (options.storage.cache) {
        options.storage.keys.push(value);
        if ($.jStorage) {
          $.jStorage.set(field + '::keys', options.storage.keys);
          $.jStorage.set(field + '::result::' + value, result);
        }
      }
    }

    // Check if field value is still the same.
    if (!async || value === $field.val()) {
      if (pass) {
        success(false);
      } else {
        fail(pageLoad, validate);
      }
    }
  };
}

/**
 * Validates form fields every time a user changes their value.
 * If any of them fail validation, submit button is disabled.
 * Check marks or X'es are placed to the right of a text field when it is
 * validated.
 *
 * @param {String} formID
 * @param {Object} options Hash containing data with keys as CSS selectors
 *   of the fields and values as their validation objects used with
 *   bindValidation().
 */
castform.validateForm = function validateForm(formID, options) {
  var $form = $(formID);
  if (!$form.length) throw Error('non-existant form id: ' + formID);
  var $submit = $form.find('[type="submit"]');

  // Default options.
  var defaults = {
    cache: {}
  , validate: []
  , required: false
  , delay: false
  , storage: { session: false, force: false, cache: false }
  , load: load
  , check: check
  , pass: pass
  , submit: submit
  };

  extend(options, defaults);

  for (var key in options.fields) {
    if (has(options.fields, key)) {
      var field = options.fields[key];
      field.$field = $form.find('[name="' + key + '"]');
      if (!field.$field.length) {
        throw Error('Form field `' + key + '` not found');
      }

      bindValidation($submit, key, field, options);
    }
  }

  options.load($submit, options);
  $form.submit(function(e) {
    $submit.attr('disabled', 'disabled');
    e.preventDefault();
    options.submit($submit, options);

    // Gather up all field values.
    var values = {};
    for (var key in options.fields) {
      if (has(options.fields, key)) {
        values[key] = options.fields[key].$field.val();
      }
    }

    // Remote call to let the server know the form has been submitted.
    castform.remoteCall('submit', formID, values, function(success, msg) {
      if (!success) {
        $submit.removeAttr('disabled');
      }
      options.formPass.client(success, msg);
    });
  });

  return $form;
};
<commit_msg>call client formPass function with window<commit_after>/*global $, castform, clone, isArray, has, seq, throttle, extend, load, check, pass, submit */

/**
 * Easy to validate form fields on change with synchronous and asyncrhonous
 * validation functions.
 *
 * Requirements
 * * jQuery
 * * twitter bootstrap
 *
 * Optional
 * * jStorage - optional
 */

/**
 * Creates a function that validates a string from a given RegExp.
 *
 * @param {RegExp} regexp
 * @return {Function(String)}
 */
function createRegexpValidator(regexp) {
  return function regexpValidator(a) {
    return regexp.test(a);
  };
}

/**
 * Creates a function that will be used for sequential execution.
 *
 * @param {Object} validate Options for validating a field.
 * @param {String} fieldValue
 * @return {Function(Function)}
 */
function createSeqFn(validate, fieldValue) {
  if (validate.async) {
    return function(callback) {
      validate.fn(fieldValue, function(pass, msg) {
        var v = clone(validate);
        v.msg = msg || v.msg;
        callback(pass, v);
      });
    };

  } else {
    return function(callback) {
      callback(validate.fn(fieldValue), validate);
    };
  }
}

/**
 * Give continuous validity feedback on a single-item text input form
 *
 * @param {jQuery} $submit Submit button.
 * @param {String} name
 * @param {Object} options Options that includes the element to watch.
 * @param {Object} parentOptions
 */
function bindValidation($submit, name, options, parentOptions) {
  var $field = options.$field;

  extend(options, parentOptions);

  if (!isArray(options.validate)) {
    options.validate = [options.validate];
  }

  // Check validation settings.
  for (var i = 0, len = options.validate.length; i < len; i++) {
    var v = options.validate[i];
    if (v instanceof RegExp || typeof v === 'function') {
      v = options.validate[i] = { fn: v };
    }

    // Throttle async functions to half a second by default.
    if (v.fn.length > 1) {
      v.fn = throttle(v.fn, v.delay || 500);
      v.async = true;
      /*
    } else if (v.delay) {
      v.fn = throttle(v.fn, v.delay);
      v.async = true;
      */
    }

    // Allow regexps for validation.
    if (v.fn instanceof RegExp) {
      v.fn = createRegexpValidator(v.fn);
    }

    // Add a default error message.
    if (!v.msg) {
      v.msg = 'Validation failed';
    }
  }

  var success = createSuccess($submit, $field, options);
  var fail = createFail($submit, $field, options);
  var check = createCheckFieldValue($field, name, options,
    success, fail);

  // Listen for the field changing value.
  $field.on('keypress input paste', check);

  // Use session storage if available and enabled.
  if ($.jStorage) {
    if (options.storage.session) {
      var storedValue = $.jStorage.get(name);
      if (storedValue && (options.storage.force || !$field.val())) {
        $field.val(storedValue);
      }
    }

    // Restore stored results if available.
    if (options.cache && options.storage.cache) {
      options.storage.keys = $.jStorage.get(name + '::keys', []);
      for (i = 0, len = options.storage.length; i < len; i++) {
        var key = options.storage.keys[i];
        var storageKey = name + '::result::' + key;
        options.cache[key] = $.jStorage.get(storageKey);
      }
      console.log('local cache');
      console.log(options.cache);
    }
  }

  // Call check function once when the page loads.
  if (options.load) {
    options.load($field, options);
  }
  check(null, true);
}

/**
 * Returns a function that when called considers a field to pass validation.
 *
 * @param {jQuery} $submit
 * @param {jQuery} $field
 * @param {Object} options
 * @returns {Function(Boolean)}
 */
function createSuccess($submit, $field, options) {
  return function success(pageLoad) {
    $field.data('validating', false);
    $field.data('errMsg', null);

    // Call given pass function.
    options.pass($field, options, pageLoad, true);

    // Check if submit button can be enabled by checking if every field
    // in the form is either not required or not currently validating and
    // its current value did not fail validation.
    for (var key in options.fields) {
      if (has(options.fields, key)) {
        var field = options.fields[key];
        var $element = field.$field;
        if (field.required &&
            (!$element.val() || $element.data('validating') ||
             $element.data('errMsg'))) return;
      }
    }

    $submit.removeAttr('disabled');
  };
}

/**
 * Returns a function that when called considers a field to have failed
 * validation.
 *
 * @param {jQuery} $submit
 * @param {jQuery} $field
 * @param {Object} options
 * @returns {Function(string)}
 */
function createFail($submit, $field, options) {
  return function fail(pageLoad, validate) {
    $field.data('errMsg', validate.msg);

    // Call the pass function.
    options.pass($field, options, pageLoad, false, validate);

    // Since there was an error, disable submit button.
    $submit.attr('disabled', 'disabled');
  };
}

/**
 * Returns a function that when called checks value
 * of a field and validates it.
 *
 * @param {jQuery} $field
 * @param {String} name
 * @param {Object} options Options that includes the element to watch.
 * @param {Function} success
 * @param {Function} failure
 * @returns {Function(Event, Boolean)}
 */
function createCheckFieldValue($field, name, options, success, fail) {
  var validate = options.validate;
  var lastValue;

  // Called when finish validating.
  var onValidate = createValidationFinished(name, options, success, fail);

  return function check(event, pageLoad) {
    var fieldValue = $field.val();

    // Check value does not equal last value.
    if (fieldValue === lastValue) return;
    lastValue = fieldValue;

    // Check cache.
    if (options.cache) {
      var cachedResult = options.cache[fieldValue];
      if (cachedResult) {
        // Use last cached result if available.
        onValidate(fieldValue, false, pageLoad,
          cachedResult[0], { msg: cachedResult[1] });
        return;
      }
    }

    // Store in browser session.
    if (options.storage.session && $.jStorage) {
      $.jStorage.set(name, fieldValue);
    }

    if (!fieldValue) {
      if (options.required) {
        fail(pageLoad, { msg: 'This field is required' });

      } else {
        success(pageLoad);
      }
      return;
    }

    var asyncInvolved = false;
    var funcs = [];
    for (var i = 0, len = validate.length; i < len; i++) {
      var v = validate[i];
      funcs[i] = createSeqFn(v, fieldValue);
      if (v.async) {
        asyncInvolved = true;
      }
    }

    // Mark this field as validating.
    $field.data('validating', true);

    // Let the `check` option know that this field is being checked.
    if (options.check) {
      options.check($field, options, pageLoad, asyncInvolved);
    }

    // Call validation functions in sequential order.
    seq(funcs, function(pass, msg) {
      onValidate(fieldValue, asyncInvolved, pageLoad, pass, msg);
    });
  };
}

/**
 * Returns a function that is called when all of a field's
 * validating functions have finished.
 *
 * @param {String} field
 * @param {Object} options
 * @param {Function} success
 * @param {Function} fail
 * @returns {Function(string, boolean, boolean, string)}
 */
function createValidationFinished(field, options, success, fail) {
  var $field = options.$field;

  return function validationFinished(value, async, pageLoad, pass, validate) {
    if (options.cache) {
      var result = [pass, validate ? validate.msg : null];
      options.cache[value] = result;

      if (options.storage.cache) {
        options.storage.keys.push(value);
        if ($.jStorage) {
          $.jStorage.set(field + '::keys', options.storage.keys);
          $.jStorage.set(field + '::result::' + value, result);
        }
      }
    }

    // Check if field value is still the same.
    if (!async || value === $field.val()) {
      if (pass) {
        success(false);
      } else {
        fail(pageLoad, validate);
      }
    }
  };
}

/**
 * Validates form fields every time a user changes their value.
 * If any of them fail validation, submit button is disabled.
 * Check marks or X'es are placed to the right of a text field when it is
 * validated.
 *
 * @param {String} formID
 * @param {Object} options Hash containing data with keys as CSS selectors
 *   of the fields and values as their validation objects used with
 *   bindValidation().
 */
castform.validateForm = function validateForm(formID, options) {
  var $form = $(formID);
  if (!$form.length) throw Error('non-existant form id: ' + formID);
  var $submit = $form.find('[type="submit"]');

  // Default options.
  var defaults = {
    cache: {}
  , validate: []
  , required: false
  , delay: false
  , storage: { session: false, force: false, cache: false }
  , load: load
  , check: check
  , pass: pass
  , submit: submit
  };

  extend(options, defaults);

  for (var key in options.fields) {
    if (has(options.fields, key)) {
      var field = options.fields[key];
      field.$field = $form.find('[name="' + key + '"]');
      if (!field.$field.length) {
        throw Error('Form field `' + key + '` not found');
      }

      bindValidation($submit, key, field, options);
    }
  }

  options.load($submit, options);
  $form.submit(function(e) {
    $submit.attr('disabled', 'disabled');
    e.preventDefault();
    options.submit($submit, options);

    // Gather up all field values.
    var values = {};
    for (var key in options.fields) {
      if (has(options.fields, key)) {
        values[key] = options.fields[key].$field.val();
      }
    }

    // Remote call to let the server know the form has been submitted.
    castform.remoteCall('submit', formID, values, function(success, msg) {
      if (!success) {
        $submit.removeAttr('disabled');
      }
      options.formPass.client(window, success, msg);
    });
  });

  return $form;
};
<|endoftext|>


<commit_before>(function(C2C, $) {

  /**
   * Set a pref_value for 'fold' cookie
   */
  function setFoldCookie(position, value) {
    value = value ? 't' : 'f';
    var date = new Date();
    date.setFullYear(date.getFullYear()+1);

    // retrieve current cookie value
    var cookie_value = /(?:^|;)\s?fold=([tfx]{20})(?:;|$)/.exec(document.cookie);
    cookie_value = cookie_value ? cookie_value[1] :  'xxxxxxxxxxxxxxxxxxxx'; // size 20

    // update position with value
    cookie_value = cookie_value.substr(0, position) +  value + cookie_value.substr(position + 1);
    document.cookie = 'fold=' + cookie_value + '; expires=' + date.toGMTString() + '; path=/';
  }

  /**
   * Save fold pref in cookie and profile
   */
  C2C.registerFoldStatus = function(pref_name, cookie_position, opened) {

    // if user logged, save pref in profile
    if ($('#name_to_use').length) {
      $.post('/users/savepref', {
        'name': pref_name + '_home_status',
        'value': !!opened
      });
    }

    // save pref in cookie
    setFoldCookie(cookie_position, opened);
  };

  /**
   * Hide or show an home section
   */
  function toggleHomeSectionView(container_id, cookie_position) {
    var div = $('#' + container_id + '_section_container');
    var title = $('#' + container_id + '_section_title, #' + container_id + '_toggle');

    var is_open = div.is(':visible');

    if (!is_open) {
      title.attr('title', C2C.section_close);
      if (/MSIE [67].0/.exec(navigator.userAgent)) {
        div.css('display', 'block'); // for ie6-7 only
      }
    } else {
      title.attr('title', C2C.section_open);
    }

    div.slideToggle(600);

    C2C.registerFoldStatus(container_id, cookie_position, !is_open);

    $('#' + container_id + ' .nav_box_top').toggleClass('small');
  }

  /**
   * Add some properties and observers to have '+' and '-' pictos for folding sections
   */
  function initHomeSections() {
    $('.nav_box_title, .home_title').mouseover(function() {
      var img = $(this).children(':first');
      var savedClass = img.attr('class').split(' ')[1];
      img.data('savedClass', savedClass)
        .removeClass(savedClass)
        .addClass('picto_' + ($(this).next().is(':visible') ? 'close' : 'open'));
    }).mouseout(function() {
      var img = $(this).children(':first');
      img.removeClass('picto_close picto_open')
        .addClass(img.data('savedClass'));
    });
  }

  function initSectionsToggle() {
    $('[data-toggle-view]').click(function (e) {
      var $this = $(this);
      e.preventDefault();
      e.stopPropagation();
      if (cp = parseInt($this.attr('data-cookie-position'), 10)) {
        toggleHomeSectionView($this.attr('data-toggle-view'), cp);
      } else {
        toggleView($this.attr('data-toggle-view'));
      }
    });
  }

  /**
   * Hide or show a container
   */
  function toggleView(container_id) {
    var alt, sign;
    var div = $('#' + container_id + '_section_container');

    var div_visible = div.is(':visible');

    if (div_visible) {
      alt = C2C.section_open;
      sign = '+';
    } else {
      alt = C2C.section_close;
      sign = '-';
    }

    $('#' + container_id + '_toggle').attr('alt', sign)
      .toggleClass('picto_open picto_close');
    $('#' + container_id + '_section_title').attr('title', alt);
    $('#tip_' + container_id).html('[' + alt + ']');

    div.slideToggle(400);
  }

  /**
   * Hide or show a single box (like weather box in outings)
   */
  C2C.toggleBox = function(box_id) {
    var alt, sign;
    var div = $('#' + box_id + '_box');

    if (!div.is(':visible')) {
      alt = C2C.section_close;
      sign = '-';
    } else {
      alt = C2C.section_open;
      sign = '+';
    }

    $('#toggle_' + box_id).attr('alt', sign)
      .toggleClass('picto_open_light picto_close_light');
    $('#' + box_id + '_box_title').attr('title', alt);

    div.slideToggle(200);
  };

  // show / hide routes (e.g. in summit pages) depending on user
  // selected activities

  function toggleRoutes(activity_id) {
    $('#' + activity_id).toggleClass('picto_open_light picto_close_light');
    $('.child_routes.' + activity_id).toggle(200);
  }

  C2C.handleRoutes = function() {
    var activity_id = $(this).attr('class').split(' ').pop();
    toggleRoutes(activity_id);
  };

  function showRoutes(activity_id) { // TODO refactoring needed :)
    toggleRoutes(activity_id);
  }

  function hideRoutes(activity_id) {
    toggleRoutes(activity_id);
  }

  function showAllRoutes() {
    var activities = $('#routes_section_container .title2');

    activities.each(function() {
      var activity_id = $(this).attr('class').split(' ').pop();
      showRoutes(activity_id);
    });
    window.location.href = '#routes_summary';
  }

  function hideAllRoutes() {
    var activities = $('#routes_section_container .title2');
    activities.each(function() {
      var activity_id = $(this).attr('class').split(' ').pop();
      hideRoutes(activity_id);
    });
  }

  /**
   * This function is called to hide routes depending on their activities and the user prefs
   */
  C2C.initRoutes = function() {
    var activities_to_show = $('#quick_switch').attr('class').split(' ');
    if (activities_to_show.length) {
      $('.child_routes').each(function() {
        var activity_id = $(this).attr('class').split(' ').pop();
        if ($.inArray(activity_id, activities_to_show)) {
          $(this).hide();
          $('#' + activity_id).toggleClass('picto_close_light picto_open_light');
        }
      });
    }
  };

  // toggle association form
  C2C.toggleForm = function(form_id) {
    $('#' + form_id + '_association').toggleClass('hide show');
  };

  function initRoutes() {
    // handle routes display
    $('#routes_section_container .title2').click(C2C.handleRoutes);
    $('#close_routes').click(hideAllRoutes);
    $('#open_routes').click(showAllRoutes);
  }

  // splitter and left navigation stuff

  /**
   * 0: splitter not displayed
   * 1: splitter will be displayed when timeout expires
   * 2: splitter displayed
   * 3: splitter will be hidden when timeout expires
   */
  var splitter_status = 0;

  function highlight_splitter(ypos) {
    $('#splitter, .ombre_haut_corner_left, .ombre_bas_corner_left').toggleClass('hl');
    $('body').append('

');
    set_splitter_pos(ypos);
    splitter_status = 2;
  }

  function unhighlight_splitter() {
    $('#splitter, .ombre_haut_corner_left, .ombre_bas_corner_left').toggleClass('hl');
    $('#splitter_arrow').remove();
    splitter_status = 0;
  }

  function set_splitter_pos(ypos) {
    var arrow = $('#splitter_arrow');
    var splitter = $('#splitter');
    var offset = splitter.offset().left;

    if (!arrow.length) { return; }

    if (splitter.hasClass('maximize')) {
      arrow.addClass('maximize');
      arrow.css('left', offset + 20 + 'px');
    } else {
      arrow.css('left', offset - 10 + 'px');
    }
    arrow.css('top', ypos + 'px');
  }

  function move_splitter_arrow(e) {
    set_splitter_pos(e.pageY);
  }

  function toggleHomeNav(savestatus) {
    // no left menu folding for ie6-7
    if (/MSIE [67].0/.exec(navigator.userAgent)) return;

    var wrapper = $('#wrapper_context');
    var splitter = $('#splitter');
    var wide = wrapper.hasClass('no_nav');

    $('.nav_box').toggle();
    wrapper.toggleClass('no_nav');
    splitter.toggleClass('maximize')
      .attr('title', splitter.data(wide ? 'title-reduce' : 'title-enlarge'));

    unhighlight_splitter();

    if (savestatus) {
      C2C.registerFoldStatus(C2C.nav_status_string, C2C.nav_status_cookie_position, wide);
    }
  }

  function toggleNav(savestatus) {
    // no left menu folding for ie6-7
    if (/MSIE [67].0/.exec(navigator.userAgent)) return;

    var content_box = $('#content_box');
    var splitter = $('#splitter');
    var wide = content_box.hasClass('wide');

    content_box.toggleClass('wide');
    splitter.toggleClass('maximize')
      .attr('title', splitter.data(wide ? 'title-reduce' : 'title-enlarge'));

    unhighlight_splitter();

    if (savestatus) {
      C2C.registerFoldStatus(C2C.nav_status_string, C2C.nav_status_cookie_position, wide);
    }
  }

  function initSplitter() {
    var splitter = $('#splitter');
    var splitter_timer = null;

    // handle splitter (but not for ie6-7)
    if (/MSIE [67].0/.exec(navigator.userAgent)) return;

    // init splitter title and class
    if ($('#content_box').hasClass('wide') || $('#wrapper_context').hasClass('no_nav')) {
      splitter.addClass('maximize').attr('title', splitter.data('title-enlarge'));
    } else {
      splitter.attr('title', splitter.data('title-reduce'));
    }

    // add event handlers on splitter
    splitter.mouseover(function(e) {
      switch (splitter_status) {
        case 3:
          clearTimeout(splitter_timer);
          splitter_status = 2;
          break;
        case 0:
          var _ypos = e.pageY;
          splitter_timer = setTimeout(function() {
            highlight_splitter(_ypos);
          }, 50);
          splitter_status = 1;
          break;
       }
    }).mouseout(function() {
      switch (splitter_status) {
        case 1:
          clearTimeout(splitter_timer);
          splitter_status = 0;
          break;
        case 2:
          splitter_timer = setTimeout(unhighlight_splitter, 600);
          splitter_status = 3;
          break;
        }
      }).mousemove(move_splitter_arrow)
      .click($('#wrapper_context').hasClass('home') ? toggleHomeNav : toggleNav);
  }

  // initialization

  $(function() {
    initSectionsToggle();
    initHomeSections();
    initRoutes();
    initSplitter();
  });

})(window.C2C = window.C2C || {}, jQuery);
<commit_msg>execute regexp only once<commit_after>(function(C2C, $) {

  var oldie = /MSIE [67].0/.exec(navigator.userAgent);

  /**
   * Set a pref_value for 'fold' cookie
   */
  function setFoldCookie(position, value) {
    value = value ? 't' : 'f';
    var date = new Date();
    date.setFullYear(date.getFullYear()+1);

    // retrieve current cookie value
    var cookie_value = /(?:^|;)\s?fold=([tfx]{20})(?:;|$)/.exec(document.cookie);
    cookie_value = cookie_value ? cookie_value[1] :  'xxxxxxxxxxxxxxxxxxxx'; // size 20

    // update position with value
    cookie_value = cookie_value.substr(0, position) +  value + cookie_value.substr(position + 1);
    document.cookie = 'fold=' + cookie_value + '; expires=' + date.toGMTString() + '; path=/';
  }

  /**
   * Save fold pref in cookie and profile
   */
  C2C.registerFoldStatus = function(pref_name, cookie_position, opened) {

    // if user logged, save pref in profile
    if ($('#name_to_use').length) {
      $.post('/users/savepref', {
        'name': pref_name + '_home_status',
        'value': !!opened
      });
    }

    // save pref in cookie
    setFoldCookie(cookie_position, opened);
  };

  /**
   * Hide or show an home section
   */
  function toggleHomeSectionView(container_id, cookie_position) {
    var div = $('#' + container_id + '_section_container');
    var title = $('#' + container_id + '_section_title, #' + container_id + '_toggle');

    var is_open = div.is(':visible');

    if (!is_open) {
      title.attr('title', C2C.section_close);
      if (oldie) {
        div.css('display', 'block'); // for ie6-7 only
      }
    } else {
      title.attr('title', C2C.section_open);
    }

    div.slideToggle(600);

    C2C.registerFoldStatus(container_id, cookie_position, !is_open);

    $('#' + container_id + ' .nav_box_top').toggleClass('small');
  }

  /**
   * Add some properties and observers to have '+' and '-' pictos for folding sections
   */
  function initHomeSections() {
    $('.nav_box_title, .home_title').mouseover(function() {
      var img = $(this).children(':first');
      var savedClass = img.attr('class').split(' ')[1];
      img.data('savedClass', savedClass)
        .removeClass(savedClass)
        .addClass('picto_' + ($(this).next().is(':visible') ? 'close' : 'open'));
    }).mouseout(function() {
      var img = $(this).children(':first');
      img.removeClass('picto_close picto_open')
        .addClass(img.data('savedClass'));
    });
  }

  function initSectionsToggle() {
    $('[data-toggle-view]').click(function (e) {
      var $this = $(this);
      e.preventDefault();
      e.stopPropagation();
      if (cp = parseInt($this.attr('data-cookie-position'), 10)) {
        toggleHomeSectionView($this.attr('data-toggle-view'), cp);
      } else {
        toggleView($this.attr('data-toggle-view'));
      }
    });
  }

  /**
   * Hide or show a container
   */
  function toggleView(container_id) {
    var alt, sign;
    var div = $('#' + container_id + '_section_container');

    var div_visible = div.is(':visible');

    if (div_visible) {
      alt = C2C.section_open;
      sign = '+';
    } else {
      alt = C2C.section_close;
      sign = '-';
    }

    $('#' + container_id + '_toggle').attr('alt', sign)
      .toggleClass('picto_open picto_close');
    $('#' + container_id + '_section_title').attr('title', alt);
    $('#tip_' + container_id).html('[' + alt + ']');

    div.slideToggle(400);
  }

  /**
   * Hide or show a single box (like weather box in outings)
   */
  C2C.toggleBox = function(box_id) {
    var alt, sign;
    var div = $('#' + box_id + '_box');

    if (!div.is(':visible')) {
      alt = C2C.section_close;
      sign = '-';
    } else {
      alt = C2C.section_open;
      sign = '+';
    }

    $('#toggle_' + box_id).attr('alt', sign)
      .toggleClass('picto_open_light picto_close_light');
    $('#' + box_id + '_box_title').attr('title', alt);

    div.slideToggle(200);
  };

  // show / hide routes (e.g. in summit pages) depending on user
  // selected activities

  function toggleRoutes(activity_id) {
    $('#' + activity_id).toggleClass('picto_open_light picto_close_light');
    $('.child_routes.' + activity_id).toggle(200);
  }

  C2C.handleRoutes = function() {
    var activity_id = $(this).attr('class').split(' ').pop();
    toggleRoutes(activity_id);
  };

  function showRoutes(activity_id) { // TODO refactoring needed :)
    toggleRoutes(activity_id);
  }

  function hideRoutes(activity_id) {
    toggleRoutes(activity_id);
  }

  function showAllRoutes() {
    var activities = $('#routes_section_container .title2');

    activities.each(function() {
      var activity_id = $(this).attr('class').split(' ').pop();
      showRoutes(activity_id);
    });
    window.location.href = '#routes_summary';
  }

  function hideAllRoutes() {
    var activities = $('#routes_section_container .title2');
    activities.each(function() {
      var activity_id = $(this).attr('class').split(' ').pop();
      hideRoutes(activity_id);
    });
  }

  /**
   * This function is called to hide routes depending on their activities and the user prefs
   */
  C2C.initRoutes = function() {
    var activities_to_show = $('#quick_switch').attr('class').split(' ');
    if (activities_to_show.length) {
      $('.child_routes').each(function() {
        var activity_id = $(this).attr('class').split(' ').pop();
        if ($.inArray(activity_id, activities_to_show)) {
          $(this).hide();
          $('#' + activity_id).toggleClass('picto_close_light picto_open_light');
        }
      });
    }
  };

  // toggle association form
  C2C.toggleForm = function(form_id) {
    $('#' + form_id + '_association').toggleClass('hide show');
  };

  function initRoutes() {
    // handle routes display
    $('#routes_section_container .title2').click(C2C.handleRoutes);
    $('#close_routes').click(hideAllRoutes);
    $('#open_routes').click(showAllRoutes);
  }

  // splitter and left navigation stuff

  /**
   * 0: splitter not displayed
   * 1: splitter will be displayed when timeout expires
   * 2: splitter displayed
   * 3: splitter will be hidden when timeout expires
   */
  var splitter_status = 0;

  function highlight_splitter(ypos) {
    $('#splitter, .ombre_haut_corner_left, .ombre_bas_corner_left').toggleClass('hl');
    $('body').append('

');
    set_splitter_pos(ypos);
    splitter_status = 2;
  }

  function unhighlight_splitter() {
    $('#splitter, .ombre_haut_corner_left, .ombre_bas_corner_left').toggleClass('hl');
    $('#splitter_arrow').remove();
    splitter_status = 0;
  }

  function set_splitter_pos(ypos) {
    var arrow = $('#splitter_arrow');
    var splitter = $('#splitter');
    var offset = splitter.offset().left;

    if (!arrow.length) { return; }

    if (splitter.hasClass('maximize')) {
      arrow.addClass('maximize');
      arrow.css('left', offset + 20 + 'px');
    } else {
      arrow.css('left', offset - 10 + 'px');
    }
    arrow.css('top', ypos + 'px');
  }

  function move_splitter_arrow(e) {
    set_splitter_pos(e.pageY);
  }

  function toggleHomeNav(savestatus) {
    // no left menu folding for ie6-7
    if (oldie) return;

    var wrapper = $('#wrapper_context');
    var splitter = $('#splitter');
    var wide = wrapper.hasClass('no_nav');

    $('.nav_box').toggle();
    wrapper.toggleClass('no_nav');
    splitter.toggleClass('maximize')
      .attr('title', splitter.data(wide ? 'title-reduce' : 'title-enlarge'));

    unhighlight_splitter();

    if (savestatus) {
      C2C.registerFoldStatus(C2C.nav_status_string, C2C.nav_status_cookie_position, wide);
    }
  }

  function toggleNav(savestatus) {
    // no left menu folding for ie6-7
    if (oldie) return;

    var content_box = $('#content_box');
    var splitter = $('#splitter');
    var wide = content_box.hasClass('wide');

    content_box.toggleClass('wide');
    splitter.toggleClass('maximize')
      .attr('title', splitter.data(wide ? 'title-reduce' : 'title-enlarge'));

    unhighlight_splitter();

    if (savestatus) {
      C2C.registerFoldStatus(C2C.nav_status_string, C2C.nav_status_cookie_position, wide);
    }
  }

  function initSplitter() {
    var splitter = $('#splitter');
    var splitter_timer = null;

    // handle splitter (but not for ie6-7)
    if (oldie) return;

    // init splitter title and class
    if ($('#content_box').hasClass('wide') || $('#wrapper_context').hasClass('no_nav')) {
      splitter.addClass('maximize').attr('title', splitter.data('title-enlarge'));
    } else {
      splitter.attr('title', splitter.data('title-reduce'));
    }

    // add event handlers on splitter
    splitter.mouseover(function(e) {
      switch (splitter_status) {
        case 3:
          clearTimeout(splitter_timer);
          splitter_status = 2;
          break;
        case 0:
          var _ypos = e.pageY;
          splitter_timer = setTimeout(function() {
            highlight_splitter(_ypos);
          }, 50);
          splitter_status = 1;
          break;
       }
    }).mouseout(function() {
      switch (splitter_status) {
        case 1:
          clearTimeout(splitter_timer);
          splitter_status = 0;
          break;
        case 2:
          splitter_timer = setTimeout(unhighlight_splitter, 600);
          splitter_status = 3;
          break;
        }
      }).mousemove(move_splitter_arrow)
      .click($('#wrapper_context').hasClass('home') ? toggleHomeNav : toggleNav);
  }

  // initialization

  $(function() {
    initSectionsToggle();
    initHomeSections();
    initRoutes();
    initSplitter();
  });

})(window.C2C = window.C2C || {}, jQuery);
<|endoftext|>


<commit_before>import response from "./response"

let user = {

  init(socket, element){ if(!element.length){ return }
    let email = element.attr('email')
    let userChannel   = socket.channel("user:" + email)
    userChannel.on("new_post", response.new_post)
    userChannel.on("delete_post", response.delete_post)
  }
}
export default user<commit_msg>Delete user.js<commit_after><|endoftext|>