<commit_before>/**
* Template helpers
*/

Template.adminLocation.onRendered(function () {
  $('body').addClass('admin');
});

// Helpers for adminLocation template
Template.adminLocation.helpers({

  imageEntries: function () {

    return Images.find({}, { sort:{ isoDate: 1 } });

  },

  tableSettings: function () {
    return {
      collection: Images.find({}, { sort:{ isoDate: 1 } }),

      showNavigation: 'auto',
      showNavigationRowsPerPage: true,
      showFilter: true,
      rowsPerPage: 10,
      fields: [
        { key: 'dsNumber', label: 'DS Number' },
        { key: 'isoDate', label: 'Date' },
        { key: 'title', label: 'Title' },
        { key: 'creationPlace', label: 'Creation place' },
        { key: 'creditLine', label: 'Credit line' },

        {
          key:'active',
          label: 'active',
          fn: function (value) {
            if (value === true) {
              return new Spacebars.SafeString('');
            } else {
              return new Spacebars.SafeString('');
            }
          },
        },

        {
          key:'_id',
          label: 'Thumbnail',
          sortable: false,
          fn: function (value) {
            var thumbPath = '/images/thumbnails/' + value + '.jpg';
            var previewPath = thumbPath;
            var imgDoc = Images.findOne({ _id: value });
            if (imgDoc) {
              if (imgDoc.imageFilePaths) {
                thumbPath = imgDoc.imageFilePaths[1].src;
                previewPath = imgDoc.imageFilePaths[0].src;
              }
            }

            return new Spacebars.SafeString(
              ''
            );
          },
        },

        {
          key:'_id',
          label: 'Actions',
          sortable: false,
          fn: function (value) {
            var htmlString = ' Edit    Delete';
            if (Images.findOne(value).active === true) htmlString += (
              '   Preview'
            );
            return new Spacebars.SafeString(htmlString);
          },
        },
      ],
    };
  },

});

// Helpers for adminEditModal template
Template.adminEditModal.helpers({

  editImage: function () {

    return Images.findOne({ _id: Session.get('adminCurrentImageId') });

  },

  updateOrInsertMode: function () {

    if (Session.get('adminCurrentImageId') && Session.get('adminCurrentImageId') !== '') {
      return 'update';
    } else {
      return 'insert';
    }

  },

  modalHeader: function () {

    if (Session.get('adminCurrentImageId') && Session.get('adminCurrentImageId') !== '') {
      return 'EDIT IMAGE';
    } else {
      return 'ADD NEW IMAGE';
    }

  },

});

Template.adminLocation.events({
  /**
  * Entry click
  */
  'click a.edit, click .btn.add':function (e) {

    var clickedId = $(e.currentTarget).attr('id');

    if (clickedId === 'addBtn') {

      Session.set('adminCurrentImageId', '');
      $('#editModal').modal('show');

    } else {

      Session.set('adminCurrentImageId', clickedId);
      $('#editModal').modal('show');

    }

  },

  'click a.delete':function (e) {

    var imgToDeleteId = $(e.currentTarget).attr('id');

    console.log('delete clicked:', imgToDeleteId);

    var response = confirm('Are you sure you want to delete Image ' + imgToDeleteId + '?');

    if (response == true) {
      Images.remove(imgToDeleteId);
    } else {
      console.log('Deletion canceled.');
    }

  },

  'click a.preview':function (e) {

    var imgToPreviewId = $(e.currentTarget).attr('id');

    // Example link to image...
    // /riverside?image=ds20001

    var currentLink = Locations.findOne().link;
    var previewURL = 'http://' + window.location.host + '/location/' + currentLink + '';
    if (imgToPreviewId) {
      previewURL += '?image=' + imgToPreviewId;
    }

    Session.set('adminCurrentPreviewURL', previewURL);
    Session.set('adminCurrentReturnURL', '/admin/locations/' + currentLink);
    Session.set('adminCurrentReturnName', Locations.findOne().title);
    console.log('teete');

    // Router.go('/admin/preview');

  },

  'mouseenter table img.tableThumb':function (e) {

    var expandSrc = $(e.currentTarget).attr('data-preview-src');
    var $preview = $('#tableThumbPreview');
    $('#tableThumbPreview img').attr('src', expandSrc);
    $preview.css('top', e.clientY - $preview.outerHeight() / 2);
    $preview.css('right', $(document).width() - e.clientX + 17);
    $preview.delay(150).stop().fadeIn(70);

  },

  'mousemove table img.tableThumb':function (e) {
    var $preview = $('#tableThumbPreview');
    $preview.css('top', e.clientY - $preview.outerHeight() / 2);
    $preview.css('right', $(document).width() - e.clientX + 17);
  },

  'mouseleave table img.tableThumb':function (e) {
    $('#tableThumbPreview').stop().hide();
  },

  'show.bs.modal':function (e) {

    // Hack to fix autoform bug.
    // Clears image upload form when
    // no imageFilePaths are found. -tn
    setTimeout(function () {
      var imgDoc = Images.findOne({ _id: Session.get('adminCurrentImageId') });
      if (imgDoc) {
        if (imgDoc.imageFilePaths) {
          // Already has image. Allow to display.
          return;
        }
      }

      $('#editModal .file-upload-clear').trigger('click');
    }, 20);

  },

  'shown.bs.modal':function (e) {

  },

});

// ImageUtil
function loadImgDimensions(doc, isUpdate, callback) {

  var editDoc;
  if (isUpdate) {
    editDoc = doc.$set;
  } else {
    editDoc = doc;
  }

  if (
    editDoc.imageFilePaths == undefined ||
    editDoc.imageFilePaths == 'undefined' ||
    !editDoc.imageFilePaths
  ) {
    callback(doc);
    return false;
  }

  var expandedSrc = editDoc.imageFilePaths[0].src;
  var thumbSrc = editDoc.imageFilePaths[1].src;
  var myImage = new Image();
  var myThumbImage = new Image();

  var expandedLoaded = false;
  var thumbLoaded = false;

  myImage.onload = function () {

    console.log('\' Expanded is ' + this.width + ' by ' + this.height + ' pixels in size.');

    editDoc.expandedWidth = this.width;
    editDoc.expandedHeight = this.height;
    editDoc.expandedAspectRatio = (this.width / this.height).toFixed(4);

    expandedLoaded = true;
    if (thumbLoaded && expandedLoaded) {
      if (isUpdate) {
        callback({ $set:editDoc });
        return true;
      } else {
        callback(editDoc);
        return true;
      }
    }

  };

  myThumbImage.onload = function () {

    console.log('\' Thumb is ' + this.width + ' by ' + this.height + ' pixels in size.');

    editDoc.thumbWidth = this.width;
    editDoc.thumbHeight = this.height;
    editDoc.thumbAspectRatio = (this.width / this.height).toFixed(4);

    thumbLoaded = true;
    if (thumbLoaded && expandedLoaded) {
      if (isUpdate) {
        callback({ $set:editDoc });
        return true;
      } else {
        callback(editDoc);
        return true;
      }
    }

  };

  myImage.onerror = function () {

    console.log('\'' + this.name + '\' (expanded) failed to load.');
    callback(doc);
    return false;

  };

  myThumbImage.onerror = function () {

    console.log('\'' + this.name + '\' (thumb) failed to load.');
    callback(doc);
    return false;

  };

  myImage.src = expandedSrc;
  myThumbImage.src = thumbSrc;

}

/**
* Hooks for autoform. Manipulate data before/after submission.
*/
AutoForm.hooks({

  formImageEntry: {

    before: {

      insert: function (doc) {

        // Add location Id to create link to current location
        doc.dsLocId = Locations.findOne().dsLocId;
        doc.generalLocationDs = Locations.findOne().title;

        // Add image meta data
        loadImgDimensions(doc, false, this.result);

      },

      update: function (doc) {

        // Add image meta data
        loadImgDimensions(doc, true, this.result);

      },

    },

    docToForm: function (doc, ss) {

      // TODO - Remove unneccessary iso prepend (cleaning old data)
      if (doc.isoDate && doc.isoDate.indexOf('iso-') != -1) {
        doc.isoDate = doc.isoDate.replace('iso-', '');
      }

      return doc;

    },

    // Called when any submit operation succeeds
    onSuccess: function (formType, result) {

      if (formType === 'insert') {
        Session.set('adminCurrentImageId', result);
      }

      console.log('New doc:');
      console.log(Images.findOne(Session.get('adminCurrentImageId')));

      // Hide modal
      $('#editModal').modal('hide');
      $('#editModal form')[0].reset();

    },

    // Called when any submit operation fails
    onError: function (formType, error) {

      console.log('Autoform error:', formType, error);

    },

  },

});
<commit_msg>Adding btn classes for the action links<commit_after>/**
* Template helpers
*/

Template.adminLocation.onRendered(function () {
  $('body').addClass('admin');
});

// Helpers for adminLocation template
Template.adminLocation.helpers({

  imageEntries: function () {

    return Images.find({}, { sort:{ isoDate: 1 } });

  },

  tableSettings: function () {
    return {
      collection: Images.find({}, { sort:{ isoDate: 1 } }),

      showNavigation: 'auto',
      showNavigationRowsPerPage: true,
      showFilter: true,
      rowsPerPage: 10,
      fields: [
        { key: 'dsNumber', label: 'DS Number' },
        { key: 'isoDate', label: 'Date' },
        { key: 'title', label: 'Title' },
        { key: 'creationPlace', label: 'Creation place' },
        { key: 'creditLine', label: 'Credit line' },

        {
          key:'active',
          label: 'active',
          fn: function (value) {
            if (value === true) {
              return new Spacebars.SafeString('');
            } else {
              return new Spacebars.SafeString('');
            }
          },
        },

        {
          key:'_id',
          label: 'Thumbnail',
          sortable: false,
          fn: function (value) {
            var thumbPath = '/images/thumbnails/' + value + '.jpg';
            var previewPath = thumbPath;
            var imgDoc = Images.findOne({ _id: value });
            if (imgDoc) {
              if (imgDoc.imageFilePaths) {
                thumbPath = imgDoc.imageFilePaths[1].src;
                previewPath = imgDoc.imageFilePaths[0].src;
              }
            }

            return new Spacebars.SafeString(
              ''
            );
          },
        },

        /* Edit */
        {
          key:'_id',
          label: 'Actions',
          sortable: false,
          fn: function (value) {
            var htmlString = '
' +
              '
Edit
';
            return new Spacebars.SafeString(htmlString);
          },
        },

        /* Delete */
        {
          key:'_id',
          label: '',
          sortable: false,
          fn: function (value) {
            var htmlstring = '
' +
              '
Delete
';
            return new Spacebars.SafeString(htmlstring);
          },
        },

        /* Preview */
        {
          key:'_id',
          label: '',
          sortable: false,
          fn: function (value) {
            var htmlString = '';
            if (Images.findOne(value).active === true) htmlString += (
              '
' +
              '
Preview
'
            );
            return new Spacebars.SafeString(htmlString);
          },
        },

      ],
    };
  },

});

