<commit_before>module.exports = {

    /**
     * Validates a date object
     * @param {Date} date - an object instantiated with the new Date constructor
     */
    isValidDate(date) {
        if (Object.prototype.toString.call(date) !== "[object Date]") {
            return false;
        }
        return !isNaN(date.getTime());
    },

    /**
     * Return abbreviated week day name
     * @param {Date}
     * @return {String}
     */
    getDayNameAbbr(date) {
        if (typeof date !== 'object') {
            throw TypeError('Invalid Type');
        }
        let dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
        return dayNames[date.getDay()];
    },

    /**
     * Return name of the month
     * @param {Number|Date}
     * @return {String}
     */
    getMonthName(month) {
        let monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
        if (typeof month === 'object') {
            return monthNames[month.getMonth()];
        }
        if (typeof month === 'number') {
            return monthNames[month];
        }
        throw TypeError('Invalid type');
    },

    /**
     * Return an abbreviated version of the month
     * @param {Number|Date}
     * @return {String}
     */
    getMonthNameAbbr(month) {
        let monthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        if (typeof month === 'object') {
            return monthAbbr[month.getMonth()];
        }
        if (typeof month === 'number') {
            return monthAbbr[month];
        }
        throw TypeError('Invalid type');
    },

    /**
     * Returns a UTC date with timezone information removed
     * @param {Date} date
     * @return {Date}
     */
    convertToUTC(date) {
        return new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
    },

    /**
     * Return the number of days in the month
     * @param {Number} year
     * @param {Number} month
     * @return {Number}
     */
    daysInMonth(year, month) {
        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
    },

    /**
     * Alternative get total number of days in month
     * @param {Number} y
     * @param {Number} m
     * @return {Number}
     */
    getDaysInMonth(y, m) {
       return /8|3|5|10/.test(--m)?30:m==1?(!(y%4)&&y%100)||!(y%400)?29:28:31;
    },

    /**
     * Returns number of days between two dates
     * @param {Date} start
     * @param {Date} end
     * @return {Number}
     */
    dayDiff(start, end) {
        const MS_PER_DAY = 1000 * 60 * 60 * 24;

        // Discard the time and time-zone information.
        let utc1 = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
        let utc2 = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());

        return Math.floor((utc2 - utc1) / MS_PER_DAY);
    },

    /**
     * Get nth suffix for date
     * @param {Number} day
     * @return {String}
     */
    getNthSuffix(day) {
        switch (day) {
            case 1:
            case 21:
            case 31:
                return 'st';
            case 2:
            case 22:
                return 'nd';
            case 3:
            case 23:
                return 'rd';
            default:
                return 'th';
        }
    },

    /**
     * Formats date object
     * @param {Date}
     * @return {String}
     */
    formatDate(date, format) {
        let year = date.getFullYear()
        let month = date.getMonth() + 1
        let day = date.getDate()
        let monthName = this.getMonthName(date.getMonth())
        let str = format
            .replace(/yyyy/, year)
            .replace(/yy/, String(year).slice(2))
            .replace(/MMMM/, this.getMonthName(date.getMonth()))
            .replace(/MMM/, this.getMonthNameAbbr(date.getMonth()))
            .replace(/MM/, ('0' + month).slice(-2))
            .replace(/M(?!a)/, month)
            .replace(/dd/, ('0' + day).slice(-2))
            .replace(/d/, day)
            .replace(/S/, this.getNthSuffix(date.getDate()))

        return str;
    },

    /**
     * Creates an array of dates for each day in between two dates.
     * @param {Date} start
     * @param {Date} end
     * @return {Array}
     */
    createDateArray(start, end) {
        let dates = [];
        while (start <= end) {
            dates.push(new Date(start))
            start.setDate(start.getDate() + 1);
        }
        return dates;
    }

}
<commit_msg>add day name to formatDate<commit_after>module.exports = {

    /**
     * Validates a date object
     * @param {Date} date - an object instantiated with the new Date constructor
     */
    isValidDate(date) {
        if (Object.prototype.toString.call(date) !== "[object Date]") {
            return false;
        }
        return !isNaN(date.getTime());
    },

    /**
     * Return abbreviated week day name
     * @param {Date}
     * @return {String}
     */
    getDayNameAbbr(date) {
        if (typeof date !== 'object') {
            throw TypeError('Invalid Type');
        }
        let dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
        return dayNames[date.getDay()];
    },

    /**
     * Return name of the month
     * @param {Number|Date}
     * @return {String}
     */
    getMonthName(month) {
        let monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
        if (typeof month === 'object') {
            return monthNames[month.getMonth()];
        }
        if (typeof month === 'number') {
            return monthNames[month];
        }
        throw TypeError('Invalid type');
    },

    /**
     * Return an abbreviated version of the month
     * @param {Number|Date}
     * @return {String}
     */
    getMonthNameAbbr(month) {
        let monthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        if (typeof month === 'object') {
            return monthAbbr[month.getMonth()];
        }
        if (typeof month === 'number') {
            return monthAbbr[month];
        }
        throw TypeError('Invalid type');
    },

    /**
     * Returns a UTC date with timezone information removed
     * @param {Date} date
     * @return {Date}
     */
    convertToUTC(date) {
        return new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
    },

    /**
     * Return the number of days in the month
     * @param {Number} year
     * @param {Number} month
     * @return {Number}
     */
    daysInMonth(year, month) {
        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
    },

    /**
     * Alternative get total number of days in month
     * @param {Number} y
     * @param {Number} m
     * @return {Number}
     */
    getDaysInMonth(y, m) {
       return /8|3|5|10/.test(--m)?30:m==1?(!(y%4)&&y%100)||!(y%400)?29:28:31;
    },

    /**
     * Returns number of days between two dates
     * @param {Date} start
     * @param {Date} end
     * @return {Number}
     */
    dayDiff(start, end) {
        const MS_PER_DAY = 1000 * 60 * 60 * 24;

        // Discard the time and time-zone information.
        let utc1 = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
        let utc2 = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());

        return Math.floor((utc2 - utc1) / MS_PER_DAY);
    },

    /**
     * Get nth suffix for date
     * @param {Number} day
     * @return {String}
     */
    getNthSuffix(day) {
        switch (day) {
            case 1:
            case 21:
            case 31:
                return 'st';
            case 2:
            case 22:
                return 'nd';
            case 3:
            case 23:
                return 'rd';
            default:
                return 'th';
        }
    },

    /**
     * Formats date object
     * @param {Date}
     * @return {String}
     */
    formatDate(date, format) {
        let year = date.getFullYear()
        let month = date.getMonth() + 1
        let day = date.getDate()
        let monthName = this.getMonthName(date.getMonth())
        let str = format
            .replace(/yyyy/, year)
            .replace(/yy/, String(year).slice(2))
            .replace(/MMMM/, this.getMonthName(date.getMonth()))
            .replace(/MMM/, this.getMonthNameAbbr(date.getMonth()))
            .replace(/MM/, ('0' + month).slice(-2))
            .replace(/M(?!a)/, month)
            .replace(/dd/, ('0' + day).slice(-2))
            .replace(/d/, day)
            .replace(/S/, this.getNthSuffix(date.getDate()))
            .replace(/D/, this.getDayNameAbbr(date))

        return str;
    },

    /**
     * Creates an array of dates for each day in between two dates.
     * @param {Date} start
     * @param {Date} end
     * @return {Array}
     */
    createDateArray(start, end) {
        let dates = [];
        while (start <= end) {
            dates.push(new Date(start))
            start.setDate(start.getDate() + 1);
        }
        return dates;
    }

}
<|endoftext|>


<commit_before>import React from 'react';

import Promise from 'promise';
import Diff from './Diff';

class DiffPanel extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      diffsArr: [],
    };
  }

  formatDiffs = (props) => {

    const LINESTATUS = {
      UNMODIFIED: 32,
      ADDED: 43,
      DELETED: 45,
    };

    if(props.diffs) {

      let diffsArr = [];
      let patches;

      let promises1 = [];
      props.diffs.forEach( (diff, index) => {
          // push all promises to get the patches from every diff
          promises1.push( diff.patches().then((retPatches) => {
            patches = retPatches;
          }) );
        });

      // perform operation on those patches after you get them
      return Promise.all(promises1)
      .then( () => {
        if(patches) {

          let promises2 = [];
          patches.forEach( (patch, index) => {

            // this array stores the Git line objects, header and file path
            // of a single diff
            let diffs = [];

            // obtain promises for all the hunks belonging to a single
            // patch. Each patch corresponds to a single file
            promises2.push( patch.hunks().then( (hunks) => {

              let promises3 = [];
              hunks.forEach( (hunk) => {

                // obtain promises for getting the lines from each hunk
                promises3.push(
                  hunk.lines().then( (lines) => {

                    // this makes it easier to stage hunks
                    diffs.push({
                      header: hunk.header(),
                      lines: lines,
                      path: patch.oldFile().path()
                    });
                  }) );
              });

              // return promises for inserting the lines into diffLines
              return Promise.all(promises3);
            })
            .then( () => {
              diffsArr.push({
                diffs: diffs,
                // diff already contains a path, but we need the old path as well as
                // the new one
                path: {
                  old: patch.oldFile().path(),
                  new: patch.newFile().path()
                }
              });
            }));
          });

          // return promises for inserting ALL the diffLines belonging to ALL the patches
          return Promise.all(promises2);
        }
      })
      .done( () => {

        /***
         * diffsArr: Array of diffFiles
         * diffFile: All the hunks from one single file
         *  |
         *  |-diffs: Array of diffs of ONE file
         *  |  diff: data of ONE hunk
         *  |   |
         *  |   |- header: string of header
         *  |   |- lines: array of Git line objects
         *  |   |- path: path of hunk
         *  |
         *  |-path: contains path of new and old file
         ***/

        this.setState({
          diffsArr: diffsArr
        });
      });
    }
  }

  componentDidMount = () => {
    this.formatDiffs(this.props);
  }

  componentWillReceiveProps = (newprops) => {
    this.formatDiffs(newprops);
  }

  render = () => {

    let diffTree = [];
    let diffSelect = [];

    this.state.diffsArr.forEach((diffFile, fileIndex) => {
      let { diffs, path } = diffFile;

      let formattedLines = [];
      diffs.forEach( (diff, diffIndex) => {
        let { header, lines, path } = diff;

        formattedLines.push(header);
        lines.forEach( (line) => {
            formattedLines.push(String.fromCharCode(line.origin())+line.content());
        });
      });

      // collecting all the header and lines of the hunks in a single file
      // and putting them in a diffDisplay object
      let diffDisplay = {
        lines:formattedLines,
        path: 'old:'+path.old+' new:'+path.new,
      };
      diffTree.push(<Diff diff={diffDisplay} key={fileIndex} />);

      // creating a column of checboxes to select individual lines/hunks
      diffSelect.push(

      // each div contains all the checkboxes of a single file

        {formattedLines.map( (line, lineIndex) => {

          const styles = {
            checkbox: {
              height: 13,
              padding: 0,
              margin: 0,
              marginTop: 1,
              marginBottom: 1,
            }
          };
          return <input type='checkbox' style={styles.checkbox} key={lineIndex} />;
        })}

      );

    });

    const styles = {
      main: {
        display: 'flex',
        width: '100%',
      },
      diffTree: {
        width: '100%',
        border: '1px solid black',
      }
    };
    return(

        {this.props.showSelect?

{diffSelect}
:
        null}

{diffTree}

    );
  }
}

