<commit_before>/**
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 30.03.18
 */
const BEM = require('imcms-bem-builder');
const components = require('imcms-components-builder');
const texts = require('imcms-i18n-texts').editors.image;
const $ = require('jquery');
const imageResize = require('imcms-image-resize');

let $heightControl, $widthControl, $hPreviewControl, $wPreviewControl;

function getNewVal($input) {
    const newVal = +$input.val();

    if (isNaN(newVal) || newVal < 0) {
        $input.val($input.val().replace(/[^0-9]/g, ''));
        return;
    }

    return newVal
}

function onValidHeightChange() {
    const newVal = getNewVal($(this));
    newVal && imageResize.setHeightProportionally(newVal, false);
    $wantedHeightControl.getInput().val(newVal);
}

function onValidWidthChange() {
    const newVal = getNewVal($(this));
    newVal && imageResize.setWidthProportionally(newVal, false);
    $wantedWidthControl.getInput().val(newVal);
}

function buildHeightControl() {
    $heightControl = components.texts.textNumber("<div>", {
        name: "height",
        placeholder: texts.height,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setHeightControl($heightControl.getInput().attr('disabled', 'disabled'));

    return $heightControl
}

function getHeightControl() {
    return $heightControl ? $heightControl : buildHeightControl()
}

function buildWidthControl() {
    $widthControl = components.texts.textNumber("<div>", {
        name: "width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setWidthControl($widthControl.getInput().attr('disabled', 'disabled'));

    return $widthControl
}

function getWidthControl() {
    return $widthControl ? $widthControl : buildWidthControl()
}

function buildPreviewHeightControl() {
    $hPreviewControl = components.texts.textNumber("<div>", {
        name: "prev-height",
        placeholder: texts.height,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setPreviewHeightControl($hPreviewControl.getInput().attr('disabled', 'disabled'));

    return $hPreviewControl
}

function getPreviewHeightControl() {
    return $hPreviewControl ? $hPreviewControl : buildPreviewHeightControl()
}

function buildPreviewWidthControl() {
    $wPreviewControl = components.texts.textNumber("<div>", {
        name: "prev-width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setPreviewWidthControl($wPreviewControl.getInput().attr('disabled', 'disabled'));

    return $wPreviewControl
}

function getPreviewWidthControl() {
    return $wPreviewControl ? $wPreviewControl : buildPreviewWidthControl()
}

let $title, $titlePrev;

function getTitle() {
    return $title || ($title = components.texts.titleText("<div>", texts.originSize))
}

function getPrevTitle() {
    return $titlePrev || ($titlePrev = components.texts.titleText("<div>", texts.wantedSize))
}

function buildOriginalSizeControls() {

    return new BEM({
        block: "imcms-original-size",
        elements: [
            {"title": getTitle()},
            {"number": getWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {"number": getHeightControl()}
        ]
    }).buildBlockStructure("<div>", {style: 'display: none;'});
}

let $wantedWidthControl;
let $wantedHeightControl;

function getWantedWidthControl() {
    return $wantedWidthControl ? $wantedWidthControl : buildWantedWidthControl();
}

function getWantedHeightControl() {
    return $wantedHeightControl ? $wantedHeightControl : buildWantedHeightControl();
}

function buildWantedSizeBlock() {

    return new BEM({
        block: "imcms-edit-size",
        elements: [
            {"title": getPrevTitle()},
            {"number": buildWantedWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {"number": buildWantedHeightControl()}
        ]
    }).buildBlockStructure("<div>");
}

function buildWantedWidthControl() {
    $wantedWidthControl = components.texts.textNumber("<div>", {
        name: "wanted-width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setWantedWidthControl($wantedWidthControl.getInput());

    return $wantedWidthControl;
}

function buildWantedHeightControl() {
    $wantedHeightControl = components.texts.textNumber("<div>", {
        name: "wanted-height",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setWantedHeightControl($wantedHeightControl.getInput());

    return $wantedHeightControl;
}

let $titleDisplay;

function getDisplayTitle() {
    return $titleDisplay || ($titleDisplay = components.texts.titleText('<div>', texts.displaySize));
}

function buildDisplaySizeBlock() {
    return new BEM({
        block: 'imcms-display-size',
        elements: [
            {'title': getDisplayTitle()},
            {'number': buildPreviewWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {'number': buildPreviewHeightControl()}
        ]
    }).buildBlockStructure('<div>');
}

function buildImageSizeControlBlock() {
    return new BEM({
        block: 'imcms-image-size-control',
        elements: {
            'wanted-size': buildWantedSizeBlock(),
            'display-size': buildDisplaySizeBlock()
        }
    }).buildBlockStructure('<div>', {style: 'display: none;'});

}

let $originalSizeControls;
let $prevSizeControls;
let $imageSizeBlock;

module.exports = {
    getWidthControl: getWidthControl,

    getHeightControl: getHeightControl,

    getPreviewHeightControl: getPreviewHeightControl,

    getPreviewWidthControl: getPreviewWidthControl,

    swapControls: (isInverted) => {
        // $widthControl.find('label').text((isInverted) ? heightLabelText : widthLabelText);
        // $heightControl.find('label').text((isInverted) ? widthLabelText : heightLabelText);
    },
    setHeight: (newHeight) => getHeightControl().getInput().val(newHeight),

    setWidth: (newWidth) => getWidthControl().getInput().val(newWidth),

    setPrevHeight: (newHeight) => getPreviewHeightControl().getInput().val(newHeight),

    setPrevWidth: (newWidth) => getPreviewWidthControl().getInput().val(newWidth),

    getOriginSizeControls: () => $originalSizeControls || ($originalSizeControls = buildOriginalSizeControls()),

    getEditSizeControls: () => $prevSizeControls || ($prevSizeControls = buildWantedSizeBlock()),

    getImageSizeControlBlock: () => $imageSizeBlock || ($imageSizeBlock = buildImageSizeControlBlock()),

    getWantedHeightControl,
    getWantedWidthControl,
};
<commit_msg>Issue IMCMS-508: Improve the image editor - Assign data wanted and display size block; - Improve swap controls; - Refactor;<commit_after>/**
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 30.03.18
 */
const BEM = require('imcms-bem-builder');
const components = require('imcms-components-builder');
const texts = require('imcms-i18n-texts').editors.image;
const $ = require('jquery');
const imageResize = require('imcms-image-resize');

let $heightControl, $widthControl, $hPreviewControl, $wPreviewControl;

function getNewVal($input) {
    const newVal = +$input.val();

    if (isNaN(newVal) || newVal < 0) {
        $input.val($input.val().replace(/[^0-9]/g, ''));
        return;
    }

    return newVal
}

function onValidHeightChange() {
    const newVal = getNewVal($(this));
    newVal && imageResize.setHeightProportionally(newVal, false);
    $wantedHeightControl.getInput().val(newVal);
}

function onValidWidthChange() {
    const newVal = getNewVal($(this));
    newVal && imageResize.setWidthProportionally(newVal, false);
    $wantedWidthControl.getInput().val(newVal);
}

function buildHeightControl() {
    $heightControl = components.texts.textNumber("<div>", {
        name: "height",
        placeholder: texts.height,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setHeightControl($heightControl.getInput().attr('disabled', 'disabled'));

    return $heightControl
}

function getHeightControl() {
    return $heightControl ? $heightControl : buildHeightControl()
}

function buildWidthControl() {
    $widthControl = components.texts.textNumber("<div>", {
        name: "width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setWidthControl($widthControl.getInput().attr('disabled', 'disabled'));

    return $widthControl
}

function getWidthControl() {
    return $widthControl ? $widthControl : buildWidthControl()
}

function buildPreviewHeightControl() {
    $hPreviewControl = components.texts.textNumber("<div>", {
        name: "prev-height",
        placeholder: texts.height,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setPreviewHeightControl($hPreviewControl.getInput().attr('disabled', 'disabled'));

    return $hPreviewControl
}

function getPreviewHeightControl() {
    return $hPreviewControl ? $hPreviewControl : buildPreviewHeightControl()
}

function buildPreviewWidthControl() {
    $wPreviewControl = components.texts.textNumber("<div>", {
        name: "prev-width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setPreviewWidthControl($wPreviewControl.getInput().attr('disabled', 'disabled'));

    return $wPreviewControl
}

function getPreviewWidthControl() {
    return $wPreviewControl ? $wPreviewControl : buildPreviewWidthControl()
}

let $title, $titlePrev;

function getTitle() {
    return $title || ($title = components.texts.titleText("<div>", texts.originSize))
}

function getPrevTitle() {
    return $titlePrev || ($titlePrev = components.texts.titleText("<div>", texts.wantedSize))
}

function buildOriginalSizeControls() {

    return new BEM({
        block: "imcms-original-size",
        elements: [
            {"title": getTitle()},
            {"number": getWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {"number": getHeightControl()}
        ]
    }).buildBlockStructure("<div>", {style: 'display: none;'});
}

let $wantedWidthControl;
let $wantedHeightControl;

function getWantedWidthControl() {
    return $wantedWidthControl ? $wantedWidthControl : buildWantedWidthControl();
}

function getWantedHeightControl() {
    return $wantedHeightControl ? $wantedHeightControl : buildWantedHeightControl();
}

function buildWantedSizeBlock() {

    return $wantedSizeControls || ($wantedSizeControls = new BEM({
        block: "imcms-edit-size",
        elements: [
            {"title": getPrevTitle()},
            {"number": buildWantedWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {"number": buildWantedHeightControl()}
        ]
    }).buildBlockStructure("<div>"));
}

function buildWantedWidthControl() {
    $wantedWidthControl = components.texts.textNumber("<div>", {
        name: "wanted-width",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidWidthChange
    });

    imageResize.setWantedWidthControl($wantedWidthControl.getInput());

    return $wantedWidthControl;
}

function buildWantedHeightControl() {
    $wantedHeightControl = components.texts.textNumber("<div>", {
        name: "wanted-height",
        placeholder: texts.width,
        error: "Error",
        onValidChange: onValidHeightChange
    });

    imageResize.setWantedHeightControl($wantedHeightControl.getInput());

    return $wantedHeightControl;
}

let $titleDisplay;

function getDisplayTitle() {
    return $titleDisplay || ($titleDisplay = components.texts.titleText('<div>', texts.displaySize));
}

function buildDisplaySizeBlock() {
    return $displaySizePrevBlock || ($displaySizePrevBlock = new BEM({
        block: 'imcms-display-size',
        elements: [
            {'title': getDisplayTitle()},
            {'number': buildPreviewWidthControl()},
            {'block-x': $("<div>", {text: 'X'})},
            {'number': buildPreviewHeightControl()}
        ]
    }).buildBlockStructure('<div>'));
}

function buildImageSizeControlBlock() {
    return new BEM({
        block: 'imcms-image-size-control',
        elements: {
            'wanted-size': buildWantedSizeBlock(),
            'display-size': buildDisplaySizeBlock()
        }
    }).buildBlockStructure('<div>', {style: 'display: none;'});

}

let $originalSizeControls;
let $displaySizePrevBlock;
let $imageSizeBlock;
let $wantedSizeControls;

module.exports = {
    getWidthControl: getWidthControl,

    getHeightControl: getHeightControl,

    getPreviewHeightControl: getPreviewHeightControl,

    getPreviewWidthControl: getPreviewWidthControl,

    swapControls: (isInverted) => {
        $wantedSizeControls.find('.imcms-title').text((isInverted) ? texts.revertWantedSize : texts.wantedSize);
        $displaySizePrevBlock.find('.imcms-title').text((isInverted) ? texts.revertDisplaySize : texts.displaySize);
    },
    setHeight: (newHeight) => getHeightControl().getInput().val(newHeight),

    setWidth: (newWidth) => getWidthControl().getInput().val(newWidth),

    setPrevHeight: (newHeight) => getPreviewHeightControl().getInput().val(newHeight),

    setPrevWidth: (newWidth) => getPreviewWidthControl().getInput().val(newWidth),

    getOriginSizeControls: () => $originalSizeControls || ($originalSizeControls = buildOriginalSizeControls()),

    getEditSizeControls: () => $wantedSizeControls || ($wantedSizeControls = buildWantedSizeBlock()),

    getDisplaySizeBlock: () => $displaySizePrevBlock || ($displaySizePrevBlock = buildDisplaySizeBlock()),

    getImageSizeControlBlock: () => $imageSizeBlock || ($imageSizeBlock = buildImageSizeControlBlock()),

    getWantedHeightControl,
    getWantedWidthControl,
};
<|endoftext|>


<commit_before>/**
 * Creates a socket instance for interacting with thisisoon.fm
 * Event handles can be passed to fmSocket using 'fmSocket.addListener("fm:player:play", eventHandler)'
 * the service will call the event handler with the arguments (data) every time a matching socket event
 * is received. `data` is a data object passed with the event, this will contain event and track data.
 * The handlers can be removed by using 'fmSocket.removeListener("fm:player:play", eventHandler)'
 *
 * @module sn.fm.sockets
 * @author SOON_
 */
angular.module("sn.fm.sockets", [
    "btford.socket-io",
])

    .factory("fmSocket", [
        "socketFactory",
        /**
         * @constructor
         * @param   {Factory} socketFactory  factory for creating socket instances
         * @returns {Object}  socket.io instance
         */
        function (socketFactory) {

            return socketFactory({
                prefix: "",
                ioSocket: io.connect("http://localdocker:8080")
            });

        }
    ]);
<commit_msg>use constant for socket server address<commit_after>/**
 * Creates a socket instance for interacting with thisisoon.fm
 * Event handles can be passed to fmSocket using 'fmSocket.addListener("fm:player:play", eventHandler)'
 * the service will call the event handler with the arguments (data) every time a matching socket event
 * is received. `data` is a data object passed with the event, this will contain event and track data.
 * The handlers can be removed by using 'fmSocket.removeListener("fm:player:play", eventHandler)'
 *
 * @module sn.fm.sockets
 * @author SOON_
 */
angular.module("sn.fm.sockets", [
    "btford.socket-io",
])

    /**
     * @constant {String} address of thisisoon.fm socket server
     */
    .constant("FM_SOCKET_ADDRESS", "http://localdocker:8080")

    .factory("fmSocket", [
        "socketFactory",
        "FM_SOCKET_ADDRESS",
        /**
         * @constructor
         * @param   {Factory} socketFactory  factory for creating socket instances
         * @returns {Object}  socket.io instance
         */
        function (socketFactory, FM_SOCKET_ADDRESS) {

            return socketFactory({
                prefix: "",
                ioSocket: io.connect(FM_SOCKET_ADDRESS)
            });

        }
    ]);
<|endoftext|>


<commit_before>define(
    'imcms-profiles-tab-builder',
    ['imcms-super-admin-tab', 'imcms-i18n-texts', 'imcms-components-builder', 'imcms-bem-builder', 'imcms-field-wrapper',
        'jquery', 'imcms-profiles-rest-api', 'imcms-profile-to-row-transformer', 'imcms-profile-editor'],
    function (SuperAdminTab, texts, components, BEM, fieldWrapper, $, profileRestApi, profileToRow, profileEditor) {

        texts = texts.superAdmin.profiles;

        var profilesLoader = {
            profiles: false,
            callback: [],
            whenProfilesLoaded: function (callback) {
                (this.profiles) ? callback(this.profiles) : this.callback.push(callback);

            },
            runCallbacks: function (profiles) {
                this.profiles = profiles;

                this.callback.forEach(function (callback) {
                    callback(profiles)
                })
            }
        };

        profileRestApi.getAllProfiles().done(function (profiles) {
            profilesLoader.runCallbacks(profiles);
        });

        function buildBlockProfiles() {

            function createTitleText() {
                return components.texts.titleText('<div>', texts.title, {})
            }

            function createButtonCreate() {
                return fieldWrapper.wrap(components.buttons.positiveButton({
                    text: texts.createButton,
                    click: onCreateNewProfile()
                }));
            }

            function buildCreateTitlesForProfiles() {
                return components.texts.titleText('<div>',
                    texts.createNewProfile.titleTextName + '|' + texts.createNewProfile.titleTextDocName, {})
            }

            return new BEM({
                block: 'imcms-profiles-block',
                elements: {
                    'profile-title': createTitleText(),
                    'create-button': createButtonCreate(),
                    'title-table-profiles': buildCreateTitlesForProfiles()
                }
            }).buildBlockStructure('<div>');
        }

        let $profileContainer;

        function onCreateNewProfile() {

        }

        function buildProfileContainer() {

            $profileContainer = $('<div>', {
                'class': 'profiles-table'
            });

            profilesLoader.whenProfilesLoaded(function (profiles) {
                $profileContainer.append(profiles.map(function (profile) {
                    return profileToRow.transform(profile);
                }))
            });

            return fieldWrapper.wrap([$profileContainer]);
        }

        return new SuperAdminTab(texts.name, [
            buildBlockProfiles(),
            buildProfileContainer(),
        ]);
    }
);
<commit_msg>IMCMS-336 New design to super admin page: profiles tab - Add block profile editor<commit_after>define(
    'imcms-profiles-tab-builder',
    ['imcms-super-admin-tab', 'imcms-i18n-texts', 'imcms-components-builder', 'imcms-bem-builder', 'imcms-field-wrapper',
        'jquery', 'imcms-profiles-rest-api', 'imcms-profile-to-row-transformer', 'imcms-profile-editor'],
    function (SuperAdminTab, texts, components, BEM, fieldWrapper, $, profileRestApi, profileToRow, profileEditor) {

        texts = texts.superAdmin.profiles;

        var profilesLoader = {
            profiles: false,
            callback: [],
            whenProfilesLoaded: function (callback) {
                (this.profiles) ? callback(this.profiles) : this.callback.push(callback);

            },
            runCallbacks: function (profiles) {
                this.profiles = profiles;

                this.callback.forEach(function (callback) {
                    callback(profiles)
                })
            }
        };

        profileRestApi.getAllProfiles().done(function (profiles) {
            profilesLoader.runCallbacks(profiles);
        });

        function buildBlockProfiles() {

            function createTitleText() {
                return components.texts.titleText('<div>', texts.title, {})
            }

            function createButtonCreate() {
                return fieldWrapper.wrap(components.buttons.positiveButton({
                    text: texts.createButton,
                    click: onCreateNewProfile()
                }));
            }

            function buildCreateTitlesForProfiles() {
                return components.texts.titleText('<div>',
                    texts.createNewProfile.titleTextName + '|' + texts.createNewProfile.titleTextDocName, {})
            }

            return new BEM({
                block: 'imcms-profiles-block',
                elements: {
                    'profile-title': createTitleText(),
                    'create-button': createButtonCreate(),
                    'title-table-profiles': buildCreateTitlesForProfiles()
                }
            }).buildBlockStructure('<div>');
        }

        let $profileContainer;

        function onCreateNewProfile() {

        }

        function buildProfileContainer() {

            $profileContainer = $('<div>', {
                'class': 'profiles-table'
            });

            profilesLoader.whenProfilesLoaded(function (profiles) {
                $profileContainer.append(profiles.map(function (profile) {
                    return profileToRow.transform(profile, profileEditor);
                }))
            });

            return fieldWrapper.wrap([$profileContainer, profileEditor.buildProfilesContainer()]);
        }

        return new SuperAdminTab(texts.name, [
            buildBlockProfiles(),
            buildProfileContainer(),
        ]);
    }
);
<|endoftext|>


<commit_before>var annotate = require('annotate');
var is = require('annois');

module.exports = annotate('fill', 'Uses given `amount` of `chr` to fill `str` beginning').
    on(is.number, is.character, is.string, function(amount, chr, str) {
        var pad = '';
        var len = amount - str.length;

        if(!chr || amount < 1 || len < 1 || len > 1000) return str;

        while(pad.length < len) {
            pad += chr;
        }

        return pad + str;
    }).
    satisfies(is.string);
<commit_msg>Remove weird empty characters<commit_after>var annotate = require('annotate');
var is = require('annois');

module.exports = annotate('fill', 'Uses given `amount` of `chr` to fill `str` beginning').
    on(is.number, is.character, is.string, function(amount, chr, str) {
        var pad = '';
        var len = amount - str.length;

        if(!chr || amount < 1 || len < 1 || len > 1000) return str;

        while(pad.length < len) {
            pad += chr;
        }

        return pad + str;
    }).
    satisfies(is.string);
<|endoftext|>


<commit_before>const async = require('async');
const logger = require('./logger');
const chalk = require('chalk');

let Operation = require('./operation');
let Step = require('./step');

class Flow {
  constructor(name, description) {
    this.name = name;
    this.description = description;
    this.steps = [];
    this.catches = [];
    this.integrations = [];
    this.params = {};
    this.handler = this.handler.bind(this); // Workaround for AWS Lamdba.
  }

  setDefaults(obj) {
    for (let key in obj) {
      this.params[key] = this.params[key] || obj[key];
    }
  }

  setOptions(obj) {
    for (let key in obj) {
      this.params[key] = obj[key];
    }
  }

  step(name, operation, params, finish) {
    if (typeof operation === 'object' && !(operation instanceof Operation)) {
      params = operation.params;
      finish = operation.finish;
      operation = operation.do;
    }
    this.steps.push(new Step(name, operation, params, finish));
    if (!(operation instanceof Function) && this.integrations.indexOf(operation.integration) === -1) {
      this.integrations.push(operation.integration);
    }
    return this;
  }

  asyncStep() {throw new Error("not implemented")}
  repeatStep() {throw new Error("not implemented")}

  catch(fn) {
    this.catches.push({index: this.steps.length, callback: fn})
    return this;
  }

  getCatch(index) {
    return this.catches.filter(c => c.index > index)[0];
  }

  execute(callback) {
    callback = callback || ((e) => {if (e) throw e});

    let finish = (err) => {
      this.destroyIntegrations(destroyErr => {
        return callback(err || destroyErr);
      })
    }

    this.executing = true;
    this.initializeIntegrations((err) => {
      if (err) return finish(err);
      this.data = {};
      this.executeFromStep(0, (err) => {
        if (err) return finish(err);
        if (this.executing) this.succeed("Success");
        finish();
      })
    });
  }

  executeFromStep(index, callback) {
    if (!this.executing) return callback();
    if (index === this.steps.length) return callback();
    let step = this.steps[index];
    step.execute(this.data, err => {
      if (err) {
        let catchBlock = this.getCatch(index);
        if (!catchBlock || !this.executing) return callback(err);
        catchBlock.callback(err, this.data);
        let newIndex = catchBlock.index;
        this.executeFromStep(catchBlock.index, callback);
      } else {
        this.executeFromStep(++index, callback);
      }
    })
  }

  stopExecution() {
    if (!this.executing) throw new Error("stopExecution() called before execute()");
    this.executing = false;
  }

  callForAllIntegrations(method, cb) {
    async.parallel(this.integrations.map((integration) => {
      return (asyncCallback) => {
        integration[method](asyncCallback);
      }
    }), cb)
  }

  initializeIntegrations(cb) {
    this.callForAllIntegrations('initialize', cb);
  }

  destroyIntegrations(cb) {
    this.callForAllIntegrations('destroy', cb);
  }

  handler(event, context, callback) {
    this.execute(callback);
  }

  fail(message) {
    this.stopExecution();
    throw new Error(message);
  }
  succeed(message) {
    this.stopExecution();
    logger.logSuccess(message);
  }
}

module.exports = Flow;
<commit_msg>add TODO<commit_after>const async = require('async');
const logger = require('./logger');
const chalk = require('chalk');

let Operation = require('./operation');
let Step = require('./step');

class Flow {
  constructor(name, description) {
    this.name = name;
    this.description = description;
    this.steps = [];
    this.catches = [];
    this.integrations = [];
    this.params = {};
    this.handler = this.handler.bind(this); // Workaround for AWS Lamdba.
  }

  setDefaults(obj) {
    for (let key in obj) {
      this.params[key] = this.params[key] || obj[key];
    }
  }

  setOptions(obj) {
    for (let key in obj) {
      this.params[key] = obj[key];
    }
  }

  step(name, operation, params, finish) {
    if (typeof operation === 'object' && !(operation instanceof Operation)) {
      params = operation.params;
      finish = operation.finish;
      operation = operation.do;
    }
    this.steps.push(new Step(name, operation, params, finish));
    if (!(operation instanceof Function) && this.integrations.indexOf(operation.integration) === -1) {
      this.integrations.push(operation.integration);
    }
    return this;
  }

  asyncStep() {throw new Error("not implemented")}
  repeatStep() {throw new Error("not implemented")}

  catch(fn) {
    this.catches.push({index: this.steps.length, callback: fn})
    return this;
  }

  getCatch(index) {
    return this.catches.filter(c => c.index > index)[0];
  }

  execute(callback) {
    callback = callback || ((e) => {if (e) throw e});

    let finish = (err) => {
      this.destroyIntegrations(destroyErr => {
        return callback(err || destroyErr);
      })
    }

    this.executing = true;
    this.initializeIntegrations((err) => {
      if (err) return finish(err);
      this.data = {};
      this.executeFromStep(0, (err) => {
        if (err) return finish(err);
        if (this.executing) this.succeed("Success");
        finish();
      })
    });
  }

  executeFromStep(index, callback) {
    if (!this.executing) return callback();
    if (index === this.steps.length) return callback();
    let step = this.steps[index];
    step.execute(this.data, err => {
      if (err) {
        let catchBlock = this.getCatch(index);
        if (!catchBlock || !this.executing) return callback(err);
        catchBlock.callback(err, this.data);
        let newIndex = catchBlock.index;
        this.executeFromStep(catchBlock.index, callback);
      } else {
        this.executeFromStep(++index, callback);
      }
    })
  }

  stopExecution() {
    if (!this.executing) throw new Error("stopExecution() called before execute()");
    this.executing = false;
  }

  callForAllIntegrations(method, cb) {
    async.parallel(this.integrations.map((integration) => {
      return (asyncCallback) => {
        integration[method](asyncCallback);
      }
    }), cb)
  }

  initializeIntegrations(cb) {
    this.callForAllIntegrations('initialize', cb);
  }

  destroyIntegrations(cb) {
    this.callForAllIntegrations('destroy', cb);
  }

  handler(event, context, callback) {
    // TODO: bind params from event.query, event.queryStringParameters, etc.
    this.execute(callback);
  }

  fail(message) {
    this.stopExecution();
    throw new Error(message);
  }
  succeed(message) {
    this.stopExecution();
    logger.logSuccess(message);
  }
}

module.exports = Flow;
<|endoftext|>


<commit_before>(function (){
  var foco = {};

  foco.priorityQueue = function (handler, concurrency){
    var listQueuing = [];
    var listProcessing = [];

    function linearSearch(list, compare){
      for(var i in list){
        if(compare(list[i])){
          return i;
        }
      }
      return -1;
    }
    function move(list, old_index, new_index) {
      if (new_index >= list.length) {
        var k = new_index - list.length;
        while ((k--) + 1) {
          list.push(undefined);
        }
      }
      list.splice(new_index, 0, list.splice(old_index, 1)[0]);
    }
    function removeProcessing(id){
      var index = linearSearch(listProcessing, function (item){
        return item.id === id;
      });
      if(index != -1){
        listProcessing.splice(index, 1);
      }
    }
    function done(){
      removeProcessing(this.id);
      processTask();
    }
    function processTask(){
      //console.log('listQueuing.length ' + listQueuing.length);
      if(listQueuing.length === 0){
        //console.log('queue empty');
      } else if(listProcessing.length < concurrency){
        //console.log('task aval ' + listProcessing.length + ' ' + concurrency);
        var task = listQueuing.shift();
        listProcessing.push(task);
        setTimeout(function (){
          handler(task.id, task.data, done.bind(task));
        }, 0);
      } else {
        //console.log('task full ' + listProcessing.length + ' ' + concurrency);
      }
    }
    var queue = {
      push: function (id, priority, data){
        var task = {
          id: id,
          priority: priority,
          data: data
        };
        var index = linearSearch(listQueuing, function (item){
          return item.priority >= priority;
        });
        if (index === -1) { // Not found
          listQueuing.push(task);
        } else {
          listQueuing.splice(index, 0, task);
        }
        processTask();
      },
      priorityChange: function (id, priority){
        var indexById = linearSearch(listQueuing, function (item){
          return item.id === id;
        });
        if (indexById === -1) {
          return ;
        }
        var indexByPriority = linearSearch(listQueuing, function (item){
          return item.priority >= priority;
        });
        move(listQueuing, indexById, indexByPriority);
      }
    };
    return queue;
  };

  if (typeof module !== 'undefined' && module.exports) { // Node.js support
    module.exports = foco;
  } else { // browser support
    root.foco = foco;
  }
})();
<commit_msg>Push new task to the last position in the same priority.<commit_after>(function (){
  var foco = {};

  foco.priorityQueue = function (handler, concurrency){
    var listQueuing = [];
    var listProcessing = [];

    function linearSearch(list, compare){
      for(var i in list){
        if(compare(list[i])){
          return i;
        }
      }
      return -1;
    }
    function move(list, old_index, new_index) {
      if (new_index >= list.length) {
        var k = new_index - list.length;
        while ((k--) + 1) {
          list.push(undefined);
        }
      }
      list.splice(new_index, 0, list.splice(old_index, 1)[0]);
    }
    function removeProcessing(id){
      var index = linearSearch(listProcessing, function (item){
        return item.id === id;
      });
      if(index != -1){
        listProcessing.splice(index, 1);
      }
    }
    function done(){
      removeProcessing(this.id);
      processTask();
    }
    function processTask(){
      //console.log('listQueuing.length ' + listQueuing.length);
      if(listQueuing.length === 0){
        //console.log('queue empty');
      } else if(listProcessing.length < concurrency){
        //console.log('task aval ' + listProcessing.length + ' ' + concurrency);
        var task = listQueuing.shift();
        listProcessing.push(task);
        setTimeout(function (){
          handler(task.id, task.data, done.bind(task));
        }, 0);
      } else {
        //console.log('task full ' + listProcessing.length + ' ' + concurrency);
      }
    }
    var queue = {
      push: function (id, priority, data){
        var task = {
          id: id,
          priority: priority,
          data: data
        };
        var index = linearSearch(listQueuing, function (item){
          return item.priority > priority;
        });
        if (index === -1) { // Not found
          listQueuing.push(task);
        } else {
          listQueuing.splice(index, 0, task);
        }
        processTask();
      },
      priorityChange: function (id, priority){
        var indexById = linearSearch(listQueuing, function (item){
          return item.id === id;
        });
        if (indexById === -1) {
          return ;
        }
        var indexByPriority = linearSearch(listQueuing, function (item){
          return item.priority > priority;
        });
        move(listQueuing, indexById, indexByPriority);
      }
    };
    return queue;
  };

  if (typeof module !== 'undefined' && module.exports) { // Node.js support
    module.exports = foco;
  } else { // browser support
    root.foco = foco;
  }
})();
<|endoftext|>


<commit_before>function Game (board) {
  this.board = board;
  this.turn = "white";
}

Game.prototype.toggleTurn = function () {
  if (this.turn === "white") {
    this.turn = "black";
  } else if (this.turn === "black") {
    this.turn = "white";
  }
  if (this.inCheck()) {
    console.log(this.turn + " is in check!");
  }
};

Game.prototype.inCheck = function () {
  var kingsSquare = this.board.currentKingSquare();
  var attackingPieces = this.board.opponentCanMoveHere(kingsSquare);
  return attackingPieces.length > 0
};

Game.prototype.availableMoves = function () {
  var moves = [];
  this.board.squares.forEach (function (square) {
    moves = moves.concat(square.legalPieces());
  });
  return moves;
};

module.exports = Game;
<commit_msg>Adds check mate functionality.<commit_after>function Game (board) {
  this.board = board;
  this.turn = "white";
}

Game.prototype.toggleTurn = function () {
  if (this.turn === "white") {
    this.turn = "black";
  } else if (this.turn === "black") {
    this.turn = "white";
  }
  if (this.checkMate()) {
    console.log(this.turn + "LOSES!");
  } else if (this.inCheck()) {
    console.log(this.turn + " is in check!");
  }
};

Game.prototype.checkMate = function () {
  debugger
  return this.availableMoves().length === 0
    && this.inCheck();
};

Game.prototype.inCheck = function () {
  var kingsSquare = this.board.currentKingSquare();
  var attackingPieces = this.board.opponentCanMoveHere(kingsSquare);
  return attackingPieces.length > 0
};

Game.prototype.availableMoves = function () {
  var moves = [];
  this.board.squares.forEach (function (square) {
    moves = moves.concat(square.legalPieces());
  });
  return moves;
};

module.exports = Game;
<|endoftext|>


<commit_before>const Ball = require('./balls');
const Paddle = require('./paddle');
const Brick = require('./brick');
const Colors = require('./colors');
const Canvas = require('./canvas');
const Styles = require('./styles');
const Sounds = require('./sounds');

var Game = function(){
  var canvas = new Canvas();

  this.size = { x: canvas.canvas.width, y: canvas.canvas.height };
  var paddle = new Paddle(this);
  var bricks = createBricks(this);

  this.bodies = createBall(this, paddle, bricks).concat(paddle).concat(bricks);
  this.score = 0;
  this.lives = 3;
  this.status = true;

  var tick = function() {
    this.move();
    this.draw(canvas);
    this.drawScore(canvas);
    this.drawLives(canvas);
    requestAnimationFrame(tick);
  }.bind(this);
  tick();
};

var createBall = function(game, paddle, bricks) {
  var ball = [];
  ball.push(new Ball(game, paddle, bricks));
  return ball;
}

var createBricks = function(game) {
  var bricks = [];
  for (var i = 0; i < 1; i++) {
    var x = (Math.floor(i / 6)) * 87
    var y = 70 + (i % 6) * 18;
    bricks.push(new Brick(game, {x: x, y: y}));
  };
  return bricks;
}

Game.prototype = {

  move: function() {
    if (!this.status) { return; }
    for (var i = 0; i < this.bodies.length; i++) {
      if (this.bodies[i].move !== undefined) {
        this.bodies[i].move();
      }
    }
  },

  draw: function(canvas) {
    canvas.clearRect(0, 0, this.size.x, this.size.y);
    var colorList = new Colors();
    for (var i = 0; i < this.bodies.length; i++) {
      if (this.bodies[i].draw !== undefined) {
        this.bodies[i].draw(canvas, colorList[i].toString());
      }
    }
  },

  drawScore: function(canvas) {
    canvas.font = '16px monospace';
    canvas.fillStyle = "#0095DD ";
    canvas.fillText("Score: "+ this.score, 8, 20);
  },

  drawLives: function(canvas) {
    canvas.font = '16px monospace';
    canvas.fillStyle = "#0095DD ";
    canvas.fillText("Lives: "+ this.lives, 700, 20);
  },

  updateGame: function() {
    this.lives -= 1

    if(this.lives > 0) {
      this.pause();
      this.resetGame();
      Styles.displayStyles('ball-reset', 'inline');
      setTimeout(function () {
        this.status = true;
        this.bodies[0].dy = 10;
        Styles.displayStyles('ball-reset', 'none');
      }.bind(this), 2000);
    }
    else {
      this.loseGame();
    }
  },

  pause: function() {
    this.bodies[0].dx = 0;
    this.bodies[0].dy = 0;
    this.status = false;
  },

  resetGame: function() {
    this.bodies[0].startAngle = 0;
    this.bodies[0].x = canvas.width/2;
    this.bodies[0].y = canvas.height-25;
    this.bodies[1].position = { x: this.size.x/2-75, y: this.size.y-15 };
  },

  winGame: function() {
    Sounds.theme.volume = 0.00;
    Styles.displayStyles('winning', 'inline');
    Sounds.win();
    Styles.showText("#won-title", "Congratulations You Won!", 0, 150);
    Styles.showText("#final-score", "Final Score: " + this.score, 0, 150);
    Styles.getId('restart').onclick = function(){
      document.location.reload();
    }
  },

  loseGame: function() {
    this.bodies[0].dy = 0;
    Sounds.theme.volume = 0.00;
    Sounds.wall.volume = 0.00;
    Styles.displayStyles('losing', 'inline');
    Sounds.death();
    Styles.showText("#lose-title", "Sorry, you died!", 0, 150);
    Styles.showText("#final-score-lose", "Final Score: " + this.score, 0, 150);
    Styles.getId('restart-lose').onclick = function(){
      document.location.reload();
    }
  }
}

module.exports = Game;<commit_msg>Added stop theme in and made 54 bricks<commit_after>const Ball = require('./balls');
const Paddle = require('./paddle');
const Brick = require('./brick');
const Colors = require('./colors');
const Canvas = require('./canvas');
const Styles = require('./styles');
const Sounds = require('./sounds');

var Game = function(){
  var canvas = new Canvas();

  this.size = { x: canvas.canvas.width, y: canvas.canvas.height };
  var paddle = new Paddle(this);
  var bricks = createBricks(this);

  this.bodies = createBall(this, paddle, bricks).concat(paddle).concat(bricks);
  this.score = 0;
  this.lives = 3;
  this.status = true;

  var tick = function() {
    this.move();
    this.draw(canvas);
    this.drawScore(canvas);
    this.drawLives(canvas);
    requestAnimationFrame(tick);
  }.bind(this);
  tick();
};

var createBall = function(game, paddle, bricks) {
  var ball = [];
  ball.push(new Ball(game, paddle, bricks));
  return ball;
}

var createBricks = function(game) {
  var bricks = [];
  for (var i = 0; i < 54; i++) {
    var x = (Math.floor(i / 6)) * 87
    var y = 70 + (i % 6) * 18;
    bricks.push(new Brick(game, {x: x, y: y}));
  };
  return bricks;
}

Game.prototype = {

  move: function() {
    if (!this.status) { return; }
    for (var i = 0; i < this.bodies.length; i++) {
      if (this.bodies[i].move !== undefined) {
        this.bodies[i].move();
      }
    }
  },

  draw: function(canvas) {
    canvas.clearRect(0, 0, this.size.x, this.size.y);
    var colorList = new Colors();
    for (var i = 0; i < this.bodies.length; i++) {
      if (this.bodies[i].draw !== undefined) {
        this.bodies[i].draw(canvas, colorList[i].toString());
      }
    }
  },

  drawScore: function(canvas) {
    canvas.font = '16px monospace';
    canvas.fillStyle = "#0095DD ";
    canvas.fillText("Score: "+ this.score, 8, 20);
  },

  drawLives: function(canvas) {
    canvas.font = '16px monospace';
    canvas.fillStyle = "#0095DD ";
    canvas.fillText("Lives: "+ this.lives, 700, 20);
  },

  updateGame: function() {
    this.lives -= 1

    if(this.lives > 0) {
      this.pause();
      this.resetGame();
      Styles.displayStyles('ball-reset', 'inline');
      setTimeout(function () {
        this.status = true;
        this.bodies[0].dy = 10;
        Styles.displayStyles('ball-reset', 'none');
      }.bind(this), 2000);
    }
    else {
      this.loseGame();
    }
  },

  pause: function() {
    this.bodies[0].dx = 0;
    this.bodies[0].dy = 0;
    this.status = false;
  },

  resetGame: function() {
    this.bodies[0].startAngle = 0;
    this.bodies[0].x = canvas.width/2;
    this.bodies[0].y = canvas.height-25;
    this.bodies[1].position = { x: this.size.x/2-75, y: this.size.y-15 };
  },

  winGame: function() {
    Sounds.stopTheme();
    Styles.displayStyles('winning', 'inline');
    Sounds.win();
    Styles.showText("#won-title", "Congratulations You Won!", 0, 150);
    Styles.showText("#final-score", "Final Score: " + this.score, 0, 150);
    Styles.getId('restart').onclick = function(){
      document.location.reload();
    }
  },

  loseGame: function() {
    this.bodies[0].dy = 0;
    Sounds.stopTheme();
    Styles.displayStyles('losing', 'inline');
    Sounds.death();
    Styles.showText("#lose-title", "Sorry, you died!", 0, 150);
    Styles.showText("#final-score-lose", "Final Score: " + this.score, 0, 150);
    Styles.getId('restart-lose').onclick = function(){
      document.location.reload();
    }
  }
}

module.exports = Game;<|endoftext|>


<commit_before>var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var canvasWidth =  canvas.width;
var canvasHeight =  canvas.height;

var Boat = require('./boat');
var Bullet = require('./bullet');
var fishies = require('./generate-fish');
var collision = require('./collision');
// var keyEvents = require('./key-events');

var bullets = [];

var boat = new Boat({x: canvasWidth/2, y: 25, width: 200, height: 150, velocity: 5});

canvas.addEventListener('keydown', function(key) {
//   var keyNumber = event.keyCode;
//   keyEvents(keyNumber);

  if (key.which === 37) {
    boat.moveBoatLeft(boat);
  } else if (key.which === 39) {
    boat.moveBoatRight(boat, canvasWidth);
  } else if (key.which === 32) {
    filterBullets();
    addBullet(bullets);
  }
});

function addBullet(bullets) {
  if (bullets.length === 0) {
    var bullet = new Bullet({}, boat);
    bullets.push(bullet);
  }
}

function activeBullet(bullet) {
  if (bullet.y > canvasHeight) {
    return false;
  } else {
    return true;
  }
}

function filterBullets() {
  bullets = bullets.filter(function(eachBullet){
    console.log(bullets);
    return activeBullet(eachBullet);
  });
}

function generateFish(fishies) {
  fishies.forEach(function (fish) {
    fish.draw(context).move()
        .reverseDirection(canvasWidth);
  });
}

function generateBullets(bullets) {
  bullets.forEach(function (bullet) {
    bullet.draw(context)
          .shoot(canvasHeight);
  });
}

function checkForCollision() {
  fishies.forEach(function(fish) {
    bullets.forEach(function(bullet) {
      if (collision(fish, bullet)) {
        fishies = fishies.filter(function(eachFish){
          return eachFish !== fish;
        });
      }
    });
  });
}

function Game() {
  clearScreen();
  startGame();
}

function startGame() {
  generateFish(fishies);
  boat.draw(context);
  generateBullets(bullets);
  checkForCollision();
}

function clearScreen() {
  context.clearRect(0, 0, canvas.width, canvas.height);
}

module.exports = Game;<commit_msg>Removes console.log<commit_after>var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var canvasWidth =  canvas.width;
var canvasHeight =  canvas.height;

var Boat = require('./boat');
var Bullet = require('./bullet');
var fishies = require('./generate-fish');
var collision = require('./collision');
// var keyEvents = require('./key-events');

var bullets = [];

var boat = new Boat({x: canvasWidth/2, y: 25, width: 200, height: 150, velocity: 5});

canvas.addEventListener('keydown', function(key) {
//   var keyNumber = event.keyCode;
//   keyEvents(keyNumber);

  if (key.which === 37) {
    boat.moveBoatLeft(boat);
  } else if (key.which === 39) {
    boat.moveBoatRight(boat, canvasWidth);
  } else if (key.which === 32) {
    filterBullets();
    addBullet(bullets);
  }
});

function addBullet(bullets) {
  if (bullets.length === 0) {
    var bullet = new Bullet({}, boat);
    bullets.push(bullet);
  }
}

function activeBullet(bullet) {
  if (bullet.y > canvasHeight) {
    return false;
  } else {
    return true;
  }
}

function filterBullets() {
  bullets = bullets.filter(function(eachBullet){
    return activeBullet(eachBullet);
  });
}

function generateFish(fishies) {
  fishies.forEach(function (fish) {
    fish.draw(context).move()
        .reverseDirection(canvasWidth);
  });
}

function generateBullets(bullets) {
  bullets.forEach(function (bullet) {
    bullet.draw(context)
          .shoot(canvasHeight);
  });
}

function checkForCollision() {
  fishies.forEach(function(fish) {
    bullets.forEach(function(bullet) {
      if (collision(fish, bullet)) {
        fishies = fishies.filter(function(eachFish){
          return eachFish !== fish;
        });
      }
    });
  });
}

function Game() {
  clearScreen();
  startGame();
}

function startGame() {
  generateFish(fishies);
  boat.draw(context);
  generateBullets(bullets);
  checkForCollision();
}

function clearScreen() {
  context.clearRect(0, 0, canvas.width, canvas.height);
}

module.exports = Game;
<|endoftext|>


<commit_before>var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;

var Boat = require('./boat');
var Bullet = require('./bullet');
var bullets = [];
var fishies = require('./fish').fishies;
var collision = require('./collision');
var boat = new Boat({x: canvasWidth/2, y: 25, width: 200, height: 150, velocity: 5, score: 0});
var gameRunning = false;
var round = 1;
var CanvasPainter = require('./canvas-painter');
var canvasPainter = new CanvasPainter(context);
var CanvasMotion = require('./canvas-motion');
var canvasMotion = new CanvasMotion(canvasWidth, canvasHeight);

canvas.addEventListener('keydown', function(key) {
  if (key.which === 37) {
    canvasMotion.moveBoatLeft(boat);
  } else if (key.which === 39) {
    canvasMotion.moveBoatRight(boat, canvasWidth);
  } else if (key.which === 32 && gameRunning) {
    filterBullets();
    addBullet(bullets);
  } else if (key.which === 13 && gameRunning === false) {
    beginScoring();
  }
});

function drawObjects() {
  canvasPainter.drawOcean();
  canvasPainter.drawFish(fishies);
  canvasPainter.drawBoat(boat);
  canvasPainter.drawBullet(bullets);
}

function moveObjects() {
  canvasMotion.moveFish(fishies, round);
  canvasMotion.moveBullet(bullets);
}

function addBullet(bullets) {
  if (bullets.length === 0) {
    var bullet = new Bullet({}, boat);
    bullets.push(bullet);
  }
}

function filterBullets() {
  bullets = bullets.filter(function(eachBullet){
    return activeBullet(eachBullet);
  });
}

function activeBullet(bullet) {
  if (bullet.y > canvasHeight) {
    return false;
  } else {
    return true;
  }
}

function checkForCollision() {
  fishies.forEach(function(fish) {
    bullets.forEach(function(bullet) {
      if (collision(fish, bullet)) {
        boat.score += fish.y;
        displayScore();
        fishies = fishies.filter(function(eachFish){
          return eachFish !== fish;
        });
      }
    });
  });
}

function beginScoring() {
  gameRunning = true;
  displayRound();
  removeGameStatus();
  gameTimer();
}

function gameTimer() {
  var seconds_left = 8;
  var interval = setInterval(function() {
    document.getElementById('timer').innerHTML = --seconds_left;
    if (seconds_left <= 0) {
      document.getElementById('timer').innerHTML = 'Time\'s up!';
      clearInterval(interval);
      gameRunning = false;
      nextRound();
    }
  }, 1000);
}

function nextRound() {
  if (boat.score >= 500 && round === 1) {
    round++;
    resetRound();
  } else if (boat.score >= 500 && round ===2) {
    round++;
    resetRound(round);
  } else if (boat.score >= 500) {
    playerWins();
  } else {
    playerLoses();
  }
}

function resetRound(round) {
  document.getElementById('game-status').innerHTML = 'Nice catch! On to the next round';
  fishies = [];
  startGame(round);
  fishies = require('./fish').fishies;
}

function clearScoreAndRound() {
  boat.score = 0;
  round = 1;
  displayScore();
}

function playerWins() {
  clearScoreAndRound();
  document.getElementById('game-status').innerHTML = 'Boy you musta been born on the bayou! You win';
  displayRound();
  resetRound();
}

function playerLoses() {
  clearScoreAndRound();
  document.getElementById('game-status').innerHTML = 'Shrimpin\' Ain\'t Easy! Try again';
  resetRound();
}

function displayScore() {
  document.getElementById('score').innerHTML = boat.score;
}

function displayRound() {
  document.getElementById('round').innerHTML = round;
}

function removeGameStatus() {
  if (gameRunning) {
    document.getElementById('game-status').innerHTML = "";
  }
}

function Game() {
  startGame(round);
}

var startGame = function() {
  clearScreen();
  drawObjects();
  moveObjects();
  checkForCollision();
};

function clearScreen() {
  context.clearRect(0, 0, canvas.width, canvas.height);
}

module.exports = Game;
<commit_msg>Abstracts advanceRound from reset round in order to display correct message<commit_after>var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;

var Boat = require('./boat');
var Bullet = require('./bullet');
var bullets = [];
var fishies = require('./fish').fishies;
var collision = require('./collision');
var boat = new Boat({x: canvasWidth/2, y: 25, width: 200, height: 150, velocity: 5, score: 0});
var gameRunning = false;
var round = 1;
var CanvasPainter = require('./canvas-painter');
var canvasPainter = new CanvasPainter(context);
var CanvasMotion = require('./canvas-motion');
var canvasMotion = new CanvasMotion(canvasWidth, canvasHeight);

canvas.addEventListener('keydown', function(key) {
  if (key.which === 37) {
    canvasMotion.moveBoatLeft(boat);
  } else if (key.which === 39) {
    canvasMotion.moveBoatRight(boat, canvasWidth);
  } else if (key.which === 32 && gameRunning) {
    filterBullets();
    addBullet(bullets);
  } else if (key.which === 13 && gameRunning === false) {
    beginScoring();
  }
});

function drawObjects() {
  canvasPainter.drawOcean();
  canvasPainter.drawFish(fishies);
  canvasPainter.drawBoat(boat);
  canvasPainter.drawBullet(bullets);
}

function moveObjects() {
  canvasMotion.moveFish(fishies, round);
  canvasMotion.moveBullet(bullets);
}

function addBullet(bullets) {
  if (bullets.length === 0) {
    var bullet = new Bullet({}, boat);
    bullets.push(bullet);
  }
}

function filterBullets() {
  bullets = bullets.filter(function(eachBullet){
    return activeBullet(eachBullet);
  });
}

function activeBullet(bullet) {
  if (bullet.y > canvasHeight) {
    return false;
  } else {
    return true;
  }
}

function checkForCollision() {
  fishies.forEach(function(fish) {
    bullets.forEach(function(bullet) {
      if (collision(fish, bullet)) {
        boat.score += fish.y;
        displayScore();
        fishies = fishies.filter(function(eachFish){
          return eachFish !== fish;
        });
      }
    });
  });
}

function beginScoring() {
  gameRunning = true;
  displayRound();
  removeGameStatus();
  gameTimer();
}

function gameTimer() {
  var seconds_left = 8;
  var interval = setInterval(function() {
    document.getElementById('timer').innerHTML = --seconds_left;
    if (seconds_left <= 0) {
      document.getElementById('timer').innerHTML = 'Time\'s up!';
      clearInterval(interval);
      gameRunning = false;
      nextRound();
    }
  }, 1000);
}

function nextRound() {
  if (boat.score >= 500 && round === 1) {
    round++;
    advanceRound();
    resetRound();
  } else if (boat.score >= 500 && round ===2) {
    round++;
    advanceRound();
    resetRound(round);
  } else if (boat.score >= 500) {
    playerWins();
  } else {
    playerLoses();
  }
}

function advanceRound() {
  document.getElementById('game-status').innerHTML = 'Nice catch! On to the next round';
}

function resetRound(round) {
  fishies = [];
  startGame(round);
  fishies = require('./fish').fishies;
}

function clearScoreAndRound() {
  boat.score = 0;
  round = 1;
  displayScore();
}

function playerWins() {
  clearScoreAndRound();
  document.getElementById('game-status').innerHTML = 'Boy you musta been born on the bayou! You win';
  displayRound();
  resetRound();
}

function playerLoses() {
  clearScoreAndRound();
  document.getElementById('game-status').innerHTML = 'Shrimpin\' Ain\'t Easy! Try again';
  resetRound();
}

function displayScore() {
  document.getElementById('score').innerHTML = boat.score;
}

function displayRound() {
  document.getElementById('round').innerHTML = round;
}

function removeGameStatus() {
  if (gameRunning) {
    document.getElementById('game-status').innerHTML = "";
  }
}

function Game() {
  startGame(round);
}

var startGame = function() {
  clearScreen();
  drawObjects();
  moveObjects();
  checkForCollision();
};

function clearScreen() {
  context.clearRect(0, 0, canvas.width, canvas.height);
}

module.exports = Game;
<|endoftext|>


<commit_before>var hashjs = require('hash.js');
var sha512 = require('sha512');

var Hash = module.exports;

Hash.sha1 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha1 hash must be of a buffer');
  var hash = (new hashjs.sha1()).update(buf).digest();
  return new Buffer(hash);
};

Hash.sha1.blocksize = 512;

Hash.sha256 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha256 hash must be of a buffer');
  var hash = (new hashjs.sha256()).update(buf).digest();
  return new Buffer(hash);
};

Hash.sha256.blocksize = 512;

Hash.sha256sha256 = function(buf) {
  try {
    return Hash.sha256(Hash.sha256(buf));
  } catch (e) {
    throw new Error('sha256sha256 hash must be of a buffer');
  }
};

Hash.ripemd160 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('ripemd160 hash must be of a buffer');
  var hash = (new hashjs.ripemd160()).update(buf).digest();
  return new Buffer(hash);
};

Hash.sha256ripemd160 = function(buf) {
  try {
    return Hash.ripemd160(Hash.sha256(buf));
  } catch (e) {
    throw new Error('sha256ripemd160 hash must be of a buffer');
  }
};

Hash.sha512 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha512 hash must be of a buffer');
  var hashbuf = sha512(buf);
  return hashbuf;
};

Hash.sha512.blocksize = 1024;

Hash.hmac = function(hashf, data, key) {
  if (!Buffer.isBuffer(data) || !Buffer.isBuffer(key))
    throw new Error('data and key must be buffers');

  //http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
  //http://tools.ietf.org/html/rfc4868#section-2
  if (!hashf.blocksize)
    throw new Error('Blocksize for hash function unknown');

  var blocksize = hashf.blocksize / 8;

  if (key.length > blocksize)
    key = hashf(key);

  if (key.length < blocksize) {
    var fill = new Buffer(blocksize);
    fill.fill(0, key.length);
    key.copy(fill);
    key = fill;
  }

  var o_key_pad = new Buffer(blocksize);
  var i_key_pad = new Buffer(blocksize);
  for (var i = 0; i < blocksize; i++) {
    o_key_pad[i] = 0x5c ^ key[i];
    i_key_pad[i] = 0x36 ^ key[i];
  }

  return hashf(Buffer.concat([o_key_pad, hashf(Buffer.concat([i_key_pad, data]))]));
};

Hash.sha1hmac = function(data, key) {
  return Hash.hmac(Hash.sha1, data, key);
};

Hash.sha1hmac.bitsize = 160;

Hash.sha256hmac = function(data, key) {
  return Hash.hmac(Hash.sha256, data, key);
};

Hash.sha256hmac.bitsize = 256;

Hash.sha512hmac = function(data, key) {
  return Hash.hmac(Hash.sha512, data, key);
};

Hash.sha512hmac.bitsize = 512;
<commit_msg>migrate towards require('crypto') away from hash.js<commit_after>var sha512 = require('sha512');
var crypto = require('crypto');
var hashjs = require('hash.js');

var Hash = module.exports;

Hash.sha1 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha1 hash must be of a buffer');
  var hashbuf = crypto.createHash('sha1').update(buf).digest();
  return hashbuf;
};

Hash.sha1.blocksize = 512;

Hash.sha256 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha256 hash must be of a buffer');
  var hashbuf = crypto.createHash('sha256').update(buf).digest();
  return hashbuf;
};

Hash.sha256.blocksize = 512;

Hash.sha256sha256 = function(buf) {
  try {
    return Hash.sha256(Hash.sha256(buf));
  } catch (e) {
    throw new Error('sha256sha256 hash must be of a buffer: ' + e);
  }
};

Hash.ripemd160 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('ripemd160 hash must be of a buffer');
  var hash = (new hashjs.ripemd160()).update(buf).digest();
  return new Buffer(hash);
};

Hash.sha256ripemd160 = function(buf) {
  try {
    return Hash.ripemd160(Hash.sha256(buf));
  } catch (e) {
    throw new Error('sha256ripemd160 hash must be of a buffer: ' + e);
  }
};

Hash.sha512 = function(buf) {
  if (!Buffer.isBuffer(buf))
    throw new Error('sha512 hash must be of a buffer');
  var hashbuf = crypto.createHash('sha512').update(buf).digest();
  return hashbuf;
};

Hash.sha512.blocksize = 1024;

Hash.hmac = function(hashf, data, key) {
  if (!Buffer.isBuffer(data) || !Buffer.isBuffer(key))
    throw new Error('data and key must be buffers');

  //http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
  //http://tools.ietf.org/html/rfc4868#section-2
  if (!hashf.blocksize)
    throw new Error('Blocksize for hash function unknown');

  var blocksize = hashf.blocksize / 8;

  if (key.length > blocksize)
    key = hashf(key);

  if (key.length < blocksize) {
    var fill = new Buffer(blocksize);
    fill.fill(0, key.length);
    key.copy(fill);
    key = fill;
  }

  var o_key_pad = new Buffer(blocksize);
  var i_key_pad = new Buffer(blocksize);
  for (var i = 0; i < blocksize; i++) {
    o_key_pad[i] = 0x5c ^ key[i];
    i_key_pad[i] = 0x36 ^ key[i];
  }

  return hashf(Buffer.concat([o_key_pad, hashf(Buffer.concat([i_key_pad, data]))]));
};

Hash.sha1hmac = function(data, key) {
  return Hash.hmac(Hash.sha1, data, key);
};

Hash.sha1hmac.bitsize = 160;

Hash.sha256hmac = function(data, key) {
  return Hash.hmac(Hash.sha256, data, key);
};

Hash.sha256hmac.bitsize = 256;

Hash.sha512hmac = function(data, key) {
  return Hash.hmac(Hash.sha512, data, key);
};

Hash.sha512hmac.bitsize = 512;
<|endoftext|>


<commit_before>/*
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
YUI.add('help', function(Y) {

    var help = [
        "",
        "YUI Doc generates API documentation from a modified JavaDoc syntax.",
        "",
        "Current version ({VERSION})",
        "",
        "Usage: yuidoc <options> <input path>",
        "",
        "Common Options:",
        "  -c, --config, --configfile <filename>  A JSON config file to provide configuration data.",
        "           You can also create a yuidoc.json file and place it",
        "           anywhere under your source tree and YUI Doc will find it",
        "           and use it.",
        "  -e, --extension <comma sep list of file extensions> The list of file extensions to parse ",
        "           for api documentation. (defaults to .js)",
        "  -x, --exclude <comma sep list of directorues> Directorys to exclude from parsing ",
        "           (defaults to '.DS_Store,.svn,CVS,.git,build_rollup_tmp,build_tmp')",
        "  -v, --version Show the current YUIDoc version",
        "  --project-version Set the doc version for the template",
        "  -N, --no-color Turn off terminal colors (for automation)",
        "  -n, --norecurse Do not recurse directories (default is to recurse)",
        "  -S, --selleck Look for Selleck component data and attach to API meta data",
        "  -V, --view Dump the Handlebars.js view data instead of writing template files",
        "  -p, --parse-only Only parse the API docs and create the JSON data, do not render templates",
        "  -o, --out <directory path> Path to put the generated files (defaults to ./out)",
        "  -t, --themedir <directory path> Path to a custom theme directory containing Handlebars templates",
        "  -h, --help Show this help",
        "  -T, --theme <simple|default> Choose one of the built in themes (default is default)",
        "",
        "  <input path> Supply a list of paths (shell globbing is handy here)",
        "",
    ].join('\n');

    Y.showHelp = function() {
        console.error(Y.Lang.sub(help, {
            VERSION: Y.packageInfo.version
        }));
        process.exit(1);
    }
});
<commit_msg>Added --server and --port options to help<commit_after>/*
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
YUI.add('help', function(Y) {

    var help = [
        "",
        "YUI Doc generates API documentation from a modified JavaDoc syntax.",
        "",
        "Current version ({VERSION})",
        "",
        "Usage: yuidoc <options> <input path>",
        "",
        "Common Options:",
        "  -c, --config, --configfile <filename>  A JSON config file to provide configuration data.",
        "           You can also create a yuidoc.json file and place it",
        "           anywhere under your source tree and YUI Doc will find it",
        "           and use it.",
        "  -e, --extension <comma sep list of file extensions> The list of file extensions to parse ",
        "           for api documentation. (defaults to .js)",
        "  -x, --exclude <comma sep list of directorues> Directorys to exclude from parsing ",
        "           (defaults to '.DS_Store,.svn,CVS,.git,build_rollup_tmp,build_tmp')",
        "  -v, --version Show the current YUIDoc version",
        "  --project-version Set the doc version for the template",
        "  -N, --no-color Turn off terminal colors (for automation)",
        "  -n, --norecurse Do not recurse directories (default is to recurse)",
        "  -S, --selleck Look for Selleck component data and attach to API meta data",
        "  -V, --view Dump the Handlebars.js view data instead of writing template files",
        "  -p, --parse-only Only parse the API docs and create the JSON data, do not render templates",
        "  -o, --out <directory path> Path to put the generated files (defaults to ./out)",
        "  -t, --themedir <directory path> Path to a custom theme directory containing Handlebars templates",
        "  -h, --help Show this help",
        "  -T, --theme <simple|default> Choose one of the built in themes (default is default)",
        "  --server Fire up the YUIDoc server for faster API doc developement",
        "  --port <Number> The port to listen on. (default is 3000)",
        "",
        "  <input path> Supply a list of paths (shell globbing is handy here)",
        "",
    ].join('\n');

    Y.showHelp = function() {
        console.error(Y.Lang.sub(help, {
            VERSION: Y.packageInfo.version
        }));
        process.exit(1);
    }
});
<|endoftext|>


<commit_before>/*!*/
// Copyright 2012 Splunk, 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.

(function() {
    "use strict";

    var Class           = require('./jquery.class').Class;
    var logger          = require('./log').Logger;
    var utils           = require('./utils');
    var CookieHandler   = require('tough-cookie');

    var root = exports || this;
    var Http = null;

    var queryBuilderMap = {
        "5": function(message) {
            var query = message.query || {};
            var post = message.post || {};
            var outputMode = query.output_mode || post.output_mode || "json";

            // If the output mode doesn't start with "json" (e.g. "csv" or
            // "xml"), we change it to "json".
            if (!utils.startsWith(outputMode, "json")) {
                outputMode = "json";
            }

            query.output_mode = outputMode;

            return query;
        },
        "4": function(message) {
            return message.query || {};
        },
        "default": function(message) {
            return queryBuilderMap["5"](message);
        },
        "none": function(message) {
            return message.query || {};
        }
    };

    /**
     * A base class for HTTP abstraction that provides the basic functionality
     * for performing GET, POST, DELETE, and REQUEST operations, and provides
     * utilities to construct uniform responses.
     *
     * Base classes should only override `makeRequest` and `parseJSON`.
     *
     * @class splunkjs.Http
     */
    module.exports = root = Http = Class.extend({
        /**
         * Constructor for `splunkjs.Http`.
         *
         * @constructor
         * @return {splunkjs.Http} A new `splunkjs.Http` instance.
         *
         * @method splunkjs.Http
         */
        init: function() {

            // We perform the bindings so that every function works
            // properly when it is passed as a callback.
            this.get                = utils.bind(this, this.get);
            this.del                = utils.bind(this, this.del);
            this.post               = utils.bind(this, this.post);
            this.request            = utils.bind(this, this.request);
            this._buildResponse     = utils.bind(this, this._buildResponse);

            // Set our default version to "none"
            this._setSplunkVersion("none");

            // Cookie store for cookie based authentication.
            this._cookieStore = {};
        },

        /*!*/
        _setSplunkVersion: function(version) {
            this.version = version;
        },

        /**
         * Performs a GET request.
         *
         * @param {String} url The URL of the GET request.
         * @param {Object} headers An object of headers for this request.
         * @param {Object} params Parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        get: function(url, headers, params, timeout, callback) {
            var message = {
                method: "GET",
                headers: headers,
                timeout: timeout,
                query: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a POST request.
         *
         * @param {String} url The URL of the POST request.
         * @param {Object} headers  An object of headers for this request.
         * @param {Object} params Parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        post: function(url, headers, params, timeout, callback) {
            headers["Content-Type"] = "application/x-www-form-urlencoded";
            var message = {
                method: "POST",
                headers: headers,
                timeout: timeout,
                post: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a DELETE request.
         *
         * @param {String} url The URL of the DELETE request.
         * @param {Object} headers An object of headers for this request.
         * @param {Object} params Query parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        del: function(url, headers, params, timeout, callback) {
            var message = {
                method: "DELETE",
                headers: headers,
                timeout: timeout,
                query: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a request.
         *
         * This function sets up how to handle a response from a request, but
         * delegates calling the request to the `makeRequest` subclass.
         *
         * @param {String} url The encoded URL of the request.
         * @param {Object} message An object with values for method, headers, timeout, and encoded body.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         * @see makeRequest
         */
        request: function(url, message, callback) {
            var that = this;
            var wrappedCallback = function(response) {
                callback = callback || function() {};

                // Handle cookies if 'set-cookie' header is in the response

                var cookieHeader = response.response.headers['set-cookie'];
                if (cookieHeader) {
                    var cookie = CookieHandler.parse(cookieHeader.toString());

                    that._cookieStore[cookie.key] = cookie.value;
                }

                // Handle callback

                if (response.status < 400 && response.status !== "abort") {
                    callback(null, response);
                }
                else {
                    callback(response);
                }
            };

            var query = utils.getWithVersion(this.version, queryBuilderMap)(message);
            var post = message.post || {};

            var encodedUrl = url + "?" + Http.encode(query);
            var body = message.body ? message.body : Http.encode(post);

            var cookieString = "";

            for (var key in this._cookieStore) {
                cookieString += key;
                cookieString += '=';
                cookieString += this._cookieStore[key];
                cookieString += '; ';
            }

            if (cookieString.length !== 0) {
                message.headers["Cookie"] = cookieString;

                // Remove Authorization header
                // Splunk will use Authorization header and ignore Cookies if Authorization header is sent
                delete message.headers["Authorization"];
            }

            var options = {
                method: message.method,
                headers: message.headers,
                timeout: message.timeout,
                body: body
            };

            // Now we can invoke the user-provided HTTP class,
            // passing in our "wrapped" callback
            return this.makeRequest(encodedUrl, options, wrappedCallback);
        },

        /**
         * Encapsulates the client-specific logic for performing a request. This
         * function is meant to be overriden by subclasses.
         *
         * @param {String} url The encoded URL of the request.
         * @param {Object} message An object with values for method, headers, timeout, and encoded body.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        makeRequest: function(url, message, callback) {
            throw new Error("UNDEFINED FUNCTION - OVERRIDE REQUIRED");
        },

        /**
         * Encapsulates the client-specific logic for parsing the JSON response.
         *
         * @param {String} json The JSON response to parse.
         * @return {Object} The parsed JSON.
         *
         * @method splunkjs.Http
         */
        parseJson: function(json) {
            throw new Error("UNDEFINED FUNCTION - OVERRIDE REQUIRED");
        },

        /**
         * Generates a unified response with the given parameters.
         *
         * @param {Object} error An error object, if one exists for the request.
         * @param {Object} response The response object.
         * @param {Object} data The response data.
         * @return {Object} A unified response object.
         *
         * @method splunkjs.Http
         */
        _buildResponse: function(error, response, data) {
            var complete_response, json = {};

            var contentType = null;
            if (response && response.headers) {
                contentType = utils.trim(response.headers["content-type"] || response.headers["Content-Type"]);
            }

            if (utils.startsWith(contentType, "application/json") && data) {
                try {
                    json = this.parseJson(data) || {};
                }
                catch(e) {
                    logger.error("Error in parsing JSON:", data, e);
                    json = data;
                }
            }
            else {
                json = data;
            }

            if (json) {
                logger.printMessages(json.messages);
            }

            complete_response = {
                response: response,
                status: (response ? response.statusCode : 0),
                data: json,
                error: error
            };

            return complete_response;
        }
    });

    /**
     * Encodes a dictionary of values into a URL-encoded format.
     *
     * @example
     *
     *      // should be a=1&b=2&b=3&b=4
     *      encode({a: 1, b: [2,3,4]})
     *
     * @param {Object} params The parameters to URL encode.
     * @return {String} The URL-encoded string.
     *
     * @function splunkjs.Http
     */
    Http.encode = function(params) {
        var encodedStr = "";

        // We loop over all the keys so we encode them.
        for (var key in params) {
            if (params.hasOwnProperty(key)) {
                // Only append the ampersand if we already have
                // something encoded, and the last character isn't
                // already an ampersand
                if (encodedStr && encodedStr[encodedStr.length - 1] !== "&") {
                    encodedStr = encodedStr + "&";
                }

                // Get the value
                var value = params[key];

                // If it's an array, we loop over each value
                // and encode it in the form &key=value[i]
                if (value instanceof Array) {
                    for (var i = 0; i < value.length; i++) {
                        encodedStr = encodedStr + key + "=" + encodeURIComponent(value[i]) + "&";
                    }
                }
                else if (typeof value === "object") {
                    for(var innerKey in value) {
                        if (value.hasOwnProperty(innerKey)) {
                            var innerValue = value[innerKey];
                            encodedStr = encodedStr + key + "=" + encodeURIComponent(value[innerKey]) + "&";
                        }
                    }
                }
                else {
                    // If it's not an array, we just encode it
                    encodedStr = encodedStr + key + "=" + encodeURIComponent(value);
                }
            }
        }

        if (encodedStr[encodedStr.length - 1] === '&') {
            encodedStr = encodedStr.substr(0, encodedStr.length - 1);
        }

        return encodedStr;
    };
})();
<commit_msg>Iterating over all cookies<commit_after>/*!*/
// Copyright 2012 Splunk, 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.

(function() {
    "use strict";

    var Class           = require('./jquery.class').Class;
    var logger          = require('./log').Logger;
    var utils           = require('./utils');
    var CookieHandler   = require('tough-cookie');

    var root = exports || this;
    var Http = null;

    var queryBuilderMap = {
        "5": function(message) {
            var query = message.query || {};
            var post = message.post || {};
            var outputMode = query.output_mode || post.output_mode || "json";

            // If the output mode doesn't start with "json" (e.g. "csv" or
            // "xml"), we change it to "json".
            if (!utils.startsWith(outputMode, "json")) {
                outputMode = "json";
            }

            query.output_mode = outputMode;

            return query;
        },
        "4": function(message) {
            return message.query || {};
        },
        "default": function(message) {
            return queryBuilderMap["5"](message);
        },
        "none": function(message) {
            return message.query || {};
        }
    };

    /**
     * A base class for HTTP abstraction that provides the basic functionality
     * for performing GET, POST, DELETE, and REQUEST operations, and provides
     * utilities to construct uniform responses.
     *
     * Base classes should only override `makeRequest` and `parseJSON`.
     *
     * @class splunkjs.Http
     */
    module.exports = root = Http = Class.extend({
        /**
         * Constructor for `splunkjs.Http`.
         *
         * @constructor
         * @return {splunkjs.Http} A new `splunkjs.Http` instance.
         *
         * @method splunkjs.Http
         */
        init: function() {

            // We perform the bindings so that every function works
            // properly when it is passed as a callback.
            this.get                = utils.bind(this, this.get);
            this.del                = utils.bind(this, this.del);
            this.post               = utils.bind(this, this.post);
            this.request            = utils.bind(this, this.request);
            this._buildResponse     = utils.bind(this, this._buildResponse);

            // Set our default version to "none"
            this._setSplunkVersion("none");

            // Cookie store for cookie based authentication.
            this._cookieStore = {};
        },

        /*!*/
        _setSplunkVersion: function(version) {
            this.version = version;
        },

        /**
         * Performs a GET request.
         *
         * @param {String} url The URL of the GET request.
         * @param {Object} headers An object of headers for this request.
         * @param {Object} params Parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        get: function(url, headers, params, timeout, callback) {
            var message = {
                method: "GET",
                headers: headers,
                timeout: timeout,
                query: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a POST request.
         *
         * @param {String} url The URL of the POST request.
         * @param {Object} headers  An object of headers for this request.
         * @param {Object} params Parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        post: function(url, headers, params, timeout, callback) {
            headers["Content-Type"] = "application/x-www-form-urlencoded";
            var message = {
                method: "POST",
                headers: headers,
                timeout: timeout,
                post: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a DELETE request.
         *
         * @param {String} url The URL of the DELETE request.
         * @param {Object} headers An object of headers for this request.
         * @param {Object} params Query parameters for this request.
         * @param {Number} timeout A timeout period.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        del: function(url, headers, params, timeout, callback) {
            var message = {
                method: "DELETE",
                headers: headers,
                timeout: timeout,
                query: params
            };

            return this.request(url, message, callback);
        },

        /**
         * Performs a request.
         *
         * This function sets up how to handle a response from a request, but
         * delegates calling the request to the `makeRequest` subclass.
         *
         * @param {String} url The encoded URL of the request.
         * @param {Object} message An object with values for method, headers, timeout, and encoded body.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         * @see makeRequest
         */
        request: function(url, message, callback) {
            var that = this;
            var wrappedCallback = function(response) {
                callback = callback || function() {};

                // Handle cookies if 'set-cookie' header is in the response

                var cookieHeaders = response.response.headers['set-cookie'];
                if (cookieHeaders) {
                    for (var cookieHeader in cookieHeaders) {
                        if (cookieHeaders.hasOwnProperty(cookieHeader)) {
                            var cookie = CookieHandler.parse(cookieHeader);
                            that._cookieStore[cookie.key] = cookie.value;
                        }
                }

                // Handle callback

                if (response.status < 400 && response.status !== "abort") {
                    callback(null, response);
                }
                else {
                    callback(response);
                }
            };

            var query = utils.getWithVersion(this.version, queryBuilderMap)(message);
            var post = message.post || {};

            var encodedUrl = url + "?" + Http.encode(query);
            var body = message.body ? message.body : Http.encode(post);

            var cookieString = "";

            for (var key in this._cookieStore) {
                if (this._cookieStore.hasOwnProperty(key)) {
                    cookieString += key;
                    cookieString += '=';
                    cookieString += this._cookieStore[key];
                    cookieString += '; ';
                }
            }

            if (cookieString.length !== 0) {
                message.headers["Cookie"] = cookieString;

                // Remove Authorization header
                // Splunk will use Authorization header and ignore Cookies if Authorization header is sent
                delete message.headers["Authorization"];
            }

            var options = {
                method: message.method,
                headers: message.headers,
                timeout: message.timeout,
                body: body
            };

            // Now we can invoke the user-provided HTTP class,
            // passing in our "wrapped" callback
            return this.makeRequest(encodedUrl, options, wrappedCallback);
        },

        /**
         * Encapsulates the client-specific logic for performing a request. This
         * function is meant to be overriden by subclasses.
         *
         * @param {String} url The encoded URL of the request.
         * @param {Object} message An object with values for method, headers, timeout, and encoded body.
         * @param {Function} callback The function to call when the request is complete: `(err, response)`.
         *
         * @method splunkjs.Http
         */
        makeRequest: function(url, message, callback) {
            throw new Error("UNDEFINED FUNCTION - OVERRIDE REQUIRED");
        },

        /**
         * Encapsulates the client-specific logic for parsing the JSON response.
         *
         * @param {String} json The JSON response to parse.
         * @return {Object} The parsed JSON.
         *
         * @method splunkjs.Http
         */
        parseJson: function(json) {
            throw new Error("UNDEFINED FUNCTION - OVERRIDE REQUIRED");
        },

        /**
         * Generates a unified response with the given parameters.
         *
         * @param {Object} error An error object, if one exists for the request.
         * @param {Object} response The response object.
         * @param {Object} data The response data.
         * @return {Object} A unified response object.
         *
         * @method splunkjs.Http
         */
        _buildResponse: function(error, response, data) {
            var complete_response, json = {};

            var contentType = null;
            if (response && response.headers) {
                contentType = utils.trim(response.headers["content-type"] || response.headers["Content-Type"]);
            }

            if (utils.startsWith(contentType, "application/json") && data) {
                try {
                    json = this.parseJson(data) || {};
                }
                catch(e) {
                    logger.error("Error in parsing JSON:", data, e);
                    json = data;
                }
            }
            else {
                json = data;
            }

            if (json) {
                logger.printMessages(json.messages);
            }

            complete_response = {
                response: response,
                status: (response ? response.statusCode : 0),
                data: json,
                error: error
            };

            return complete_response;
        }
    });

    /**
     * Encodes a dictionary of values into a URL-encoded format.
     *
     * @example
     *
     *      // should be a=1&b=2&b=3&b=4
     *      encode({a: 1, b: [2,3,4]})
     *
     * @param {Object} params The parameters to URL encode.
     * @return {String} The URL-encoded string.
     *
     * @function splunkjs.Http
     */
    Http.encode = function(params) {
        var encodedStr = "";

        // We loop over all the keys so we encode them.
        for (var key in params) {
            if (params.hasOwnProperty(key)) {
                // Only append the ampersand if we already have
                // something encoded, and the last character isn't
                // already an ampersand
                if (encodedStr && encodedStr[encodedStr.length - 1] !== "&") {
                    encodedStr = encodedStr + "&";
                }

                // Get the value
                var value = params[key];

                // If it's an array, we loop over each value
                // and encode it in the form &key=value[i]
                if (value instanceof Array) {
                    for (var i = 0; i < value.length; i++) {
                        encodedStr = encodedStr + key + "=" + encodeURIComponent(value[i]) + "&";
                    }
                }
                else if (typeof value === "object") {
                    for(var innerKey in value) {
                        if (value.hasOwnProperty(innerKey)) {
                            var innerValue = value[innerKey];
                            encodedStr = encodedStr + key + "=" + encodeURIComponent(value[innerKey]) + "&";
                        }
                    }
                }
                else {
                    // If it's not an array, we just encode it
                    encodedStr = encodedStr + key + "=" + encodeURIComponent(value);
                }
            }
        }

        if (encodedStr[encodedStr.length - 1] === '&') {
            encodedStr = encodedStr.substr(0, encodedStr.length - 1);
        }

        return encodedStr;
    };
})();
<|endoftext|>