// Helpers for adminEditModal template
Template.adminEditModal.helpers({

  editImage: function () {

    return Images.findOne({ _id: Session.get('adminCurrentImageId') });

  },

  updateOrInsertMode: function () {

    if (Session.get('adminCurrentImageId') && Session.get('adminCurrentImageId') !== '') {
      return 'update';
    } else {
      return 'insert';
    }

  },

  modalHeader: function () {

    if (Session.get('adminCurrentImageId') && Session.get('adminCurrentImageId') !== '') {
      return 'EDIT IMAGE';
    } else {
      return 'ADD NEW IMAGE';
    }

  },

});

Template.adminLocation.events({
  /**
  * Entry click
  */
  'click a.edit, click .btn.add':function (e) {

    var clickedId = $(e.currentTarget).attr('id');

    if (clickedId === 'addBtn') {

      Session.set('adminCurrentImageId', '');
      $('#editModal').modal('show');

    } else {

      Session.set('adminCurrentImageId', clickedId);
      $('#editModal').modal('show');

    }

  },

  'click a.delete':function (e) {

    var imgToDeleteId = $(e.currentTarget).attr('id');

    console.log('delete clicked:', imgToDeleteId);

    var response = confirm('Are you sure you want to delete Image ' + imgToDeleteId + '?');

    if (response == true) {
      Images.remove(imgToDeleteId);
    } else {
      console.log('Deletion canceled.');
    }

  },

  'click a.preview':function (e) {

    var imgToPreviewId = $(e.currentTarget).attr('id');

    // Example link to image...
    // /riverside?image=ds20001

    var currentLink = Locations.findOne().link;
    var previewURL = 'http://' + window.location.host + '/location/' + currentLink + '';
    if (imgToPreviewId) {
      previewURL += '?image=' + imgToPreviewId;
    }

    Session.set('adminCurrentPreviewURL', previewURL);
    Session.set('adminCurrentReturnURL', '/admin/locations/' + currentLink);
    Session.set('adminCurrentReturnName', Locations.findOne().title);
    console.log('teete');

    // Router.go('/admin/preview');

  },

  'mouseenter table img.tableThumb':function (e) {

    var expandSrc = $(e.currentTarget).attr('data-preview-src');
    var $preview = $('#tableThumbPreview');
    $('#tableThumbPreview img').attr('src', expandSrc);
    $preview.css('top', e.clientY - $preview.outerHeight() / 2);
    $preview.css('right', $(document).width() - e.clientX + 17);
    $preview.delay(150).stop().fadeIn(70);

  },

  'mousemove table img.tableThumb':function (e) {
    var $preview = $('#tableThumbPreview');
    $preview.css('top', e.clientY - $preview.outerHeight() / 2);
    $preview.css('right', $(document).width() - e.clientX + 17);
  },

  'mouseleave table img.tableThumb':function (e) {
    $('#tableThumbPreview').stop().hide();
  },

  'show.bs.modal':function (e) {

    // Hack to fix autoform bug.
    // Clears image upload form when
    // no imageFilePaths are found. -tn
    setTimeout(function () {
      var imgDoc = Images.findOne({ _id: Session.get('adminCurrentImageId') });
      if (imgDoc) {
        if (imgDoc.imageFilePaths) {
          // Already has image. Allow to display.
          return;
        }
      }

      $('#editModal .file-upload-clear').trigger('click');
    }, 20);

  },

  'shown.bs.modal':function (e) {

  },

});

// ImageUtil
function loadImgDimensions(doc, isUpdate, callback) {

  var editDoc;
  if (isUpdate) {
    editDoc = doc.$set;
  } else {
    editDoc = doc;
  }

  if (
    editDoc.imageFilePaths == undefined ||
    editDoc.imageFilePaths == 'undefined' ||
    !editDoc.imageFilePaths
  ) {
    callback(doc);
    return false;
  }

  var expandedSrc = editDoc.imageFilePaths[0].src;
  var thumbSrc = editDoc.imageFilePaths[1].src;
  var myImage = new Image();
  var myThumbImage = new Image();

  var expandedLoaded = false;
  var thumbLoaded = false;

  myImage.onload = function () {

    console.log('\' Expanded is ' + this.width + ' by ' + this.height + ' pixels in size.');

    editDoc.expandedWidth = this.width;
    editDoc.expandedHeight = this.height;
    editDoc.expandedAspectRatio = (this.width / this.height).toFixed(4);

    expandedLoaded = true;
    if (thumbLoaded && expandedLoaded) {
      if (isUpdate) {
        callback({ $set:editDoc });
        return true;
      } else {
        callback(editDoc);
        return true;
      }
    }

  };

  myThumbImage.onload = function () {

    console.log('\' Thumb is ' + this.width + ' by ' + this.height + ' pixels in size.');

    editDoc.thumbWidth = this.width;
    editDoc.thumbHeight = this.height;
    editDoc.thumbAspectRatio = (this.width / this.height).toFixed(4);

    thumbLoaded = true;
    if (thumbLoaded && expandedLoaded) {
      if (isUpdate) {
        callback({ $set:editDoc });
        return true;
      } else {
        callback(editDoc);
        return true;
      }
    }

  };

  myImage.onerror = function () {

    console.log('\'' + this.name + '\' (expanded) failed to load.');
    callback(doc);
    return false;

  };

  myThumbImage.onerror = function () {

    console.log('\'' + this.name + '\' (thumb) failed to load.');
    callback(doc);
    return false;

  };

  myImage.src = expandedSrc;
  myThumbImage.src = thumbSrc;

}

/**
* Hooks for autoform. Manipulate data before/after submission.
*/
AutoForm.hooks({

  formImageEntry: {

    before: {

      insert: function (doc) {

        // Add location Id to create link to current location
        doc.dsLocId = Locations.findOne().dsLocId;
        doc.generalLocationDs = Locations.findOne().title;

        // Add image meta data
        loadImgDimensions(doc, false, this.result);

      },

      update: function (doc) {

        // Add image meta data
        loadImgDimensions(doc, true, this.result);

      },

    },

    docToForm: function (doc, ss) {

      // TODO - Remove unneccessary iso prepend (cleaning old data)
      if (doc.isoDate && doc.isoDate.indexOf('iso-') != -1) {
        doc.isoDate = doc.isoDate.replace('iso-', '');
      }

      return doc;

    },

    // Called when any submit operation succeeds
    onSuccess: function (formType, result) {

      if (formType === 'insert') {
        Session.set('adminCurrentImageId', result);
      }

      console.log('New doc:');
      console.log(Images.findOne(Session.get('adminCurrentImageId')));

      // Hide modal
      $('#editModal').modal('hide');
      $('#editModal form')[0].reset();

    },

    // Called when any submit operation fails
    onError: function (formType, error) {

      console.log('Autoform error:', formType, error);

    },

  },

});
<|endoftext|>


<commit_before>/**
 * Git cloning with template variables.
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

/**
 * Gitemplate constructor.
 */
exports.Gitemplate = Gitemplate;

/**
 * Create a new Gitemplate.
 *
 * @return {object}
 */
exports.create = function create() { return new Gitemplate(); };

/**
 * Extend Gitemplate.prototype.
 *
 * @param {object} ext
 * @return {object} Merge result.
 */
exports.extend = function extendProto(ext) { return extend(Gitemplate.prototype, ext); };

const util = require('util');
const sprintf = util.format;
const outerShelljs = require('outer-shelljs');
const longCon = require('long-con');

const requireComponent = require('../component/require');
const configurable = requireComponent('configurable.js');
const extend = requireComponent('extend');
const escapeRe = requireComponent('escape-regexp');
const defShellOpt = {silent: true};

/**
 * Gitemplate constructor.
 *
 * Usage:
 *
 *     const gt = require('gitemplate').create();
 *     gt
 *       .set('name', this.name)
 *       .set('src', this.src)
 *       .set('dst', this.dst)
 *       .set('desc', this.desc)
 *       .set('json', this.json)
 *       .set('repo', this.repo);
 *     gt.cloneRepo();
 *
 * Configuration:
 *
 * - `{string} desc` `gitemplate_desc` replacement value
 * - `{string} dst` Clone path
 * - `{object} json` Replacement key/value pairs from `--json`
 * - `{string} name` `gitemplate_name` replacement value
 * - `{string} originSha` `gitemplate_originSha` replacement value
 * - `{string} originUrl` `gitemplate_originUrl` replacement value
 * - `{string} src` Source repository URL/path
 * - `{string} year` `gitemplate_year` replacement value
 *
 * Properties:
 *
 * - `{object} shelljs` `OuterShelljs` instance
 * - `{object} stdout`
 *
 * @see OuterShelljs https://github.com/codeactual/outer-shelljs/blob/master/docs/OuterShelljs.md
 */
function Gitemplate() {
  this.settings = {
    name: '',
    desc: '',
    json: {},
    repo: '',
    year: (new Date()).getUTCFullYear(),
    originSha: '',
    originUrl: ''
  };

  this.shelljs = outerShelljs.create();

  const lc = longCon.create().set('time', false);
  this.stdout = lc.create('gitemplate', console.log); // eslint-disable-line no-console
}

configurable(Gitemplate.prototype);

/**
 * Apply collected configuration.
 */
Gitemplate.prototype.init = function init() {
  if (this.get('verbose')) {
    defShellOpt.silent = false;
  }

  if (!defShellOpt.silent) {
    this.shelljs.on('cmd', this.onShellCmd.bind(this));
  }
};