export default DiffPanel;<commit_msg>Frontend: line obj(s) passed to callback function<commit_after>import React from 'react';

import Promise from 'promise';
import Diff from './Diff';

class DiffPanel extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      diffsArr: [],
    };
  }

  formatDiffs = (props) => {

    const LINESTATUS = {
      UNMODIFIED: 32,
      ADDED: 43,
      DELETED: 45,
    };

    if(props.diffs) {

      let diffsArr = [];
      let patches;

      let promises1 = [];
      props.diffs.forEach( (diff, index) => {
          // push all promises to get the patches from every diff
          promises1.push( diff.patches().then((retPatches) => {
            patches = retPatches;
          }) );
        });

      // perform operation on those patches after you get them
      return Promise.all(promises1)
      .then( () => {
        if(patches) {

          let promises2 = [];
          patches.forEach( (patch, index) => {

            // this array stores the Git line objects, header and file path
            // of a single diff
            let diffs = [];

            // obtain promises for all the hunks belonging to a single
            // patch. Each patch corresponds to a single file
            promises2.push( patch.hunks().then( (hunks) => {

              let promises3 = [];
              hunks.forEach( (hunk) => {

                // obtain promises for getting the lines from each hunk
                promises3.push(
                  hunk.lines().then( (lines) => {

                    // this makes it easier to stage hunks
                    diffs.push({
                      header: hunk.header(),
                      lines: lines,
                      path: patch.oldFile().path()
                    });
                  }) );
              });

              // return promises for inserting the lines into diffLines
              return Promise.all(promises3);
            })
            .then( () => {
              diffsArr.push({
                diffs: diffs,
                // diff already contains a path, but we need the old path as well as
                // the new one
                path: {
                  old: patch.oldFile().path(),
                  new: patch.newFile().path()
                }
              });
            }));
          });

          // return promises for inserting ALL the diffLines belonging to ALL the patches
          return Promise.all(promises2);
        }
      })
      .done( () => {

        /***
         * diffsArr: Array of diffFiles
         * diffFile: All the hunks from one single file
         *  |
         *  |-diffs: Array of diffs of ONE file
         *  |  diff: data of ONE hunk
         *  |   |
         *  |   |- header: string of header
         *  |   |- lines: array of Git line objects
         *  |   |- path: path of hunk
         *  |
         *  |-path: contains path of new and old file
         ***/

        this.setState({
          diffsArr: diffsArr
        });
      });
    }
  }

  checkboxCB = (data, path) => {
    if(Array.isArray(data))
      console.log(data.map((line) => {return line.content();}));
    else
      console.log(data.content());
    console.log(path, event);
  }

  componentDidMount = () => {
    this.formatDiffs(this.props);
  }

  componentWillReceiveProps = (newprops) => {
    this.formatDiffs(newprops);
  }

  render = () => {

    let diffTree = [];
    let diffSelect = [];

    this.state.diffsArr.forEach((diffFile, fileIndex) => {
      let { diffs, path } = diffFile;

      let formattedLines = [];

      diffs.forEach( (diff, diffIndex) => {
        let { header, lines, path } = diff;

        formattedLines.push(header);
        lines.forEach( (line) => {
            formattedLines.push(String.fromCharCode(line.origin())+line.content());
        });
      });

      // collecting all the header and lines of the hunks in a single file
      // and putting them in a diffDisplay object
      let diffDisplay = {
        lines:formattedLines,
        path: 'old:'+path.old+' new:'+path.new,
      };
      diffTree.push(<Diff diff={diffDisplay} key={fileIndex} />);

      // creating a column of checboxes to select individual lines/hunks
      diffSelect.push(

      // each div contains all the checkboxes of a single file

        {diffs.map( (diff, diffIndex) => {
          let { header, lines, path } = diff;

          let callbackFn = (data, path) => {
            this.checkboxCB(data, path);
          }
          const styles = {
            checkbox: {
              height: 13,
              padding: 0,
              margin: 0,
              marginTop: 1,
              marginBottom: 1,
            }
          };
          // the header calls the callback with an array containing all the difflines
          // and the line calls the callback with its corresponding diffline
          return (

            <input type='checkbox' style={styles.checkbox}
            onChange={() => {callbackFn(lines, path)}} />
              {lines.map( (line, lineIndex) => {
                return <input type='checkbox' style={styles.checkbox}
                key={lineIndex} onChange={(event) => {console.log(event.target); callbackFn(line, path, event);}} />;
              })}

          );

        })}

      );

    });

    const styles = {
      main: {
        display: 'flex',
        width: '100%',
      },
      diffTree: {
        width: '100%',
        border: '1px solid black',
      }
    };
    return(

        {this.props.showSelect?

{diffSelect}
:
        null}

{diffTree}

    );
  }
}

export default DiffPanel;<|endoftext|>


<commit_before>// Contains utils to download the locale data for the current language, eventually
// requiring the `Intl` polyfill for browser not supporting it
// It is used in client.js *before* rendering the root component.

import isIntlLocaleSupported from "intl-locales-supported";

const debug = require("debug")("isomorphic500");

