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

/**
 * @namespace fieldSettings
 * @type {Object}
 *
 * @description
 * The default properties and methods for a field in vulcanval {@link settings.fields}
 * configuration.
 */
const fieldSettings = {

  /**
   * The field name. This property is always required.
   *
   * @type {String}
   */
  name: null,

  /**
   * Field will be ignored in validation if `true`.
   *
   * @type {Boolean}
   * @default false
   */
  disabled: null,

  /**
   * Field is required and cannot be undefined. If the field is not required but
   * it has a
   * {@link https://developer.mozilla.org/en-US/docs/Glossary/Truthy truthy value},
   * then this will pass over all validators.
   *
   * @type {Boolean}
   * @default false
   */
  required: null,

  /**
   * The validators list. This is an object with keys as the validators names and
   * values as their configuration. If the value is simply a boolean `true`,
   * the validator will be invoked without options. It it is string, number or
   * object it will be send as validator options. If value is `false`, the validator
   * will not be used.
   *
   * These won't be used if the field value is boolean.
   *
   * You can use all validators from the {@link https://www.npmjs.com/package/validator validator}
   * package.
   *
   * @type {Object}
   */
  validators: null,

  /**
   * Only client-side.
   *
   * What event to listen to trigger the first validation on field.
   *
   * @type {String}
   * @default Inherited from {@link settings}
   */
  firstValidationEvent: null,

  /**
   * Only client-side.
   *
   * After first validation, what events to listen to re-validate field.
   *
   * @type {String}
   * @default Inherited from {@link settings}
   */
  validationEvents: null,

  /**
   * Only client-side.
   *
   * Validate field elements on instance time.
   *
   * @type {Boolean}
   * @default false
   */
  autostart: null,

  /**
   * Only client-side.
   *
   * When a field is validated, don't show changes visually nor show messages.
   * This is used to know whether they are valid or not, update the fields
   * elements states and trigger events.
   *
   * If the field is an `<input>` type `hidden`, this will be set as `true`.
   *
   * @type {Boolean}
   * @default false
   */
  intern: null,

  /**
   * Only client-side.
   *
   * Ignore field in validation in server side.
   *
   * @type {Boolean}
   * @default false
   */
  onlyUI: null,

  /**
   * Only client-side.
   *
   * The element where to set the current field message error. If not specified,
   * the messages won't be shown on UI. This is a jQuery selector.
   *
   * @type {external:jQuery}
   */
  display: null,

  /**
   * Only client-side.
   *
   * Display jQuery element.
   *
   * @private
   * @type {external:jQuery}
   */
  $display: null,

  /**
   * Only client-side.
   *
   * jQuery `<label>` elements which have `for` attribute to the field element.
   *
   * @private
   * @type {external:jQuery}
   */
  $labels: null,

  /**
   * Only client-side.
   *
   * Field jQuery element.
   *
   * The field node element saves the jQuery data states:
   * - {undefined|Boolean} vv-modified - If the field has been modified by the user
   *   after the validation process has been set. undefined if it's unknown.
   * - {undefined|Boolean} vv-valid - If the field is valid. undefined if it's unknown.
   * - {Boolean|String} vv-msg - The error message if field is invalid. false if
   *   field is valid.
   *
   * The field node element triggers an event called `vv-modify` to inform about
   * a change in the field which affects the validation process. This event
   * receives an object parameter describing:
   * - {String} name - Field name.
   * - {*} value - Field value.
   * - {Boolean} valid - Field status.
   * - {Boolean|String} msg - If field is invalid the error, otherwise false.
   *
   * @private
   * @type {external:jQuery}
   */
  $el: null,

  /**
   * Only client-side.
   *
   * Field onFirstChange event (this is defined by user).
   *
   * @private
   * @type {Function}
   */
  onFirstChange: null,

  /**
   * Only client-side.
   *
   * Field onChange event (this is defined by user).
   *
   * @private
   * @type {Function}
   */
  onChange: null,

  /**
   * Only client-side.
   *
   * Field onBlur event.
   *
   * @private
   * @type {Function}
   */
  onBlur: null,

  /**
   * A condition gate to verify if the field will be validated. Receives
   * the field value as first parameter and has to return a boolean, if `true`
   * the validation will procced as normal, otherwise the validation will halt.
   *
   * This is a function
   * with the {@link utilityContext utility context} as function context so don't use
   * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions arrow functions}.
   *
   * @method
   * @return {Boolean}
   */
  onlyIf: null,

  /**
   * Only client-side.
   *
   * Method to get the value of the field. This will have the {@link utilityContext utilty context}
   * so don't use
   * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions arrow functions}.
   *
   * By default this can retrieve the value of `<input>`s of any kind except `submit`, 'reset'
   * and `button`, `<textarea>`s and `<select>`s.
   *
   * You can overwrite this to create your own custom field value getter.
   *
   * @param  {external:jQuery} $field - The field element.
   * @return {*} The value returned will depend on the type of element.
   */
  value ($field) {

    // @FIXIT: Make the space trimmer works with an option.

    var type, name, val;

    if (!$field) {
      return;
    }

    else if ($field[0].tagName === 'INPUT') {

      type = String($field.attr('type')).toUpperCase();
      name = $field.attr('name') || $field.data('vv-name');

      if (type === 'CHECKBOX') {
        return $field.prop('checked');
      }
      if (type === 'RADIO') {
        return $field.parents('form, body').first().find(`input[type="radio"][name="${name}"]:checked`).val() || '';
      }
      else if (type !== 'BUTTON' && type !== 'SUBMIT' && type !== 'RESET') {
        return utils.trimSpaces($field.val());
      }
    }

    else if ($field[0].tagName === 'TEXTAREA' || $field[0].tagName === 'SELECT') {
      return utils.trimSpaces($field.val());
    }
  },

  /**
   * Extend field settings default configuration.
   *
   * @private
   * @param  {Object} custom
   * @return {Object}
   */
  extend (custom) {
    return extend(true, {}, this, custom);
  }
};

module.exports = fieldSettings;
<commit_msg>update: fieldSettings<commit_after>const extend = require('extend');
const utils = require('./utils');

/**
 * @namespace fieldSettings
 * @type {Object}
 *
 * @description
 * The default properties and methods for a field.
 *
 * This is configured in {@link settings.fields} array property.
 *
 * Each field settings can be affected by the main {@link settings} and by the
 * {@link fieldsetSettings}.
 */