/**
 * Display details about each command in `--verbose` mode.
 *
 * Handler for the `cmd` event emitted from `OuterShelljs`.
 *
 * @api private
 */
Gitemplate.prototype.onShellCmd = function onShellCmd(method, args) {
  this.stdout('%s(%s)', method, JSON.stringify(args));
};

/**
 * Clone the configured repo.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.cloneRepo = function cloneRepo() {
  const dst = this.get('dst');
  if (this.shelljs._('test', '-e', dst)) {
    return {code: 1, output: 'Destination already exists'};
  }
  return this.shelljs._(
    'exec',
    sprintf('git clone %s %s', this.get('src'), dst),
    defShellOpt
  );
};

/**
 * Remove `.git/` to prepare for a fresh init and remote origin.
 */
Gitemplate.prototype.rmGitDir = function rmGitDir() {
  this.shelljs._('rm', '-rf', this.get('dst') + '/.git');
};

/**
 * Replace macros found in repo file content.
 */
Gitemplate.prototype.replaceContentVars = function replaceContentVars() {
  const cmdHead = "find %s -type f -exec perl -p -i -e 's/";
  const cmdFoot = "/%s/gi' {} \\;";
  const dst = this.get('dst');
  const passThruKeys = ['name', 'desc', 'repo', 'year', 'originSha', 'originUrl'];
  let res = {code: 0};
  const self = this;

  passThruKeys.forEach(function forEachKey(key) {
    if (res.code !== 0) { // Prior exec() failed, bail out.
      return;
    }
    res = self.shelljs._(
      'exec',
      sprintf(cmdHead + gitemplateEscVar(key) + cmdFoot, dst, escapeRe(self.get(key))),
      defShellOpt
    );
  });
  if (res.code !== 0) { return res; }

  const json = this.get('json');
  Object.keys(json).forEach(function forEachKey(key) {
    res = self.shelljs._(
      'exec',
      sprintf(cmdHead + gitemplateEscVar(key) + cmdFoot, dst, escapeRe(json[key])),
      defShellOpt
    );
    if (res.code !== 0) { return res; }
  });

  return res;
};

/**
 * Replace macros found in repo file names.
 */
Gitemplate.prototype.replaceNameVars = function replaceNameVars() {
  const self = this;
  const name = this.get('name');
  const dst = this.get('dst');

  const nameVar = gitemplateVar('name');
  function mvNameVar(target) {
    self.shelljs._('mv', target, target.replace(nameVar, name));
  }

  let targets = this.shelljs._('find', dst).filter(function filterDir(file) { // In dir names
    return self.shelljs._('test', '-d', file) && file.match(nameVar);
  });
  targets.forEach(mvNameVar);
  targets = this.shelljs._('find', dst).filter(function filterFile(file) { // In file names
    return self.shelljs._('test', '-f', file) && file.match(nameVar);
  });
  targets.forEach(mvNameVar);

  const json = this.get('json');
  const jsonKeys = Object.keys(json);
  jsonKeys.forEach(function forEachKey(key) {
    const escapedKey = gitemplateEscVarCaseInsRe(key);
    function mvJsonVar(target) {
      self.shelljs._('mv', target, target.replace(escapedKey, json[key]));
    }

    const targets = self.shelljs._('find', dst).filter(function filterDir(file) {
      return self.shelljs._('test', '-d', file) && file.match(escapedKey);
    });
    targets.forEach(mvJsonVar);
  });

  jsonKeys.forEach(function forEachKey(key) {
    const escapedKey = gitemplateEscVarCaseInsRe(key);
    function mvJsonVar(target) {
      self.shelljs._('mv', target, target.replace(escapedKey, json[key]));
    }

    const targets = self.shelljs._('find', dst).filter(function filterFile(file) {
      return self.shelljs._('test', '-f', file) && file.match(escapedKey);
    });
    targets.forEach(mvJsonVar);
  });
};

/**
 * Initialize a repo in the clone dir.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.initRepo = function initRepo() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git init', defShellOpt);
};

/**
 * Set GitHub remote origin.
 */
Gitemplate.prototype.setGithubOrigin = function setGithubOrigin() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._(
    'exec',
    sprintf('git remote add origin git@github.com:%s.git', this.get('repo')),
    defShellOpt
  );
};

/**
 * Get replacement value for `gitemplate_originSha`.
 *
 * @return {string}
 * @api private
 */
Gitemplate.prototype.getRepoOriginSha = function getRepoOriginSha() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git rev-parse HEAD', defShellOpt).output.slice(0, 10);
};

/**
 * Get replacement value for `gitemplate_originUrl`.
 *
 * @return {string}
 * @api private
 */
Gitemplate.prototype.getRepoOriginUrl = function getRepoOriginUrl() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git remote show origin', defShellOpt).output.match(/Fetch\s+URL: (\S+)/)[1];
};

/**
 * Run the `.gitemplate.postreplace` script if present.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.runPostReplace = function runPostReplace() {
  const dst = this.get('dst');
  const script = dst + '/.gitemplate.postreplace';
  if (!this.shelljs._('test', '-e', script)) {
    return;
  }
  this.shelljs._('cd', dst);
  const res = this.shelljs._('exec', script, defShellOpt);
  if (res.code === 0) {
    this.shelljs._('rm', '-f', script);
  }
  return res;
};

function gitemplateVar(key) { return 'gitemplate_' + key; }
function gitemplateEscVar(key) { return escapeRe(gitemplateVar(key)); }
function gitemplateEscVarCaseInsRe(key) { return new RegExp(gitemplateEscVar(key), 'i'); }
<commit_msg>fix(runPostReplace): inconsistent return structure<commit_after>/**
 * Git cloning with template variables.
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

/**
 * Gitemplate constructor.
 */
exports.Gitemplate = Gitemplate;

/**
 * Create a new Gitemplate.
 *
 * @return {object}
 */
exports.create = function create() { return new Gitemplate(); };

/**
 * Extend Gitemplate.prototype.
 *
 * @param {object} ext
 * @return {object} Merge result.
 */
exports.extend = function extendProto(ext) { return extend(Gitemplate.prototype, ext); };

const util = require('util');
const sprintf = util.format;
const outerShelljs = require('outer-shelljs');
const longCon = require('long-con');

const requireComponent = require('../component/require');
const configurable = requireComponent('configurable.js');
const extend = requireComponent('extend');
const escapeRe = requireComponent('escape-regexp');
const defShellOpt = {silent: true};

/**
 * Gitemplate constructor.
 *
 * Usage:
 *
 *     const gt = require('gitemplate').create();
 *     gt
 *       .set('name', this.name)
 *       .set('src', this.src)
 *       .set('dst', this.dst)
 *       .set('desc', this.desc)
 *       .set('json', this.json)
 *       .set('repo', this.repo);
 *     gt.cloneRepo();
 *
 * Configuration:
 *
 * - `{string} desc` `gitemplate_desc` replacement value
 * - `{string} dst` Clone path
 * - `{object} json` Replacement key/value pairs from `--json`
 * - `{string} name` `gitemplate_name` replacement value
 * - `{string} originSha` `gitemplate_originSha` replacement value
 * - `{string} originUrl` `gitemplate_originUrl` replacement value
 * - `{string} src` Source repository URL/path
 * - `{string} year` `gitemplate_year` replacement value
 *
 * Properties:
 *
 * - `{object} shelljs` `OuterShelljs` instance
 * - `{object} stdout`
 *
 * @see OuterShelljs https://github.com/codeactual/outer-shelljs/blob/master/docs/OuterShelljs.md
 */
function Gitemplate() {
  this.settings = {
    name: '',
    desc: '',
    json: {},
    repo: '',
    year: (new Date()).getUTCFullYear(),
    originSha: '',
    originUrl: ''
  };

  this.shelljs = outerShelljs.create();

  const lc = longCon.create().set('time', false);
  this.stdout = lc.create('gitemplate', console.log); // eslint-disable-line no-console
}

configurable(Gitemplate.prototype);

/**
 * Apply collected configuration.
 */
Gitemplate.prototype.init = function init() {
  if (this.get('verbose')) {
    defShellOpt.silent = false;
  }

  if (!defShellOpt.silent) {
    this.shelljs.on('cmd', this.onShellCmd.bind(this));
  }
};

/**
 * Display details about each command in `--verbose` mode.
 *
 * Handler for the `cmd` event emitted from `OuterShelljs`.
 *
 * @api private
 */
Gitemplate.prototype.onShellCmd = function onShellCmd(method, args) {
  this.stdout('%s(%s)', method, JSON.stringify(args));
};

/**
 * Clone the configured repo.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.cloneRepo = function cloneRepo() {
  const dst = this.get('dst');
  if (this.shelljs._('test', '-e', dst)) {
    return {code: 1, output: 'Destination already exists'};
  }
  return this.shelljs._(
    'exec',
    sprintf('git clone %s %s', this.get('src'), dst),
    defShellOpt
  );
};

/**
 * Remove `.git/` to prepare for a fresh init and remote origin.
 */
Gitemplate.prototype.rmGitDir = function rmGitDir() {
  this.shelljs._('rm', '-rf', this.get('dst') + '/.git');
};

/**
 * Replace macros found in repo file content.
 */
Gitemplate.prototype.replaceContentVars = function replaceContentVars() {
  const cmdHead = "find %s -type f -exec perl -p -i -e 's/";
  const cmdFoot = "/%s/gi' {} \\;";
  const dst = this.get('dst');
  const passThruKeys = ['name', 'desc', 'repo', 'year', 'originSha', 'originUrl'];
  let res = {code: 0};
  const self = this;

  passThruKeys.forEach(function forEachKey(key) {
    if (res.code !== 0) { // Prior exec() failed, bail out.
      return;
    }
    res = self.shelljs._(
      'exec',
      sprintf(cmdHead + gitemplateEscVar(key) + cmdFoot, dst, escapeRe(self.get(key))),
      defShellOpt
    );
  });
  if (res.code !== 0) { return res; }

  const json = this.get('json');
  Object.keys(json).forEach(function forEachKey(key) {
    res = self.shelljs._(
      'exec',
      sprintf(cmdHead + gitemplateEscVar(key) + cmdFoot, dst, escapeRe(json[key])),
      defShellOpt
    );
    if (res.code !== 0) { return res; }
  });

  return res;
};

/**
 * Replace macros found in repo file names.
 */