const IntlUtils = {

  // Returns a promise which is resolved when Intl has been polyfilled

  loadIntlPolyfill(locale) {

    if (window.Intl && isIntlLocaleSupported(locale)) {
      // all fine: Intl is in the global scope and the locale data is available
      return Promise.resolve();
    }

    return new Promise((resolve) => {
      debug("Intl or locale data for %s not available, downloading the polyfill...", locale);

      // When building: create a intl chunk with webpack
      // When executing: run the callback once the chunk has been download.
      require.ensure(["intl"], (require) => {
        require("intl"); // apply the polyfill
        debug("Intl polyfill for %s has been loaded", locale);
        resolve();
      }, "intl");

    });

  },

  // Returns a promise which is resolved as the required locale-data chunks
  // has been downloaded with webpack's require.ensure. For each language,
  // we make two different chunks: one for browsers supporting `intl` and one
  // for those who don't.
  // The react-intl locale-data is required, for example, by the FormattedRelative
  // component.
  loadLocaleData(locale) {
    const hasIntl = isIntlLocaleSupported(locale);

    // Make sure ReactIntl is in the global scope: this is required for adding locale-data
    // Since ReactIntl needs the `Intl` polyfill to be required (sic) we must place
    // this require here, when loadIntlPolyfill is supposed to be present
    require("expose?ReactIntl!react-intl");

    return new Promise((resolve) => {

      switch (locale) {

        // italian
        case "it":

          if (!hasIntl) {

            require.ensure([
                "intl/locale-data/jsonp/it",
                "react-intl/dist/locale-data/it"
              ], (require) => {
              require("intl/locale-data/jsonp/it");
              require("react-intl/dist/locale-data/it");
              debug("Intl and ReactIntl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-it");
          }
          else {
            require.ensure([
                "react-intl/dist/locale-data/it"
              ], (require) => {
              require("react-intl/dist/locale-data/it");
              debug("ReactIntl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-it-no-intl");
          }

        break;

        // portugues
        case "pt":

          if (!hasIntl) {

            require.ensure([
                "intl/locale-data/jsonp/pt",
                "react-intl/dist/locale-data/pt"
              ], (require) => {

                require("intl/locale-data/jsonp/pt");
                debug("Intl locale-data for %s has been downloaded", locale);
                resolve();
              }, "locale-pt");
            }
            else {
              require.ensure([
                  "react-intl/dist/locale-data/pt"
                ], (require) => {
                require("react-intl/dist/locale-data/pt");
                debug("ReactIntl locale-data for %s has been downloaded", locale);
                resolve();
              }, "locale-pt-no-intl");
            }
        break;

        // english
        default:
          if (!hasIntl) {
            require.ensure([
                "intl/locale-data/jsonp/en"
              ], (require) => {

              require("intl/locale-data/jsonp/en");
              debug("Intl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-en");
          }
          else {
            resolve();
          }

      }

    });

  }

};

export default IntlUtils;
<commit_msg>Require react-intl locale data for pt (#65)<commit_after>// Contains utils to download the locale data for the current language, eventually
// requiring the `Intl` polyfill for browser not supporting it
// It is used in client.js *before* rendering the root component.

import isIntlLocaleSupported from "intl-locales-supported";

const debug = require("debug")("isomorphic500");

const IntlUtils = {

  // Returns a promise which is resolved when Intl has been polyfilled

  loadIntlPolyfill(locale) {

    if (window.Intl && isIntlLocaleSupported(locale)) {
      // all fine: Intl is in the global scope and the locale data is available
      return Promise.resolve();
    }

    return new Promise((resolve) => {
      debug("Intl or locale data for %s not available, downloading the polyfill...", locale);

      // When building: create a intl chunk with webpack
      // When executing: run the callback once the chunk has been download.
      require.ensure(["intl"], (require) => {
        require("intl"); // apply the polyfill
        debug("Intl polyfill for %s has been loaded", locale);
        resolve();
      }, "intl");

    });

  },

  // Returns a promise which is resolved as the required locale-data chunks
  // has been downloaded with webpack's require.ensure. For each language,
  // we make two different chunks: one for browsers supporting `intl` and one
  // for those who don't.
  // The react-intl locale-data is required, for example, by the FormattedRelative
  // component.
  loadLocaleData(locale) {
    const hasIntl = isIntlLocaleSupported(locale);

    // Make sure ReactIntl is in the global scope: this is required for adding locale-data
    // Since ReactIntl needs the `Intl` polyfill to be required (sic) we must place
    // this require here, when loadIntlPolyfill is supposed to be present
    require("expose?ReactIntl!react-intl");

    return new Promise((resolve) => {

      switch (locale) {

        // italian
        case "it":

          if (!hasIntl) {

            require.ensure([
                "intl/locale-data/jsonp/it",
                "react-intl/dist/locale-data/it"
              ], (require) => {
              require("intl/locale-data/jsonp/it");
              require("react-intl/dist/locale-data/it");
              debug("Intl and ReactIntl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-it");
          }
          else {
            require.ensure([
                "react-intl/dist/locale-data/it"
              ], (require) => {
              require("react-intl/dist/locale-data/it");
              debug("ReactIntl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-it-no-intl");
          }

        break;

        // portugues
        case "pt":

          if (!hasIntl) {

            require.ensure([
                "intl/locale-data/jsonp/pt",
                "react-intl/dist/locale-data/pt"
              ], (require) => {
                require("intl/locale-data/jsonp/pt");
                require("react-intl/dist/locale-data/pt");
                debug("Intl locale-data for %s has been downloaded", locale);
                resolve();
              }, "locale-pt");
            }
            else {
              require.ensure([
                  "react-intl/dist/locale-data/pt"
                ], (require) => {
                require("react-intl/dist/locale-data/pt");
                debug("ReactIntl locale-data for %s has been downloaded", locale);
                resolve();
              }, "locale-pt-no-intl");
            }
        break;

        // english
        default:
          if (!hasIntl) {
            require.ensure([
                "intl/locale-data/jsonp/en"
              ], (require) => {

              require("intl/locale-data/jsonp/en");
              debug("Intl locale-data for %s has been downloaded", locale);
              resolve();
            }, "locale-en");
          }
          else {
            resolve();
          }
      }

    });

  }

};

export default IntlUtils;
<|endoftext|>


<commit_before>(function(){

  var
    // global object
    global = this;

  test("scope(code) must run code in private context",function(){
    var
      hasRun = false;
    scope(function(context){
      hasRun = true;
      notStrictEqual(context,global,"code must not run in global context");
    });
    ok(hasRun,"code must run synchronously");
  });

  test("scope(code,needs) must import needs from global context",function(){
    var
      hasRun = false;

    scope(function(context){
      hasRun = true;
      notStrictEqual(context, global, "code must not run in global context");
      strictEqual(
        context.undefined,
        global.undefined,
        "undefined must be imported from global context"
      );
      strictEqual(
        context.document,
        global.document,
        "document must be imported from global context"
      );
      strictEqual(
        context.window,
        global.window,
        "window must be imported from global context"
      );
      strictEqual(
        context.Date,
        global.Date,
        "Date must be imported from global context"
      );
      strictEqual(
        context.Number,
        global.Number,
        "Number must be imported from global context"
      );
      strictEqual(
        context.setTimeout,
        global.setTimeout,
        "setTimeout must be imported from global context"
      );
    },[
      "a","ab","abc", // missing
      "undefined","document","window","Date","Number","setTimeout" // expected
      ]
    );
    ok(hasRun,"code must run synchronously, in spite of missing needs");
  });

  test("scope(code,needs,name) must set result in private context",function(){
    var
      hasRun = false,
      privateContext,
      codeName1 = "module1",
      codeResult1 = {result:"value1"};

    scope(function(context){
      hasRun = true;
      notStrictEqual(context, global, "code must not run in global context");
      privateContext = context;
      return codeResult1;
    },["a","ab","abc"],codeName1);
    ok(hasRun,"code must run synchronously, ignoring needs");
    strictEqual(
      typeof privateContext,
      "object",
      "private context must be an object"
    );
    strictEqual(
      privateContext[codeName1],
      codeResult1,
      "result value must be set in private context"
    );

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    });

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    },[]);

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    },[],"module2");

  });

}());
<commit_msg>Add tests for replacement of scope() using scope-private.js<commit_after>(function(){

  var
    // global object
    global = this;

  test("scope(code) must run code in private context",function(){
    var
      hasRun = false;
    scope(function(context){
      hasRun = true;
      notStrictEqual(context,global,"code must not run in global context");
    });
    ok(hasRun,"code must run synchronously");
  });

  test("scope(code,needs) must import needs from global context",function(){
    var
      hasRun = false;

    scope(function(context){
      hasRun = true;
      notStrictEqual(context, global, "code must not run in global context");
      strictEqual(
        context.undefined,
        global.undefined,
        "undefined must be imported from global context"
      );
      strictEqual(
        context.document,
        global.document,
        "document must be imported from global context"
      );
      strictEqual(
        context.window,
        global.window,
        "window must be imported from global context"
      );
      strictEqual(
        context.Date,
        global.Date,
        "Date must be imported from global context"
      );
      strictEqual(
        context.Number,
        global.Number,
        "Number must be imported from global context"
      );
      strictEqual(
        context.setTimeout,
        global.setTimeout,
        "setTimeout must be imported from global context"
      );
    },[
      "a","ab","abc", // missing
      "undefined","document","window","Date","Number","setTimeout" // expected
      ]
    );
    ok(hasRun,"code must run synchronously, in spite of missing needs");
  });

  test("scope(code,needs,name) must set result in private context",function(){
    var
      hasRun = false,
      privateContext,
      codeName1 = "module1",
      codeResult1 = {result:"value1"},
      originalScope,
      scopeReplacement = function(){/* replacement for scope() */};

    scope(function(context){
      hasRun = true;
      notStrictEqual(context, global, "code must not run in global context");
      privateContext = context;
      return codeResult1;
    },["a","ab","abc"],codeName1);
    ok(hasRun,"code must run synchronously, ignoring needs");
    strictEqual(
      typeof privateContext,
      "object",
      "private context must be an object"
    );
    strictEqual(
      privateContext[codeName1],
      codeResult1,
      "result value must be set in private context"
    );

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    });

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    },[]);

    scope(function(context){
      strictEqual(context,privateContext,"private context must be shared");
    },[],"module2");

    originalScope = global.scope;
    scope(function(context){
      return scopeReplacement;
    },[],"scope");
    strictEqual(
      privateContext.scope,
      scopeReplacement,
      "scope() is expected to be replaced in private context"
    );
    strictEqual(
      global.scope,
      scopeReplacement,
      "scope() is expected to be replaced in global context"
    );
    // restore origin scope() to allow further tests
    privateContext.scope = originalScope;
    global.scope = originalScope;
  });

}());
<|endoftext|>


<commit_before>const { HttpStatusError } = require('common-errors');
const { FIELDS_TO_STRINGIFY, FILES_TAGS_FIELD } = require('../constant');
const safeParse = require('./safeParse');
const perf = require('ms-perf');
const handlePipelineError = require('./pipelineError');
const zipObject = require('lodash/zipObject');

const STRINGIFY_FIELDS = zipObject(FIELDS_TO_STRINGIFY);
const JSON_FIELDS = zipObject([FILES_TAGS_FIELD, 'files']);
const hasOwnProperty = Object.prototype.hasOwnProperty;

module.exports = function fetchData(key, omitFields = []) {
  const { redis } = this;
  const timer = perf('fetchData');

  return redis
    .pipeline()
    .exists(key)
    .hgetall(key)
    .exec()
    .tap(timer('redis'))
    .then(handlePipelineError)
    .tap(timer('handleError'))
    .spread((fileExists, data) => {
      if (!fileExists) {
        throw new HttpStatusError(404, 'could not find associated data');
      }

      const output = {};
      const fields = Object.keys(data);

      fields.forEach((field) => {
        if (omitFields.indexOf(field) >= 0) {
          return;
        }

        const value = data[field];
        if (hasOwnProperty.call(JSON_FIELDS, field)) {
          output[field] = safeParse(value, []);
        } else if (hasOwnProperty.call(STRINGIFY_FIELDS, field)) {
          output[field] = safeParse(value);
        } else {
          output[field] = value;
        }
      });

      return output;
    })
    .tap(timer('remapping'))
    .finally(timer);
};
<commit_msg>fix: optimize partial functions on fetchData<commit_after>const { HttpStatusError } = require('common-errors');
const { FIELDS_TO_STRINGIFY, FILES_TAGS_FIELD } = require('../constant');
const safeParse = require('./safeParse');
const perf = require('ms-perf');
const handlePipelineError = require('./pipelineError');
const zipObject = require('lodash/zipObject');

/**
 * Helper constants
 */
const STRINGIFY_FIELDS = zipObject(FIELDS_TO_STRINGIFY);
const JSON_FIELDS = zipObject([FILES_TAGS_FIELD, 'files']);
const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * Remaps & json-parses some of the fields
 */
function remapData(field) {
  if (this.omitFields.indexOf(field) >= 0) {
    return;
  }

  const value = this.data[field];
  if (hasOwnProperty.call(JSON_FIELDS, field)) {
    this.output[field] = safeParse(value, []);
  } else if (hasOwnProperty.call(STRINGIFY_FIELDS, field)) {
    this.output[field] = safeParse(value);
  } else {
    this.output[field] = value;
  }
}

/**
 * Checks error & remaps data
 */
function reserializeData(fileExists, data) {
  if (!fileExists) {
    throw new HttpStatusError(404, 'could not find associated data');
  }

  const output = {};
  const fields = Object.keys(data);
  const ctx = { output, data, omitFields: this.omitFields };

  fields.forEach(remapData, ctx);

  return output;
}

/**
 * Fetches data
 * @param  {String} key
 * @param  {Array}  [omitFields=[]]
 */
module.exports = function fetchData(key, omitFields = []) {
  const { redis } = this;
  const timer = perf(`fetchData:${key}`);

  return redis
    .pipeline()
    .exists(key)
    .hgetall(key)
    .exec()
    .tap(timer('redis'))
    .then(handlePipelineError)
    .tap(timer('handleError'))
    .bind({ omitFields })
    .spread(reserializeData)
    .tap(timer('remapping'))
    .finally(timer);
};
<|endoftext|>


<commit_before>export default class GameLoop {
  loop = () => {
    this.subscribers.forEach((callback) => {
      callback.call();
    });

    this.loopID = window.requestAnimationFrame(this.loop);
  }
  constructor() {
    this.subscribers = [];
    this.loopID = null;
  }
  start() {
    if (!this.loopID) {
      this.loop();
    }
  }
  stop() {
    window.cancelAnimationFrame(this.loopID);
  }
  subscribe(callback) {
    return this.subscribers.push(callback);
  }
  unsubscribe(id) {
    this.subscribers.splice((id - 1), 1);
  }
}
<commit_msg>Unsubscribe index of ID, not ID itself<commit_after>export default class GameLoop {
  loop = () => {
    this.subscribers.forEach((callback) => {
      callback.call();
    });

    this.loopID = window.requestAnimationFrame(this.loop);
  }
  constructor() {
    this.subscribers = [];
    this.loopID = null;
  }
  start() {
    if (!this.loopID) {
      this.loop();
    }
  }
  stop() {
    window.cancelAnimationFrame(this.loopID);
  }
  subscribe(callback) {
    return this.subscribers.push(callback);
  }
  unsubscribe(id) {
    this.subscribers.splice(this.subscribers.indexOf(id), 1);
  }
}
<|endoftext|>


<commit_before>/*
  multigraph_edit.js - Licence: GNU GPL Affero, Author: Trystan Lea

  draws multigraph feedlist table and handles feedlist table dynamic
  actions such as add a feed, left, right, fill.
*/

var multigraph_id = 0;
var multigraph_feedlist = [];
var multigraphs=[];
var multigraphs_name=[];
var movingtime = false;
var showtag = true;

var baseElement = "#box-options";

// Multigraph new and selector interface
function multigraphGUI(){
  $("#viewbtn").hide();
  $(baseElement).html(multigraphDropdown());
  load_events();
}

function multigraphDropdown(){
  multigraphs_name = [];
  multigraphs = multigraph.getlist();
  var options = "";
  for (z in multigraphs) {
    multigraphs_name[multigraphs[z]['id']] = multigraphs[z]['name'];
    options +="<option value='"+multigraphs[z]['id']+"'>"+multigraphs[z]['id']+": "+multigraphs[z]['name']+"</option>";
  }
  var out = "
No multigraphs created yet, click new to create one:
";
  if (options){
    out = "<select id='multigraph-selector' class='form-control' style='width:160px'><option>Select multigraph:</option>"+options+"</select>";
  }
  return out+"<button id='multigraph-new-button' class='btn btn-info' style='float:right'>New multigraph</button>

";
}

// Multigraph editor interface
function draw_multigraph_feedlist_editor(){
  if (multigraph_feedlist === undefined){
    $("#embedcode").val('');
    $("#feedtable").html('');
    return;
  }

  if (multigraph_feedlist === null) multigraph_feedlist = [];
  if (typeof multigraph_feedlist[0] !== 'undefined' && multigraph_feedlist[0]['end'] != 0)
    movingtime=false;
  else
    movingtime=true;

  if (typeof multigraph_feedlist[0] !== 'undefined' && typeof multigraph_feedlist[0]['showtag'] !== 'undefined')
    showtag = multigraph_feedlist[0]['showtag'];
  else
    showtag = true;

  var out = "";
  out += '
';
  out += '
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
Delete Multigraph

';
  out += '

Deleting a multigraph is permanent.
Make sure no Dashboard continue to use the deleted multigraph

Are you sure you want to delete?

';
  out += '
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button><button id="confirmdelete" class="btn btn-primary">Delete permanently</button>

';

  out += "
";
  out += "
Feed	Left	Right	Fill
";

  var publicfeed = 1;
  for (z in multigraph_feedlist) {
    out += "
";
    out += ""+multigraph_feedlist[z]['tag']+": "+multigraph_feedlist[z]['name']+"	";
    if (!multigraph_feedlist[z]['left'] && !multigraph_feedlist[z]['right'])  multigraph_feedlist[z]['left'] = true; // Default is left
    var checked = ""; if (multigraph_feedlist[z]['left']) checked = "checked";
    out += "<input listid='"+z+"' class='left' type='checkbox' "+checked+" />	";
    var checked = ""; if (multigraph_feedlist[z]['right']) checked = "checked";
    out += "<input listid='"+z+"' class='right' type='checkbox' "+checked+" />	";
    var checked = ""; if (multigraph_feedlist[z]['fill']) checked = "checked";
    out += "<input listid='"+z+"' class='fill' type='checkbox' "+checked+" />	";
    out += "	";
    out += "
";
    var setColour = ""; if (multigraph_feedlist[z]['lineColour']) setColour = multigraph_feedlist[z]['lineColour'];
    out += "
";
    out += "Line Colour	";
    out += "<input id='lineColour' listid='"+z+"' style='width:110px' type='color' value='#"+setColour+"'>	";
    out += "
";
    var checked = "checked"; if (!multigraph_feedlist[z]['skipmissing']) checked = "";
    out += "
";
    out += "Skip missing data	";
    out += "<input id='skipmissing'  listid='"+z+"' type='checkbox' "+checked+" />	";
    out += "	";
    out += "
";
    if (publicfeed == 1) publicfeed = (get_feed_public(multigraph_feedlist[z]['id']));
  }
  var visurl = path+"vis/"+"multigraph?mid="+multigraph_id;
  if (publicfeed == 1) $("#embedcode").val(''); else $("#embedcode").val('Some of the feeds selected are not public, to embed a visualisation publicly first make the feeds that you want to use public.\n\nTo embed privately:\n\n');
  out += "
";
  out += ""+select_feed('feedselect', feedlist, 0)+"	";
  out += "	";
  out += "	";
  out += "<input id='add' type='button' class='btn' value='Add'/ >	";
  out += "	";
  out += "
";
  out += "
Floating time	";
  var checked = ""; if (movingtime) checked = "checked";
  out += "<input id='movingtime' type='checkbox' "+checked+" />	";
  out += "	";
  out += "	";
  out += "
";
  out += "
Show tag name	";
  var checked = ""; if (showtag) checked = "checked";
  out += "<input id='showtag' type='checkbox' "+checked+" />	";
  out += "	";
  out += "	";
  out += "
";
  out += "
";
  var name = "
Name<input class='options' id='multigraph-name' value='"+multigraphs_name[multigraph_id]+"' type='text'>
";
  out += name+"<button id='delete-multigraph-button' class='btn btn-danger'>Delete</button>";
  out += "<button id='save-multigraph-button' class='btn btn-success' style='float:right'>Not modified</button>";
  $("#feedtable").html(out);
}

function get_feed_name(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['name'];
  }
}