const fieldSettings = {

  /**
   * The field name. This property is always required.
   *
   * @type {String}
   */
  name: null,

  /**
   * Field will be ignored in validation if `true`.
   *
   * @type {Boolean}
   * @default false
   */
  disabled: null,

  /**
   * Field is required and cannot be undefined. If the field is not required but
   * it has a
   * {@link https://developer.mozilla.org/en-US/docs/Glossary/Truthy truthy value},
   * then this will pass over all validators.
   *
   * @type {Boolean}
   * @default false
   */
  required: null,

  /**
   * Only client-side.
   *
   * Validate field elements on instance time.
   *
   * @type {Boolean}
   * @default false
   */
  autostart: null,

  /**
   * Only client-side.
   *
   * When a field is validated, don't show changes visually nor show messages.
   * This is used to know whether they are valid or not, update the fields
   * elements states and trigger events.
   *
   * If the field is an `<input>` type `hidden`, this will be set as `true`.
   *
   * @type {Boolean}
   * @default false
   */
  intern: null,

  /**
   * Only client-side.
   *
   * Ignore field in validation in server side.
   *
   * @type {Boolean}
   * @default false
   */
  onlyUI: null,

  /**
   * Only client-side.
   *
   * What event to listen to trigger the first validation on field.
   *
   * @type {String}
   * @default Inherited from {@link settings}
   */
  firstValidationEvent: null,

  /**
   * Only client-side.
   *
   * After first validation, what events to listen to re-validate field.
   *
   * @type {String}
   * @default Inherited from {@link settings}
   */
  validationEvents: null,

  /**
   * The validators list. This is an object with keys as the validators names and
   * values as their configuration. If the value is simply a boolean `true`,
   * the validator will be invoked without options. It it is string, number or
   * object it will be send as validator options. If value is `false`, the validator
   * will not be used.
   *
   * These won't be used if the field value is boolean.
   *
   * You can use all validators from the {@link https://www.npmjs.com/package/validator validator}
   * package.
   *
   * @type {Object}
   */
  validators: null,

  /**
   * Only client-side.
   *
   * Field jQuery element.
   *
   * The field node element saves the jQuery data states:
   * - {undefined|Boolean} vv-modified - If the field has been modified by the user
   *   after the validation process has been set. undefined if it's unknown.
   * - {undefined|Boolean} vv-valid - If the field is valid. undefined if it's unknown.
   * - {Boolean|String} vv-msg - The error message if field is invalid. false if
   *   field is valid.
   *
   * The field node element triggers an event called `vv-modify` to inform about
   * a change in the field which affects the validation process. This event
   * receives an object parameter describing:
   * - {String} name - Field name.
   * - {*} value - Field value.
   * - {Boolean} valid - Field status.
   * - {Boolean|String} msg - If field is invalid the error, otherwise false.
   *
   * @private
   * @type {external:jQuery}
   */
  $el: null,

  /**
   * Only client-side.
   *
   * The element where to set the current field message error. If not specified,
   * the messages won't be shown on UI. This is a jQuery selector.
   *
   * @type {external:jQuery}
   */
  display: null,

  /**
   * Only client-side.
   *
   * Display jQuery element.
   *
   * @private
   * @type {external:jQuery}
   */
  $display: null,

  /**
   * Only client-side.
   *
   * jQuery `<label>` elements which have `for` attribute to the field element.
   *
   * @private
   * @type {external:jQuery}
   */
  $labels: null,

  /**
   * Only client-side.
   *
   * Field onFirstChange event (this is defined by user).
   *
   * @private
   * @type {Function}
   */
  onFirstChange: null,

  /**
   * Only client-side.
   *
   * Field onChange event (this is defined by user).
   *
   * @private
   * @type {Function}
   */
  onChange: null,

  /**
   * Only client-side.
   *
   * Field onBlur event.
   *
   * @private
   * @type {Function}
   */
  onBlur: null,

  /**
   * A condition gate to verify if the field will be validated. Receives
   * the field value as first parameter and has to return a boolean, if `true`
   * the validation will procced as normal, otherwise the validation will halt.
   *
   * This is a function
   * with the {@link utilityContext utility context} as function context so don't use
   * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions arrow functions}.
   *
   * @method
   * @return {Boolean}
   */
  onlyIf: null,

  /**
   * Only client-side.
   *
   * Method to get the value of the field. This will have the {@link utilityContext utilty context}
   * so don't use
   * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions arrow functions}.
   *
   * By default this can retrieve the value of `<input>`s of any kind except `submit`, 'reset'
   * and `button`, `<textarea>`s and `<select>`s.
   *
   * You can overwrite this to create your own custom field value getter.
   *
   * @param  {external:jQuery} $field - The field element.
   * @return {*} The value returned will depend on the type of element.
   */
  value ($field) {

    // @FIXIT: Make the space trimmer works with an option.

    var type, name, val;

    if (!$field) {
      return;
    }

    else if ($field[0].tagName === 'INPUT') {

      type = String($field.attr('type')).toUpperCase();
      name = $field.attr('name') || $field.data('vv-name');

      if (type === 'CHECKBOX') {
        return $field.prop('checked');
      }
      if (type === 'RADIO') {
        return $field.parents('form, body').first().find(`input[type="radio"][name="${name}"]:checked`).val() || '';
      }
      else if (type !== 'BUTTON' && type !== 'SUBMIT' && type !== 'RESET') {
        return utils.trimSpaces($field.val());
      }
    }

    else if ($field[0].tagName === 'TEXTAREA' || $field[0].tagName === 'SELECT') {
      return utils.trimSpaces($field.val());
    }
  },

  /**
   * Extend field settings default configuration.
   *
   * @private
   * @param  {Object} custom
   * @return {Object}
   */
  extend (custom) {
    return extend(Object.create(fieldSettings), custom);
  }
};

module.exports = fieldSettings;
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var c<commit_msg>Commit all the required changes<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var co<|endoftext|>


<commit_before>import palette from './palette';

import assign from 'lodash.assign';

//the bounds of the set
const LEFT_EDGE = -2.5;
const RIGHT_EDGE = 1;
const TOP_EDGE = -1;
const BOTTOM_EDGE = 1;

//this is a bitshift operation, not a bool
//i normally wouldn't, but it's really convenient
const MAX_RADIUS = (1 << 16);

//because the bounds of the set are uneven, we're horizontally offset this much
const HORIZONTAL_OFFSET = LEFT_EDGE - ((LEFT_EDGE - RIGHT_EDGE) / 2);

//width / height ratio of the bounds of the set
const MANDEL_RATIO = (RIGHT_EDGE - LEFT_EDGE) / (BOTTOM_EDGE - TOP_EDGE);

const MIMETYPE_PNG = 'image/png';

const DEFAULT_SETTINGS = {
    palette: 'rainbow',
    maxIterations: 1000, //probably better NOT to set this in the options?
    mandelbrotColor: {
        r: 0,
        g: 0,
        b: 0
    }
};

export default class Renderer {
    constructor(canvas, options) {

        options = assign({}, options, DEFAULT_SETTINGS);

        this._canvas = canvas;
        this._context = this._canvas.getContext('2d');
        this._imageData = this._context.createImageData(this._canvas.width, this._canvas.height);
        this._data = this._imageData.data;

        this._maxIterations = options.maxIterations;
        this._mandelbrotColor = options.mandelbrotColor;
        this._palette = palette[options.palette];

        //TODO: decide if this is beset approach.
        //is it better to let user be absolute in this?
        //or to enforce perfect cycle of palette?
        this._maxIterations = this._maxIterations + (this._maxIterations % this._palette.length);

        this.updateViewportSize();

        this._scale = 1;
        this._dx = HORIZONTAL_OFFSET;
        this._dy = 0;
    }

    get DataUrl() {
        return this._canvas.toDataURL(MIMETYPE_PNG);
    }

    get x() {
        return this._dx;
    }

    get y() {
        return this._dy;
    }

    get scale() {
        return this._scale;
    }

    plot(x, y, color) {
        //the canvas pixel data is a bit awkward to get at...
        //see: https://www.w3.org/TR/2dcontext/#pixel-manipulation
        var dataIndex = (y * this._imageData.width + x) * 4;
        if (dataIndex < this._data.length && dataIndex >= 0) {
            this._data[dataIndex] = color.r;
            this._data[dataIndex + 1] = color.g;
            this._data[dataIndex + 2] = color.b;
            this._data[dataIndex + 3] = 255; //max saturation
        }
    }

    updateViewportSize() {
        //width / height ratio of the viewport
        this._imageData = this._context.createImageData(this._canvas.width, this._canvas.height);
        this._data = this._imageData.data;
        this._imageRatio = this._imageData.width / this._imageData.height;

        var ratio = 1;
        var product = 0;

        this._topEdge = TOP_EDGE;
        this._bottomEdge = BOTTOM_EDGE;
        this._leftEdge = LEFT_EDGE;
        this._rightEdge = RIGHT_EDGE;

        //modify the bounds we display based on the
        //difference between the viewport ratio and
        //the ratio of the bounds of the mandelbrot
        if (this._imageRatio > MANDEL_RATIO) {
            ratio = (this._imageRatio / MANDEL_RATIO);
            product = (RIGHT_EDGE - LEFT_EDGE) * ratio;

            this._leftEdge = -product * (2.5 / 3.5);
            this._rightEdge = product * (1 / 3.5);
        } else {
            ratio = (MANDEL_RATIO / this._imageRatio);
            product = (BOTTOM_EDGE - TOP_EDGE) * ratio;

            this._topEdge = -product * (1 / 2.0);
            this._bottomEdge = product * (1 / 2.0);
        }
    }

    updateRealBoundaries() {
        //the Real (ℝ) boundaries of the rendering given the zoom and offset
        this.xMax = this._rightEdge / this.scale + this.x;
        this.xMin = this._leftEdge / this.scale + this.x;
        this.yMax = this._bottomEdge / this.scale + this.y;
        this.yMin = this._topEdge / this.scale + this.y;

        //translation of "Pixel space" to Real (ℝ) space
        //i.e., these variables represent the Real difference
        //between two pixels, horizonatally and vertically
        this.xStep = (this.xMax - this.xMin) / this._imageData.width;
        this.yStep = (this.yMax - this.yMin) / this._imageData.height;
    }

    interpolateValue(val1, val2, fraction) {
        return (1 - fraction) * val1 + fraction * val2;
        //return val1 + (val2 - val1) * fraction;
    }