Gitemplate.prototype.replaceNameVars = function replaceNameVars() {
  const self = this;
  const name = this.get('name');
  const dst = this.get('dst');

  const nameVar = gitemplateVar('name');
  function mvNameVar(target) {
    self.shelljs._('mv', target, target.replace(nameVar, name));
  }

  let targets = this.shelljs._('find', dst).filter(function filterDir(file) { // In dir names
    return self.shelljs._('test', '-d', file) && file.match(nameVar);
  });
  targets.forEach(mvNameVar);
  targets = this.shelljs._('find', dst).filter(function filterFile(file) { // In file names
    return self.shelljs._('test', '-f', file) && file.match(nameVar);
  });
  targets.forEach(mvNameVar);

  const json = this.get('json');
  const jsonKeys = Object.keys(json);
  jsonKeys.forEach(function forEachKey(key) {
    const escapedKey = gitemplateEscVarCaseInsRe(key);
    function mvJsonVar(target) {
      self.shelljs._('mv', target, target.replace(escapedKey, json[key]));
    }

    const targets = self.shelljs._('find', dst).filter(function filterDir(file) {
      return self.shelljs._('test', '-d', file) && file.match(escapedKey);
    });
    targets.forEach(mvJsonVar);
  });

  jsonKeys.forEach(function forEachKey(key) {
    const escapedKey = gitemplateEscVarCaseInsRe(key);
    function mvJsonVar(target) {
      self.shelljs._('mv', target, target.replace(escapedKey, json[key]));
    }

    const targets = self.shelljs._('find', dst).filter(function filterFile(file) {
      return self.shelljs._('test', '-f', file) && file.match(escapedKey);
    });
    targets.forEach(mvJsonVar);
  });
};

/**
 * Initialize a repo in the clone dir.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.initRepo = function initRepo() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git init', defShellOpt);
};

/**
 * Set GitHub remote origin.
 */
Gitemplate.prototype.setGithubOrigin = function setGithubOrigin() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._(
    'exec',
    sprintf('git remote add origin git@github.com:%s.git', this.get('repo')),
    defShellOpt
  );
};

/**
 * Get replacement value for `gitemplate_originSha`.
 *
 * @return {string}
 * @api private
 */
Gitemplate.prototype.getRepoOriginSha = function getRepoOriginSha() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git rev-parse HEAD', defShellOpt).output.slice(0, 10);
};

/**
 * Get replacement value for `gitemplate_originUrl`.
 *
 * @return {string}
 * @api private
 */
Gitemplate.prototype.getRepoOriginUrl = function getRepoOriginUrl() {
  this.shelljs._('cd', this.get('dst'));
  return this.shelljs._('exec', 'git remote show origin', defShellOpt).output.match(/Fetch\s+URL: (\S+)/)[1];
};

/**
 * Run the `.gitemplate.postreplace` script if present.
 *
 * @return {object} `shelljs.exec()` result
 */
Gitemplate.prototype.runPostReplace = function runPostReplace() {
  const dst = this.get('dst');
  const script = dst + '/.gitemplate.postreplace';
  if (!this.shelljs._('test', '-e', script)) {
    return {code: 0, res: ''};
  }
  this.shelljs._('cd', dst);
  const res = this.shelljs._('exec', script, defShellOpt);
  if (res.code === 0) {
    this.shelljs._('rm', '-f', script);
  }
  return res;
};

function gitemplateVar(key) { return 'gitemplate_' + key; }
function gitemplateEscVar(key) { return escapeRe(gitemplateVar(key)); }
function gitemplateEscVarCaseInsRe(key) { return new RegExp(gitemplateEscVar(key), 'i'); }
<|endoftext|>


<commit_before>const validRulesKeys = require('../_constants/validRulesKeys');
const getRelativeRoot = require('./getRelativeRoot');

module.exports = function buildPath(targetObj, path, values, pathArr, curPathIdx, pathObj) {

  pathArr = pathArr || path.split('/');
  pathObj = pathObj || targetObj;
  curPathIdx = curPathIdx || 0;

  const curPathKey = pathArr[curPathIdx];
  if (!pathObj[curPathKey]) { pathObj[curPathKey] = {}; }

  pathObj = pathObj[curPathKey];

  if (curPathIdx < pathArr.length - 1) {
    return buildPath(targetObj, path, values, pathArr, curPathIdx + 1, pathObj);
  }

  const valueKeys = Object.getOwnPropertyNames(values);
  valueKeys.forEach((valueKey) => {
    if (!validRulesKeys[valueKey]) { return; }

    const valueKeyRules = values[valueKey];
    const finalValueKey = `.${valueKey}`;
    const relativeRootStr = 'newDataRoot().';

    if (valueKeyRules.indexOf(relativeRootStr) !== -1) {
      const relativeRoot = getRelativeRoot(curPathIdx);
      pathObj[finalValueKey] = valueKeyRules.replace(relativeRootStr, relativeRoot);
    } else {
      pathObj[finalValueKey] = valueKeyRules;
    }

  });

  return targetObj;

}
<commit_msg>added: pathRules can now be a boolean that is translated to a string on build.<commit_after>const validRulesKeys = require('../_constants/validRulesKeys');
const getRelativeRoot = require('./getRelativeRoot');

module.exports = function buildPath(targetObj, path, values, pathArr, curPathIdx, pathObj) {

  pathArr = pathArr || path.split('/');
  pathObj = pathObj || targetObj;
  curPathIdx = curPathIdx || 0;

  const curPathKey = pathArr[curPathIdx];
  if (!pathObj[curPathKey]) { pathObj[curPathKey] = {}; }

  pathObj = pathObj[curPathKey];

  if (curPathIdx < pathArr.length - 1) {
    return buildPath(targetObj, path, values, pathArr, curPathIdx + 1, pathObj);
  }

  const valueKeys = Object.getOwnPropertyNames(values);
  valueKeys.forEach((valueKey) => {
    if (!validRulesKeys[valueKey]) { return; }

    const valueKeyRules = values[valueKey].toString();
    const finalValueKey = `.${valueKey}`;
    const relativeRootStr = 'newDataRoot().';

    if (valueKeyRules.indexOf(relativeRootStr) !== -1) {
      const relativeRoot = getRelativeRoot(curPathIdx);
      pathObj[finalValueKey] = valueKeyRules.replace(relativeRootStr, relativeRoot);
    } else {
      pathObj[finalValueKey] = valueKeyRules;
    }

  });

  return targetObj;

}
<|endoftext|>


<commit_before>// Load our dependencies
var assert = require('assert');
var async = require('async');
var fs = require('fs');
var path = require('path');
var Readable = require('stream').Readable;
var _ = require('underscore');
var gutil = require('gulp-util');
var Minimatch = require('minimatch').Minimatch;
var templater = require('spritesheet-templates');
var spritesmith = require('spritesmith');
var through2 = require('through2');
var url = require('url2');

function ExtFormat() {
  this.formatObj = {};
}
ExtFormat.prototype = {
  add: function (name, val) {
    this.formatObj[name] = val;
  },
  get: function (filepath) {
    // Grab the extension from the filepath
    var ext = path.extname(filepath);
    var lowerExt = ext.toLowerCase();

    // Look up the file extenion from our format object
    var formatObj = this.formatObj;
    var format = formatObj[lowerExt];
    return format;
  }
};

// Create img and css formats
var imgFormats = new ExtFormat();
var cssFormats = new ExtFormat();

// Add our img formats
imgFormats.add('.png', 'png');
imgFormats.add('.jpg', 'jpeg');
imgFormats.add('.jpeg', 'jpeg');

// Add our css formats
cssFormats.add('.styl', 'stylus');
cssFormats.add('.stylus', 'stylus');
cssFormats.add('.sass', 'sass');
cssFormats.add('.scss', 'scss');
cssFormats.add('.less', 'less');
cssFormats.add('.json', 'json');
cssFormats.add('.css', 'css');

// Copy/paste helper from gulp
// https://github.com/wearefractal/glob-stream/blob/v5.0.0/index.js#L131-L138
function unrelative(cwd, glob) {
  var mod = '';
  if (glob[0] === '!') {
    mod = glob[0];
    glob = glob.slice(1);
  }
  return mod + path.resolve(cwd, glob);
}

// Define helper for coordinate naming
function getCoordinateName(filepath) {
  // Extract the image name (exlcuding extension)
  var fullname = path.basename(filepath);
  var nameParts = fullname.split('.');

  // If there is are more than 2 parts, pop the last one
  if (nameParts.length >= 2) {
    nameParts.pop();
  }

  // Return our modified filename
  return nameParts.join('.');
}