function get_feed_tag(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['tag'];
  }
}

function get_feed_datatype(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['datatype'];
  }
}

function get_feed_public(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['public'];
  }
}

function update_multigraph_feedlist_names(){
  for (m in multigraph_feedlist) {
    if (typeof multigraph_feedlist[m] !== 'undefined'){
        var feedid = multigraph_feedlist[m]['id'];
        multigraph_feedlist[m]['tag'] = get_feed_tag(feedid);
        multigraph_feedlist[m]['name'] = get_feed_name(feedid);
    }
  }
}

function modified(){
  $(baseElement + ' #save-multigraph-button').attr('class','btn btn-warning').text("Changed, press to save");
}

// Events
function load_events(){
  $(baseElement).unbind();

  $(baseElement).on("change","#multigraph-selector",function(event){
    multigraph_id = $(this).val();
    if (multigraph_id > 0) {
      multigraph_feedlist = multigraph.get(multigraph_id)['feedlist'];
      update_multigraph_feedlist_names()
    } else {
      multigraph_id=0;
      multigraph_feedlist=undefined;
      //$("#feedtable").html("");
    }
    // Draw multigraph feedlist editor
    draw_multigraph_feedlist_editor();
    // Draw multigraph
    multigraph_init("#visiframe");
    vis_feed_data();
  });

  $(baseElement).on("click","#multigraph-new-button",function(event){
    multigraph_id = multigraph.new();
    $(baseElement).html(multigraphDropdown());            // Reload all
    $(baseElement + ' #multigraph-selector').val(multigraph_id);  // Refresh
    $(baseElement + ' #multigraph-selector').change();            //
  });

  $(baseElement).on("click","#add",function(event){
    var feedid = $("#feedselect").val();
    multigraph_feedlist.push({'id':feedid,'tag':get_feed_tag(feedid),'name':get_feed_name(feedid),'datatype':get_feed_datatype(feedid),'left':false,'right':false,'fill':false,'end':0,'skipmissing':true});
    draw_multigraph_feedlist_editor();
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#movingtime",function(event){
    movingtime = $(this)[0].checked;
    vis_feed_data();
    modified();
  });
  $(baseElement).on("click","#showtag",function(event){
    showtag = $(this)[0].checked;
    multigraph_feedlist[0]['showtag'] = showtag;
    vis_feed_data();
    modified();
  });
  // Event for every change event in the lineColour input for each line in the plot.
  $(baseElement).on("input","#lineColour",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]["lineColour"] = $(this)[0].value.replace('#','');
    modified();
  });
  // This only fires when the user either deselects the lineColour text-box, or hits enter
  $(baseElement).on("change","#lineColour",function(event){
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#skipmissing",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['skipmissing'] = $(this)[0].checked;
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click",".left",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['left'] = $(this)[0].checked;
    if (multigraph_feedlist[z]['left'] == true && multigraph_feedlist[z]['right'] == true)
      multigraph_feedlist[z]['right'] = false;
    $(".right[listid="+z+"]").attr("checked",false);

    vis_feed_data();
    modified();
  });

  $(baseElement).on("click",".right",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['right'] = $(this)[0].checked;
    if (multigraph_feedlist[z]['left'] == true && multigraph_feedlist[z]['right'] == true)
      multigraph_feedlist[z]['left'] = false;
    $(".left[listid="+z+"]").attr("checked",false);
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click",".fill",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['fill'] = $(this)[0].checked;
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#multigraph-feed-remove-button",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist.splice(z,1);
    draw_multigraph_feedlist_editor();
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#delete-multigraph-button",function(){
    $('#myModal').modal('show');
  });

  $(baseElement).on("click","#confirmdelete",function() {
    multigraph.remove(multigraph_id);
    $('#myModal').modal('hide');
    $(baseElement).html(multigraphDropdown());         // Reload all
    //$(baseElement + ' #multigraph-selector').val(undefined);  // Refresh
    $(baseElement + ' #multigraph-selector').change(); //
  });

  $(baseElement).on("input propertychange paste","#multigraph-name",function(){
    modified();
  });

  $(baseElement).on("click","#save-multigraph-button",function(event){
    // Save multigraph view start and end time to feedlist array
    if (typeof multigraph_feedlist[0] !== 'undefined') {
      multigraph_feedlist[0].timeWindow = view.end - view.start;
      if (movingtime) multigraph_feedlist[0].end = 0;
      else multigraph_feedlist[0].end = view.end;
    }
    var new_name=$("#multigraph-name").val();
    if(new_name=="") new_name="No name";

    var result = multigraph.set(multigraph_id,multigraph_feedlist,new_name);
    if (result.success) {
        $(baseElement).html(multigraphDropdown());                    // Reload all
        $(baseElement + ' #multigraph-selector').val(multigraph_id);  // Refresh
        $(baseElement + ' #multigraph-selector').change();            //
        $(baseElement + ' #save-multigraph-button').attr('class','btn btn-success').text('Saved');
    }
    else { alert('ERROR: Could not save Multigraph. '+result.message); }
  });
}
<commit_msg>Update multigraph_edit.js<commit_after>/*
  multigraph_edit.js - Licence: GNU GPL Affero, Author: Trystan Lea

  draws multigraph feedlist table and handles feedlist table dynamic
  actions such as add a feed, left, right, fill.
*/

var multigraph_id = 0;
var multigraph_feedlist = [];
var multigraphs=[];
var multigraphs_name=[];
var movingtime = false;
var showtag = true;
var autorefresh = 0;
var showlegend = true;