    interpolateColor(color1, color2, fraction) {
            return {
                r: this.interpolateValue(color1.r, color2.r, fraction),
                g: this.interpolateValue(color1.g, color2.g, fraction),
                b: this.interpolateValue(color1.b, color2.b, fraction),
            };
        }
        //scale: how far we've zoomed in from the default
        //dx0: displacement of perspective horizontally
        //dy0: displacement of perspective vertically
    render(scale, dx0, dy0) {
        this._scale = scale;
        this._dx = dx0 - HORIZONTAL_OFFSET / this._scale;
        this._dy = dy0;

        this.updateRealBoundaries();

        //An implementation of the Escape Time Algorithm
        //https://en.wikipedia.org/wiki/Mandelbrot_set#Escape_time_algorithm
        for (var canvasY = 0; canvasY < this._imageData.height; canvasY++) {
            for (var canvasX = 0; canvasX < this._imageData.width; canvasX++) {
                //scale the pixel values to be within the bounds of the set
                var pos = this.canvasPositionToRealPosition(canvasX, canvasY);
                var x0 = pos.x;
                var y0 = pos.y;

                var x = 0.0;
                var y = 0.0;

                var iteration = 0;
                while (x * x + y * y < MAX_RADIUS * 2 && iteration < this._maxIterations) {
                    var tempX = x * x - y * y + x0;
                    y = 2 * x * y + y0;
                    x = tempX;
                    iteration++;
                }

                //deafult to black unless we managed to rule this pixel out
                var color = this._mandelbrotColor;

                if (iteration < this._maxIterations) {
                    var log_zn = Math.log(x * x + y * y) / 2;
                    var nu = Math.log(log_zn / Math.log(2)) / Math.log(2);
                    iteration = iteration + 1 - nu;

                    var color1 = this._palette[Math.floor(iteration) % this._palette.length];
                    var color2 = this._palette[(Math.floor(iteration) + 1) % this._palette.length];

                    color = this.interpolateColor(color1, color2, iteration % 1);
                }

                this.plot(canvasX, canvasY, color);
            }
        }

        //TODO: decide if worth bothering adding below commented code for debugging purposes
        /*
        var whitePos = {
            x: this._imageData.width/2,
            y: this._imageData.height/2
        };

        for (var whiteY = 0; whiteY < this._imageData.height; whiteY++) {
            this.plot(whitePos.x, whiteY, {
                r: 255,
                g: 255,
                b: 255
            });
        }
        for (var whiteX = 0; whiteX < this._imageData.width; whiteX++) {
            this.plot(whiteX, whitePos.y, {
                r: 255,
                g: 255,
                b: 255
            });
        }

        var redPos = this.realPositionToCanvasPosition(0, 0);

        //draw the Real coordinate space axis
        for (var redX = 0; redX < this._imageData.width; redX++) {
            this.plot(redX, redPos.y, {
                r: 255,
                g: 0,
                b: 0
            });
        }

        for (var redY = 0; redY < this._imageData.height; redY++) {
            this.plot(redPos.x, redY, {
                r: 255,
                g: 0,
                b: 0
            });
        }
        */

        //draw it!
        this._context.putImageData(this._imageData, 0, 0);
    }

    realPositionToCanvasPosition(realX, realY) {
        return {
            x: parseInt((realX - this.xMin) / this.xStep),
            y: parseInt((realY - this.yMin) / this.yStep)
        };
    }

    canvasPositionToRealPosition(canvasX, canvasY) {
        //scale the pixel values to frame the bounds of the set
        return {
            x: this.xMin + this.xStep * canvasX,
            y: this.yMin + this.yStep * canvasY
        };
    }
}
<commit_msg>minor comment updates, more to come<commit_after>import palette from './palette';

import assign from 'lodash.assign';

//the bounds of the set
const LEFT_EDGE = -2.5;
const RIGHT_EDGE = 1;
const TOP_EDGE = -1;
const BOTTOM_EDGE = 1;

//this is a bitshift operation, not a bool
//i normally wouldn't, but it's really convenient
const MAX_RADIUS = (1 << 16);

//because the bounds of the set are uneven, we're horizontally offset this much
const HORIZONTAL_OFFSET = LEFT_EDGE - ((LEFT_EDGE - RIGHT_EDGE) / 2);

//width / height ratio of the bounds of the set
const MANDEL_RATIO = (RIGHT_EDGE - LEFT_EDGE) / (BOTTOM_EDGE - TOP_EDGE);

const MIMETYPE_PNG = 'image/png';

const DEFAULT_SETTINGS = {
    palette: 'rainbow',
    maxIterations: 1000, //probably better NOT to set this in the options?
    mandelbrotColor: {
        r: 0,
        g: 0,
        b: 0
    }
};

export default class Renderer {
    constructor(canvas, options) {

        options = assign({}, options, DEFAULT_SETTINGS);

        this._canvas = canvas;
        this._context = this._canvas.getContext('2d');
        this._imageData = this._context.createImageData(this._canvas.width, this._canvas.height);
        this._data = this._imageData.data;

        this._maxIterations = options.maxIterations;
        this._mandelbrotColor = options.mandelbrotColor;
        this._palette = palette[options.palette];

        //TODO: decide if this is beset approach.
        //is it better to let user be absolute in this?
        //or to enforce perfect cycle of palette?
        this._maxIterations = this._maxIterations + (this._maxIterations % this._palette.length);

        this.updateViewportSize();

        this._scale = 1;
        this._dx = HORIZONTAL_OFFSET;
        this._dy = 0;
    }

    get DataUrl() {
        return this._canvas.toDataURL(MIMETYPE_PNG);
    }

    get x() {
        return this._dx;
    }

    get y() {
        return this._dy;
    }

    get scale() {
        return this._scale;
    }

    plot(x, y, color) {
        //the canvas pixel data is a bit awkward to get at...
        //see: https://www.w3.org/TR/2dcontext/#pixel-manipulation
        var dataIndex = (y * this._imageData.width + x) * 4;
        if (dataIndex < this._data.length && dataIndex >= 0) {
            this._data[dataIndex] = color.r;
            this._data[dataIndex + 1] = color.g;
            this._data[dataIndex + 2] = color.b;
            this._data[dataIndex + 3] = 255; //max saturation
        }
    }

    updateViewportSize() {
        //width / height ratio of the viewport
        this._imageData = this._context.createImageData(this._canvas.width, this._canvas.height);
        this._data = this._imageData.data;
        this._imageRatio = this._imageData.width / this._imageData.height;

        var ratio = 1;
        var product = 0;

        this._topEdge = TOP_EDGE;
        this._bottomEdge = BOTTOM_EDGE;
        this._leftEdge = LEFT_EDGE;
        this._rightEdge = RIGHT_EDGE;

        //modify the bounds we display based on the
        //difference between the viewport ratio and
        //the ratio of the bounds of the mandelbrot
        if (this._imageRatio > MANDEL_RATIO) {
            ratio = (this._imageRatio / MANDEL_RATIO);
            product = (RIGHT_EDGE - LEFT_EDGE) * ratio;

            this._leftEdge = -product * (2.5 / 3.5);
            this._rightEdge = product * (1 / 3.5);
        } else {
            ratio = (MANDEL_RATIO / this._imageRatio);
            product = (BOTTOM_EDGE - TOP_EDGE) * ratio;

            this._topEdge = -product * (1 / 2.0);
            this._bottomEdge = product * (1 / 2.0);
        }
    }

    updateRealBoundaries() {
        //the Real (ℝ) boundaries of the rendering given the zoom and offset
        this.xMax = this._rightEdge / this.scale + this.x;
        this.xMin = this._leftEdge / this.scale + this.x;
        this.yMax = this._bottomEdge / this.scale + this.y;
        this.yMin = this._topEdge / this.scale + this.y;

        //translation of "Pixel space" to Real (ℝ) space
        //i.e., these variables represent the Real difference
        //between two pixels, horizonatally and vertically
        this.xStep = (this.xMax - this.xMin) / this._imageData.width;
        this.yStep = (this.yMax - this.yMin) / this._imageData.height;
    }

    interpolateValue(val1, val2, fraction) {
        return (1 - fraction) * val1 + fraction * val2;
    }