// Create a gulp-spritesmith function
function gulpSpritesmith(params) {
  var imgName = params.imgName;
  var cssName = params.cssName;
  assert(imgName, 'An `imgName` parameter was not provided to `gulp.spritesmith` (required)');
  assert(cssName, 'A `cssName` parameter was not provided to `gulp.spritesmith` (required)');

  // If there are settings for retina, verify our all of them are present
  var retinaSrcFilter = params.retinaSrcFilter;
  var retinaImgName = params.retinaImgName;
  if (retinaSrcFilter || retinaImgName) {
    assert(retinaSrcFilter && retinaImgName, 'Retina settings detected. We must have both `retinaSrcFilter` and ' +
      '`retinaImgName` provided for retina to work');
  }

  // Define our output streams
  var imgStream = new Readable({objectMode: true});
  imgStream._read = function imgRead () {
    // Do nothing, let the `finish` handler take care of this
  };
  var cssStream = new Readable({objectMode: true});
  cssStream._read = function cssRead () {
    // Do nothing, let the `finish` handler take care of this
  };

  // Create a stream to take in images
  var images = [];
  var onData = function (file, encoding, cb) {
    if (file.path) {
      images.push(file);
    }
    cb();
  };

  // When we have completed our input
  var onEnd = function (cb) {
    // If there are no images present, exit early
    // DEV: This is against the behavior of `spritesmith` but pro-gulp
    // DEV: See https://github.com/twolfson/gulp.spritesmith/issues/17
    if (images.length === 0) {
      imgStream.push(null);
      cssStream.push(null);
      return cb();
    }

    // Determine the format of the image
    var imgOpts = params.imgOpts || {};
    var imgFormat = imgOpts.format || imgFormats.get(imgName) || 'png';

    // Set up the defautls for imgOpts
    imgOpts = _.defaults({}, imgOpts, {format: imgFormat});

    // If we have retina settings, filter out the retina images
    var retinaImages;
    if (retinaSrcFilter) {
      // Filter out our retina files
      // https://github.com/wearefractal/glob-stream/blob/v5.0.0/index.js#L84-L87
      retinaImages = [];
      var retinaSrcPatterns = Array.isArray(retinaSrcFilter) ? retinaSrcFilter : [retinaSrcFilter];
      images = images.filter(function filterSrcFile (file) {
        // If we have a retina file, filter it out
        var matched = retinaSrcPatterns.some(function matchMinimatches (retinaSrcPattern) {
          var minimatch = new Minimatch(unrelative(file.cwd, retinaSrcPattern));
          return minimatch.match(file.path);
        });
        if (matched) {
          retinaImages.push(file);
          return false;
        // Otherwise, keep it in the src files
        } else {
          return true;
        }
      });

      // If we have a different amount of normal and retina images, complain and leave
      assert(images.length === retinaImages.length,
        'Retina settings detected but ' + retinaImages.length + ' retina images were found. ' +
        'We have ' + images.length + ' normal images and expect these numbers to line up. ' +
        'Please double check `retinaSrcFilter`.');
    }

    // Decouple vinyl files from filepaths
    images = _.pluck(images, 'path');
    if (retinaImages) {
      retinaImages = _.pluck(retinaImages, 'path');
    }

    // Prepare spritesmith parameters
    var spritesmithParams = {
      src: images,
      engine: params.engine,
      algorithm: params.algorithm,
      padding: params.padding || 0,
      algorithmOpts: params.algorithmOpts || {},
      engineOpts: params.engineOpts || {},
      exportOpts: imgOpts
    };
    var that = this;

    // In parallel
    async.parallel([
      // Run our normal task
      function generateNormalSpritesheet (callback) {
        spritesmith(spritesmithParams, callback);
      },
      // If we have a retina task, run it as well
      function generateRetinaSpritesheet (callback) {
        if (retinaImages) {
          var retinaParams = _.defaults({
            src: retinaImages,
            padding: spritesmithParams.padding * 2
          }, spritesmithParams);
          spritesmith(retinaParams, callback);
        } else {
          process.nextTick(callback);
        }
      }
    ], function handleSpritesheets (err, resultArr) {
      // If an error occurred, emit it
      if (err) {
        return cb(err);
      }

      // Otherwise, write out the image
      var result = resultArr[0];
      var retinaResult = resultArr[1];
      var imgFile = new gutil.File({
        path: imgName,
        contents: new Buffer(result.image, 'binary')
      });
      that.push(imgFile);
      imgStream.push(imgFile);
      if (retinaResult) {
        var retinaImgFile = new gutil.File({
          path: retinaImgName,
          contents: new Buffer(retinaResult.image, 'binary')
        });
        that.push(retinaImgFile);
      }
      imgStream.push(null);

      // START OF DUPLICATE CODE FROM grunt-spritesmith
      // Generate a listing of CSS variables
      var coordinates = result.coordinates;
      var properties = result.properties;
      var spritePath = params.imgPath || url.relative(cssName, imgName);
      var spritesheetData = {
        width: properties.width,
        height: properties.height,
        image: spritePath
      };
      var cssVarMap = params.cssVarMap || function noop () {};
      var cleanCoords = [];

      // Clean up the file name of the file
      Object.getOwnPropertyNames(coordinates).sort().forEach(function (file) {
        // Extract out our name
        var name = getCoordinateName(file);
        var coords = coordinates[file];

        // Specify the image for the sprite
        coords.name = name;
        coords.source_image = file;
        // DEV: `image`, `total_width`, `total_height` are deprecated as they are overwritten in `spritesheet-templates`
        coords.image = spritePath;
        coords.total_width = properties.width;
        coords.total_height = properties.height;

        // Map the coordinates through cssVarMap
        coords = cssVarMap(coords) || coords;

        // Save the cleaned name and coordinates
        cleanCoords.push(coords);
      });

      // If we have retina sprites
      var retinaCleanCoords;
      var retinaGroups;
      var retinaSpritesheetInfo;
      if (retinaResult) {
        // Generate a listing of CSS variables
        var retinaCoordinates = retinaResult.coordinates;
        var retinaProperties = retinaResult.properties;
        var retinaSpritePath = params.retinaImgPath || url.relative(cssName, retinaImgName);
        retinaSpritesheetInfo = {
          width: retinaProperties.width,
          height: retinaProperties.height,
          image: retinaSpritePath
        };
        // DEV: We reuse cssVarMap
        retinaCleanCoords = [];

        // Clean up the file name of the file
        Object.getOwnPropertyNames(retinaCoordinates).sort().forEach(function prepareRetinaTemplateData (file) {
          var name = getCoordinateName(file);
          var coords = retinaCoordinates[file];
          coords.name = name;
          coords.source_image = file;
          coords.image = retinaSpritePath;
          coords.total_width = retinaProperties.width;
          coords.total_height = retinaProperties.height;
          coords = cssVarMap(coords) || coords;
          retinaCleanCoords.push(coords);
        });

        // Generate groups for our coordinates
        retinaGroups = cleanCoords.map(function getRetinaGroups (normalSprite, i) {
          // Assert that image sizes line up for debugging purposes
          var retinaSprite = retinaCleanCoords[i];
          assert(retinaSprite.width === normalSprite.width * 2 || retinaSprite.height !== normalSprite.height * 2,
            'Normal sprite has inconsistent size with retina sprite. ' +
            '"' + normalSprite.name + '" is ' + normalSprite.width + 'x' + normalSprite.height + ' while ' +
            '"' + retinaSprite.name + '" is ' + retinaSprite.width + 'x' + retinaSprite.height + '.');

          // Generate our group
          // DEV: Name is inherited from `cssVarMap` on normal sprite
          return {
            name: normalSprite.name,
            index: i
          };
        });
      }

      // If there is a custom template, use it
      var cssFormat = 'spritesmith-custom';
      var cssTemplate = params.cssTemplate;
      if (cssTemplate) {
        if (typeof cssTemplate === 'function') {
          templater.addTemplate(cssFormat, cssTemplate);
        } else {
          templater.addHandlebarsTemplate(cssFormat, fs.readFileSync(cssTemplate, 'utf8'));
        }
      // Otherwise, override the cssFormat and fallback to 'json'
      } else {
        cssFormat = params.cssFormat;
        if (!cssFormat) {
          cssFormat = cssFormats.get(cssName) || 'json';

          // If we are dealing with retina items, move to retina flavor (e.g. `scss` -> `scss_retina`)
          if (retinaGroups) {
            cssFormat += '_retina';
          }
        }
      }

      // Render the variables via `spritesheet-templates`
      var cssStr = templater({
        sprites: cleanCoords,
        spritesheet: spritesheetData,
        spritesheet_info: {
          name: params.cssSpritesheetName
        },
        retina_groups: retinaGroups,
        retina_sprites: retinaCleanCoords,
        retina_spritesheet: retinaSpritesheetInfo,
        retina_spritesheet_info: {
          name: params.cssRetinaSpritesheetName
        },
        retina_groups_info: {
          name: params.cssRetinaGroupsName
        }
      }, {
        format: cssFormat,
        formatOpts: params.cssOpts || {}
      });
      // END OF DUPLICATE CODE FROM grunt-spritesmith

      // Output the CSS
      var cssFile = new gutil.File({
        path: cssName,
        contents: new Buffer(cssStr)
      });
      that.push(cssFile);
      cssStream.push(cssFile);
      cssStream.push(null);
      cb();
    });
  };

  // Return output stream with two sub-streams:
  // - master stream includes all files
  // - 'css' stream for css only
  // - 'img' stream for images only
  var retStream = through2.obj(onData, onEnd);
  retStream.css = cssStream;
  retStream.img = imgStream;
  return retStream;
}

module.exports = gulpSpritesmith;
<commit_msg>Add retinaImgFile to imgStream<commit_after>// Load our dependencies
var assert = require('assert');
var async = require('async');
var fs = require('fs');
var path = require('path');
var Readable = require('stream').Readable;
var _ = require('underscore');
var gutil = require('gulp-util');
var Minimatch = require('minimatch').Minimatch;
var templater = require('spritesheet-templates');
var spritesmith = require('spritesmith');
var through2 = require('through2');
var url = require('url2');

function ExtFormat() {
  this.formatObj = {};
}
ExtFormat.prototype = {
  add: function (name, val) {
    this.formatObj[name] = val;
  },
  get: function (filepath) {
    // Grab the extension from the filepath
    var ext = path.extname(filepath);
    var lowerExt = ext.toLowerCase();

    // Look up the file extenion from our format object
    var formatObj = this.formatObj;
    var format = formatObj[lowerExt];
    return format;
  }
};

// Create img and css formats
var imgFormats = new ExtFormat();
var cssFormats = new ExtFormat();

// Add our img formats
imgFormats.add('.png', 'png');
imgFormats.add('.jpg', 'jpeg');
imgFormats.add('.jpeg', 'jpeg');

// Add our css formats
cssFormats.add('.styl', 'stylus');
cssFormats.add('.stylus', 'stylus');
cssFormats.add('.sass', 'sass');
cssFormats.add('.scss', 'scss');
cssFormats.add('.less', 'less');
cssFormats.add('.json', 'json');
cssFormats.add('.css', 'css');

// Copy/paste helper from gulp
// https://github.com/wearefractal/glob-stream/blob/v5.0.0/index.js#L131-L138
function unrelative(cwd, glob) {
  var mod = '';
  if (glob[0] === '!') {
    mod = glob[0];
    glob = glob.slice(1);
  }
  return mod + path.resolve(cwd, glob);
}

// Define helper for coordinate naming
function getCoordinateName(filepath) {
  // Extract the image name (exlcuding extension)
  var fullname = path.basename(filepath);
  var nameParts = fullname.split('.');

  // If there is are more than 2 parts, pop the last one
  if (nameParts.length >= 2) {
    nameParts.pop();
  }

  // Return our modified filename
  return nameParts.join('.');
}