var baseElement = "#box-options";

// Multigraph new and selector interface
function multigraphGUI(){
  $("#viewbtn").hide();
  $(baseElement).html(multigraphDropdown());
  load_events();
}

function multigraphDropdown(){
  multigraphs_name = [];
  multigraphs = multigraph.getlist();
  var options = "";
  for (z in multigraphs) {
    multigraphs_name[multigraphs[z]['id']] = multigraphs[z]['name'];
    options +="<option value='"+multigraphs[z]['id']+"'>"+multigraphs[z]['id']+": "+multigraphs[z]['name']+"</option>";
  }
  var out = "
No multigraphs created yet, click new to create one:
";
  if (options){
    out = "<select id='multigraph-selector' class='form-control' style='width:160px'><option>Select multigraph:</option>"+options+"</select>";
  }
  return out+"<button id='multigraph-new-button' class='btn btn-info' style='float:right'>New multigraph</button>

";
}

// Multigraph editor interface
function draw_multigraph_feedlist_editor(){
  if (multigraph_feedlist === undefined){
    $("#embedcode").val('');
    $("#feedtable").html('');
    return;
  }

  if (multigraph_feedlist === null) multigraph_feedlist = [];
  if (typeof multigraph_feedlist[0] !== 'undefined' && multigraph_feedlist[0]['end'] != 0)
    movingtime=false;
  else
    movingtime=true;

  if (typeof multigraph_feedlist[0] !== 'undefined' && typeof multigraph_feedlist[0]['showtag'] !== 'undefined')
    showtag = multigraph_feedlist[0]['showtag'];
  else
    showtag = true;

  if (typeof multigraph_feedlist[0] !== 'undefined' && typeof multigraph_feedlist[0]['autorefresh'] !== 'undefined')
    autorefresh = multigraph_feedlist[0]['autorefresh'];
  else
    autorefresh = 0;

  if (typeof multigraph_feedlist[0] !== 'undefined' && typeof multigraph_feedlist[0]['showlegend'] !== 'undefined')
    showlegend = multigraph_feedlist[0]['showlegend'];
  else
    showlegend = true;

  var out = "";
  out += '
';
  out += '
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
Delete Multigraph

';
  out += '

Deleting a multigraph is permanent.
Make sure no Dashboard continue to use the deleted multigraph

Are you sure you want to delete?

';
  out += '
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button><button id="confirmdelete" class="btn btn-primary">Delete permanently</button>

';

  out += "
";
  out += "
Feed	Left	Right	Fill
";

  var publicfeed = 1;
  for (z in multigraph_feedlist) {
    out += "
";
    out += ""+multigraph_feedlist[z]['tag']+": "+multigraph_feedlist[z]['name']+"	";
    if (!multigraph_feedlist[z]['left'] && !multigraph_feedlist[z]['right'])  multigraph_feedlist[z]['left'] = true; // Default is left
    var checked = ""; if (multigraph_feedlist[z]['left']) checked = "checked";
    out += "<input listid='"+z+"' class='left' type='checkbox' "+checked+" />	";
    var checked = ""; if (multigraph_feedlist[z]['right']) checked = "checked";
    out += "<input listid='"+z+"' class='right' type='checkbox' "+checked+" />	";
    var checked = ""; if (multigraph_feedlist[z]['fill']) checked = "checked";
    out += "<input listid='"+z+"' class='fill' type='checkbox' "+checked+" />	";
    out += "	";
    out += "
";
    var setColour = ""; if (multigraph_feedlist[z]['lineColour']) setColour = multigraph_feedlist[z]['lineColour'];
    out += "
";
    out += "Line Colour	";
    out += "<input id='lineColour' listid='"+z+"' style='width:110px' type='color' value='#"+setColour+"'>	";
    out += "
";
    var checked = "checked"; if (!multigraph_feedlist[z]['skipmissing']) checked = "";
    out += "
";
    out += "Skip missing data	";
    out += "<input id='skipmissing'  listid='"+z+"' type='checkbox' "+checked+" />	";
    var checked = ""; if (multigraph_feedlist[z]['stacked']) checked = "checked";
    out += "Stack	";
    out += "<input id='stacked'  listid='"+z+"' type='checkbox' "+checked+" />	";
    out += "	";
    out += "
";
    if (publicfeed == 1) publicfeed = (get_feed_public(multigraph_feedlist[z]['id']));
  }
  var visurl = path+"vis/"+"multigraph?mid="+multigraph_id;
  if (publicfeed == 1) $("#embedcode").val(''); else $("#embedcode").val('Some of the feeds selected are not public, to embed a visualisation publicly first make the feeds that you want to use public.\n\nTo embed privately:\n\n');
  out += "
";
  out += ""+select_feed('feedselect', feedlist, 0)+"	";
  out += "	";
  out += "	";
  out += "<input id='add' type='button' class='btn' value='Add'/ >	";
  out += "	";
  out += "
";
  out += "
Floating time	";
  var checked = ""; if (movingtime) checked = "checked";
  out += "<input id='movingtime' type='checkbox' "+checked+" />	";
  out += "	";
  out += "	";
  out += "
";
  out += "
Show tag name	";
  var checked = ""; if (showtag) checked = "checked";
  out += "<input id='showtag' type='checkbox' "+checked+" />	";
  out += "	";
  out += "	";
  out += "
";
  out += "
Refresh Interval(s)	";
  out += "<input style='width:110px' id='autorefresh' value='" + autorefresh + "'/>	";
  out += "	";
  out += "	";
  out += "
";
  out += "
Show Legend	";
  var checked = ""; if (showlegend) checked = "checked";
  out += "<input id='showlegend' type='checkbox' "+checked+" />	";
  out += "	";
  out += "	";
  out += "
";
  out += "
";
  var name = "
Name<input class='options' id='multigraph-name' value='"+multigraphs_name[multigraph_id]+"' type='text'>
";
  out += name+"<button id='delete-multigraph-button' class='btn btn-danger'>Delete</button>";
  out += "<button id='save-multigraph-button' class='btn btn-success' style='float:right'>Not modified</button>";
  $("#feedtable").html(out);
}

function get_feed_name(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['name'];
  }
}

function get_feed_tag(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['tag'];
  }
}

function get_feed_datatype(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['datatype'];
  }
}

function get_feed_public(id){
  for (z in feedlist){
    if (feedlist[z]['id'] == id) return feedlist[z]['public'];
  }
}

function update_multigraph_feedlist_names(){
  for (m in multigraph_feedlist) {
    if (typeof multigraph_feedlist[m] !== 'undefined'){
        var feedid = multigraph_feedlist[m]['id'];
        multigraph_feedlist[m]['tag'] = get_feed_tag(feedid);
        multigraph_feedlist[m]['name'] = get_feed_name(feedid);
    }
  }
}

function modified(){
  $(baseElement + ' #save-multigraph-button').attr('class','btn btn-warning').text("Changed, press to save");
}

// Events
function load_events(){
  $(baseElement).unbind();

  $(baseElement).on("change","#multigraph-selector",function(event){
    multigraph_id = $(this).val();
    if (multigraph_id > 0) {
      multigraph_feedlist = multigraph.get(multigraph_id)['feedlist'];
      update_multigraph_feedlist_names()
    } else {
      multigraph_id=0;
      multigraph_feedlist=undefined;
      //$("#feedtable").html("");
    }
    // Draw multigraph feedlist editor
    draw_multigraph_feedlist_editor();
    // Draw multigraph
    multigraph_init("#visiframe");
    vis_feed_data();
  });

  $(baseElement).on("click","#multigraph-new-button",function(event){
    multigraph_id = multigraph.new();
    $(baseElement).html(multigraphDropdown());            // Reload all
    $(baseElement + ' #multigraph-selector').val(multigraph_id);  // Refresh
    $(baseElement + ' #multigraph-selector').change();            //
  });

  $(baseElement).on("click","#add",function(event){
    var feedid = $("#feedselect").val();
    multigraph_feedlist.push({'id':feedid,'tag':get_feed_tag(feedid),'name':get_feed_name(feedid),'datatype':get_feed_datatype(feedid),'left':false,'right':false,'fill':false,'end':0,'skipmissing':true});
    draw_multigraph_feedlist_editor();
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#movingtime",function(event){
    movingtime = $(this)[0].checked;
    vis_feed_data();
    modified();
  });
  $(baseElement).on("click","#showtag",function(event){
    showtag = $(this)[0].checked;
    multigraph_feedlist[0]['showtag'] = showtag;
    vis_feed_data();
    modified();
  });
  $(baseElement).on("change","#autorefresh",function(event){
    autorefresh = $(this)[0].value;
    multigraph_feedlist[0]['autorefresh'] = autorefresh;
    // vis_feed_data(); doesn't affect data
    modified();
  });
  $(baseElement).on("click","#showlegend",function(event){
    showlegend = $(this)[0].checked;
    multigraph_feedlist[0]['showlegend'] = showlegend;
    vis_feed_data();
    modified();
  });
  // Event for every change event in the lineColour input for each line in the plot.
  $(baseElement).on("input","#lineColour",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]["lineColour"] = $(this)[0].value.replace('#','');
    modified();
  });
  // This only fires when the user either deselects the lineColour text-box, or hits enter
  $(baseElement).on("change","#lineColour",function(event){
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#skipmissing",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['skipmissing'] = $(this)[0].checked;
    vis_feed_data();
    modified();
  });

   $(baseElement).on("click","#stacked",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['stacked'] = $(this)[0].checked;
    vis_feed_data();
    modified();
  });

 $(baseElement).on("click",".left",function(event){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['left'] = $(this)[0].checked;
    if (multigraph_feedlist[z]['left'] == true && multigraph_feedlist[z]['right'] == true)
      multigraph_feedlist[z]['right'] = false;
    $(".right[listid="+z+"]").attr("checked",false);

    vis_feed_data();
    modified();
  });

  $(baseElement).on("click",".right",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['right'] = $(this)[0].checked;
    if (multigraph_feedlist[z]['left'] == true && multigraph_feedlist[z]['right'] == true)
      multigraph_feedlist[z]['left'] = false;
    $(".left[listid="+z+"]").attr("checked",false);
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click",".fill",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist[z]['fill'] = $(this)[0].checked;
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#multigraph-feed-remove-button",function(){
    var z = $(this).attr('listid');
    multigraph_feedlist.splice(z,1);
    draw_multigraph_feedlist_editor();
    vis_feed_data();
    modified();
  });

  $(baseElement).on("click","#delete-multigraph-button",function(){
    $('#myModal').modal('show');
  });

  $(baseElement).on("click","#confirmdelete",function() {
    multigraph.remove(multigraph_id);
    $('#myModal').modal('hide');
    $(baseElement).html(multigraphDropdown());         // Reload all
    //$(baseElement + ' #multigraph-selector').val(undefined);  // Refresh
    $(baseElement + ' #multigraph-selector').change(); //
  });

  $(baseElement).on("input propertychange paste","#multigraph-name",function(){
    modified();
  });

  $(baseElement).on("click","#save-multigraph-button",function(event){
    // Save multigraph view start and end time to feedlist array
    if (typeof multigraph_feedlist[0] !== 'undefined') {
      multigraph_feedlist[0].timeWindow = view.end - view.start;
      if (movingtime) multigraph_feedlist[0].end = 0;
      else multigraph_feedlist[0].end = view.end;
    }
    var new_name=$("#multigraph-name").val();
    if(new_name=="") new_name="No name";

    var result = multigraph.set(multigraph_id,multigraph_feedlist,new_name);
    if (result.success) {
        $(baseElement).html(multigraphDropdown());                    // Reload all
        $(baseElement + ' #multigraph-selector').val(multigraph_id);  // Refresh
        $(baseElement + ' #multigraph-selector').change();            //
        $(baseElement + ' #save-multigraph-button').attr('class','btn btn-success').text('Saved');
    }
    else { alert('ERROR: Could not save Multigraph. '+result.message); }
  });
}
<|endoftext|>