    interpolateColor(color1, color2, fraction) {
            return {
                r: this.interpolateValue(color1.r, color2.r, fraction),
                g: this.interpolateValue(color1.g, color2.g, fraction),
                b: this.interpolateValue(color1.b, color2.b, fraction),
            };
        }
        //scale: how far we've zoomed in from the default
        //dx0: displacement of perspective horizontally
        //dy0: displacement of perspective vertically
    render(scale, dx0, dy0) {
        this._scale = scale;
        this._dx = dx0 - HORIZONTAL_OFFSET / this._scale;
        this._dy = dy0;

        this.updateRealBoundaries();

        //An implementation of the Escape Time Algorithm with continuous coloring
        //almost directly from https://en.wikipedia.org/wiki/Mandelbrot_set#Escape_time_algorithm
        //with https://en.wikipedia.org/wiki/Mandelbrot_set#Continuous_.28smooth.29_coloring
        for (var canvasY = 0; canvasY < this._imageData.height; canvasY++) {
            for (var canvasX = 0; canvasX < this._imageData.width; canvasX++) {
                //scale the pixel values to be within the bounds of the set
                var pos = this.canvasPositionToRealPosition(canvasX, canvasY);
                var x0 = pos.x;
                var y0 = pos.y;

                var x = 0.0;
                var y = 0.0;

                var iteration = 0;
                while (x * x + y * y < MAX_RADIUS * 2 && iteration < this._maxIterations) {
                    var tempX = x * x - y * y + x0;
                    y = 2 * x * y + y0;
                    x = tempX;
                    iteration++;
                }

                //deafult to black unless we managed to rule this pixel out
                var color = this._mandelbrotColor;

                if (iteration < this._maxIterations) {
                    var log_zn = Math.log(x * x + y * y) / 2;
                    var nu = Math.log(log_zn / Math.log(2)) / Math.log(2);
                    iteration = iteration + 1 - nu;

                    var color1 = this._palette[Math.floor(iteration) % this._palette.length];
                    var color2 = this._palette[(Math.floor(iteration) + 1) % this._palette.length];

                    color = this.interpolateColor(color1, color2, iteration % 1);
                }

                this.plot(canvasX, canvasY, color);
            }
        }

        //TODO: decide if worth bothering adding below commented code for debugging purposes
        /*
        var whitePos = {
            x: this._imageData.width/2,
            y: this._imageData.height/2
        };

        for (var whiteY = 0; whiteY < this._imageData.height; whiteY++) {
            this.plot(whitePos.x, whiteY, {
                r: 255,
                g: 255,
                b: 255
            });
        }
        for (var whiteX = 0; whiteX < this._imageData.width; whiteX++) {
            this.plot(whiteX, whitePos.y, {
                r: 255,
                g: 255,
                b: 255
            });
        }

        var redPos = this.realPositionToCanvasPosition(0, 0);

        //draw the Real coordinate space axis
        for (var redX = 0; redX < this._imageData.width; redX++) {
            this.plot(redX, redPos.y, {
                r: 255,
                g: 0,
                b: 0
            });
        }

        for (var redY = 0; redY < this._imageData.height; redY++) {
            this.plot(redPos.x, redY, {
                r: 255,
                g: 0,
                b: 0
            });
        }
        */

        //draw it!
        this._context.putImageData(this._imageData, 0, 0);
    }

    realPositionToCanvasPosition(realX, realY) {
        return {
            x: parseInt((realX - this.xMin) / this.xStep),
            y: parseInt((realY - this.yMin) / this.yStep)
        };
    }

    canvasPositionToRealPosition(canvasX, canvasY) {
        //scale the pixel values to frame the bounds of the set
        return {
            x: this.xMin + this.xStep * canvasX,
            y: this.yMin + this.yStep * canvasY
        };
    }
}
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

process.on('exit', fun<commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

process.on('exit', func<|endoftext|>


<commit_before>(function (angular) {
    ////AngularJS Code ////
    angular.module('cpControllers').controller('mainPageController', ['$scope', '$location', '$sce', 'songHistoryFactory', mainPageController]);

    function mainPageController($scope, $location, $sce, songHistoryFactory) {
        console.log("inside MainController");
//        var this = $scope;
        this.recents = songHistoryFactory.getRecentSongs();
        this.searchResult;
        SC.initialize({
            client_id: "d652006c469530a4a7d6184b18e16c81"
        });
    }
})(angular);<commit_msg>separated controllers but still on same scope<commit_after>(function (angular) {
    ////AngularJS Code ////
    angular.module('cpControllers').controller('mainPageController', ['$scope', '$location', '$sce', 'songHistoryFactory', mainPageController]);

    function mainPageController($scope, $location, $sce, songHistoryFactory) {
        console.log("inside MainController");
//        var this = $scope;
        this.recents = songHistoryFactory.getRecentSongs();
        this.searchResult;
        SC.initialize({
            client_id: "d652006c469530a4a7d6184b18e16c81"
        });
    }
})(angular);
///test<|endoftext|>


<commit_before>/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule SyntheticUIEvent
 * @typechecks static-only
 */

"use strict";

var SyntheticEvent = require('SyntheticEvent');

/**
 * @interface UIEvent
 * @see http://www.w3.org/TR/DOM-Level-3-Events/
 */
var UIEventInterface = {
  view: null,
  detail: null
};

/**
 * @param {object} dispatchConfig Configuration used to dispatch this event.
 * @param {string} dispatchMarker Marker identifying the event target.
 * @param {object} nativeEvent Native browser event.
 * @extends {SyntheticEvent}
 */
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) {
  SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
}

SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);

module.exports = SyntheticUIEvent;
<commit_msg>Normalize view and detail properties<commit_after>/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule SyntheticUIEvent
 * @typechecks static-only
 */

"use strict";

var SyntheticEvent = require('SyntheticEvent');

var getEventTarget = require('getEventTarget');

/**
 * @interface UIEvent
 * @see http://www.w3.org/TR/DOM-Level-3-Events/
 */
var UIEventInterface = {
  view: function(event) {
    if (event.view) {
      return event.view;
    } else {
      var target = getEventTarget(event);
      if (target != null && target.window === target) {
        // target is a window object
        return target;
      } else {
        var doc = target.ownerDocument;
        return doc.defaultView || doc.parentWindow;
      }
    }
  },
  detail: function(event) {
    return event.detail || 0;
  }
};

/**
 * @param {object} dispatchConfig Configuration used to dispatch this event.
 * @param {string} dispatchMarker Marker identifying the event target.
 * @param {object} nativeEvent Native browser event.
 * @extends {SyntheticEvent}
 */
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) {
  SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
}

SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);

module.exports = SyntheticUIEvent;
<|endoftext|>


<commit_before>function get(i){
    return document.getElementById(i)
}
function resize(){
    width = get('canvas').width = window.innerWidth;
    height = get('canvas').height = window.innerHeight;

    x = width/2;
    y = height/2;

    i = canvas.createLinearGradient(0,height*.05,0,height);
    i.addColorStop(0,'#000');
    i.addColorStop(1,'#a99');
    canvas.fillStyle = i;

    i = 3;
    canvas.translate(x,y);
    do{
        canvas.rotate(rotate);
        canvas.beginPath();
        canvas.moveTo(0,0);
        canvas.lineTo(width,width);
        canvas.lineTo(-width,width);
        canvas.closePath();
        canvas.fill()
    }while(i--)
}
var canvas = get('canvas').getContext('2d');
var height = 0;
var i = 0;
var rotate = 90*(Math.PI/180);
var width = 0;
var x = 0;
var y = 0;

resize();

window.onresize = resize
<commit_msg>improved formatting<commit_after>function get(i){
    return document.getElementById(i)
}
function resize(){
    width = get('canvas').width = window.innerWidth;
    height = get('canvas').height = window.innerHeight;

    x = width / 2;
    y = height / 2;

    i = canvas.createLinearGradient(
        0,
        height * .05,
        0,
        height
    );
    i.addColorStop(0,'#000');
    i.addColorStop(1,'#a99');
    canvas.fillStyle = i;

    i = 3;
    canvas.translate(x,y);
    do{
        canvas.rotate(rotate);
        canvas.beginPath();
        canvas.moveTo(0,0);
        canvas.lineTo(width,width);
        canvas.lineTo(-width,width);
        canvas.closePath();
        canvas.fill()
    }while(i--)
}
var canvas = get('canvas').getContext('2d');
var height = 0;
var i = 0;
var rotate = 90 * (Math.PI / 180);
var width = 0;
var x = 0;
var y = 0;

resize();

window.onresize = resize
<|endoftext|>


<commit_before>'use strict';
require('dotenv').load();
require('newrelic');
var express = require('express');
var app     = express();
var fs = require('fs');
var API = require('./api.js');
var logger = require('morgan');
var session = require('express-session');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var methodOverride = require('method-override');
//API.runUpdater();
app.use(logger('combined'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride());
app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true
}));

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
});