// Create a gulp-spritesmith function
function gulpSpritesmith(params) {
  var imgName = params.imgName;
  var cssName = params.cssName;
  assert(imgName, 'An `imgName` parameter was not provided to `gulp.spritesmith` (required)');
  assert(cssName, 'A `cssName` parameter was not provided to `gulp.spritesmith` (required)');

  // If there are settings for retina, verify our all of them are present
  var retinaSrcFilter = params.retinaSrcFilter;
  var retinaImgName = params.retinaImgName;
  if (retinaSrcFilter || retinaImgName) {
    assert(retinaSrcFilter && retinaImgName, 'Retina settings detected. We must have both `retinaSrcFilter` and ' +
      '`retinaImgName` provided for retina to work');
  }

  // Define our output streams
  var imgStream = new Readable({objectMode: true});
  imgStream._read = function imgRead () {
    // Do nothing, let the `finish` handler take care of this
  };
  var cssStream = new Readable({objectMode: true});
  cssStream._read = function cssRead () {
    // Do nothing, let the `finish` handler take care of this
  };

  // Create a stream to take in images
  var images = [];
  var onData = function (file, encoding, cb) {
    if (file.path) {
      images.push(file);
    }
    cb();
  };

  // When we have completed our input
  var onEnd = function (cb) {
    // If there are no images present, exit early
    // DEV: This is against the behavior of `spritesmith` but pro-gulp
    // DEV: See https://github.com/twolfson/gulp.spritesmith/issues/17
    if (images.length === 0) {
      imgStream.push(null);
      cssStream.push(null);
      return cb();
    }

    // Determine the format of the image
    var imgOpts = params.imgOpts || {};
    var imgFormat = imgOpts.format || imgFormats.get(imgName) || 'png';

    // Set up the defautls for imgOpts
    imgOpts = _.defaults({}, imgOpts, {format: imgFormat});

    // If we have retina settings, filter out the retina images
    var retinaImages;
    if (retinaSrcFilter) {
      // Filter out our retina files
      // https://github.com/wearefractal/glob-stream/blob/v5.0.0/index.js#L84-L87
      retinaImages = [];
      var retinaSrcPatterns = Array.isArray(retinaSrcFilter) ? retinaSrcFilter : [retinaSrcFilter];
      images = images.filter(function filterSrcFile (file) {
        // If we have a retina file, filter it out
        var matched = retinaSrcPatterns.some(function matchMinimatches (retinaSrcPattern) {
          var minimatch = new Minimatch(unrelative(file.cwd, retinaSrcPattern));
          return minimatch.match(file.path);
        });
        if (matched) {
          retinaImages.push(file);
          return false;
        // Otherwise, keep it in the src files
        } else {
          return true;
        }
      });

      // If we have a different amount of normal and retina images, complain and leave
      assert(images.length === retinaImages.length,
        'Retina settings detected but ' + retinaImages.length + ' retina images were found. ' +
        'We have ' + images.length + ' normal images and expect these numbers to line up. ' +
        'Please double check `retinaSrcFilter`.');
    }

    // Decouple vinyl files from filepaths
    images = _.pluck(images, 'path');
    if (retinaImages) {
      retinaImages = _.pluck(retinaImages, 'path');
    }

    // Prepare spritesmith parameters
    var spritesmithParams = {
      src: images,
      engine: params.engine,
      algorithm: params.algorithm,
      padding: params.padding || 0,
      algorithmOpts: params.algorithmOpts || {},
      engineOpts: params.engineOpts || {},
      exportOpts: imgOpts
    };
    var that = this;

    // In parallel
    async.parallel([
      // Run our normal task
      function generateNormalSpritesheet (callback) {
        spritesmith(spritesmithParams, callback);
      },
      // If we have a retina task, run it as well
      function generateRetinaSpritesheet (callback) {
        if (retinaImages) {
          var retinaParams = _.defaults({
            src: retinaImages,
            padding: spritesmithParams.padding * 2
          }, spritesmithParams);
          spritesmith(retinaParams, callback);
        } else {
          process.nextTick(callback);
        }
      }
    ], function handleSpritesheets (err, resultArr) {
      // If an error occurred, emit it
      if (err) {
        return cb(err);
      }

      // Otherwise, write out the image
      var result = resultArr[0];
      var retinaResult = resultArr[1];
      var imgFile = new gutil.File({
        path: imgName,
        contents: new Buffer(result.image, 'binary')
      });
      that.push(imgFile);
      imgStream.push(imgFile);
      if (retinaResult) {
        var retinaImgFile = new gutil.File({
          path: retinaImgName,
          contents: new Buffer(retinaResult.image, 'binary')
        });
        that.push(retinaImgFile);
        imgStream.push(retinaImgFile);
      }
      imgStream.push(null);

      // START OF DUPLICATE CODE FROM grunt-spritesmith
      // Generate a listing of CSS variables
      var coordinates = result.coordinates;
      var properties = result.properties;
      var spritePath = params.imgPath || url.relative(cssName, imgName);
      var spritesheetData = {
        width: properties.width,
        height: properties.height,
        image: spritePath
      };
      var cssVarMap = params.cssVarMap || function noop () {};
      var cleanCoords = [];

      // Clean up the file name of the file
      Object.getOwnPropertyNames(coordinates).sort().forEach(function (file) {
        // Extract out our name
        var name = getCoordinateName(file);
        var coords = coordinates[file];

        // Specify the image for the sprite
        coords.name = name;
        coords.source_image = file;
        // DEV: `image`, `total_width`, `total_height` are deprecated as they are overwritten in `spritesheet-templates`
        coords.image = spritePath;
        coords.total_width = properties.width;
        coords.total_height = properties.height;

        // Map the coordinates through cssVarMap
        coords = cssVarMap(coords) || coords;

        // Save the cleaned name and coordinates
        cleanCoords.push(coords);
      });

      // If we have retina sprites
      var retinaCleanCoords;
      var retinaGroups;
      var retinaSpritesheetInfo;
      if (retinaResult) {
        // Generate a listing of CSS variables
        var retinaCoordinates = retinaResult.coordinates;
        var retinaProperties = retinaResult.properties;
        var retinaSpritePath = params.retinaImgPath || url.relative(cssName, retinaImgName);
        retinaSpritesheetInfo = {
          width: retinaProperties.width,
          height: retinaProperties.height,
          image: retinaSpritePath
        };
        // DEV: We reuse cssVarMap
        retinaCleanCoords = [];

        // Clean up the file name of the file
        Object.getOwnPropertyNames(retinaCoordinates).sort().forEach(function prepareRetinaTemplateData (file) {
          var name = getCoordinateName(file);
          var coords = retinaCoordinates[file];
          coords.name = name;
          coords.source_image = file;
          coords.image = retinaSpritePath;
          coords.total_width = retinaProperties.width;
          coords.total_height = retinaProperties.height;
          coords = cssVarMap(coords) || coords;
          retinaCleanCoords.push(coords);
        });

        // Generate groups for our coordinates
        retinaGroups = cleanCoords.map(function getRetinaGroups (normalSprite, i) {
          // Assert that image sizes line up for debugging purposes
          var retinaSprite = retinaCleanCoords[i];
          assert(retinaSprite.width === normalSprite.width * 2 || retinaSprite.height !== normalSprite.height * 2,
            'Normal sprite has inconsistent size with retina sprite. ' +
            '"' + normalSprite.name + '" is ' + normalSprite.width + 'x' + normalSprite.height + ' while ' +
            '"' + retinaSprite.name + '" is ' + retinaSprite.width + 'x' + retinaSprite.height + '.');

          // Generate our group
          // DEV: Name is inherited from `cssVarMap` on normal sprite
          return {
            name: normalSprite.name,
            index: i
          };
        });
      }

      // If there is a custom template, use it
      var cssFormat = 'spritesmith-custom';
      var cssTemplate = params.cssTemplate;
      if (cssTemplate) {
        if (typeof cssTemplate === 'function') {
          templater.addTemplate(cssFormat, cssTemplate);
        } else {
          templater.addHandlebarsTemplate(cssFormat, fs.readFileSync(cssTemplate, 'utf8'));
        }
      // Otherwise, override the cssFormat and fallback to 'json'
      } else {
        cssFormat = params.cssFormat;
        if (!cssFormat) {
          cssFormat = cssFormats.get(cssName) || 'json';

          // If we are dealing with retina items, move to retina flavor (e.g. `scss` -> `scss_retina`)
          if (retinaGroups) {
            cssFormat += '_retina';
          }
        }
      }

      // Render the variables via `spritesheet-templates`
      var cssStr = templater({
        sprites: cleanCoords,
        spritesheet: spritesheetData,
        spritesheet_info: {
          name: params.cssSpritesheetName
        },
        retina_groups: retinaGroups,
        retina_sprites: retinaCleanCoords,
        retina_spritesheet: retinaSpritesheetInfo,
        retina_spritesheet_info: {
          name: params.cssRetinaSpritesheetName
        },
        retina_groups_info: {
          name: params.cssRetinaGroupsName
        }
      }, {
        format: cssFormat,
        formatOpts: params.cssOpts || {}
      });
      // END OF DUPLICATE CODE FROM grunt-spritesmith

      // Output the CSS
      var cssFile = new gutil.File({
        path: cssName,
        contents: new Buffer(cssStr)
      });
      that.push(cssFile);
      cssStream.push(cssFile);
      cssStream.push(null);
      cb();
    });
  };

  // Return output stream with two sub-streams:
  // - master stream includes all files
  // - 'css' stream for css only
  // - 'img' stream for images only
  var retStream = through2.obj(onData, onEnd);
  retStream.css = cssStream;
  retStream.img = imgStream;
  return retStream;
}

module.exports = gulpSpritesmith;
<|endoftext|>


<commit_before>
/* TODO: Allow and adjust for padding */

function remove_video_and_refresh_list(video_div) {
    video_div.fadeOut(1000, function() {video_div.remove();});
}

function run_and_disappear(eventdata) {
    var this_anchor = $(this);
    var video_div = this_anchor.parent().parent();
    jQuery.ajax({
        url: this_anchor.attr('href'),
        success: function() {
            remove_video_and_refresh_list(video_div);}});
    return false;
}