<commit_before>/* @flow strict-local */
import type { PmRecipientUser, Message, Outbox, User } from '../types';

// TODO types: this union is confusing
export const normalizeRecipients = (recipients: $ReadOnlyArray<{ email: string }> | string) =>
  !Array.isArray(recipients)
    ? recipients
    : recipients
        .map(s => s.email.trim())
        .filter(x => x.length > 0)
        .sort()
        .join(',');

export const normalizeRecipientsSansMe = (
  recipients: $ReadOnlyArray<{ email: string }>,
  ownEmail: string,
) =>
  recipients.length === 1
    ? recipients[0].email
    : normalizeRecipients(recipients.filter(r => r.email !== ownEmail));

/**
 * Returns a filtered array of recipients for a private message.
 * If the message is a self PM, returns an array containing a single
 * element - the current user. Otherwise, returns all recipients
 * except the current user.
 */
export const filteredRecipientsForPM = (
  message: Message | Outbox,
  ownUser: User,
): PmRecipientUser[] =>
  message.display_recipient.length === 1 && message.display_recipient[0].email === ownUser.email
    ? message.display_recipient
    : message.display_recipient.filter(r => r.email !== ownUser.email);

export const getRecipientsIds = (recipients: PmRecipientUser[], ownEmail?: string): string =>
  recipients.length === 2
    ? recipients.filter(r => r.email !== ownEmail)[0].id.toString()
    : recipients
        .map(s => s.id)
        .sort((a, b) => a - b)
        .join(',');

export const isSameRecipient = (
  message1: Message | Outbox,
  message2: Message | Outbox,
): boolean => {
  if (message1 === undefined || message2 === undefined) {
    return false;
  }

  if (message1.type !== message2.type) {
    return false;
  }

  switch (message1.type) {
    case 'private':
      return (
        normalizeRecipients(message1.display_recipient).toLowerCase()
        === normalizeRecipients(message2.display_recipient).toLowerCase()
      );
    case 'stream':
      return (
        message1.display_recipient.toLowerCase() === message2.display_recipient.toLowerCase()
        && message1.subject.toLowerCase() === message2.subject.toLowerCase()
      );
    default:
      // Invariant
      return false;
  }
};
<commit_msg>recipient [nfc]: Slightly simplify filteredRecipientsForPM code.<commit_after>/* @flow strict-local */
import type { PmRecipientUser, Message, Outbox, User } from '../types';

// TODO types: this union is confusing
export const normalizeRecipients = (recipients: $ReadOnlyArray<{ email: string }> | string) =>
  !Array.isArray(recipients)
    ? recipients
    : recipients
        .map(s => s.email.trim())
        .filter(x => x.length > 0)
        .sort()
        .join(',');

export const normalizeRecipientsSansMe = (
  recipients: $ReadOnlyArray<{ email: string }>,
  ownEmail: string,
) =>
  recipients.length === 1
    ? recipients[0].email
    : normalizeRecipients(recipients.filter(r => r.email !== ownEmail));

/**
 * Returns a filtered array of recipients for a private message.
 * If the message is a self PM, returns an array containing a single
 * element - the current user. Otherwise, returns all recipients
 * except the current user.
 */
export const filteredRecipientsForPM = (
  message: Message | Outbox,
  ownUser: User,
): PmRecipientUser[] => {
  const { display_recipient } = message;
  return display_recipient.length === 1
    ? display_recipient
    : display_recipient.filter(r => r.email !== ownUser.email);
};

export const getRecipientsIds = (recipients: PmRecipientUser[], ownEmail?: string): string =>
  recipients.length === 2
    ? recipients.filter(r => r.email !== ownEmail)[0].id.toString()
    : recipients
        .map(s => s.id)
        .sort((a, b) => a - b)
        .join(',');

export const isSameRecipient = (
  message1: Message | Outbox,
  message2: Message | Outbox,
): boolean => {
  if (message1 === undefined || message2 === undefined) {
    return false;
  }

  if (message1.type !== message2.type) {
    return false;
  }

  switch (message1.type) {
    case 'private':
      return (
        normalizeRecipients(message1.display_recipient).toLowerCase()
        === normalizeRecipients(message2.display_recipient).toLowerCase()
      );
    case 'stream':
      return (
        message1.display_recipient.toLowerCase() === message2.display_recipient.toLowerCase()
        && message1.subject.toLowerCase() === message2.subject.toLowerCase()
      );
    default:
      // Invariant
      return false;
  }
};
<|endoftext|>


<commit_before>Seed({
		name : "Mold.Lib.VDom.Components.MoldBind",
		dna : "component",
		include : [
			"->Mold.DNA.Component"
		],
		directives : [
			{
				at : "attribute",
				name : "mold-bind",
				//watchable : true,
				collect : {
					attribute : [
						"mold-bind"
					]
				}
			}
		]
	},
	function(node, element, collection){
		var path = element.moldModel.path;
		var model = element.moldModel.model;

		var setData = function(data){
			if(element.val() !== data){
				element.val(data);
			}
		}

		var bindingName = collection["mold-bind"];

		var initBinding = function(){

			if(path && model){

				if(~bindingName.indexOf('.')){
					var subPath = bindingName.substring(0, bindingName.indexOf('.'))
					var modelName = bindingName.substring(bindingName.indexOf('.') + 1, bindingName.length);
				}else{
					var modelName = bindingName;
				}
				switch(element.attr('type')){
					case "text":
						element.on("keyup", function(){
							console.log("path", path + "." + collection["mold-bind"]);

							model.set(path + "." + collection["mold-bind"], element.val());
						})
						break;
					case "radio":
						//element.on
				}

				model.on(path + ".changed", function(e){
					setData(e.data[modelName]);
				})

				if(subPath){
					var data = model.get(path + "." + subPath);
				}else{
					var data = model.get(path);
				}

				setData(data[modelName]);
			}
		}

		Mold.watch(element.moldModel, "model", function(name, value, newValue){
			model = newValue;
			initBinding();
		})

		Mold.watch(element.moldModel, "path", function(name, value, newValue){
			path = newValue;
			initBinding();
		})

		initBinding();
	}
);<commit_msg>binding extended<commit_after>/**
 * @description binds model data to an element
 * @example Mold/Test/Lib/Template#binding
 */