app.get('/api/', function(req, res){
    res.send('Please visit the GitHub page');
});

app.get('/api/scrape/:id', function(req, res){
    var id = req.param('id');//0003193
    var course = API.CourseScraper().init(id);
    course.then(function(data){
        res.json(data);
    }, function(err){

    });
});

// E.g. ?name=Wilson%20M%20Dr&department=Computer Science
app.get('/api/staff', function(req, res){
    API.getStaffByShort(req.query.name, req.query.department, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/room/:room', function(req, res){
    // Return further room info, including staff details, room is the room code
    API.getRoomInfo(req.params.room, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/module/:code', function(req, res){
    API.getModule(req.params.code, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/courses/modules/username/:username', function(req, res){
    API.getCourseByUsername(req.params.username, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/courses/modules/((\\d+))', function(req, res){
    API.getCourse(req.params[0], function(data){
        if(!data) {
            return res.status(404).send({error: 'Not found'});
        }
        var courseData = {};
        courseData.name = data.name;
        var course = API.CourseScraper().init(req.params[0]);
        course.then(function(course){
            courseData.department = course.department;
            if(typeof req.query.exclude !== 'undefined'){
                if(req.query.exclude.length > 0){

                    for(var i = 0; i < course.data.length; i++){
                        var newModules = [];
                        var modules = course.data[i].modules;
                        for(var j = 0; j < modules.length; j++){
                            var module = modules[j];
                            if(req.query.exclude.indexOf(module.code) === -1){
                                newModules.push(module);
                            }
                        }
                        course.data[i].modules = newModules;
                    }
                }
            }
            if(req.query.type === 'csv'){
                var startWeek = new Date(2015, 8, 14);
                var csv = 'Subject,Start Date,Start Time,End Date,End Time,Location\n';
                course.data.forEach(function(day, k){
                    day.modules.forEach(function(module){
                        module.weeks.forEach(function(week){
                            var weekDate = new Date(startWeek);
                            weekDate.setDate(weekDate.getDate() + (week * 7) + k);
                            weekDate = weekDate.getDate() + '/' + (weekDate.getMonth()+1) + '/' + weekDate.getFullYear();
                            csv += module.name + ',' + weekDate + ',' + module.time.start + ',' + weekDate + ',' + module.time.end + ',' + module.room + '\n';
                        });
                    });
                });
                res.set({'Content-Disposition':'attachment; filename=\'timetable.csv\''});
                return res.send(csv);
            }
            courseData.days = course.data;
            res.json(courseData);
        }, function(err){
            console.log(err);
        });
    });
});

app.get('/api/courses/((\\w+))', function(req, res){
    API.getCourses(req.params[0], function(data){
        res.send(data);
    });
});

app.use(express.static(__dirname + '/dist'));

app.listen(process.env.PORT || 8081);

exports = module.exports = app;
<commit_msg>fix(express): Fixs express not using X-Forwarded-For<commit_after>'use strict';
require('dotenv').load();
require('newrelic');
var express = require('express');
var app     = express();
var fs = require('fs');
var API = require('./api.js');
var logger = require('morgan');
var session = require('express-session');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var methodOverride = require('method-override');
//API.runUpdater();
app.use(logger('combined'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride());
app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true
}));
app.set('trust proxy', '127.0.0.1');

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
});

app.get('/api/', function(req, res){
    res.send('Please visit the GitHub page');
});

app.get('/api/scrape/:id', function(req, res){
    var id = req.param('id');//0003193
    var course = API.CourseScraper().init(id);
    course.then(function(data){
        res.json(data);
    }, function(err){

    });
});