function load_video(eventdata) {
    var viddiv = $(this);
    var video_url = $(this).find('.click_to_display').attr('href');
    var admin_rightpane = $('#admin_rightpane');
    jQuery.ajax({
            url: video_url,
            success: function(data) {
                admin_rightpane.empty().append(data);
                if (typeof edit_widgets_setup === 'function') {
                    edit_widgets_setup();
                }
                var selected = $('div.selected');
                selected.removeClass('selected');
                selected.addClass('unselected');
                viddiv.removeClass('unselected');
                viddiv.addClass('selected');
                }});
    return false;
}

function load_click_callbacks() {
    $('div.video .approve_reject .approve').click(
        run_and_disappear);
    $('div.video .approve_reject .reject').click(
        run_and_disappear);
    $('div.video .approve_reject .feature').click(
        run_and_disappear);
    $('div.video').click(load_video);
}

function scroll_admin() {
    admin_table = document.getElementById('admin_table');
    admin_leftpane = document.getElementById('admin_leftpane');
    admin_rightpane = document.getElementById('admin_rightpane');
    if (admin_rightpane.clientHeight > window.innerHeight) {
        diff = admin_rightpane.clientHeight - window.innerHeight;
    } else {
        diff = 0;
    }
    if (admin_table.offsetTop + diff > window.scrollY) {
        admin_rightpane.style.top = (admin_table.offsetTop - window.scrollY) + 'px';
    } else {
        admin_rightpane.style.top = (-diff) + 'px';
    }
    admin_rightpane.style.right = admin_table.offsetLeft + 'px';
    admin_leftpane.style.width = (admin_table.clientWidth - 590) + 'px';
    admin_rightpane.style.display = "block";
}

if ('attachEvent' in window) {
    window.attachEvent('onload', scroll_admin);
    window.attachEvent('onload', load_click_callbacks);
    window.attachEvent('onscroll', scroll_admin);
    window.attachEvent('onresize', scroll_admin);
}
else {
    window.addEventListener('load', scroll_admin, false);
    window.addEventListener('load', load_click_callbacks, false);
    window.addEventListener('scroll', scroll_admin, false);
    window.addEventListener('resize', scroll_admin, false);
}

<commit_msg>Bug #12271: To Be Review Page Cut Off<commit_after>
/* TODO: Allow and adjust for padding */

function remove_video_and_refresh_list(video_div) {
    video_div.fadeOut(1000, function() {video_div.remove();});
}

function run_and_disappear(eventdata) {
    var this_anchor = $(this);
    var video_div = this_anchor.parent().parent();
    jQuery.ajax({
        url: this_anchor.attr('href'),
        success: function() {
            remove_video_and_refresh_list(video_div);}});
    return false;
}

function load_video(eventdata) {
    var viddiv = $(this);
    var video_url = $(this).find('.click_to_display').attr('href');
    var admin_rightpane = $('#admin_rightpane');
    jQuery.ajax({
            url: video_url,
            success: function(data) {
                admin_rightpane.empty().append(data);
                if (typeof edit_widgets_setup === 'function') {
                    edit_widgets_setup();
                }
                var selected = $('div.selected');
                selected.removeClass('selected');
                selected.addClass('unselected');
                viddiv.removeClass('unselected');
                viddiv.addClass('selected');
                }});
    return false;
}

function load_click_callbacks() {
    $('div.video .approve_reject .approve').click(
        run_and_disappear);
    $('div.video .approve_reject .reject').click(
        run_and_disappear);
    $('div.video .approve_reject .feature').click(
        run_and_disappear);
    $('div.video').click(load_video);
}

function scroll_admin() {
    admin_table = document.getElementById('admin_table');
    admin_leftpane = document.getElementById('admin_leftpane');
    admin_rightpane = document.getElementById('admin_rightpane');
    if (admin_rightpane.clientHeight > window.innerHeight) {
        diff = admin_rightpane.clientHeight - window.innerHeight;
    } else {
        diff = 0;
    }
    if (admin_table.offsetTop + diff > window.scrollY) {
        admin_rightpane.style.top = (admin_table.offsetTop - window.scrollY) + 'px';
    } else {
        admin_rightpane.style.top = (-diff) + 'px';
    }
    admin_rightpane.style.right = admin_table.offsetLeft + 'px';
    admin_leftpane.style.width = (admin_table.clientWidth - 590) + 'px';
    admin_rightpane.style.display = "block";
    if (admin_leftpane.clientHeight < admin_rightpane.clientHeight) {
        admin_leftpane.style.height = admin_rightpane.clientHeight + 'px';
    }
}

if ('attachEvent' in window) {
    window.attachEvent('onload', scroll_admin);
    window.attachEvent('onload', load_click_callbacks);
    window.attachEvent('onscroll', scroll_admin);
    window.attachEvent('onresize', scroll_admin);
}
else {
    window.addEventListener('load', scroll_admin, false);
    window.addEventListener('load', load_click_callbacks, false);
    window.addEventListener('scroll', scroll_admin, false);
    window.addEventListener('resize', scroll_admin, false);
}

<|endoftext|>


<commit_before>import axios from 'axios';
import { browserHistory } from 'react-router'
import * as types from '../constants/actionTypes';
import { HOUSEHOLDS_ENDPOINT } from '../constants/apiEndpoints';

// Fetch a list of households
export function fetchHouseholds() {
  const request = axios.get(HOUSEHOLDS_ENDPOINT);

  return (dispatch) => {
    // thunks allow for pre-processing actions, calling apis, and dispatching multiple actions
    request.then(({data}) => {
      dispatch({
        type: types.FETCH_HOUSEHOLDS,
        payload: data
      });
    });
  };
}

// Fetch a single household by id
export function fetchHousehold(id) {
  const request = axios.get(`${HOUSEHOLDS_ENDPOINT}/${id}`);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.FETCH_HOUSEHOLD,
        payload: data
      });
    });
  }
}

// Create a new household
export function createHousehold(props, successRedirect = '/') {
  const request = axios.post(`${HOUSEHOLDS_ENDPOINT}`, props);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.CREATE_HOUSEHOLD,
        payload: data
      });
      // Redirect after create success
      browserHistory.push(successRedirect);
    });
  }
}

// Delete a household by id
export function deleteHousehold(id, successRedirect = '/') {
  const request = axios.delete(`${HOUSEHOLDS_ENDPOINT}/${id}`);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.DELETE_HOUSEHOLD,
        payload: id
      });
      // Redirect after after delete success
      browserHistory.push(successRedirect);
    });
  }
}
<commit_msg>Cleaned up household endpoint<commit_after>import axios from 'axios';
import { browserHistory } from 'react-router'
import * as types from '../constants/actionTypes';
import { HOUSEHOLDS_ENDPOINT } from '../constants/apiEndpoints';

// Fetch a list of households
export function fetchHouseholds() {
  const request = axios.get(HOUSEHOLDS_ENDPOINT);

  return (dispatch) => {
    // thunks allow for pre-processing actions, calling apis, and dispatching multiple actions
    request.then(({data}) => {
      dispatch({
        type: types.FETCH_HOUSEHOLDS,
        payload: data
      });
    });
  };
}

// Fetch a single household by id
export function fetchHousehold(id) {
  const request = axios.get(`${HOUSEHOLDS_ENDPOINT}/${id}`);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.FETCH_HOUSEHOLD,
        payload: data
      });
    });
  }
}

// Create a new household
export function createHousehold(props, successRedirect = '/') {
  const request = axios.post(HOUSEHOLDS_ENDPOINT, props);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.CREATE_HOUSEHOLD,
        payload: data
      });
      // Redirect after create success
      browserHistory.push(successRedirect);
    });
  }
}

// Delete a household by id
export function deleteHousehold(id, successRedirect = '/') {
  const request = axios.delete(`${HOUSEHOLDS_ENDPOINT}/${id}`);

  return (dispatch) => {
    request.then(({data}) => {
      dispatch({
        type: types.DELETE_HOUSEHOLD,
        payload: id
      });
      // Redirect after after delete success
      browserHistory.push(successRedirect);
    });
  }
}
<|endoftext|>


<commit_before>

/**
 *
 * @summary 盈利计算模块 模块设计原则：独立不要有外部依赖,需要的都通过参数传递的方式来完成
 * */
var profit = ((function () {
    function profitMoney(options) {
        //用户设置
        this.userSettings = options.userSettings;
    }

    /**
     *
     * @summary 单次投注中奖后的盈利金额  奖金-本次投注金额=单次盈利金额
     * @param {String} investNumberString 投注的号码字符
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 盈利金额
     * */
    profitMoney.prototype.winMoney = function (investNumberString, playModeEnumItem) {
        var money = 0;
        var prizeMoney = this.userSettings.normalSettings.prizeMoney;//最大奖金
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        var investMoney = this.investMoney(investNumberString, playModeEnumItem);
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                money = prizeMoney - investMoney;
                break;
            case playModeEnumItem.jiao://角模式
                money = (prizeMoney / 10) - investMoney;
                break;
            case playModeEnumItem.feng://分模式
                money = (prizeMoney / 100) - investMoney;
                break;
        }
        return money;
    };

    /**
     *
     * @summary 投注的金额
     * @param {String} investNumberString 投注的号码字符
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 本局投注金额
     * */
    profitMoney.prototype.investMoney = function (investNumberString, playModeEnumItem) {
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        var investNumberCount = investNumberString.trim().split(/[ ,]/);
        var investMoney = investNumberCount * 2;
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                investMoney = investMoney;
                break;
            case playModeEnumItem.jiao://角模式
                investMoney = investMoney / 10;
                break;
            case playModeEnumItem.feng://分模式
                investMoney = investMoney / 100;
                break;
        }
        return investMoney;
    };

    /**
     *
     * @summary 当前账户余额
     * */
    profitMoney.prototype.currentAccountBalance = function () {

    };

    //design for test
    module.exports = profitMoney;
    return profitMoney;
})());<commit_msg>added new functionality in the profit module.<commit_after>//Testing requirement.
var currentAccountBalance = require('../global/globalVar.js').currentAccountBalance;

/**
 *
 * @summary 盈利计算模块 模块设计原则：独立不要有外部依赖,需要的都通过参数传递的方式来完成
 * */