Seed({
		name : "Mold.Lib.VDom.Components.MoldBind",
		dna : "component",
		include : [
			"->Mold.DNA.Component"
		],
		directives : [
			{
				at : "attribute",
				name : "mold-bind",
				//watchable : true,
				collect : {
					attribute : [
						"mold-bind"
					]
				}
			}
		]
	},
	function(node, element, collection){
		var path = element.moldModel.path;
		var model = element.moldModel.model;

		var setData = function(data){
			if(element.val() !== data){
				element.val(data);
			}
		}

		var bindingName = collection["mold-bind"];

		var initBinding = function(){

			if(path && model){

				if(~bindingName.indexOf('.')){
					var subPath = bindingName.substring(0, bindingName.indexOf('.'))
					var modelName = bindingName.substring(bindingName.indexOf('.') + 1, bindingName.length);
				}else{
					var modelName = bindingName;
				}
				switch(element.attr('type')){

					case "range":
					case "radio":
					case "checkbox":
						element.on("change", function(){
							console.log("value", element.val())
							model.set(path + "." + collection["mold-bind"], element.val());
						})
						break;

					default :
						element.on("keyup", function(){
							model.set(path + "." + collection["mold-bind"], element.val());
						})
						break;
				}

				if(element.tagName.toLowerCase() === "select"){
					element.on("change", function(){
						console.log("value", element.val())
						model.set(path + "." + collection["mold-bind"], element.val());
					})
				}

				model.on(path + ".changed", function(e){

					setData(e.data[modelName]);
				})

				if(subPath){
					var data = model.get(path + "." + subPath);
				}else{
					var data = model.get(path);
				}

				setData(data[modelName]);
			}
		}

		Mold.watch(element.moldModel, "model", function(name, value, newValue){
			model = newValue;
			initBinding();
		})

		Mold.watch(element.moldModel, "path", function(name, value, newValue){
			path = newValue;
			initBinding();
		})

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


<commit_before>/*eslint no-console: ["error", { allow: ["log"] }] */

var assert = require('chai').assert
var after = require('mocha').after
var validate = require('../index.js')
var request = require('sync-request')
var fs = require('fs')
var AdmZip = require('adm-zip')
var path = require('path')
var Test = require('mocha/lib/test')
var test_version = '68bed388276c7898f787bc13c37e0249d827e5ac'

function getDirectories(srcpath) {
  return fs.readdirSync(srcpath).filter(function(file) {
    return fs.statSync(path.join(srcpath, file)).isDirectory()
  })
}

var missing_session_files = [
  '7t_trt',
  'ds006',
  'ds007',
  'ds008',
  'ds051',
  'ds052',
  'ds105',
  'ds108',
  'ds109',
  'ds113b',
  'ds000117',
  'ds000246',
  'ds000247',
]

function assertErrorCode(errors, expected_error_code) {
  var matchingErrors = errors.filter(function(error) {
    return error.code === expected_error_code
  })
  assert(matchingErrors.length >= 0)
}

var suite = describe('BIDS example datasets ', function() {
  this.timeout(100000)

  before(function(done) {
    if (!fs.existsSync('tests/data/BIDS-examples-' + test_version + '/')) {
      console.log('downloading test data')
      var response = request(
        'GET',
        'http://github.com/INCF/BIDS-examples/archive/' + test_version + '.zip',
      )
      if (!fs.existsSync('tests/data')) {
        fs.mkdirSync('tests/data')
      }
      fs.writeFileSync('tests/data/examples.zip', response.body)
      var zip = new AdmZip('tests/data/examples.zip')
      console.log('unzipping test data')
      zip.extractAllTo('tests/data/', true)
    }

    var datasetDirectories = getDirectories(
      'tests/data/BIDS-examples-' + test_version + '/',
    )

    datasetDirectories.forEach(function testDataset(path) {
      suite.addTest(
        new Test(path, function(isdone) {
          var options = { ignoreNiftiHeaders: true }
          validate.BIDS(
            'tests/data/BIDS-examples-' + test_version + '/' + path + '/',
            options,
            function(issues) {
              var errors = issues.errors
              var warnings = issues.warnings
              assert.deepEqual(errors, [])
              var session_flag = false
              for (var warning in warnings) {
                if (warnings[warning]['code'] === '38') {
                  session_flag = true
                  break
                }
              }
              if (missing_session_files.indexOf(path) === -1) {
                assert.deepEqual(session_flag, false)
              } else {
                assert.deepEqual(session_flag, true)
              }
              isdone()
            },
          )
        }),
      )
    })
    done()
  })

  // we need to have at least one non-dynamic test
  it('validates path without trailing backslash', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues, summary) {
        var errors = issues.errors
        var warnings = issues.warnings
        assert(summary.sessions.length === 0)
        assert(summary.subjects.length === 16)
        assert.deepEqual(summary.tasks, ['balloon analog risk task'])
        assert(summary.modalities.includes('T1w'))
        assert(summary.modalities.includes('inplaneT2'))
        assert(summary.modalities.includes('bold'))
        assert(summary.totalFiles === 133)
        assert.deepEqual(errors, [])
        assert(warnings.length === 2 && warnings[0].code === '13')
        isdone()
      },
    )
  })

  // we need to have at least one non-dynamic test
  it('validates dataset with valid nifti headers', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_headers', options, function(
      issues,
      summary,
    ) {
      var errors = issues.errors
      var warnings = issues.warnings
      assert(summary.sessions.length === 0)
      assert(summary.subjects.length === 1)
      assert.deepEqual(summary.tasks, ['rhyme judgment'])
      assert(summary.modalities.includes('T1w'))
      assert(summary.modalities.includes('bold'))
      assert(summary.totalFiles === 10)
      assert(errors[0].code === '60')
      assert(warnings.length === 3 && warnings[0].code === '13')
      isdone()
    })
  })

  // test for duplicate files present with both .nii and .nii.gz extension
  it('validates dataset for duplicate files present with both .nii and .nii.gz extension', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '74')
      isdone()
    })
  })

  // test for illegal characters used in acq and task name
  it('validates dataset with illegal characters in task name', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '58')
      isdone()
    })
  })

  // test for illegal characters used in sub name
  it('validates dataset with illegal characters in sub name', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '64')
      isdone()
    })
  })

  // Catch some browser specific iteration issues with for .. in loops
  describe('with enumerable array prototype methods', function() {
    before(function() {
      // Patch in a potentially iterable prototype
      Array.prototype.broken = function() {
        /* custom extension */
      }
    })
    after(function() {
      // Unpatch the above
      delete Array.prototype.broken
    })
    it('validates dataset with illegal characters in task name', function(isdone) {
      var options = { ignoreNiftiHeaders: false }
      validate.BIDS('tests/data/valid_filenames', options, function(issues) {
        assertErrorCode(issues.errors, '58')
        isdone()
      })
    })
  })

  it('checks for subjects with no valid data', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS('tests/data/no_valid_data', options, function(issues) {
      assertErrorCode(issues.errors, '67')
      isdone()
    })
  })

  it('checks for tabular files without corresponding data dictionaries', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues) {
        assert(issues.warnings.length === 2 && issues.warnings[1].code === '82')
        isdone()
      },
    )
  })

  it('validates ieeg modalities', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues, summary) {
        var errors = issues.errors
        var warnings = issues.warnings
        assert(summary.sessions.length === 0)
        assert(summary.subjects.length === 16)
        assert.deepEqual(summary.tasks, ['balloon analog risk task'])
        assert(summary.modalities.includes('T1w'))
        assert(summary.modalities.includes('inplaneT2'))
        assert(summary.modalities.includes('bold'))
        assert(summary.totalFiles === 133)
        assert.deepEqual(errors, [])
        assert(warnings.length === 2 && warnings[0].code === '13')
        isdone()
      },
    )
  })
})
<commit_msg>temporarily fix tests<commit_after>/*eslint no-console: ["error", { allow: ["log"] }] */

var assert = require('chai').assert
var after = require('mocha').after
var validate = require('../index.js')
var request = require('sync-request')
var fs = require('fs')
var AdmZip = require('adm-zip')
var path = require('path')
var Test = require('mocha/lib/test')
var test_version = '7817e60d06f74fd1b080db6942e5de36052d7242'

function getDirectories(srcpath) {
  return fs.readdirSync(srcpath).filter(function(file) {
    return fs.statSync(path.join(srcpath, file)).isDirectory()
  })
}

var missing_session_files = [
  '7t_trt',
  'ds006',
  'ds007',
  'ds008',
  'ds051',
  'ds052',
  'ds105',
  'ds108',
  'ds109',
  'ds113b',
  'ds000117',
  'ds000246',
  'ds000247',
]

function assertErrorCode(errors, expected_error_code) {
  var matchingErrors = errors.filter(function(error) {
    return error.code === expected_error_code
  })
  assert(matchingErrors.length >= 0)
}

var suite = describe('BIDS example datasets ', function() {
  this.timeout(100000)

  before(function(done) {
    if (!fs.existsSync('tests/data/BIDS-examples-' + test_version + '/')) {
      console.log('downloading test data')
      var response = request(
        'GET',
        'http://github.com/INCF/BIDS-examples/archive/' + test_version + '.zip',
      )
      if (!fs.existsSync('tests/data')) {
        fs.mkdirSync('tests/data')
      }
      fs.writeFileSync('tests/data/examples.zip', response.body)
      var zip = new AdmZip('tests/data/examples.zip')
      console.log('unzipping test data')
      zip.extractAllTo('tests/data/', true)
    }

    var datasetDirectories = getDirectories(
      'tests/data/BIDS-examples-' + test_version + '/',
    )

    datasetDirectories.forEach(function testDataset(path) {
      suite.addTest(
        new Test(path, function(isdone) {
          var options = { ignoreNiftiHeaders: true }
          validate.BIDS(
            'tests/data/BIDS-examples-' + test_version + '/' + path + '/',
            options,
            function(issues) {
              var errors = issues.errors
              var warnings = issues.warnings
              assert.deepEqual(errors, [])
              var session_flag = false
              for (var warning in warnings) {
                if (warnings[warning]['code'] === '38') {
                  session_flag = true
                  break
                }
              }
              if (missing_session_files.indexOf(path) === -1) {
                assert.deepEqual(session_flag, false)
              } else {
                assert.deepEqual(session_flag, true)
              }
              isdone()
            },
          )
        }),
      )
    })
    done()
  })

  // we need to have at least one non-dynamic test
  it('validates path without trailing backslash', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues, summary) {
        var errors = issues.errors
        var warnings = issues.warnings
        assert(summary.sessions.length === 0)
        assert(summary.subjects.length === 16)
        assert.deepEqual(summary.tasks, ['balloon analog risk task'])
        assert(summary.modalities.includes('T1w'))
        assert(summary.modalities.includes('inplaneT2'))
        assert(summary.modalities.includes('bold'))
        assert(summary.totalFiles === 133)
        assert.deepEqual(errors, [])
        assert(warnings.length === 2 && warnings[0].code === '13')
        isdone()
      },
    )
  })

  // we need to have at least one non-dynamic test
  it('validates dataset with valid nifti headers', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_headers', options, function(
      issues,
      summary,
    ) {
      var errors = issues.errors
      var warnings = issues.warnings
      assert(summary.sessions.length === 0)
      assert(summary.subjects.length === 1)
      assert.deepEqual(summary.tasks, ['rhyme judgment'])
      assert(summary.modalities.includes('T1w'))
      assert(summary.modalities.includes('bold'))
      assert(summary.totalFiles === 10)
      assert(errors[0].code === '60')
      assert(warnings.length === 3 && warnings[0].code === '13')
      isdone()
    })
  })

  // test for duplicate files present with both .nii and .nii.gz extension
  it('validates dataset for duplicate files present with both .nii and .nii.gz extension', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '74')
      isdone()
    })
  })

  // test for illegal characters used in acq and task name
  it('validates dataset with illegal characters in task name', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '58')
      isdone()
    })
  })

  // test for illegal characters used in sub name
  it('validates dataset with illegal characters in sub name', function(isdone) {
    var options = { ignoreNiftiHeaders: false }
    validate.BIDS('tests/data/valid_filenames', options, function(issues) {
      assertErrorCode(issues.errors, '64')
      isdone()
    })
  })

  // Catch some browser specific iteration issues with for .. in loops
  describe('with enumerable array prototype methods', function() {
    before(function() {
      // Patch in a potentially iterable prototype
      Array.prototype.broken = function() {
        /* custom extension */
      }
    })
    after(function() {
      // Unpatch the above
      delete Array.prototype.broken
    })
    it('validates dataset with illegal characters in task name', function(isdone) {
      var options = { ignoreNiftiHeaders: false }
      validate.BIDS('tests/data/valid_filenames', options, function(issues) {
        assertErrorCode(issues.errors, '58')
        isdone()
      })
    })
  })

  it('checks for subjects with no valid data', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS('tests/data/no_valid_data', options, function(issues) {
      assertErrorCode(issues.errors, '67')
      isdone()
    })
  })

  it('checks for tabular files without corresponding data dictionaries', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues) {
        assert(issues.warnings.length === 2 && issues.warnings[1].code === '82')
        isdone()
      },
    )
  })

  it('validates ieeg modalities', function(isdone) {
    var options = { ignoreNiftiHeaders: true }
    validate.BIDS(
      'tests/data/BIDS-examples-' + test_version + '/ds001',
      options,
      function(issues, summary) {
        var errors = issues.errors
        var warnings = issues.warnings
        assert(summary.sessions.length === 0)
        assert(summary.subjects.length === 16)
        assert.deepEqual(summary.tasks, ['balloon analog risk task'])
        assert(summary.modalities.includes('T1w'))
        assert(summary.modalities.includes('inplaneT2'))
        assert(summary.modalities.includes('bold'))
        assert(summary.totalFiles === 133)
        assert.deepEqual(errors, [])
        assert(warnings.length === 2 && warnings[0].code === '13')
        isdone()
      },
    )
  })
})
<|endoftext|>