// E.g. ?name=Wilson%20M%20Dr&department=Computer Science
app.get('/api/staff', function(req, res){
    API.getStaffByShort(req.query.name, req.query.department, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/room/:room', function(req, res){
    // Return further room info, including staff details, room is the room code
    API.getRoomInfo(req.params.room, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/module/:code', function(req, res){
    API.getModule(req.params.code, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/courses/modules/username/:username', function(req, res){
    API.getCourseByUsername(req.params.username, function(data){
        if(!data){
            res.status(404).send({error: 'Not found'});
        }else{
            res.send(data);
        }
    });
});

app.get('/api/courses/modules/((\\d+))', function(req, res){
    API.getCourse(req.params[0], function(data){
        if(!data) {
            return res.status(404).send({error: 'Not found'});
        }
        var courseData = {};
        courseData.name = data.name;
        var course = API.CourseScraper().init(req.params[0]);
        course.then(function(course){
            courseData.department = course.department;
            if(typeof req.query.exclude !== 'undefined'){
                if(req.query.exclude.length > 0){

                    for(var i = 0; i < course.data.length; i++){
                        var newModules = [];
                        var modules = course.data[i].modules;
                        for(var j = 0; j < modules.length; j++){
                            var module = modules[j];
                            if(req.query.exclude.indexOf(module.code) === -1){
                                newModules.push(module);
                            }
                        }
                        course.data[i].modules = newModules;
                    }
                }
            }
            if(req.query.type === 'csv'){
                var startWeek = new Date(2015, 8, 14);
                var csv = 'Subject,Start Date,Start Time,End Date,End Time,Location\n';
                course.data.forEach(function(day, k){
                    day.modules.forEach(function(module){
                        module.weeks.forEach(function(week){
                            var weekDate = new Date(startWeek);
                            weekDate.setDate(weekDate.getDate() + (week * 7) + k);
                            weekDate = weekDate.getDate() + '/' + (weekDate.getMonth()+1) + '/' + weekDate.getFullYear();
                            csv += module.name + ',' + weekDate + ',' + module.time.start + ',' + weekDate + ',' + module.time.end + ',' + module.room + '\n';
                        });
                    });
                });
                res.set({'Content-Disposition':'attachment; filename=\'timetable.csv\''});
                return res.send(csv);
            }
            courseData.days = course.data;
            res.json(courseData);
        }, function(err){
            console.log(err);
        });
    });
});

app.get('/api/courses/((\\w+))', function(req, res){
    API.getCourses(req.params[0], function(data){
        res.send(data);
    });
});

app.use(express.static(__dirname + '/dist'));

app.listen(process.env.PORT || 8081);

exports = module.exports = app;
<|endoftext|>


<commit_before>VRtwglQuadTest = require('./VRtwglQuadTest.js');

console.log("INIT");
var twglTestElements=document.getElementsByTagName("twglTest");
for(twglTestIt = 0;twglTestIt < twglTestElements.length; twglTestIt++) {
  console.log("FOUND");
  var twglTestElement = twglTestElements[twglTestIt];
  var vrTwglQuadTest = new VRtwglQuadTest();
  vrTwglQuadTest.init(twglTestElement);
  vrTwglQuadTest.resize();
  window.addEventListener('resize', vrTwglQuadTest.resize, false);
  vrTwglQuadTest.anim();
}
<commit_msg>compartmentalizing test<commit_after>
// create a test quad from this element: <twglTest></twglTest>
runTest = function() {
  VRtwglQuadTest = require('./VRtwglQuadTest.js');

  console.log("INIT");
  var twglTestElements=document.getElementsByTagName("twglTest");
  for(twglTestIt = 0;twglTestIt < twglTestElements.length; twglTestIt++) {
    console.log("FOUND");
    var twglTestElement = twglTestElements[twglTestIt];
    var vrTwglQuadTest = new VRtwglQuadTest();
    vrTwglQuadTest.init(twglTestElement);
    vrTwglQuadTest.resize();
    window.addEventListener('resize', vrTwglQuadTest.resize, false);
    vrTwglQuadTest.anim();
  }
}

runTest();
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    for (var counter = 0; counter < length; counter++)
    {
      var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
      var args = ['commit', outFile, '-m', message]
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [time in seconds]")
}

function sleep(seconds) {
  var endTime = new Date().getT<commit_msg>Grammar fix<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    for (var counter = 0; counter < length; counter++)
    {
      var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
      var args = ['commit', outFile, '-m', message]
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [time in seconds]")
}

function sleep(seconds) {
  var endTime = new Date().getTi<|endoftext|>


<commit_before>/**
 * Uploads media files.
 *
 * @author	Matthias Schmidt
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Media/List/Upload
 */
define(
	[
		'Core', 'Dom/Util', '../Upload'
	],
	function(
		Core, DomUtil, MediaUpload
	)
{
	"use strict";

	if (!COMPILER_TARGET_DEFAULT) {
		var Fake = function() {};
		Fake.prototype = {
			_createButton: function() {},
			_success: function() {},
			_upload: function() {},
			_createFileElement: function() {},
			_getParameters: function() {},
			_uploadFiles: function() {},
			_createFileElements: function() {},
			_failure: function() {},
			_insertButton: function() {},
			_progress: function() {},
			_removeButton: function() {}
		};
		return Fake;
	}

	/**
	 * @constructor
	 */
	function MediaListUpload(buttonContainerId, targetId, options) {
		MediaUpload.call(this, buttonContainerId, targetId, options);
	}
	Core.inherit(MediaListUpload, MediaUpload, {
		/**
		 * Creates the upload button.
		 */
		_createButton: function() {
			MediaListUpload._super.prototype._createButton.call(this);

			var icon = elCreate('span');
			icon.className = 'icon icon16 fa-upload';
			DomUtil.prepend(icon, elBySel('span', this._button));
		},

		/**
		 * @see	WoltLabSuite/Core/Upload#_getParameters
		 */
		_getParameters: function() {
			if (this._options.categoryId) {
				return Core.extend(MediaListUpload._super.prototype._getParameters.call(this), {
					categoryID: this._options.categoryId
				});
			}

			return MediaListUpload._super.prototype._getParameters.call(this);
		}
	});

	return MediaListUpload;
});
<commit_msg>Add missing space between icon and text of media list's upload button<commit_after>/**
 * Uploads media files.
 *
 * @author	Matthias Schmidt
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Media/List/Upload
 */
define(
	[
		'Core', 'Dom/Util', '../Upload'
	],
	function(
		Core, DomUtil, MediaUpload
	)
{
	"use strict";

	if (!COMPILER_TARGET_DEFAULT) {
		var Fake = function() {};
		Fake.prototype = {
			_createButton: function() {},
			_success: function() {},
			_upload: function() {},
			_createFileElement: function() {},
			_getParameters: function() {},
			_uploadFiles: function() {},
			_createFileElements: function() {},
			_failure: function() {},
			_insertButton: function() {},
			_progress: function() {},
			_removeButton: function() {}
		};
		return Fake;
	}

	/**
	 * @constructor
	 */
	function MediaListUpload(buttonContainerId, targetId, options) {
		MediaUpload.call(this, buttonContainerId, targetId, options);
	}
	Core.inherit(MediaListUpload, MediaUpload, {
		/**
		 * Creates the upload button.
		 */
		_createButton: function() {
			MediaListUpload._super.prototype._createButton.call(this);

			var span = elBySel('span', this._button);

			var space = document.createTextNode(' ');
			DomUtil.prepend(space, span);

			var icon = elCreate('span');
			icon.className = 'icon icon16 fa-upload';
			DomUtil.prepend(icon, span);
		},

		/**
		 * @see	WoltLabSuite/Core/Upload#_getParameters
		 */
		_getParameters: function() {
			if (this._options.categoryId) {
				return Core.extend(MediaListUpload._super.prototype._getParameters.call(this), {
					categoryID: this._options.categoryId
				});
			}

			return MediaListUpload._super.prototype._getParameters.call(this);
		}
	});

	return MediaListUpload;
});
<|endoftext|>


<commit_before>import TextField from '@ember/component/text-field';
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { observer, computed } from '@ember/object';
import Object from '@ember/object';
import $ from 'jquery';

function wrapFolder(folderID, folderName) {
    return {
        "name": folderName,
        "id": folderID,
        "isFolder": true,

        get(name) {
            if (name === "name") return folderName;
            else if (name === "id") return folderID;
            else return null;
        }
    };
}

TextField.reopen({
    attributeBindings: ['multiple']
});

export default Component.extend({
    model: null,
    classNames: ['tale-tab-files'],
    internalState: service(),
    store: service(),
    folderNavs: service(),
    router: service(),

    fileBreadCrumbs: computed(function () {
        return {};
    }),
    currentBreadCrumb: computed(function () {
        return [];
    }),
    currentNav: computed(function () {
        return {};
    }),
    currentNavCommand: "home",
    currentNavTitle: "Home",
    parentId: null,
    file: "",

    fileChosen: observer('file', function () {
        if (this.get('file') === "") return;
        let uploader = $('.nice.upload.hidden');
        let files = uploader[0].files;
        let dz = window.Dropzone.forElement(".dropzone");
        for (let i = 0; i < files.length; i++) {
            dz.addFile(files[i]);
        }
        this.set('file', '');
    }),

    init() {
        this._super(...arguments);
        let state = this.get('internalState');

        state.setCurrentBreadCrumb(null);
        state.setCurrentFileBreadcrumbs([]); // new nav folder, reset crumbs
        state.setCurrentFolderName("");

        this.set("currentBreadCrumb", null);
        this.set("fileBreadCrumbs", []);

        this.set('fileData', this.model);
        this.set("currentFolderId", state.getCurrentFolderID());

        this.get("folderNavs").getCurrentFolderNavAndSetOn(this);

        let fileBreadCrumbs = state.getCurrentFileBreadcrumbs();
        if (!(fileBreadCrumbs && fileBreadCrumbs.length)) {
            fileBreadCrumbs = [];
            state.setCurrentFileBreadcrumbs(fileBreadCrumbs); // new collection, reset crumbs
        }

        if (state.getCurrentParentType() !== 'user') {
            let bc = wrapFolder(state.getCurrentFolderID(), state.getCurrentFolderName());
            this.set("currentBreadCrumb", bc);
            state.setCurrentBreadCrumb(bc);
        }

        this.set("fileBreadCrumbs", state.getCurrentFileBreadcrumbs()); // new collection, reset crumbs
    },

    actions: {
        refresh() {
            let state = this.get('internalState');
            let myController = this;
            let itemID = state.getCurrentFolderID();

            let folderContents = myController.store.query('folder', {
                parentId: itemID,
                parentType: "folder",
                reload: true,
                adapterOptions: {
                    queryParams: {
                        limit: "0"
                    }
                }
            });

            let itemContents = myController.store.query('item', {
                folderId: itemID,
                reload: true,
                adapterOptions: {
                    queryParams: {
                        limit: "0"
                    }
                }
            });

            let newModel = {
                'folderContents': folderContents,
                'itemContents': itemContents
            };

            myController.set("fileData", newModel);
        },

        //----------------------------------------------------------------------------
        navClicked: function (nav) {
            let controller = this;
            let state = this.get('internalState');

            let folderContents = null;
            let itemContents = null;

            state.setCurrentNavCommand(nav.command);
            this.set('currentNav', nav);
            this.set("currentNavCommand", nav.command);
            this.set("currentNavTitle", nav.name);

            if (nav.command === "home" || nav.command === "user_data" || nav.command === "workspace") {
                folderContents = controller.get('store').query('folder', {
                    parentId: nav.parentId,
                    parentType: nav.parentType,
                    name: nav.name,
                    reload: true,
                    adapterOptions: {
                        queryParams: {
                            limit: "0"
                        }
                    }
                }).then(folders => {
                    if (folders.length) {
                        let folder_id = folders.content[0].id;

                        state.setCurrentFolderID(folder_id);
                        state.setCurrentParentId(nav.parentId);
                        state.setCurrentParentType(nav.parentType);
                        state.setCurrentFolderName(nav.name);
                        controller.set("currentFolderId", folder_id);

                        itemContents = controller.store.query('item', {
                            folderId: folder_id,
                            reload: true,
                            adapterOptions: {
                                queryParams: {
                                    limit: "0"
                                }
                            }
                        });
                        return controller.store.query('folder', {
                            "parentId": folder_id,
                            "parentType": "folder"
                        });
                    }
                    throw new Error(nav.name + " folder not found.");
                })
                    .catch(() => {
                        return;
                    });
            } else if (nav.command === "recent") {
                let uniqueSetOfRecentFolders = [];
                let recentFolders = state.getRecentFolders().filter(folder => {
                    let index = uniqueSetOfRecentFolders.findIndex(added => {
                        return added === folder;
                    });
                    let isAdded = index < 0 ? false : true;
                    if (!isAdded) {
                        uniqueSetOfRecentFolders.push(folder);
                        return true;
                    }
                    return false;
                });
                let payload = JSON.stringify({
                    "folder": recentFolders
                });
                folderContents = controller.get('store').query('resource', {
                    "resources": payload
                });
                // alert("Not implemented yet ...");
            }

            let newModel = {};
            folderContents
                .then(_folderContents => {
                    newModel.folderContents = _folderContents;
                    return itemContents;
                })
                .then(_itemContents => {
                    newModel.itemContents = _itemContents;
                })
                .finally(() => {
                    controller.set("fileData", newModel);
                });

            state.setCurrentBreadCrumb(null);
            state.setCurrentFileBreadcrumbs([]); // new nav folder, reset crumbs
            state.setCurrentFolderName("");
            this.set("currentBreadCrumb", null);
            this.set("fileBreadCrumbs", []);

        },

        //----------------------------------------------------------------------------
        itemClicked: function (item, isFolder) {
            let state = this.get('internalState');
            let myController = this;

            let itemID = item.get('_id');
            let itemName = item.get('name');

            if (isFolder === "true") {
                this.store.find('folder', itemID).then(function (folder) {
                    myController.set("parentId", folder.get('parentId'));

                    state.setCurrentParentId(folder.get('parentId'));
                    state.setCurrentParentType(folder.get('parentCollection'));

                    let folderContents, itemContents;
                    try {
                        folderContents = myController.store.query('folder', {
                            parentId: itemID,
                            parentType: "folder"
                        });
                        itemContents = myController.store.query('item', {
                            folderId: itemID
                        });

                        let newModel = {
                            'folderContents': folderContents,
                            'itemContents': itemContents
                        };
                        myController.set("fileData", newModel);
                    } catch (e) {
                        // TODO(Adam): better handle this somehow. for now I just log a message
                    }
                    // add to history (recent folders visited)

                    // NOTE(Adam): The following code was moved into the "find folder .then" clause. We need this here
                    //             to make sure we only update breadcrumbs after successfully navigating into the folder.
                    state.addFolderToRecentFolders(itemID);

                    state.setCurrentFolderID(itemID);
                    state.setCurrentFolderName(itemName);

                    myController.set("currentFolderId", itemID);

                    let previousBreadCrumb = state.getCurrentBreadCrumb();

                    state.setCurrentBreadCrumb(item);

                    let fileBreadCrumbs = state.getCurrentFileBreadcrumbs();

                    if (previousBreadCrumb) { // NOTE(Adam): prevent from pushing a null value into the array
                        fileBreadCrumbs.push(previousBreadCrumb);
                    }

                    state.setCurrentFileBreadcrumbs(fileBreadCrumbs);

                    myController.set("currentBreadCrumb", state.getCurrentBreadCrumb());
                    myController.set("fileBreadCrumbs", state.getCurrentFileBreadcrumbs());
                });

            } /* else {
          // myController.get('router').transitionTo('upload.view', item.get('id'));
        } */
        },

        breadcrumbClicked: function (item) {
            let state = this.get('internalState');
            let crumbs = state.getCurrentFileBreadcrumbs();

            let previousItem = null;
            let newCrumbs = [];
            for (let i; i < crumbs.length; ++i) {
                if (crumbs[i].name === item.get('name'))
                    break;
                else {
                    newCrumbs.append(crumbs[i]);
                    previousItem = crumbs[i];
                }
            }

            state.setCurrentFileBreadcrumbs(newCrumbs);
            state.setCurrentFolderID(item._id);
            state.setCurrentFolderName(item.name);
            state.setCurrentBreadCrumb(previousItem); // need to set this because itemClicked is expecting the previous breadcrumb.

            this.set('currentFolderId', item._id);

            this.send('itemClicked', Object.create(item), "true");
        },

        //----------------------------------------------------------------------------
        openUploadDialog() {
            $('.nice.upload.hidden').click();
        },

        //----------------------------------------------------------------------------
        openModal(modalName) {
            let modal = $('.ui.' + modalName + '.modal');
            modal.parent().prependTo($(document.body));
            modal.modal('show');
        },

        //----------------------------------------------------------------------------
        insertNewFolder(folder) {
            let parentId = folder.get('parentId');
            let parentType = folder.get('parentCollection');

            let folderContents = this.store.query('folder', {
                parentId: parentId,
                parentType: parentType
            });
            let itemContents = this.fileData.itemContents;
            let collections = this.fileData.collections;
            let newModel = {
                'folderContents': folderContents,
                'itemContents': itemContents,
                'collections': collections
            };
            this.set('fileData', newModel);
        },

        //-----------------------------------------------------------------------------
        openCreateFolderModal() {
            // NOTE(Adam): Certain Semantic UI components depends heavily on jquery to work properly. The Modal component is one such component
            //             , and although its bad practice to include jquery, it is needed here until we can
            //             replace Semantic UI Modals with something else.
            // (see: https://semantic-org.github.io/Semantic-UI-Ember/#/modules/modal)

            $('.ui.modal.newfolder').modal('show');
        },

        //-----------------------------------------------------------------------------
        openRegisterModal() {
            $('.ui.modal.harvester').modal('show');
        },
        updateSessionData(listOfSelectedItems) {
            // console.log('updating session data...');
            // NOTE: Structure of the list looks like this:

            /*
              [
                {
                  "id": "59aeb3f246a83d0001ab6777",
                  "name": "us85co.xls",
                  "_modelType": "item"
                },
                {
                  "id": "59aeb3f246a83d0001ab6775",
                  "name": "usco2000.xls",
                  "_modelType": "item"
                },
                {
                  "id": "59aeb3f246a83d0001ab677b",
                  "name": "datadict2005.html",
                  "_modelType": "item"
                }
              ]
            */

            // do something with selected items here ...
        },
        openSelectDataModal() {
            $('.ui.modal.selectdata').modal('show');
        },
        closeSelectDataModal() {
            $('.ui.modal.selectdata').modal('hide');
        }

    }
});
<commit_msg>Fetch session data for a tale<commit_after>import TextField from '@ember/component/text-field';
import Component from '@ember/component';
import { A } from '@ember/array';
import { inject as service } from '@ember/service';
import { observer, computed } from '@ember/object';
import Object from '@ember/object';
import $ from 'jquery';

function wrapFolder(folderID, folderName) {
    return {
        "name": folderName,
        "id": folderID,
        "isFolder": true,

        get(name) {
            if (name === "name") return folderName;
            else if (name === "id") return folderID;
            else return null;
        }
    };
}

TextField.reopen({
    attributeBindings: ['multiple']
});

export default Component.extend({
    model: null,
    classNames: ['tale-tab-files'],
    internalState: service(),
    store: service(),
    folderNavs: service(),
    router: service(),

    fileBreadCrumbs: computed(function () {
        return {};
    }),
    currentBreadCrumb: computed(function () {
        return [];
    }),
    currentNav: computed(function () {
        return {};
    }),
    currentNavCommand: "home",
    currentNavTitle: "Home",
    parentId: null,
    file: "",

    fileChosen: observer('file', function () {
        if (this.get('file') === "") return;
        let uploader = $('.nice.upload.hidden');
        let files = uploader[0].files;
        let dz = window.Dropzone.forElement(".dropzone");
        for (let i = 0; i < files.length; i++) {
            dz.addFile(files[i]);
        }
        this.set('file', '');
    }),

    init() {
        this._super(...arguments);
        let state = this.get('internalState');

        state.setCurrentBreadCrumb(null);
        state.setCurrentFileBreadcrumbs([]); // new nav folder, reset crumbs
        state.setCurrentFolderName("");

        this.set("currentBreadCrumb", null);
        this.set("fileBreadCrumbs", []);

        this.set('fileData', this.model);
        this.set("currentFolderId", state.getCurrentFolderID());

        this.get("folderNavs").getCurrentFolderNavAndSetOn(this);

        let fileBreadCrumbs = state.getCurrentFileBreadcrumbs();
        if (!(fileBreadCrumbs && fileBreadCrumbs.length)) {
            fileBreadCrumbs = [];
            state.setCurrentFileBreadcrumbs(fileBreadCrumbs); // new collection, reset crumbs
        }

        if (state.getCurrentParentType() !== 'user') {
            let bc = wrapFolder(state.getCurrentFolderID(), state.getCurrentFolderName());
            this.set("currentBreadCrumb", bc);
            state.setCurrentBreadCrumb(bc);
        }

        this.set("fileBreadCrumbs", state.getCurrentFileBreadcrumbs()); // new collection, reset crumbs
    },

    actions: {
        refresh() {
            let state = this.get('internalState');
            let myController = this;
            let itemID = state.getCurrentFolderID();

            let folderContents = myController.store.query('folder', {
                parentId: itemID,
                parentType: "folder",
                reload: true,
                adapterOptions: {
                    queryParams: {
                        limit: "0"
                    }
                }
            });

            let itemContents = myController.store.query('item', {
                folderId: itemID,
                reload: true,
                adapterOptions: {
                    queryParams: {
                        limit: "0"
                    }
                }
            });

            let newModel = {
                'folderContents': folderContents,
                'itemContents': itemContents
            };

            myController.set("fileData", newModel);
        },

        //----------------------------------------------------------------------------
        navClicked: function (nav) {
            let controller = this;
            let state = this.get('internalState');

            let folderContents = null;
            let itemContents = null;

            state.setCurrentNavCommand(nav.command);
            this.set('currentNav', nav);
            this.set("currentNavCommand", nav.command);
            this.set("currentNavTitle", nav.name);

            if (nav.command === "home" || nav.command === "workspace") {
                folderContents = controller.get('store').query('folder', {
                    parentId: nav.parentId,
                    parentType: nav.parentType,
                    name: nav.name,
                    reload: true,
                    adapterOptions: {
                        queryParams: {
                            limit: "0"
                        }
                    }
                }).then(folders => {
                    if (folders.length) {
                        let folder_id = folders.content[0].id;

                        state.setCurrentFolderID(folder_id);
                        state.setCurrentParentId(nav.parentId);
                        state.setCurrentParentType(nav.parentType);
                        state.setCurrentFolderName(nav.name);
                        controller.set("currentFolderId", folder_id);

                        itemContents = controller.store.query('item', {
                            folderId: folder_id,
                            reload: true,
                            adapterOptions: {
                                queryParams: {
                                    limit: "0"
                                }
                            }
                        });
                        return controller.store.query('folder', {
                            "parentId": folder_id,
                            "parentType": "folder"
                        });
                    }
                    throw new Error(nav.name + " folder not found.");
                })
                    .catch(() => {
                        return;
                    });
            } else if (nav.command === "recent") {
                let uniqueSetOfRecentFolders = [];
                let recentFolders = state.getRecentFolders().filter(folder => {
                    let index = uniqueSetOfRecentFolders.findIndex(added => {
                        return added === folder;
                    });
                    let isAdded = index < 0 ? false : true;
                    if (!isAdded) {
                        uniqueSetOfRecentFolders.push(folder);
                        return true;
                    }
                    return false;
                });
                let payload = JSON.stringify({
                    "folder": recentFolders
                });
                folderContents = controller.get('store').query('resource', {
                    "resources": payload
                });
                // alert("Not implemented yet ...");
            } else if (nav.command === "user_data") {
              let sessionId = controller.model.get('sessionId');
              folderContents = controller.get('store').findRecord('dm', sessionId, { adapterOptions: { insertPath: 'session' }})
                .then(session => {
                  console.log('session', session);
                  return session.get('dataSet').map(item => {
                    let {itemId, mountPath} = item;
                    return {id: itemId, name: mountPath, _modelType: 'item' };
                  });
                })
              ;
              itemContents = Promise.resolve(A([]));
            }

            let newModel = {};
            folderContents
                .then(_folderContents => {
                    console.log('folder contents', _folderContents);
                    newModel.folderContents = _folderContents;
                    return itemContents;
                })
                .then(_itemContents => {
                    newModel.itemContents = _itemContents;
                })
                .finally(() => {
                    controller.set("fileData", newModel);
                })
            ;

            state.setCurrentBreadCrumb(null);
            state.setCurrentFileBreadcrumbs([]); // new nav folder, reset crumbs
            state.setCurrentFolderName("");
            this.set("currentBreadCrumb", null);
            this.set("fileBreadCrumbs", []);

        },

        //----------------------------------------------------------------------------
        itemClicked: function (item, isFolder) {
            let state = this.get('internalState');
            let myController = this;

            let itemID = item.get('_id');
            let itemName = item.get('name');

            if (isFolder === "true") {
                this.store.find('folder', itemID).then(function (folder) {
                    myController.set("parentId", folder.get('parentId'));

                    state.setCurrentParentId(folder.get('parentId'));
                    state.setCurrentParentType(folder.get('parentCollection'));

                    let folderContents, itemContents;
                    try {
                        folderContents = myController.store.query('folder', {
                            parentId: itemID,
                            parentType: "folder"
                        });
                        itemContents = myController.store.query('item', {
                            folderId: itemID
                        });

                        let newModel = {
                            'folderContents': folderContents,
                            'itemContents': itemContents
                        };
                        myController.set("fileData", newModel);
                    } catch (e) {
                        // TODO(Adam): better handle this somehow. for now I just log a message
                    }
                    // add to history (recent folders visited)

                    // NOTE(Adam): The following code was moved into the "find folder .then" clause. We need this here
                    //             to make sure we only update breadcrumbs after successfully navigating into the folder.
                    state.addFolderToRecentFolders(itemID);

                    state.setCurrentFolderID(itemID);
                    state.setCurrentFolderName(itemName);

                    myController.set("currentFolderId", itemID);

                    let previousBreadCrumb = state.getCurrentBreadCrumb();

                    state.setCurrentBreadCrumb(item);

                    let fileBreadCrumbs = state.getCurrentFileBreadcrumbs();

                    if (previousBreadCrumb) { // NOTE(Adam): prevent from pushing a null value into the array
                        fileBreadCrumbs.push(previousBreadCrumb);
                    }

                    state.setCurrentFileBreadcrumbs(fileBreadCrumbs);

                    myController.set("currentBreadCrumb", state.getCurrentBreadCrumb());
                    myController.set("fileBreadCrumbs", state.getCurrentFileBreadcrumbs());
                });

            } /* else {
          // myController.get('router').transitionTo('upload.view', item.get('id'));
        } */
        },

        breadcrumbClicked: function (item) {
            let state = this.get('internalState');
            let crumbs = state.getCurrentFileBreadcrumbs();

            let previousItem = null;
            let newCrumbs = [];
            for (let i; i < crumbs.length; ++i) {
                if (crumbs[i].name === item.get('name'))
                    break;
                else {
                    newCrumbs.append(crumbs[i]);
                    previousItem = crumbs[i];
                }
            }

            state.setCurrentFileBreadcrumbs(newCrumbs);
            state.setCurrentFolderID(item._id);
            state.setCurrentFolderName(item.name);
            state.setCurrentBreadCrumb(previousItem); // need to set this because itemClicked is expecting the previous breadcrumb.

            this.set('currentFolderId', item._id);

            this.send('itemClicked', Object.create(item), "true");
        },

        //----------------------------------------------------------------------------
        openUploadDialog() {
            $('.nice.upload.hidden').click();
        },

        //----------------------------------------------------------------------------
        openModal(modalName) {
            let modal = $('.ui.' + modalName + '.modal');
            modal.parent().prependTo($(document.body));
            modal.modal('show');
        },

        //----------------------------------------------------------------------------
        insertNewFolder(folder) {
            let parentId = folder.get('parentId');
            let parentType = folder.get('parentCollection');

            let folderContents = this.store.query('folder', {
                parentId: parentId,
                parentType: parentType
            });
            let itemContents = this.fileData.itemContents;
            let collections = this.fileData.collections;
            let newModel = {
                'folderContents': folderContents,
                'itemContents': itemContents,
                'collections': collections
            };
            this.set('fileData', newModel);
        },

        //-----------------------------------------------------------------------------
        openCreateFolderModal() {
            // NOTE(Adam): Certain Semantic UI components depends heavily on jquery to work properly. The Modal component is one such component
            //             , and although its bad practice to include jquery, it is needed here until we can
            //             replace Semantic UI Modals with something else.
            // (see: https://semantic-org.github.io/Semantic-UI-Ember/#/modules/modal)

            $('.ui.modal.newfolder').modal('show');
        },

        //-----------------------------------------------------------------------------
        openRegisterModal() {
            $('.ui.modal.harvester').modal('show');
        },
        updateSessionData(listOfSelectedItems) {
            // console.log('updating session data...');
            // NOTE: Structure of the list looks like this:

            /*
              [
                {
                  "id": "59aeb3f246a83d0001ab6777",
                  "name": "us85co.xls",
                  "_modelType": "item"
                },
                {
                  "id": "59aeb3f246a83d0001ab6775",
                  "name": "usco2000.xls",
                  "_modelType": "item"
                },
                {
                  "id": "59aeb3f246a83d0001ab677b",
                  "name": "datadict2005.html",
                  "_modelType": "item"
                }
              ]
            */

            // do something with selected items here ...
        },
        openSelectDataModal() {
            $('.ui.modal.selectdata').modal('show');
        },
        closeSelectDataModal() {
            $('.ui.modal.selectdata').modal('hide');
        }

    }
});
<|endoftext|>