var profit = ((function () {
    function profitMoney(options) {
        //用户设置
        this.userSettings = options.userSettings;
    }

    /**
     *
     * @summary 单次投注中奖后的盈利金额  奖金-本次投注金额=单次盈利金额
     * @param {String} investNumberString 投注的号码字符
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 盈利金额
     * */
    profitMoney.prototype.getWinMoney = function (investNumberString, playModeEnumItem) {
        var money = 0;
        var prizeMoney = this.userSettings.normalSettings.prizeMoney;//最大奖金
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        var investMoney = this.investMoney(investNumberString, playModeEnumItem);
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                money = prizeMoney - investMoney;
                break;
            case playModeEnumItem.jiao://角模式
                money = (prizeMoney / 10) - investMoney;
                break;
            case playModeEnumItem.feng://分模式
                money = (prizeMoney / 100) - investMoney;
                break;
        }
        return money;
    };

    /**
     *
     * @summary 投注的金额
     * @param {String} investNumberString 投注的号码字符
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 本局投注金额
     * */
    profitMoney.prototype.getInvestMoney = function (investNumberString, playModeEnumItem) {
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        var investNumberCount = investNumberString.trim().split(/[ ,]/);
        var investMoney = investNumberCount * 2;
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                investMoney = investMoney;
                break;
            case playModeEnumItem.jiao://角模式
                investMoney = investMoney / 10;
                break;
            case playModeEnumItem.feng://分模式
                investMoney = investMoney / 100;
                break;
        }
        return investMoney;
    };

    /**
     *
     * @summary 获取投注之后的当前账户余额
     * @param {String} investNumberString 投注的号码字符
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 当前账户余额
     * */
    profitMoney.prototype.setAccountBalanceAfterInvest = function (investNumberString, playModeEnumItem) {
        if (currentAccountBalance == null) {
            currentAccountBalance = this.userSettings.normalSettings.accountBalance;
        }
        //当前投注金额
        var investMoney = this.investMoney(investNumberString, playModeEnumItem);
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                currentAccountBalance = currentAccountBalance - investMoney;
                break;
            case playModeEnumItem.jiao://角模式
                currentAccountBalance = (currentAccountBalance / 10) - investMoney;
                break;
            case playModeEnumItem.feng://分模式
                currentAccountBalance = (currentAccountBalance / 100) - investMoney;
                break;
        }
    };

    /**
     *
     * @summary 获取总盈利金额
     * @param {Object} playModeEnumItem 玩法模式枚举值
     * @return {Number} 总盈利金额
     * */
    profitMoney.prototype.getTotalWinMoney = function (playModeEnumItem) {
        if (currentAccountBalance == null) {
            currentAccountBalance = this.userSettings.normalSettings.accountBalance;
        }
        var totalWinMoney = currentAccountBalance - this.userSettings.normalSettings.accountBalance;
        var playMode = this.userSettings.normalSettings.playMode;//玩法模式
        switch (playMode) {
            case playModeEnumItem.yuan://元模式
                totalWinMoney = totalWinMoney;
                break;
            case playModeEnumItem.jiao://角模式
                totalWinMoney = totalWinMoney / 10;
                break;
            case playModeEnumItem.feng://分模式
                totalWinMoney = totalWinMoney / 100;
                break;
        }
    };

    //Testing requirement.
    module.exports = profitMoney;
    return profitMoney;
})());<|endoftext|>


<commit_before>'use strict';
/**
 * @file Retrieve contacts for the account
 */

var config = require('../../config/configuration.js');
var mapper = require('./mapper.js');
var request = require('request');
var async = require('async');
var rarity = require('rarity');

/**
 * Use the Google refresh token to get a new accessToken,
 *
 * @param {String} refreshToken Refresh token issued by Google
 * @param {Function} cb First parameter is the error (if any), then the new accessToken (valid for one hour)
 */
var refreshAccessToken = function(refreshToken, cb) {

  // See https://developers.google.com/accounts/docs/OAuth2WebServer#refresh for details
  var params = {
    url: 'https://accounts.google.com/o/oauth2/token',
    form: {
      'refresh_token': refreshToken,
      'client_id': config.googleId,
      'client_secret': config.googleSecret,
      'grant_type': 'refresh_token'
    },
    json: true
  };

  request.post(params, function (err, res) {
    if(err){
      return cb(err);
    }

    if(res.statusCode === 401){
      return cb(new Error("Access to this refresh_token has been revoked."));
    }
    if(res.statusCode !== 200) {
      return cb(new Error("Google Error: " + res.body.message));
    }

    cb(null, res.body.access_token);
  });
};

/**
 * Retrieve all contacts associated with this user account,
 *
 * @param {String} accessToken AccessToken to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), then an array of all the contacts.
 */
var retrieveContacts = function(accessToken, since, cb) {

  // Pad n to have a length of width,
  // pad(1, 3) == 001
  var pad = function(n, width) {
    width = width || 2;
    n = n + '';
    return n.length >= width ? n : new Array(width - n.length + 1).join(0) + n;
  };

  // Date, formatted as 2007-03-16T00:00:00
  var formattedDate = since.getFullYear() + '-' + pad(since.getMonth() + 1) + '-' + pad(since.getDate()) + 'T' + pad(since.getHours()) + ':' + pad(since.getMinutes()) + ':' + pad(since.getSeconds());

  async.waterfall([
    function requestContacts(cb) {
      // See https://developers.google.com/google-apps/contacts/v3/?csw=1#retrieving_contacts_using_query_parameters for details
      var params = {
        url: 'https://www.google.com/m8/feeds/contacts/default/full',
        qs: {
          alt: 'json',
          'max-results': 100000,
          'showdeleted': true,
          'orderby': 'lastmodified',
          'updated-min': formattedDate
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, cb);
    },
    function getContacts(resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      cb(null, body.feed.entry ? body.feed.entry.map(mapper):[]);
    },
    function requestGroups(contacts, cb) {
      var params = {
        url: 'https://www.google.com/m8/feeds/groups/default/full',

        qs: {
          alt: 'json'
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, rarity.carry([contacts], cb));
    },
    function getGroups(contacts, resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      var groups = {};
      body.feed.entry.forEach(function(r) {
        groups[r.id['$t']] = r.title['$t'];
      });

      cb(null, contacts, groups);
    },
    function associateContactsAndGroups(contacts, groups, cb) {
      contacts.forEach(function(contact) {
        if(contact.groups) {
          for(var i = 0, len = contact.groups.length; i < len; i += 1) {
            contact.groups[i] = groups[contact.groups[i]];
          }
        }
      });

      cb(null, contacts);
    }
  ], cb);
};

/**
 * Download all contacts from the specified Google Account.
 *
 * @param {String} refreshToken Refresh_token to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), second an array of all the contacts.
 */
module.exports = function(refreshToken, since, cb) {
  refreshAccessToken(refreshToken, function(err, accessToken) {
    if(err) {
      return cb(err);
    }

    retrieveContacts(accessToken, since, cb);
  });
};
<commit_msg>Use .map instead of a for<commit_after>'use strict';
/**
 * @file Retrieve contacts for the account
 */

var config = require('../../config/configuration.js');
var mapper = require('./mapper.js');
var request = require('request');
var async = require('async');
var rarity = require('rarity');

/**
 * Use the Google refresh token to get a new accessToken,
 *
 * @param {String} refreshToken Refresh token issued by Google
 * @param {Function} cb First parameter is the error (if any), then the new accessToken (valid for one hour)
 */
var refreshAccessToken = function(refreshToken, cb) {

  // See https://developers.google.com/accounts/docs/OAuth2WebServer#refresh for details
  var params = {
    url: 'https://accounts.google.com/o/oauth2/token',
    form: {
      'refresh_token': refreshToken,
      'client_id': config.googleId,
      'client_secret': config.googleSecret,
      'grant_type': 'refresh_token'
    },
    json: true
  };

  request.post(params, function (err, res) {
    if(err){
      return cb(err);
    }

    if(res.statusCode === 401){
      return cb(new Error("Access to this refresh_token has been revoked."));
    }
    if(res.statusCode !== 200) {
      return cb(new Error("Google Error: " + res.body.message));
    }

    cb(null, res.body.access_token);
  });
};

/**
 * Retrieve all contacts associated with this user account,
 *
 * @param {String} accessToken AccessToken to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), then an array of all the contacts.
 */
var retrieveContacts = function(accessToken, since, cb) {

  // Pad n to have a length of width,
  // pad(1, 3) == 001
  var pad = function(n, width) {
    width = width || 2;
    n = n + '';
    return n.length >= width ? n : new Array(width - n.length + 1).join(0) + n;
  };

  // Date, formatted as 2007-03-16T00:00:00
  var formattedDate = since.getFullYear() + '-' + pad(since.getMonth() + 1) + '-' + pad(since.getDate()) + 'T' + pad(since.getHours()) + ':' + pad(since.getMinutes()) + ':' + pad(since.getSeconds());

  async.waterfall([
    function requestContacts(cb) {
      // See https://developers.google.com/google-apps/contacts/v3/?csw=1#retrieving_contacts_using_query_parameters for details
      var params = {
        url: 'https://www.google.com/m8/feeds/contacts/default/full',
        qs: {
          alt: 'json',
          'max-results': 100000,
          'showdeleted': true,
          'orderby': 'lastmodified',
          'updated-min': formattedDate
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, cb);
    },
    function getContacts(resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      cb(null, body.feed.entry ? body.feed.entry.map(mapper):[]);
    },
    function requestGroups(contacts, cb) {
      var params = {
        url: 'https://www.google.com/m8/feeds/groups/default/full',

        qs: {
          alt: 'json'
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, rarity.carry([contacts], cb));
    },
    function getGroups(contacts, resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      var groups = {};
      body.feed.entry.forEach(function(r) {
        groups[r.id['$t']] = r.title['$t'];
      });

      cb(null, contacts, groups);
    },
    function associateContactsAndGroups(contacts, groups, cb) {
      contacts.forEach(function(contact) {
        if(contact.groups) {
          contact.groups = contact.groups.map(function(id) {
            return groups[id];
          });
        }
      });

      cb(null, contacts);
    }
  ], cb);
};

/**
 * Download all contacts from the specified Google Account.
 *
 * @param {String} refreshToken Refresh_token to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), second an array of all the contacts.
 */
module.exports = function(refreshToken, since, cb) {
  refreshAccessToken(refreshToken, function(err, accessToken) {
    if(err) {
      return cb(err);
    }

    retrieveContacts(accessToken, since, cb);
  });
};
<|endoftext|>