<commit_before>
var _          = require('lodash');
var Promise    = require('bluebird');
var neo4j      = require('../io/neo4j');
var app        = require('../index');
var random     = require('../lib/random');
var agent      = require('supertest-as-promised').agent(app);
var schemas    = require('../schemas');
var User       = require('../models/user');
var Message    = require('../models/message');
var makeToken  = require('../lib/sign-jwt');
var usernames  = require('./usernames.json');
var lorem      = require('lorem-ipsum');

function append (target, source) {
	Array.prototype.push.apply(target, source);
}

var conditions;

module.exports = exports = function bootstrap (options) {
	conditions = {
		users: [],
		userMap: {},
		topics: [],
		tails: [],
	};

	options = _.defaults(options, {
		users: 0,
		topics: 0,
		topicConfig: {},
		depth: 0,
		messageConfigs: [],
	});

	return neo4j.run('MATCH (n) DETACH DELETE (n)').then(() => {
		var d = {};

		var userCount = options.users || 0;
		if (options.depth) {
			userCount += (options.depth || 0) * (options.topics || 1);
		} else if (options.topics) {
			userCount += options.topics;
		}

		if (userCount) {
			d.users = exports.createUsers(userCount);
		}

		if (options.topics) {
			d.topics = d.users.then(() => exports.createTopics(options.topics));
		}

		if (options.chains || options.depth) {
			d.tails = d.users.then(() => Promise.all(
				_.times(options.chains || 1, () => exports.createChain(options.depth))
			));
		}

		return Promise.props(d);
	}).then(() => conditions);
};

exports.agent = agent;
exports.schemas = schemas;
exports.inspect = (value, depth) => console.log(require('util').inspect(value, { colors: true, depth: depth || 6 })); // eslint-disable-line no-console

exports.generateUsername = function () {
	return _.times(2, () => usernames[random(usernames.length - 1)])
		.map(_.capitalize).join('');
};

exports.createUsers = function (count) {
	var usernames = _.times(count, exports.generateUsername);
	return Promise.map(usernames, (username) => Promise.join(
		User.createWithPassword(username, 'password'),
		makeToken(username),
		(user, token) => {
			user.token = token;
			return user;
		}
	)).then((users) => {
		if (conditions) {
			append(conditions.users, users);
			users.forEach((user) => {
				conditions.userMap[user.username] = user;
			});
		}
		return users;
	});
};

exports.createMessage = function (user, parent, settings) {
	var username;
	if (_.isObjectLike(user) && user.username) {
		username = user.username;
	} else if (typeof user === 'string') {
		username = user;
	} else if (typeof user === 'number' && conditions) {
		username = conditions.users[user % (conditions.users.length - 1)].username;
	} else if (conditions) {
		username = random.from(conditions.users).username;
	} else {
		return Promise.reject(new Error('Bootstrap could not find a user to create a message for'));
	}

	var inReplyTo;
	if (_.isObjectLike(parent)) {
		inReplyTo = parent.id;
	} else if (typeof parent === 'string') {
		inReplyTo = parent;
	}

	var opts = Object.assign({
		username,
		body: lorem(),
		inReplyTo,
	}, settings);

	return Message.create(opts).then((message) => {
		if (_.isObjectLike(parent)) {
			parent.replies = parent.replies || [];
			parent.replies.push(message);
			message.parent = parent;
		}
		return message;
	});
};

exports.createTopics = function (count, settings) {
	var pTopics = _.times(count, (i) => exports.createMessage(i, null, settings && settings[i]));

	return Promise.all(pTopics)
		.then((topics) => {
			if (conditions) {
				append(conditions.topics, topics);
				append(conditions.tails, topics);
			}
			return topics;
		});
};

exports.createChain = function (depth, messages, parent) {
	var tail;

	if (typeof parent === 'object') {
		tail = parent;
	} else if (typeof parent === 'string') {
		tail = Message.getById(parent);
	}

	function addMessage (parent, level) {
		if (level + 1 > depth) return Promise.resolve(parent);
		return exports.createMessage(null, parent, messages && messages[level])
			.then((message) => {
				if (!parent) conditions.topics.push(message);
				return addMessage(message, level + 1);
			});
	}

	return Promise.join(tail, 0, addMessage)
		.then((tail) => {
			if (conditions) {
				var i = conditions.tails.indexOf(parent);
				if (i > -1) {
					conditions.tails[i] = tail;
				} else {
					conditions.tails.push(tail);
				}
			}
			return tail;
		});

};
<commit_msg>bootstrap.js: fix divide by zero when there is only one user<commit_after>
var _          = require('lodash');
var Promise    = require('bluebird');
var neo4j      = require('../io/neo4j');
var app        = require('../index');
var random     = require('../lib/random');
var agent      = require('supertest-as-promised').agent(app);
var schemas    = require('../schemas');
var User       = require('../models/user');
var Message    = require('../models/message');
var makeToken  = require('../lib/sign-jwt');
var usernames  = require('./usernames.json');
var lorem      = require('lorem-ipsum');

function append (target, source) {
	Array.prototype.push.apply(target, source);
}

var conditions;

module.exports = exports = function bootstrap (options) {
	conditions = {
		users: [],
		userMap: {},
		topics: [],
		tails: [],
	};

	options = _.defaults(options, {
		users: 0,
		topics: 0,
		topicConfig: {},
		depth: 0,
		messageConfigs: [],
	});

	return neo4j.run('MATCH (n) DETACH DELETE (n)').then(() => {
		var d = {};

		var userCount = options.users || 0;
		if (options.depth) {
			userCount += (options.depth || 0) * (options.topics || 1);
		} else if (options.topics) {
			userCount += options.topics;
		}

		if (userCount) {
			d.users = exports.createUsers(userCount);
		}

		if (options.topics) {
			d.topics = d.users.then(() => exports.createTopics(options.topics));
		}

		if (options.chains || options.depth) {
			d.tails = d.users.then(() => Promise.all(
				_.times(options.chains || 1, () => exports.createChain(options.depth))
			));
		}

		return Promise.props(d);
	}).then(() => conditions);
};

exports.agent = agent;
exports.schemas = schemas;
exports.inspect = (value, depth) => console.log(require('util').inspect(value, { colors: true, depth: depth || 6 })); // eslint-disable-line no-console

exports.generateUsername = function () {
	return _.times(2, () => usernames[random(usernames.length - 1)])
		.map(_.capitalize).join('');
};

exports.createUsers = function (count) {
	var usernames = _.times(count, exports.generateUsername);
	return Promise.map(usernames, (username) => Promise.join(
		User.createWithPassword(username, 'password'),
		makeToken(username),
		(user, token) => {
			user.token = token;
			return user;
		}
	)).then((users) => {
		if (conditions) {
			append(conditions.users, users);
			users.forEach((user) => {
				conditions.userMap[user.username] = user;
			});
		}
		return users;
	});
};

exports.createMessage = function (user, parent, settings) {
	var username;
	if (_.isObjectLike(user) && user.username) {
		username = user.username;
	} else if (typeof user === 'string') {
		username = user;
	} else if (typeof user === 'number' && conditions) {
		username = conditions.users[user % Math.max(conditions.users.length - 1, 1)].username;
	} else if (conditions) {
		username = random.from(conditions.users).username;
	} else {
		return Promise.reject(new Error('Bootstrap could not find a user to create a message for'));
	}

	var inReplyTo;
	if (_.isObjectLike(parent)) {
		inReplyTo = parent.id;
	} else if (typeof parent === 'string') {
		inReplyTo = parent;
	}

	var opts = Object.assign({
		username,
		body: lorem(),
		inReplyTo,
	}, settings);

	return Message.create(opts).then((message) => {
		if (_.isObjectLike(parent)) {
			parent.replies = parent.replies || [];
			parent.replies.push(message);
			message.parent = parent;
		}
		return message;
	});
};

exports.createTopics = function (count, settings) {
	var pTopics = _.times(count, (i) => exports.createMessage(i, null, settings && settings[i]));

	return Promise.all(pTopics)
		.then((topics) => {
			if (conditions) {
				append(conditions.topics, topics);
				append(conditions.tails, topics);
			}
			return topics;
		});
};

exports.createChain = function (depth, messages, parent) {
	var tail;

	if (typeof parent === 'object') {
		tail = parent;
	} else if (typeof parent === 'string') {
		tail = Message.getById(parent);
	}

	function addMessage (parent, level) {
		if (level + 1 > depth) return Promise.resolve(parent);
		return exports.createMessage(null, parent, messages && messages[level])
			.then((message) => {
				if (!parent) conditions.topics.push(message);
				return addMessage(message, level + 1);
			});
	}

	return Promise.join(tail, 0, addMessage)
		.then((tail) => {
			if (conditions) {
				var i = conditions.tails.indexOf(parent);
				if (i > -1) {
					conditions.tails[i] = tail;
				} else {
					conditions.tails.push(tail);
				}
			}
			return tail;
		});

};
<|endoftext|>


<commit_before>/** @constructor */
PuzL.GameScreen = function( game )
{
  this.gameShell    = null;
  this.parentScreen = null;
};
//window['GameScreen'] = PuzL.GameScreen;

PuzL.GameScreen.prototype.id = "";

PuzL.GameScreen.prototype.initialize = function()
{

};

PuzL.GameScreen.prototype.preload = function()
{
  this.stage.disableVisibilityChange = !this.gameShell.gameShellSettings.pauseOnLoseFocus;
  this.stage.smoothed = !this.gameShell.gameShellSettings.pixelPerfect;

  this.initialize();
};

PuzL.GameScreen.prototype.postInitialize = function()
{

};

PuzL.GameScreen.prototype.create = function()
{
  this.postInitialize();
};
<commit_msg>Ensured game canvases go crisp (pixels not smoothed) when game shell setting is such.<commit_after>/** @constructor */
PuzL.GameScreen = function( game )
{
  this.gameShell    = null;
  this.parentScreen = null;
};
//window['GameScreen'] = PuzL.GameScreen;

PuzL.GameScreen.prototype.id = "";

PuzL.GameScreen.prototype.initialize = function()
{

};

PuzL.GameScreen.prototype.preload = function()
{
  this.stage.disableVisibilityChange = !this.gameShell.gameShellSettings.pauseOnLoseFocus;
  this.stage.smoothed = !this.gameShell.gameShellSettings.pixelPerfect;

  if( !this.stage.smoothed )
  {
    Phaser.Canvas.setImageRenderingCrisp( this.game.canvas );
  }

  this.initialize();
};

PuzL.GameScreen.prototype.postInitialize = function()
{

};

PuzL.GameScreen.prototype.create = function()
{
  this.postInitialize();
};
<|endoftext|>